Permalink
Browse files

Merge branch 'master' into NEXUS-5094_purgeSnapshotWithClassifier

Conflicts:
	nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/DefaultSnapshotRemover.java
  • Loading branch information...
2 parents 6395c1f + 040cc7d commit ffab40cec1256c3b45223e74e55ab1e4d66001c1 @kellyrob99 kellyrob99 committed Apr 30, 2013
Showing with 2,710 additions and 129,494 deletions.
  1. +5 −0 nexus-bootstrap/pom.xml
  2. +111 −0 ...ootstrap/src/main/java/org/sonatype/nexus/bootstrap/jetty/InstrumentedSelectChannelConnector.java
  3. +48 −0 nexus-client-core-testsuite/src/test/java/org/sonatype/nexus/client/testsuite/UserIT.java
  4. +18 −2 nexus-core/pom.xml
  5. +1 −2 nexus-core/src/main/java/org/sonatype/nexus/apachehttpclient/Hc4ProviderBase.java
  6. +2 −1 nexus-core/src/main/java/org/sonatype/nexus/apachehttpclient/Hc4ProviderImpl.java
  7. +86 −0 nexus-core/src/main/java/org/sonatype/nexus/apachehttpclient/InstrumentedHttpClient.java
  8. +128 −0 nexus-core/src/main/java/org/sonatype/nexus/apachehttpclient/InstrumentedRequestDirector.java
  9. +60 −0 nexus-core/src/main/java/org/sonatype/nexus/formfields/RepoTargetComboFormField.java
  10. +3 −2 nexus-core/src/main/java/org/sonatype/nexus/guice/NexusModules.java
  11. +84 −0 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/AbstractFileDeletingWalkerProcessor.java
  12. +413 −0 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/DefaultReleaseRemover.java
  13. +7 −50 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/DefaultSnapshotRemover.java
  14. +57 −0 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/ReleaseRemovalRequest.java
  15. +69 −0 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/ReleaseRemovalResult.java
  16. +28 −0 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/ReleaseRemover.java
  17. +59 −0 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/ReleaseRemoverTask.java
  18. +72 −0 ...s-core/src/main/java/org/sonatype/nexus/maven/tasks/descriptors/ReleaseRemovalTaskDescriptor.java
  19. +2 −0 nexus-core/src/main/java/org/sonatype/nexus/plugins/DefaultNexusPluginManager.java
  20. +3 −0 nexus-core/src/main/java/org/sonatype/nexus/plugins/rest/AbstractNexusIndexHtmlCustomizer.java
  21. +0 −146 nexus-core/src/main/java/org/sonatype/nexus/plugins/rest/AbstractUiContributionBuilder.java
  22. +0 −79 nexus-core/src/main/java/org/sonatype/nexus/plugins/rest/IndexHtmlSnippetBuilder.java
  23. +1 −2 nexus-core/src/main/java/org/sonatype/nexus/plugins/rest/NexusIndexHtmlCustomizer.java
  24. +0 −153 nexus-core/src/main/java/org/sonatype/nexus/plugins/rest/UiContributionBuilder.java
  25. +0 −89 nexus-core/src/main/java/org/sonatype/nexus/plugins/rest/UiContributor.java
  26. +9 −12 nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/AbstractMavenRepository.java
  27. +71 −62 ...re/src/main/java/org/sonatype/nexus/proxy/maven/routing/internal/scrape/AmazonS3IndexScraper.java
  28. +2 −1 nexus-core/src/main/java/org/sonatype/nexus/proxy/registry/RepositoryRegistry.java
  29. +3 −3 nexus-core/src/main/java/org/sonatype/nexus/proxy/repository/AbstractGroupRepository.java
  30. +33 −29 nexus-core/src/main/java/org/sonatype/nexus/proxy/repository/AbstractProxyRepository.java
  31. +8 −8 nexus-core/src/main/java/org/sonatype/nexus/proxy/repository/AbstractRepository.java
  32. +0 −39 nexus-core/src/main/java/org/sonatype/nexus/timing/Timed.java
  33. +0 −104 nexus-core/src/main/java/org/sonatype/nexus/timing/TimedInterceptor.java
  34. +0 −36 nexus-core/src/main/java/org/sonatype/nexus/timing/TimingModule.java
  35. +23 −0 nexus-core/src/main/java/org/sonatype/nexus/util/Condition.java
  36. +68 −50 nexus-core/src/main/java/org/sonatype/scheduling/DefaultTaskConfigManager.java
  37. +26 −0 nexus-core/src/main/resources/META-INF/nexus/static-security.xml
  38. +5 −0 nexus-core/src/test/java/org/sonatype/nexus/AbstractMavenRepoContentTests.java
  39. +156 −0 nexus-core/src/test/java/org/sonatype/nexus/maven/tasks/DefaultReleaseRemoverIT.java
  40. +219 −0 nexus-core/src/test/java/org/sonatype/nexus/maven/tasks/DefaultReleaseRemoverTest.java
  41. +1 −1 ...test/java/org/sonatype/nexus/proxy/maven/routing/internal/TextFilePrefixSourceMarshallerTest.java
  42. +267 −72 ...rc/test/java/org/sonatype/nexus/proxy/maven/routing/internal/scrape/AmazonS3IndexScraperTest.java
  43. +115 −0 ...est/java/org/sonatype/nexus/proxy/maven/routing/internal/scrape/AmazonS3LiveIndexScraperTest.java
  44. +67 −0 ...src/test/java/org/sonatype/nexus/proxy/maven/routing/internal/scrape/S3PagedDeliverBehaviour.java
  45. +39 −0 .../test/java/org/sonatype/nexus/proxy/maven/routing/internal/scrape/S3ResponseHeadersBehaviour.java
  46. +3 −2 nexus-core/src/test/java/org/sonatype/scheduling/DefaultTaskConfigManagerTest.java
  47. BIN nexus-core/src/test/resources/reposes/releases/org/sonatype/test/1.0.1/test-1.0.1-sources.jar
  48. +1 −0 nexus-core/src/test/resources/reposes/releases/org/sonatype/test/1.0.1/test-1.0.1-sources.jar.sha1
  49. BIN nexus-core/src/test/resources/reposes/releases/org/sonatype/test/1.0.1/test-1.0.1.jar
  50. +1 −0 nexus-core/src/test/resources/reposes/releases/org/sonatype/test/1.0.1/test-1.0.1.jar.sha1
  51. +29 −0 nexus-core/src/test/resources/reposes/releases/org/sonatype/test/1.0.1/test-1.0.1.pom
  52. +1 −0 nexus-core/src/test/resources/reposes/releases/org/sonatype/test/1.0.1/test-1.0.1.pom.sha1
  53. BIN nexus-core/src/test/resources/reposes/releases/org/sonatype/test/1.0/test-1.0-sources.jar
  54. +1 −0 nexus-core/src/test/resources/reposes/releases/org/sonatype/test/1.0/test-1.0-sources.jar.sha1
  55. BIN nexus-core/src/test/resources/reposes/releases/org/sonatype/test/1.0/test-1.0.jar
  56. +1 −0 nexus-core/src/test/resources/reposes/releases/org/sonatype/test/1.0/test-1.0.jar.sha1
  57. +29 −0 nexus-core/src/test/resources/reposes/releases/org/sonatype/test/1.0/test-1.0.pom
  58. +1 −0 nexus-core/src/test/resources/reposes/releases/org/sonatype/test/1.0/test-1.0.pom.sha1
  59. BIN ...re/src/test/resources/reposes/releases/org/sonatype/test/2.1000.9999/test-2.1000.9999-sources.jar
  60. +1 −0 ...c/test/resources/reposes/releases/org/sonatype/test/2.1000.9999/test-2.1000.9999-sources.jar.sha1
  61. BIN nexus-core/src/test/resources/reposes/releases/org/sonatype/test/2.1000.9999/test-2.1000.9999.jar
  62. +1 −0 ...-core/src/test/resources/reposes/releases/org/sonatype/test/2.1000.9999/test-2.1000.9999.jar.sha1
  63. +29 −0 nexus-core/src/test/resources/reposes/releases/org/sonatype/test/2.1000.9999/test-2.1000.9999.pom
  64. +1 −0 ...-core/src/test/resources/reposes/releases/org/sonatype/test/2.1000.9999/test-2.1000.9999.pom.sha1
  65. +1 −1 ...her/src/main/java/org/sonatype/nexus/bundle/launcher/support/DefaultNexusBundleConfiguration.java
  66. +4 −0 nexus-logging-extras/src/main/resources/META-INF/log/logback-nexus.xml
  67. +15 −0 nexus-oss-webapp/pom.xml
  68. +4 −0 nexus-oss-webapp/src/main/assembly/bundle.xml
  69. +6 −5 nexus-oss-webapp/src/main/resources/content/bin/jsw/conf/wrapper.conf
  70. +2 −2 nexus-oss-webapp/src/main/resources/content/conf/jetty.xml
  71. +21 −0 nexus-plugin-api/pom.xml
  72. +1 −1 nexus-runtime-platform/pom.xml
  73. +3 −1 ...c/test/java/org/sonatype/nexus/integrationtests/upgrades/nexus652/Nexus652Beta5To10UpgradeIT.java
  74. +6 −2 ...t/nexus-test-harness-launcher/src/main/java/org/sonatype/nexus/test/booter/Jetty8NexusBooter.java
  75. +25 −100 nexus-webapp/pom.xml
  76. +122 −0 nexus-webapp/src/main/java/org/sonatype/nexus/webapp/MetricsModule.java
  77. +32 −0 nexus-webapp/src/main/java/org/sonatype/nexus/webapp/WebappModule.java
  78. +0 −3,324 nexus-webapp/src/main/webapp/ext-3.4.1/adapter/ext/ext-base-debug.js
  79. +0 −18 nexus-webapp/src/main/webapp/ext-3.4.1/adapter/ext/ext-base.js
  80. +0 −2,232 nexus-webapp/src/main/webapp/ext-3.4.1/adapter/jquery/ext-jquery-adapter-debug.js
  81. +0 −18 nexus-webapp/src/main/webapp/ext-3.4.1/adapter/jquery/ext-jquery-adapter.js
  82. +0 −2,261 nexus-webapp/src/main/webapp/ext-3.4.1/adapter/prototype/ext-prototype-adapter-debug.js
  83. +0 −18 nexus-webapp/src/main/webapp/ext-3.4.1/adapter/prototype/ext-prototype-adapter.js
  84. +0 −2,027 nexus-webapp/src/main/webapp/ext-3.4.1/adapter/yui/ext-yui-adapter-debug.js
  85. +0 −18 nexus-webapp/src/main/webapp/ext-3.4.1/adapter/yui/ext-yui-adapter.js
  86. +0 −52,237 nexus-webapp/src/main/webapp/ext-3.4.1/ext-all-debug-w-comments.js
  87. +0 −52,237 nexus-webapp/src/main/webapp/ext-3.4.1/ext-all-debug.js
  88. +0 −18 nexus-webapp/src/main/webapp/ext-3.4.1/ext-all.js
  89. +0 −24 nexus-webapp/src/main/webapp/ext-3.4.1/license.txt
  90. +0 −125 nexus-webapp/src/main/webapp/ext-3.4.1/release-notes.html
  91. +0 −54 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/debug.css
  92. +0 −5,347 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/ext-all-notheme.css
  93. +0 −18 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/ext-all.css
  94. +0 −18 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/reset-min.css
  95. +0 −65 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/borders.css
  96. +0 −91 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/box.css
  97. +0 −456 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/button.css
  98. +0 −56 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/combo.css
  99. +0 −356 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/core.css
  100. +0 −282 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/date-picker.css
  101. +0 −72 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/dd.css
  102. +0 −37 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/debug.css
  103. +0 −70 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/dialog.css
  104. +0 −103 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/editor.css
  105. +0 −608 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/form.css
  106. +0 −604 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/grid.css
  107. +0 −307 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/layout.css
  108. +0 −97 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/list-view.css
  109. +0 −256 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/menu.css
  110. +0 −141 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/panel-reset.css
  111. +0 −504 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/panel.css
  112. +0 −76 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/pivotgrid.css
  113. +0 −57 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/progress.css
  114. +0 −164 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/qtips.css
  115. +0 −24 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/reset.css
  116. +0 −160 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/resizable.css
  117. +0 −114 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/slider.css
  118. +0 −404 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/tabs.css
  119. +0 −257 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/toolbar.css
  120. +0 −229 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/tree.css
  121. +0 −233 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/structure/window.css
  122. +0 −36 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/borders.css
  123. +0 −85 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/box.css
  124. +0 −147 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/button.css
  125. +0 −54 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/combo.css
  126. +0 −92 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/core.css
  127. +0 −156 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/date-picker.css
  128. +0 −40 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/dd.css
  129. +0 −35 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/debug.css
  130. +0 −45 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/dialog.css
  131. +0 −27 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/editor.css
  132. +0 −187 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/form.css
  133. +0 −299 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/grid.css
  134. +0 −67 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/layout.css
  135. +0 −54 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/list-view.css
  136. +0 −90 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/menu.css
  137. +0 −105 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/panel.css
  138. +0 −46 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/progress.css
  139. +0 −55 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/qtips.css
  140. +0 −55 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/resizable.css
  141. +0 −32 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/slider.css
  142. +0 −130 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/tabs.css
  143. +0 −131 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/toolbar.css
  144. +0 −176 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/tree.css
  145. +0 −98 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-access/window.css
  146. +0 −40 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-gray/borders.css
  147. +0 −85 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-gray/box.css
  148. +0 −105 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-gray/button.css
  149. +0 −54 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-gray/combo.css
  150. +0 −94 nexus-webapp/src/main/webapp/ext-3.4.1/resources/css/theme-gray/core.css
Sorry, we could not display the entire diff because too many files (1,865) changed.
View
5 nexus-bootstrap/pom.xml
@@ -41,6 +41,11 @@
</dependency>
<dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-jetty</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>tanukisoft</groupId>
<artifactId>wrapper</artifactId>
<scope>provided</scope>
View
111 .../src/main/java/org/sonatype/nexus/bootstrap/jetty/InstrumentedSelectChannelConnector.java
@@ -0,0 +1,111 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2007-2012 Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.bootstrap.jetty;
+
+import com.yammer.metrics.Metrics;
+import com.yammer.metrics.core.Counter;
+import com.yammer.metrics.core.Meter;
+import com.yammer.metrics.core.MetricsRegistry;
+import com.yammer.metrics.core.Timer;
+import org.eclipse.jetty.io.Connection;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Custom re-implementation of {@link com.yammer.metrics.jetty.InstrumentedSelectChannelConnector}
+ * which sets up metrics collection on {@link #doStart()} instead of in CTOR.
+ *
+ * @since 2.5
+ */
+public final class InstrumentedSelectChannelConnector
+ extends SelectChannelConnector
+{
+ private static final Logger log = LoggerFactory.getLogger(InstrumentedSelectChannelConnector.class);
+
+ private final MetricsRegistry registry;
+
+ private Timer duration;
+
+ private Meter accepts, connects, disconnects;
+
+ private Counter connections;
+
+ public InstrumentedSelectChannelConnector() {
+ registry = Metrics.defaultRegistry();
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ String port = String.valueOf(getPort());
+
+ this.duration = registry.newTimer(SelectChannelConnector.class,
+ "connection-duration",
+ port,
+ TimeUnit.MILLISECONDS,
+ TimeUnit.SECONDS);
+
+ this.accepts = registry.newMeter(SelectChannelConnector.class,
+ "accepts",
+ port,
+ "connections",
+ TimeUnit.SECONDS);
+
+ this.connects = registry.newMeter(SelectChannelConnector.class,
+ "connects",
+ port,
+ "connections",
+ TimeUnit.SECONDS);
+
+ this.disconnects = registry.newMeter(SelectChannelConnector.class,
+ "disconnects",
+ port,
+ "connections",
+ TimeUnit.SECONDS);
+
+ this.connections = registry.newCounter(SelectChannelConnector.class,
+ "active-connections",
+ port);
+
+ log.info("Metrics enabled");
+
+ super.doStart();
+ }
+
+ // TODO: remove metrics on doStop()
+
+ @Override
+ public void accept(final int acceptorID) throws IOException {
+ super.accept(acceptorID);
+ accepts.mark();
+ }
+
+ @Override
+ protected void connectionOpened(final Connection connection) {
+ connections.inc();
+ super.connectionOpened(connection);
+ connects.mark();
+ }
+
+ @Override
+ protected void connectionClosed(final Connection connection) {
+ super.connectionClosed(connection);
+ disconnects.mark();
+ final long duration = System.currentTimeMillis() - connection.getTimeStamp();
+ this.duration.update(duration, TimeUnit.MILLISECONDS);
+ connections.dec();
+ }
+}
View
48 nexus-client-core-testsuite/src/test/java/org/sonatype/nexus/client/testsuite/UserIT.java
@@ -0,0 +1,48 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2007-2012 Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.client.testsuite;
+
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+import org.junit.Test;
+import org.sonatype.nexus.client.core.NexusClient;
+import org.sonatype.nexus.client.core.subsystem.security.Users;
+
+/**
+ * @since 2.5
+ */
+public class UserIT
+ extends NexusClientITSupport
+{
+
+ public UserIT( final String nexusBundleCoordinates )
+ {
+ super( nexusBundleCoordinates );
+ }
+
+ /**
+ * Related to NEXUS-5037 ensure that html escaped passwords(specifically quote character in this case) can be used as credentials.
+ */
+ @Test
+ public void testUserWithSingleQuotePassword()
+ {
+ Users users = client().getSubsystem( Users.class );
+ String password = "\"";
+ users.create( "test" ).withPassword( password ).withRole( "nx-admin" ).withEmail( "no@where.com" ).save();
+ NexusClient client = createNexusClient( nexus(), "test", password );
+ //will fail if can't authenticate
+ assertThat( client.getNexusStatus(), is( notNullValue() ) );
+ }
+}
View
20 nexus-core/pom.xml
@@ -257,8 +257,24 @@
</dependency>
<dependency>
- <groupId>org.javasimon</groupId>
- <artifactId>javasimon-core</artifactId>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-guice</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>com.yammer.metrics</groupId>
+ <artifactId>metrics-httpclient</artifactId>
</dependency>
<!-- Testing -->
View
3 nexus-core/src/main/java/org/sonatype/nexus/apachehttpclient/Hc4ProviderBase.java
@@ -255,9 +255,8 @@ protected void configureProxy( final DefaultHttpClient httpClient, final RemoteP
* Sub-classed here to customize the http processor and to keep a sane logger name.
*/
private static class DefaultHttpClientImpl
- extends DefaultHttpClient
+ extends InstrumentedHttpClient
{
-
private DefaultHttpClientImpl( final ClientConnectionManager conman, final HttpParams params )
{
super( conman, params );
View
3 nexus-core/src/main/java/org/sonatype/nexus/apachehttpclient/Hc4ProviderImpl.java
@@ -18,6 +18,7 @@
import javax.inject.Named;
import javax.inject.Singleton;
+import com.yammer.metrics.httpclient.InstrumentedClientConnManager;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.conn.ClientConnectionOperator;
import org.apache.http.conn.scheme.PlainSocketFactory;
@@ -269,7 +270,7 @@ protected PoolingClientConnectionManager createClientConnectionManager(
schemeRegistry.register( new Scheme( "http", 80, PlainSocketFactory.getSocketFactory() ) );
schemeRegistry.register( new Scheme( "https", 443, SSLSocketFactory.getSocketFactory() ) );
- final PoolingClientConnectionManager connManager = new PoolingClientConnectionManager( schemeRegistry )
+ final PoolingClientConnectionManager connManager = new InstrumentedClientConnManager( schemeRegistry )
{
@Override
protected ClientConnectionOperator createConnectionOperator( final SchemeRegistry defaultSchemeRegistry )
View
86 nexus-core/src/main/java/org/sonatype/nexus/apachehttpclient/InstrumentedHttpClient.java
@@ -0,0 +1,86 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2007-2012 Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.apachehttpclient;
+
+import com.yammer.metrics.Metrics;
+import com.yammer.metrics.core.MetricsRegistry;
+import com.yammer.metrics.httpclient.InstrumentedClientConnManager;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.http.ConnectionReuseStrategy;
+import org.apache.http.client.*;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.ConnectionKeepAliveStrategy;
+import org.apache.http.conn.routing.HttpRoutePlanner;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpProcessor;
+import org.apache.http.protocol.HttpRequestExecutor;
+
+// NOTE: Duplicated and augmented from original 2.2.0 source to change signature of CTOR ClientConnectionManager parameter
+// NOTE: Should get this changes into metrics-httpclient and avoid needing this
+
+public class InstrumentedHttpClient extends DefaultHttpClient {
+ private final Log log = LogFactory.getLog(getClass());
+
+ private final MetricsRegistry registry;
+
+ public InstrumentedHttpClient(MetricsRegistry registry,
+ ClientConnectionManager manager,
+ HttpParams params) {
+ super(manager, params);
+ this.registry = registry;
+ }
+
+ public InstrumentedHttpClient(ClientConnectionManager manager, HttpParams params) {
+ this(Metrics.defaultRegistry(), manager, params);
+ }
+
+ public InstrumentedHttpClient(HttpParams params) {
+ this(new InstrumentedClientConnManager(), params);
+ }
+
+ public InstrumentedHttpClient() {
+ this(null);
+ }
+
+ @Override
+ protected RequestDirector createClientRequestDirector(HttpRequestExecutor requestExec,
+ ClientConnectionManager conman,
+ ConnectionReuseStrategy reustrat,
+ ConnectionKeepAliveStrategy kastrat,
+ HttpRoutePlanner rouplan,
+ HttpProcessor httpProcessor,
+ HttpRequestRetryHandler retryHandler,
+ RedirectStrategy redirectStrategy,
+ AuthenticationStrategy targetAuthStrategy,
+ AuthenticationStrategy proxyAuthStrategy,
+ UserTokenHandler userTokenHandler,
+ HttpParams params) {
+ return new InstrumentedRequestDirector(
+ registry,
+ log,
+ requestExec,
+ conman,
+ reustrat,
+ kastrat,
+ rouplan,
+ httpProcessor,
+ retryHandler,
+ redirectStrategy,
+ targetAuthStrategy,
+ proxyAuthStrategy,
+ userTokenHandler,
+ params);
+ }
+}
View
128 ...s-core/src/main/java/org/sonatype/nexus/apachehttpclient/InstrumentedRequestDirector.java
@@ -0,0 +1,128 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2007-2012 Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.apachehttpclient;
+
+import com.yammer.metrics.core.MetricsRegistry;
+import com.yammer.metrics.core.Timer;
+import com.yammer.metrics.core.TimerContext;
+import org.apache.commons.logging.Log;
+import org.apache.http.*;
+import org.apache.http.client.*;
+import org.apache.http.conn.ClientConnectionManager;
+import org.apache.http.conn.ConnectionKeepAliveStrategy;
+import org.apache.http.conn.routing.HttpRoutePlanner;
+import org.apache.http.impl.client.DefaultRequestDirector;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpProcessor;
+import org.apache.http.protocol.HttpRequestExecutor;
+
+import java.io.IOException;
+
+// NOTE: Duplicated and unchanged from original 2.2.0 source to support change in InstrumentedHttpClient
+// NOTE: Should get this changes into metrics-httpclient and avoid needing this
+
+class InstrumentedRequestDirector
+ extends DefaultRequestDirector {
+ private final static String GET = "GET", POST = "POST", HEAD = "HEAD", PUT = "PUT",
+ OPTIONS = "OPTIONS", DELETE = "DELETE", TRACE = "TRACE",
+ CONNECT = "CONNECT", MOVE = "MOVE", PATCH = "PATCH";
+
+ private final Timer getTimer;
+ private final Timer postTimer;
+ private final Timer headTimer;
+ private final Timer putTimer;
+ private final Timer deleteTimer;
+ private final Timer optionsTimer;
+ private final Timer traceTimer;
+ private final Timer connectTimer;
+ private final Timer moveTimer;
+ private final Timer patchTimer;
+ private final Timer otherTimer;
+
+ InstrumentedRequestDirector(MetricsRegistry registry,
+ Log log,
+ HttpRequestExecutor requestExec,
+ ClientConnectionManager conman,
+ ConnectionReuseStrategy reustrat,
+ ConnectionKeepAliveStrategy kastrat,
+ HttpRoutePlanner rouplan,
+ HttpProcessor httpProcessor,
+ HttpRequestRetryHandler retryHandler,
+ RedirectStrategy redirectStrategy,
+ AuthenticationStrategy targetAuthStrategy,
+ AuthenticationStrategy proxyAuthStrategy,
+ UserTokenHandler userTokenHandler,
+ HttpParams params) {
+ super(log,
+ requestExec,
+ conman,
+ reustrat,
+ kastrat,
+ rouplan,
+ httpProcessor,
+ retryHandler,
+ redirectStrategy,
+ targetAuthStrategy,
+ proxyAuthStrategy,
+ userTokenHandler,
+ params);
+ getTimer = registry.newTimer(HttpClient.class, "get-requests");
+ postTimer = registry.newTimer(HttpClient.class, "post-requests");
+ headTimer = registry.newTimer(HttpClient.class, "head-requests");
+ putTimer = registry.newTimer(HttpClient.class, "put-requests");
+ deleteTimer = registry.newTimer(HttpClient.class, "delete-requests");
+ optionsTimer = registry.newTimer(HttpClient.class, "options-requests");
+ traceTimer = registry.newTimer(HttpClient.class, "trace-requests");
+ connectTimer = registry.newTimer(HttpClient.class, "connect-requests");
+ moveTimer = registry.newTimer(HttpClient.class, "move-requests");
+ patchTimer = registry.newTimer(HttpClient.class, "patch-requests");
+ otherTimer = registry.newTimer(HttpClient.class, "other-requests");
+ }
+
+ @Override
+ public HttpResponse execute(HttpHost target, HttpRequest request, HttpContext context) throws HttpException, IOException {
+ final TimerContext timerContext = timer(request).time();
+ try {
+ return super.execute(target, request, context);
+ } finally {
+ timerContext.stop();
+ }
+ }
+
+ private Timer timer(HttpRequest request) {
+ final String method = request.getRequestLine().getMethod();
+ if (GET.equalsIgnoreCase(method)) {
+ return getTimer;
+ } else if (POST.equalsIgnoreCase(method)) {
+ return postTimer;
+ } else if (PUT.equalsIgnoreCase(method)) {
+ return putTimer;
+ } else if (HEAD.equalsIgnoreCase(method)) {
+ return headTimer;
+ } else if (DELETE.equalsIgnoreCase(method)) {
+ return deleteTimer;
+ } else if (OPTIONS.equalsIgnoreCase(method)) {
+ return optionsTimer;
+ } else if (TRACE.equalsIgnoreCase(method)) {
+ return traceTimer;
+ } else if (CONNECT.equalsIgnoreCase(method)) {
+ return connectTimer;
+ } else if (PATCH.equalsIgnoreCase(method)) {
+ return patchTimer;
+ } else if (MOVE.equalsIgnoreCase(method)) {
+ return moveTimer;
+ }
+ return otherTimer;
+ }
+}
View
60 nexus-core/src/main/java/org/sonatype/nexus/formfields/RepoTargetComboFormField.java
@@ -0,0 +1,60 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2007-2012 Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.formfields;
+
+/**
+ * The model for a combo field allowing for selection of Repository Targets.
+ *
+ * @since 2.5
+ */
+public class RepoTargetComboFormField
+ extends AbstractFormField<String>
+{
+
+ public static final String DEFAULT_HELP_TEXT = "Select the repository target to apply ";
+
+ public static final String DEFAULT_LABEL = "Repository Target";
+
+ public RepoTargetComboFormField( String id, String label, String helpText, boolean required,
+ String regexValidation )
+ {
+ super( id, label, helpText, required, regexValidation );
+ }
+
+ public RepoTargetComboFormField( String id, String label, String helpText, boolean required )
+ {
+ super( id, label, helpText, required );
+ }
+
+ public RepoTargetComboFormField( String id, boolean required )
+ {
+ super( id, DEFAULT_LABEL, DEFAULT_HELP_TEXT, required );
+ }
+
+ public RepoTargetComboFormField( String id )
+ {
+ super( id, DEFAULT_LABEL, DEFAULT_HELP_TEXT, false );
+ }
+
+ public String getType()
+ {
+ return "repo-target";
+ }
+
+ public RepoTargetComboFormField withInitialValue( final String initialValue )
+ {
+ setInitialValue( initialValue );
+ return this;
+ }
+
+}
View
5 nexus-core/src/main/java/org/sonatype/nexus/guice/NexusModules.java
@@ -13,9 +13,9 @@
package org.sonatype.nexus.guice;
-import org.apache.shiro.guice.aop.ShiroAopModule;
-
import com.google.inject.AbstractModule;
+import com.yammer.metrics.guice.InstrumentationModule;
+import org.apache.shiro.guice.aop.ShiroAopModule;
/**
* Nexus guice modules.
@@ -33,6 +33,7 @@
@Override
protected void configure() {
install(new ShiroAopModule());
+ install(new InstrumentationModule());
}
}
View
84 ...ore/src/main/java/org/sonatype/nexus/maven/tasks/AbstractFileDeletingWalkerProcessor.java
@@ -0,0 +1,84 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2007-2012 Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.maven.tasks;
+
+import org.sonatype.nexus.proxy.IllegalOperationException;
+import org.sonatype.nexus.proxy.ItemNotFoundException;
+import org.sonatype.nexus.proxy.ResourceStoreRequest;
+import org.sonatype.nexus.proxy.StorageException;
+import org.sonatype.nexus.proxy.item.StorageCollectionItem;
+import org.sonatype.nexus.proxy.item.StorageItem;
+import org.sonatype.nexus.proxy.maven.MavenRepository;
+import org.sonatype.nexus.proxy.storage.UnsupportedStorageOperationException;
+import org.sonatype.nexus.proxy.walker.AbstractWalkerProcessor;
+import org.sonatype.nexus.proxy.walker.WalkerContext;
+import org.sonatype.nexus.proxy.wastebasket.DeleteOperation;
+
+/**
+ * Common utility methods for WalkerProcessor implementations that perform
+ * file delete operations as part of their processing.
+ *
+ * @since 2.5
+ */
+public abstract class AbstractFileDeletingWalkerProcessor extends AbstractWalkerProcessor
+{
+
+ /**
+ * Inspect the given collection and delete it from the repository if it no longer has any files.
+ */
+ protected void removeDirectoryIfEmpty( MavenRepository repository, StorageCollectionItem coll )
+ throws StorageException, IllegalOperationException, UnsupportedStorageOperationException
+ {
+ try
+ {
+ if ( repository.list( false, coll ).size() > 0 )
+ {
+ return;
+ }
+ // directory is empty, never move to trash
+ repository.deleteItem( false, createResourceStoreRequest( coll, DeleteOperation.DELETE_PERMANENTLY ) );
+ }
+ catch ( ItemNotFoundException e )
+ {
+ // silent, this happens if whole GAV is removed and the dir is removed too
+ }
+ }
+
+ /**
+ * Create a request to delete an item.
+ */
+ protected ResourceStoreRequest createResourceStoreRequest( final StorageItem item, final WalkerContext ctx )
+ {
+ ResourceStoreRequest request = new ResourceStoreRequest( item );
+
+ if ( ctx.getContext().containsKey( DeleteOperation.DELETE_OPERATION_CTX_KEY ) )
+ {
+ request.getRequestContext().put( DeleteOperation.DELETE_OPERATION_CTX_KEY,
+ ctx.getContext().get( DeleteOperation.DELETE_OPERATION_CTX_KEY ) );
+ }
+
+ return request;
+ }
+
+ /**
+ * Create a request to delete an item with the specified DeleteOperation.
+ */
+ protected ResourceStoreRequest createResourceStoreRequest( final StorageCollectionItem item,
+ final DeleteOperation operation )
+ {
+ ResourceStoreRequest request = new ResourceStoreRequest( item );
+ request.getRequestContext().put( DeleteOperation.DELETE_OPERATION_CTX_KEY, operation );
+ return request;
+ }
+
+}
View
413 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/DefaultReleaseRemover.java
@@ -0,0 +1,413 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2007-2012 Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.maven.tasks;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.sonatype.nexus.maven.tasks.descriptors.ReleaseRemovalTaskDescriptor.ID;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import org.sonatype.nexus.logging.AbstractLoggingComponent;
+import org.sonatype.nexus.maven.tasks.descriptors.ReleaseRemovalTaskDescriptor;
+import org.sonatype.nexus.proxy.IllegalOperationException;
+import org.sonatype.nexus.proxy.ItemNotFoundException;
+import org.sonatype.nexus.proxy.NoSuchRepositoryException;
+import org.sonatype.nexus.proxy.ResourceStoreRequest;
+import org.sonatype.nexus.proxy.StorageException;
+import org.sonatype.nexus.proxy.item.StorageCollectionItem;
+import org.sonatype.nexus.proxy.item.StorageFileItem;
+import org.sonatype.nexus.proxy.item.StorageItem;
+import org.sonatype.nexus.proxy.maven.MavenRepository;
+import org.sonatype.nexus.proxy.maven.RepositoryPolicy;
+import org.sonatype.nexus.proxy.maven.gav.Gav;
+import org.sonatype.nexus.proxy.maven.version.GenericVersionParser;
+import org.sonatype.nexus.proxy.maven.version.InvalidVersionSpecificationException;
+import org.sonatype.nexus.proxy.maven.version.Version;
+import org.sonatype.nexus.proxy.maven.version.VersionParser;
+import org.sonatype.nexus.proxy.registry.ContentClass;
+import org.sonatype.nexus.proxy.registry.RepositoryRegistry;
+import org.sonatype.nexus.proxy.repository.GroupRepository;
+import org.sonatype.nexus.proxy.repository.ProxyRepository;
+import org.sonatype.nexus.proxy.repository.Repository;
+import org.sonatype.nexus.proxy.target.Target;
+import org.sonatype.nexus.proxy.target.TargetRegistry;
+import org.sonatype.nexus.proxy.target.TargetStoreWalkerFilter;
+import org.sonatype.nexus.proxy.walker.ConjunctionWalkerFilter;
+import org.sonatype.nexus.proxy.walker.DefaultWalkerContext;
+import org.sonatype.nexus.proxy.walker.DottedStoreWalkerFilter;
+import org.sonatype.nexus.proxy.walker.Walker;
+import org.sonatype.nexus.proxy.walker.WalkerContext;
+import org.sonatype.nexus.proxy.walker.WalkerFilter;
+import org.sonatype.nexus.proxy.wastebasket.DeleteOperation;
+import org.sonatype.scheduling.TaskUtil;
+
+/**
+ * @since 2.5
+ */
+@Named
+@Singleton
+public class DefaultReleaseRemover
+ extends AbstractLoggingComponent
+ implements ReleaseRemover
+{
+
+ private final RepositoryRegistry repositoryRegistry;
+
+ private final TargetRegistry targetRegistry;
+
+ private final Walker walker;
+
+ private final ContentClass maven2ContentClass;
+
+ private final VersionParser versionScheme = new GenericVersionParser();
+
+ @Inject
+ public DefaultReleaseRemover( final RepositoryRegistry repositoryRegistry, final TargetRegistry targetRegistry,
+ final Walker walker,
+ final @Named( "maven2" ) ContentClass maven2ContentClass )
+ {
+ this.repositoryRegistry = checkNotNull( repositoryRegistry );
+ this.targetRegistry = checkNotNull(targetRegistry);
+ this.walker = checkNotNull( walker );
+ this.maven2ContentClass = checkNotNull( maven2ContentClass );
+ }
+
+ @Override
+ public ReleaseRemovalResult removeReleases( final ReleaseRemovalRequest request )
+ throws NoSuchRepositoryException
+ {
+ logDetails( request );
+ ReleaseRemovalResult result = new ReleaseRemovalResult( request.getRepositoryId() );
+
+ Repository repository = repositoryRegistry.getRepository( request.getRepositoryId() );
+ Target repositoryTarget = targetRegistry.getRepositoryTarget( request.getTargetId() );
+
+ if ( !Strings.isNullOrEmpty( request.getTargetId() ) && repositoryTarget == null )
+ {
+ throw new IllegalStateException(
+ "The specified repository target does not exist. Perhaps it has been deleted since this repository target was configured? Target id = "
+ + request.getTargetId() );
+ }
+
+ if ( !process( request, result, repository, repositoryTarget ) )
+ {
+ throw new IllegalArgumentException( "The repository with ID=" + repository.getId() + " is not valid for "
+ + ID );
+ }
+ getLogger().debug( "Results of {} are: {}", ReleaseRemovalTaskDescriptor.ID, result );
+ return result;
+ }
+
+ private boolean process( final ReleaseRemovalRequest request, final ReleaseRemovalResult result,
+ final Repository repository, final Target repositoryTarget )
+ {
+ if ( !repository.getRepositoryContentClass().isCompatible( maven2ContentClass ) )
+ {
+ getLogger().debug( "Skipping '{}' is not a maven 2 repository", repository.getId() );
+ return false;
+ }
+
+ if ( !repository.getLocalStatus().shouldServiceRequest() )
+ {
+ getLogger().debug( "Skipping '{}' because the repository is out of service", repository.getId() );
+ return false;
+ }
+
+ if ( repository.getRepositoryKind().isFacetAvailable( ProxyRepository.class ) )
+ {
+ getLogger().debug( "Skipping '{}' because it is a proxy repository", repository.getId() );
+ return false;
+ }
+
+ if ( repository.getRepositoryKind().isFacetAvailable( GroupRepository.class ) )
+ {
+ getLogger().debug( "Skipping '{}' because it is a group repository", repository.getId() );
+ return false;
+ }
+
+ MavenRepository mavenRepository = repository.adaptToFacet( MavenRepository.class );
+
+ if(mavenRepository == null)
+ {
+ getLogger().debug( "Skipping '{}' because it could not be adapted to MavenRepository", repository.getId() );
+ return false;
+ }
+
+ if ( !RepositoryPolicy.RELEASE.equals( mavenRepository.getRepositoryPolicy() ) )
+ {
+ getLogger().debug( "Skipping '{}' because it is a snapshot or mixed repository", repository.getId() );
+ return false;
+ }
+
+ removeReleasesFromMavenRepository( mavenRepository, request, result, repositoryTarget );
+ return true;
+ }
+
+ private void removeReleasesFromMavenRepository( final MavenRepository repository,
+ final ReleaseRemovalRequest request,
+ final ReleaseRemovalResult result,
+ final Target repositoryTarget )
+ {
+ TaskUtil.checkInterruption();
+
+ if ( !repository.getLocalStatus().shouldServiceRequest() )
+ {
+ return;
+ }
+
+ getLogger().debug(
+ "Collecting deletable releases on repository '" + repository.getId() + "' from storage directory "
+ + repository.getLocalUrl() );
+
+ DefaultWalkerContext ctxMain =
+ new DefaultWalkerContext( repository, new ResourceStoreRequest( "/" ),
+ determineFilter( repositoryTarget ) );
+
+ ctxMain.getContext().put( DeleteOperation.DELETE_OPERATION_CTX_KEY, DeleteOperation.MOVE_TO_TRASH );
+
+ ctxMain.getProcessors().add( new ReleaseRemovalWalkerProcessor( repository, request, result, repositoryTarget ) );
+
+ walker.walk( ctxMain );
+
+ if ( ctxMain.getStopCause() != null )
+ {
+ result.setSuccessful( false );
+ }
+ }
+
+ /**
+ * Create an appropriate filter based on the repositoryTarget
+ */
+ private WalkerFilter determineFilter( final Target repositoryTarget )
+ {
+ if ( repositoryTarget == null )
+ {
+ return new DottedStoreWalkerFilter();
+ }
+ return ConjunctionWalkerFilter.satisfiesAllOf( new DottedStoreWalkerFilter(),
+ new TargetStoreWalkerFilter( repositoryTarget ) );
+ }
+
+ private void logDetails( final ReleaseRemovalRequest request )
+ {
+ getLogger().info( "Removing older releases from repository: {}", request.getRepositoryId() );
+ if(getLogger().isDebugEnabled())
+ {
+ getLogger().debug( "With parameters: " );
+ getLogger().debug( " NumberOfVersionsToKeep: {}", request.getNumberOfVersionsToKeep() );
+ getLogger().debug( " RepositoryTarget applied: {}", request.getTargetId() );
+ }
+ }
+
+ private class ReleaseRemovalWalkerProcessor
+ extends AbstractFileDeletingWalkerProcessor
+ {
+
+ private static final String POSSIBLY_EMPTY_COLLECTIONS = "possiblyEmptyCollections";
+
+ private final MavenRepository repository;
+
+ private final ReleaseRemovalRequest request;
+
+ private final Map<Version, List<StorageFileItem>> deletableVersionsAndFiles =
+ new HashMap<Version, List<StorageFileItem>>();
+
+ private final Map<Gav, Map<Version, List<StorageFileItem>>> groupArtifactToVersions =
+ new HashMap<Gav, Map<Version, List<StorageFileItem>>>();
+
+ private final ReleaseRemovalResult result;
+
+ private final Target repositoryTarget;
+
+ private int deletedFiles = 0;
+
+ private ReleaseRemovalWalkerProcessor( final MavenRepository repository,
+ final ReleaseRemovalRequest request, final ReleaseRemovalResult result,
+ final Target repositoryTarget )
+ {
+ this.repository = repository;
+ this.request = request;
+ this.result = result;
+ this.repositoryTarget = repositoryTarget;
+ }
+
+ @Override
+ public void processItem( final WalkerContext context, final StorageItem item )
+ throws Exception
+ {
+ }
+
+ @Override
+ public void onCollectionExit( final WalkerContext context, final StorageCollectionItem coll )
+ throws Exception
+ {
+ try
+ {
+ doOnCollectionExit( context, coll );
+ }
+ catch ( Exception e )
+ {
+ // we always simply log the exception and continue
+ getLogger().warn( "{} failed to process path: '{}'.", ID, coll.getPath(), e );
+ }
+ }
+
+ private void doOnCollectionExit( final WalkerContext context, final StorageCollectionItem coll )
+ throws ItemNotFoundException, StorageException, IllegalOperationException,
+ InvalidVersionSpecificationException
+ {
+ deletableVersionsAndFiles.clear();
+
+ Collection<StorageItem> items = repository.list( false, coll );
+ Gav gav = null;
+ for ( StorageItem item : items )
+ {
+ if ( !item.isVirtual() && !StorageCollectionItem.class.isAssignableFrom( item.getClass() ) )
+ {
+ gav =
+ ( (MavenRepository) coll.getRepositoryItemUid().getRepository() ).getGavCalculator().pathToGav(
+ item.getPath() );
+ if ( gav != null )
+ {
+ addCollectionToContext( context, coll );
+
+ maybeAddStorageFileItemToMap( gav, (StorageFileItem) item );
+ }
+ }
+ }
+ // if a gav can be calculated, it should be shared by all files in the collection
+ if ( null != gav )
+ {
+ groupVersions( groupArtifactToVersions, deletableVersionsAndFiles, gav );
+ }
+ }
+
+ /**
+ * Compare the item path to the RepositoryTarget(if it is declared) and only include files that match that pattern.
+ * While the walker itself handles GAV paths, this ensures that we also respect patterns with file-level granularity.
+ */
+ private void maybeAddStorageFileItemToMap( final Gav gav, final StorageFileItem item )
+ {
+ if ( repositoryTarget != null && !repositoryTarget.isPathContained(
+ item.getRepositoryItemUid().getRepository().getRepositoryContentClass(), item
+ .getPath() ) )
+ {
+ getLogger().debug( "Excluding file: {} from deletion due to repositoryTarget: {}.", item.getName(), repositoryTarget.getName() );
+ return;
+ }
+ addStorageFileItemToMap( deletableVersionsAndFiles, gav, (StorageFileItem) item );
+ }
+
+ /**
+ * Store visited collections so we can later determine if we need to delete them.
+ */
+ private void addCollectionToContext( final WalkerContext context, final StorageCollectionItem coll )
+ {
+ if ( !context.getContext().containsKey( POSSIBLY_EMPTY_COLLECTIONS ) )
+ {
+ context.getContext().put( POSSIBLY_EMPTY_COLLECTIONS, Lists.<StorageCollectionItem>newArrayList() );
+ }
+ ( (List<StorageCollectionItem>) context.getContext().get( POSSIBLY_EMPTY_COLLECTIONS ) ).add( coll );
+ }
+
+ /**
+ * Map Group + Artifact to each version with those GA coordinates
+ */
+ private void groupVersions( final Map<Gav, Map<Version, List<StorageFileItem>>> groupArtifactToVersions,
+ final Map<Version, List<StorageFileItem>> versionsAndFiles,
+ final Gav gav )
+ {
+ //ga only coordinates
+ Gav ga = new Gav( gav.getGroupId(), gav.getArtifactId(), "" );
+ if ( !groupArtifactToVersions.containsKey( ga ) )
+ {
+ groupArtifactToVersions.put( ga, Maps.newHashMap( versionsAndFiles ) );
+ }
+ groupArtifactToVersions.get( ga ).putAll( versionsAndFiles );
+ }
+
+ protected void addStorageFileItemToMap( Map<Version, List<StorageFileItem>> map, Gav gav, StorageFileItem item )
+ {
+ Version key = null;
+ try
+ {
+ key = versionScheme.parseVersion( gav.getVersion() );
+ }
+ catch ( InvalidVersionSpecificationException e )
+ {
+ throw new IllegalStateException( "Unable to determine version for " + gav.getVersion() +
+ ", cannot proceed with deletion of releases unless"
+ + "all version information can be parsed into major.minor.incremental version." );
+ }
+
+ if ( !map.containsKey( key ) )
+ {
+ map.put( key, new ArrayList<StorageFileItem>() );
+ }
+
+ map.get( key ).add( item );
+ }
+
+ @Override
+ public void afterWalk( final WalkerContext context )
+ throws Exception
+ {
+ for ( Map.Entry<Gav, Map<Version, List<StorageFileItem>>> gavListEntry : groupArtifactToVersions.entrySet() )
+ {
+ Map<Version, List<StorageFileItem>> versions = gavListEntry.getValue();
+ if ( versions.size() > request.getNumberOfVersionsToKeep() )
+ {
+ getLogger().debug( "{} will delete {} versions of artifact with g={} a={}",
+ ReleaseRemovalTaskDescriptor.ID,
+ versions.size() - request.getNumberOfVersionsToKeep(),
+ gavListEntry.getKey().getGroupId(), gavListEntry.getKey().getArtifactId() );
+
+ List<Version> sortedVersions = Lists.newArrayList( versions.keySet() );
+ Collections.sort( sortedVersions );
+ List<Version> toDelete =
+ sortedVersions.subList( 0, versions.size() - request.getNumberOfVersionsToKeep() );
+ getLogger().debug( "Will delete these specific versions: {}", toDelete );
+ for ( Version version : toDelete )
+ {
+ for ( StorageFileItem storageFileItem : versions.get( version ) )
+ {
+ repository.deleteItem( createResourceStoreRequest( storageFileItem, context ) );
+ deletedFiles++;
+ }
+ }
+ if ( context.getContext().containsKey( POSSIBLY_EMPTY_COLLECTIONS ) )
+ {
+ for ( StorageCollectionItem coll : (List<StorageCollectionItem>) context.getContext().get(
+ POSSIBLY_EMPTY_COLLECTIONS ) )
+ {
+ removeDirectoryIfEmpty( repository, coll );
+ }
+ }
+ }
+ }
+ result.setDeletedFileCount( deletedFiles );
+ result.setSuccessful( true );
+ }
+ }
+}
View
57 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/DefaultSnapshotRemover.java
@@ -310,7 +310,7 @@ private void logDetails( SnapshotRemovalRequest request )
}
private class SnapshotRemoverWalkerProcessor
- extends AbstractWalkerProcessor
+ extends AbstractFileDeletingWalkerProcessor
{
private static final long MILLIS_IN_A_DAY = 86400000L;
@@ -567,7 +567,7 @@ public void doOnCollectionExit( WalkerContext context, StorageCollectionItem col
}
}
- removeDirectoryIfEmpty( coll );
+ removeDirectoryIfEmpty( repository, coll );
updateMetadataIfNecessary( context, coll );
@@ -640,9 +640,12 @@ private void deleteFiles( final WalkerContext context,
}
catch ( ItemNotFoundException e )
{
- if ( getLogger().isDebugEnabled() )
+ // NEXUS-5682 Since checksum files are no longer physically represented on the file system,
+ // it is expected that they will generate ItemNotFoundException. Log at trace level only for
+ // diagnostic purposes.
+ if ( getLogger().isTraceEnabled() )
{
- getLogger().debug( "Could not delete file:", e );
+ getLogger().trace( "Could not delete file:", e );
}
}
catch ( Exception e )
@@ -712,31 +715,6 @@ private void updateMetadataIfNecessary( WalkerContext context, StorageCollection
}
}
- private void removeDirectoryIfEmpty( StorageCollectionItem coll )
- throws StorageException, IllegalOperationException, UnsupportedStorageOperationException
- {
- try
- {
- if ( repository.list( false, coll ).size() > 0 )
- {
- return;
- }
-
- if ( getLogger().isDebugEnabled() )
- {
- getLogger().debug(
- "Removing the empty directory leftover: UID=" + coll.getRepositoryItemUid().toString() );
- }
-
- // directory is empty, never move to trash
- repository.deleteItem( false, createResourceStoreRequest( coll, DeleteOperation.DELETE_PERMANENTLY ) );
- }
- catch ( ItemNotFoundException e )
- {
- // silent, this happens if whole GAV is removed and the dir is removed too
- }
- }
-
public boolean releaseExistsForSnapshot( Gav snapshotGav, Map<String, Object> context )
{
long releaseTimestamp = -1;
@@ -814,27 +792,6 @@ public boolean releaseExistsForSnapshot( Gav snapshotGav, Map<String, Object> co
|| ( releaseTimestamp > 0 && startTime > releaseTimestamp + gracePeriodInMillis );
}
- private ResourceStoreRequest createResourceStoreRequest( final StorageItem item, final WalkerContext ctx )
- {
- ResourceStoreRequest request = new ResourceStoreRequest( item );
-
- if ( ctx.getContext().containsKey( DeleteOperation.DELETE_OPERATION_CTX_KEY ) )
- {
- request.getRequestContext().put( DeleteOperation.DELETE_OPERATION_CTX_KEY,
- ctx.getContext().get( DeleteOperation.DELETE_OPERATION_CTX_KEY ) );
- }
-
- return request;
- }
-
- private ResourceStoreRequest createResourceStoreRequest( final StorageCollectionItem item,
- final DeleteOperation operation )
- {
- ResourceStoreRequest request = new ResourceStoreRequest( item );
- request.getRequestContext().put( DeleteOperation.DELETE_OPERATION_CTX_KEY, operation );
- return request;
- }
-
public int getDeletedSnapshots()
{
return deletedSnapshots;
View
57 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/ReleaseRemovalRequest.java
@@ -0,0 +1,57 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2007-2012 Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.maven.tasks;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Encapsulate parameters to {@link ReleaseRemover}
+ *
+ * @since 2.5
+ */
+public class ReleaseRemovalRequest
+{
+ private final String repositoryId;
+
+ private final int numberOfVersionsToKeep;
+
+ private final String targetId;
+
+ /**
+ *
+ * @param repositoryId the repository to target
+ * @param numberOfVersionsToKeep the number of released versions to keep for Group/Artifact in the repository
+ * @param targetId (optional) Repository Target id to be applied
+ */
+ public ReleaseRemovalRequest( final String repositoryId, final int numberOfVersionsToKeep, final String targetId )
+ {
+ this.repositoryId = checkNotNull(repositoryId);
+ this.numberOfVersionsToKeep = checkNotNull(numberOfVersionsToKeep);
+ this.targetId = targetId;
+ }
+
+ public String getRepositoryId()
+ {
+ return repositoryId;
+ }
+
+ public int getNumberOfVersionsToKeep()
+ {
+ return numberOfVersionsToKeep;
+ }
+
+ public String getTargetId()
+ {
+ return targetId;
+ }
+}
View
69 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/ReleaseRemovalResult.java
@@ -0,0 +1,69 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2007-2012 Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.maven.tasks;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Simple struct for consolidating results of ReleaseRemoval task.
+ *
+ * @since 2.5
+ */
+public class ReleaseRemovalResult
+{
+ private final String repoId;
+
+ private int deletedFileCount;
+
+ private boolean isSuccessful = false;
+
+ public ReleaseRemovalResult( final String repoId )
+ {
+ this.repoId = checkNotNull(repoId);
+ }
+
+ public String getRepoId()
+ {
+ return repoId;
+ }
+
+ public int getDeletedFileCount()
+ {
+ return deletedFileCount;
+ }
+
+ public void setDeletedFileCount( final int deletedFileCount )
+ {
+ this.deletedFileCount = deletedFileCount;
+ }
+
+ public boolean isSuccessful()
+ {
+ return isSuccessful;
+ }
+
+ public void setSuccessful( final boolean successful )
+ {
+ isSuccessful = successful;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ReleaseRemovalResult{" +
+ "repoId='" + repoId + '\'' +
+ ", deletedFileCount=" + deletedFileCount +
+ ", isSuccessful=" + isSuccessful +
+ '}';
+ }
+}
View
28 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/ReleaseRemover.java
@@ -0,0 +1,28 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2007-2012 Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.maven.tasks;
+
+import org.sonatype.nexus.proxy.NoSuchRepositoryException;
+
+/**
+ * @since 2.5.0
+ */
+public interface ReleaseRemover
+{
+
+ /**
+ * Conditionally remove released artifacts from a repository based on the request.
+ */
+ ReleaseRemovalResult removeReleases( ReleaseRemovalRequest request )
+ throws NoSuchRepositoryException;
+}
View
59 nexus-core/src/main/java/org/sonatype/nexus/maven/tasks/ReleaseRemoverTask.java
@@ -0,0 +1,59 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2007-2012 Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.maven.tasks;
+
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.sonatype.nexus.maven.tasks.descriptors.ReleaseRemovalTaskDescriptor;
+import org.sonatype.nexus.scheduling.AbstractNexusRepositoriesTask;
+import org.sonatype.scheduling.SchedulerTask;
+
+/**
+ * @since 2.5
+ */
+@Component( role = SchedulerTask.class, hint = ReleaseRemovalTaskDescriptor.ID, instantiationStrategy = "per-lookup" )
+public class ReleaseRemoverTask extends AbstractNexusRepositoriesTask<ReleaseRemovalResult>
+{
+
+ @Requirement
+ private ReleaseRemover releaseRemover;
+
+ @Override
+ protected String getRepositoryFieldId()
+ {
+ return ReleaseRemovalTaskDescriptor.REPOSITORY_FIELD_ID;
+ }
+
+ @Override
+ protected ReleaseRemovalResult doRun()
+ throws Exception
+ {
+ int numberOfVersionsToKeep = Integer.parseInt(
+ getParameter( ReleaseRemovalTaskDescriptor.NUMBER_OF_VERSIONS_TO_KEEP_FIELD_ID ) );
+ String targetId = getParameter( ReleaseRemovalTaskDescriptor.REPOSITORY_TARGET_FIELD_ID );
+ return releaseRemover.removeReleases(
+ new ReleaseRemovalRequest( getRepositoryId(), numberOfVersionsToKeep, targetId ) );
+ }
+
+ @Override
+ protected String getAction()
+ {
+ return getClass().getSimpleName();
+ }
+
+ @Override
+ protected String getMessage()
+ {
+ return "Removing old releases from repository " + getRepositoryName();
+ }
+}
View
72 ...rc/main/java/org/sonatype/nexus/maven/tasks/descriptors/ReleaseRemovalTaskDescriptor.java
@@ -0,0 +1,72 @@
+/*
+ * Sonatype Nexus (TM) Open Source Version
+ * Copyright (c) 2007-2012 Sonatype, Inc.
+ * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
+ *
+ * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
+ * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
+ *
+ * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
+ * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
+ * Eclipse Foundation. All other trademarks are the property of their respective owners.
+ */
+package org.sonatype.nexus.maven.tasks.descriptors;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import com.google.common.collect.ImmutableList;
+import org.codehaus.plexus.component.annotations.Component;
+import org.sonatype.nexus.formfields.FormField;
+import org.sonatype.nexus.formfields.NumberTextFormField;
+import org.sonatype.nexus.formfields.RepoComboFormField;
+import org.sonatype.nexus.formfields.RepoTargetComboFormField;
+import org.sonatype.nexus.formfields.StringTextFormField;
+import org.sonatype.nexus.tasks.descriptors.AbstractScheduledTaskDescriptor;
+import org.sonatype.nexus.tasks.descriptors.ScheduledTaskDescriptor;
+
+/**
+ * @since 2.5
+ */
+@Named
+@Singleton
+public class ReleaseRemovalTaskDescriptor
+ extends AbstractScheduledTaskDescriptor
+{
+
+ public static final String ID = "ReleaseRemoverTask";
+
+ public static final String REPOSITORY_FIELD_ID = "repositoryId";
+
+ public static final String NUMBER_OF_VERSIONS_TO_KEEP_FIELD_ID = "numberOfVersionsToKeep";
+
+ public static final String REPOSITORY_TARGET_FIELD_ID = "repositoryTarget";
+
+ private final List<FormField> formFields = ImmutableList.<FormField>of(
+ new RepoComboFormField( REPOSITORY_FIELD_ID, FormField.MANDATORY ),
+ new NumberTextFormField(
+ NUMBER_OF_VERSIONS_TO_KEEP_FIELD_ID, "Number to keep", "The number of versions for each GA to keep",
+ FormField.MANDATORY ),
+ new RepoTargetComboFormField( REPOSITORY_TARGET_FIELD_ID, "Repository Target",
+ "Select a repository target to apply", FormField.OPTIONAL )
+ );
+
+ public String getId()
+ {
+ return ID;
+ }
+
+ public String getName()
+ {
+ return "Remove Releases From Repository";
+ }
+
+ @Override
+ public List<FormField> formFields()
+ {
+ return formFields;
+ }
+}
View
2 nexus-core/src/main/java/org/sonatype/nexus/plugins/DefaultNexusPluginManager.java
@@ -30,6 +30,7 @@
import javax.inject.Named;
import javax.inject.Singleton;
+import com.yammer.metrics.annotation.Timed;
import org.codehaus.plexus.DefaultPlexusContainer;
import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.classworlds.realm.DuplicateRealmException;
@@ -137,6 +138,7 @@ public DefaultNexusPluginManager( final RepositoryTypeRegistry repositoryTypeReg
return new HashMap<GAVCoordinate, PluginResponse>( pluginResponses );
}
+ @Timed
public Collection<PluginManagerResponse> activateInstalledPlugins()
{
final List<PluginManagerResponse> result = new ArrayList<PluginManagerResponse>();
View
3 ...-core/src/main/java/org/sonatype/nexus/plugins/rest/AbstractNexusIndexHtmlCustomizer.java
@@ -17,6 +17,9 @@
import java.util.Map;
import java.util.Properties;
+/**
+ * @deprecated Use {@link org.sonatype.nexus.plugins.ui.contribution.UiContributor}
+ */
public class AbstractNexusIndexHtmlCustomizer
implements NexusIndexHtmlCustomizer
{
View
146 nexus-core/src/main/java/org/sonatype/nexus/plugins/rest/AbstractUiContributionBuilder.java
@@ -1,146 +0,0 @@
-/*
- * Sonatype Nexus (TM) Open Source Version
- * Copyright (c) 2007-2012 Sonatype, Inc.
- * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
- *
- * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
- * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
- *
- * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
- * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
- * Eclipse Foundation. All other trademarks are the property of their respective owners.
- */
-package org.sonatype.nexus.plugins.rest;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.Object;
-import java.lang.String;
-import java.net.URL;
-import java.util.Properties;
-
-import org.sonatype.nexus.logging.AbstractLoggingComponent;
-
-/**
- * Base class for UI contribution builders
- *
- * @see UiContributionBuilder
- * @see IndexHtmlSnippetBuilder
- * @since 2.4
- */
-public abstract class AbstractUiContributionBuilder<T>
- extends AbstractLoggingComponent
-{
-
- protected final Object owner;
-
- protected final String groupId;
-
- protected final String artifactId;
-
- protected String encoding = "UTF-8";
-
- public AbstractUiContributionBuilder( final Object owner, final String groupId, final String artifactId )
- {
- this.owner = checkNotNull( owner );
- this.groupId = checkNotNull( groupId );
- this.artifactId = checkNotNull( artifactId );
- }
-
- /**
- * Attempt to detect version from the POM of owner.
- */
- private String detectVersion() {
- Properties props = new Properties();
-
- String path = String.format("/META-INF/maven/%s/%s/pom.properties", groupId, artifactId);
- InputStream input = owner.getClass().getResourceAsStream(path);
-
- if (input == null) {
- getLogger().warn("Unable to detect version; failed to load: {}", path);
- return null;
- }
-
- try {
- props.load(input);
- }
- catch (IOException e) {
- getLogger().warn("Failed to load POM: {}", path, e);
- return null;
- }
-
- return props.getProperty("version");
- }
-
- /**
- * Attempt to detect timestamp of the file referenced by the path. If the path is resolved from a jar, the jar
- * timestamp is used. If the path is resolved from filesystem directly, as is the case for exploded plugins for
- * example, the file timestamp is used. If the path is resolved from other sources or cannot be resolved, current
- * timestamp is used.
- */
- private long getTimestamp(String path) {
- if (!path.startsWith("/")) {
- path = "/" + path;
- }
- URL url = owner.getClass().getResource( path );
- if (url != null) {
- if ("file".equalsIgnoreCase(url.getProtocol())) {
- return new File(url.getFile()).lastModified();
- }
- String resolvedPath = url.toExternalForm();
- if (resolvedPath.toLowerCase().startsWith("jar:file:")) {
- resolvedPath = resolvedPath.substring("jar:file:".length());
- resolvedPath = resolvedPath.substring(0, resolvedPath.length() - path.length() - 1);
- File file = new File(resolvedPath);
- if (file.exists()) {
- return file.lastModified();
- }
- }
- }
- return System.currentTimeMillis();
- }
-
- /**
- * Return a string suitable for use as suffix to a plain-URL to enforce version/caching semantics.
- */
- public String getCacheBuster(String path) {
- String version = detectVersion();
- if (version == null) {
- return "";
- }
- else if (version.endsWith("SNAPSHOT")) {
- // append timestamp for SNAPSHOT versions to help sort out cache problems
- return String.format("?v=%s&t=%s", version, getTimestamp( path ));
- }
- else {
- return "?v=" + version;
- }
- }
-
- /**
- * Returns the default relative url for the given extension.
- *
- * @param extension The file extension.
- * @param bust Whether to append cachebuster parameters
- * @return A relative url of the form "static/$extension/$artifactId-all.$extension".
- */
- public String getDefaultPath( final String extension, final boolean bust )
- {
- final String path = String.format( "static/%s/%s-all.%s", extension, artifactId, extension );
- if ( bust )
- {
- return path + getCacheBuster( path );
- }
- return path;
- }
-
- public String getDefaultPath( final String extension )
- {
- return getDefaultPath( extension, true );
- }
-
- public abstract T build();
-}
View
79 nexus-core/src/main/java/org/sonatype/nexus/plugins/rest/IndexHtmlSnippetBuilder.java
@@ -1,79 +0,0 @@
-/*
- * Sonatype Nexus (TM) Open Source Version
- * Copyright (c) 2007-2012 Sonatype, Inc.
- * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
- *
- * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
- * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
- *
- * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
- * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
- * Eclipse Foundation. All other trademarks are the property of their respective owners.
- */
-
-package org.sonatype.nexus.plugins.rest;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import java.util.List;
-
-import com.google.common.collect.Lists;
-
-/**
- * Helper to build HTML snippets for use in {@link NexusIndexHtmlCustomizer} implementations.
- *
- * @since 2.4
- */
-public class IndexHtmlSnippetBuilder
- extends AbstractUiContributionBuilder<String>
-{
-
- private final List<String> styleRefs = Lists.newArrayList();
-
- private final List<String> scriptRefs = Lists.newArrayList();
-
- public IndexHtmlSnippetBuilder(final Object owner, final String groupId, final String artifactId) {
- super(owner, groupId, artifactId);
- }
-
- public IndexHtmlSnippetBuilder styleRef(final String fileName) {
- checkNotNull(fileName);
- styleRefs.add(fileName);
- return this;
- }
-
- public IndexHtmlSnippetBuilder defaultStyleRef() {
- return styleRef( getDefaultPath( "css" ));
- }
-
- public IndexHtmlSnippetBuilder scriptRef(final String fileName) {
- checkNotNull(fileName);
- scriptRefs.add(fileName);
- return this;
- }
-
- public IndexHtmlSnippetBuilder defaultScriptRef() {
- return scriptRef( getDefaultPath( "js" ));
- }
-
- public IndexHtmlSnippetBuilder encoding(final String encoding) {
- this.encoding = checkNotNull(encoding);
- return this;
- }
-
- public String build() {
- StringBuilder buff = new StringBuilder();
-
- for (String style : styleRefs) {
- buff.append(String.format("<link rel='stylesheet' href='%s%s' type='text/css' media='screen' charset='%s'/>", style, getCacheBuster(style), encoding));
- buff.append("\n");
- }
-
- for (String script : scriptRefs) {
- buff.append(String.format("<script src='%s%s' type='text/javascript' charset='%s'></script>", script, getCacheBuster(script), encoding));
- buff.append("\n");
- }
-
- return buff.toString();
- }
-}
View
3 nexus-core/src/main/java/org/sonatype/nexus/plugins/rest/NexusIndexHtmlCustomizer.java
@@ -13,7 +13,6 @@
package org.sonatype.nexus.plugins.rest;
import java.util.Map;
-
import javax.inject.Singleton;
import org.sonatype.plugin.ExtensionPoint;
@@ -42,7 +41,7 @@
*
* @author cstamas
*
- * @deprecated since 2.4. Use {@link UiContributor} instead.
+ * @deprecated since 2.4. Use org.sonatype.nexus.plugins.ui.contribution.UiContributor from nexus-ui-extjs3-plugin instead.
*/
@ExtensionPoint
@Singleton
View
153 nexus-core/src/main/java/org/sonatype/nexus/plugins/rest/UiContributionBuilder.java
@@ -1,153 +0,0 @@
-/*
- * Sonatype Nexus (TM) Open Source Version
- * Copyright (c) 2007-2012 Sonatype, Inc.
- * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
- *
- * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
- * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
- *
- * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
- * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
- * Eclipse Foundation. All other trademarks are the property of their respective owners.
- */
-package org.sonatype.nexus.plugins.rest;
-
-import java.util.List;
-
-import com.google.common.collect.Lists;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Builder for contributions used to activate plugin UI.
- *
- * @see UiContributor
- * @since 2.4
- */
-public class UiContributionBuilder
- extends AbstractUiContributionBuilder<UiContributor.UiContribution>
-{
-
- private String module;
-
- private List<String> dependencies = Lists.newLinkedList();
-
- private Condition condition = new Condition()
- {
- @Override
- public boolean isSatisfied()
- {
- return true;
- }
- };
-
- public UiContributionBuilder( final Object owner, final String groupId, final String artifactId )
- {
- super( owner, groupId, artifactId );
- }
-
- /**
- * Sets the entry point to use. If no module is set, the builder will use "artifactId-boot" as a default
- * module name.
- */
- public UiContributionBuilder boot( final String module )
- {
- this.module = module;
- return this;
- }
-
- /**
- * Adds a dependency.
- */
- public UiContributionBuilder withDependency( final String dependency )
- {
- checkNotNull(dependency);
- dependencies.add( dependency );
- return this;
- }
-
- /**
- * Adds the default location for a compressed plugin js file: {@code static/js/${artifactId}-all.js}.
- */
- public UiContributionBuilder withDefaultAggregateDependency()
- {
- final String js = getDefaultPath( "js", true );
- return withDependency( js );
- }
-
- private void maybeAddDefaultCssDependency()
- {
- final String path = getDefaultPath( "css", false );
- if ( owner.getClass().getClassLoader().getResource( path ) != null )
- {
- withDependency( "css!" + path + getCacheBuster( path ) );
- }
- }
-
- /**
- * Adds the default css dependency if it is available: {@code static/js/${artifactId}-all.css}.
- */
- public UiContributionBuilder withDefaultCssDependency()
- {
- maybeAddDefaultCssDependency();
- return this;
- }
-
- public UiContributionBuilder setDefaultModule()
- {
- return boot( artifactId + "-boot" );
- }
-
- @Override
- public UiContributor.UiContribution build()
- {
- return build( false );
- }
-
- /**
- * If no module is set, the builder will use "artifactId-boot" as a default
- * module name.
- * <p/>
- * If no dependencies are set, the builder will add the default CSS dependency,
- * if it is available by Classloader resource lookup.
- * <p/>
- * If no dependencies are set, the builder will add the default JS dependency,
- * unless the debug parameter is set to true.
- */
- public UiContributor.UiContribution build( final boolean debug )
- {
- if ( module == null )
- {
- setDefaultModule();
- }
-
- if ( dependencies.isEmpty() )
- {
- // always add css dependency, also needed when debug is requested
- maybeAddDefaultCssDependency();
- // if (!debug ) // FIXME debug mode will only be available after reorganization of the js file locations (static vs. non-static)
- withDefaultAggregateDependency();
- }
-
- return new UiContributor.UiContribution( module, dependencies, condition.isSatisfied() );
- }
-
- /**
- * Add a condition to the builder that is evaluated on {@link #build} to determine if the contribution is enabled or not.
- *
- * @param condition The condition which must be satisfied to enable the contribution.
- */
- public UiContributionBuilder withCondition( final Condition condition )
- {
- this.condition = checkNotNull(condition);
- return this;
- }
-
- /**
- * @see #withCondition(Condition)
- */
- public static interface Condition
- {
- boolean isSatisfied();
- }
-}
View
89 nexus-core/src/main/java/org/sonatype/nexus/plugins/rest/UiContributor.java
@@ -1,89 +0,0 @@
-/*
- * Sonatype Nexus (TM) Open Source Version
- * Copyright (c) 2007-2012 Sonatype, Inc.
- * All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
- *
- * This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
- * which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
- *
- * Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
- * of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
- * Eclipse Foundation. All other trademarks are the property of their respective owners.
- */
-package org.sonatype.nexus.plugins.rest;
-
-import java.util.List;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Used to look up plugins contributing proper require.js UI code.
- *
- * @since 2.4
- */
-public interface UiContributor
-{
-
- /**
- * Called on Nexus UI page load.
- * @param debug true if debug code should be delivered; false otherwise.
- * @return An object containing information about what to load for the UI.
- */
- UiContribution contribute(boolean debug);
-
- /**
- * Contains dependencies to load and the base module to use, for example:
- *
- * dependencies: ["js/static/plugin-all.js"]
- *
- * module name: "Nexus/plugin/bootstrap"
- *
- * where plugin-all.js contains require.js module definitions (e.g. `define("Nexus/plugin/bootstrap", ["Nexus/plugin/dep1"], function() {}` ).
- *
- * @since 2.4
- * @see UiContributionBuilder
- */
- class UiContribution
- {
- private String module;
-
- private List<String> dependencies;
-
- private boolean enabled;
-
- /**
- * @see UiContributionBuilder
- */
- public UiContribution( final String module, final List<String> dependencies, final boolean enabled )
- {
- this.module = checkNotNull(module);
- this.dependencies = checkNotNull(dependencies);
- this.enabled = enabled;
- }
-
- /**
- * The dependencies to load before the module defined by {@link #getModule()} is required.
- * May be any valid require.js dependency name (url, module name, plugin)
- *
- * @return the list of dependencies to load.
- */
- public List<String> getDependencies() {
- return dependencies;
- }
-
- /**
- * The module that is used to initialize the plugin.
- *
- * @return the module name.
- */
- public String getModule() {
- return module;
- }
-
- public boolean isEnabled()
- {
- return enabled;
- }
- }
-
-}
View
21 nexus-core/src/main/java/org/sonatype/nexus/proxy/maven/AbstractMavenRepository.java
@@ -48,8 +48,8 @@
import org.sonatype.nexus.proxy.item.uid.IsHiddenAttribute;
import org.sonatype.nexus.proxy.maven.EvictUnusedMavenItemsWalkerProcessor.EvictUnusedMavenItemsWalkerFilter;
import org.sonatype.nexus.proxy.maven.packaging.ArtifactPackagingMapper;
-import org.sonatype.nexus.proxy.maven.routing.ProxyRequestFilter;
import org.sonatype.nexus.proxy.maven.routing.Manager;
+import org.sonatype.nexus.proxy.maven.routing.ProxyRequestFilter;
import org.sonatype.nexus.proxy.repository.AbstractProxyRepository;
import org.sonatype.nexus.proxy.repository.DefaultRepositoryKind;
import org.sonatype.nexus.proxy.repository.HostedRepository;
@@ -414,7 +414,7 @@ protected StorageItem doRetrieveItem( ResourceStoreRequest request )
throw new ItemNotFoundException( reasonFor( request, this,
"Retrieval of %s from %s is forbidden by repository policy %s.", request.getRequestPath(),
- RepositoryStringUtils.getHumanizedNameString( this ), getRepositoryPolicy() ) );
+ this, getRepositoryPolicy() ) );
}
if ( getRepositoryKind().isFacetAvailable( ProxyRepository.class )
@@ -454,14 +454,12 @@ private StorageItem doRetrieveArtifactItem( ResourceStoreRequest hashRequest, St
}
@Override
- protected boolean shouldTryRemote( final ResourceStoreRequest request )
+ protected void shouldTryRemote( final ResourceStoreRequest request )
throws IllegalOperationException, ItemNotFoundException
{