From 5ab7b11dd82d748f9e0744120ead2cf21bcd8384 Mon Sep 17 00:00:00 2001 From: Kelly Robinson Date: Tue, 2 May 2017 15:17:14 -0700 Subject: [PATCH] upstream: b=3.3.1-release-branch,r=5b4aa3b1cb7aa5f63c971f1a462689a502615595,t=2017-04-27-1557-35442 --- assemblies/nexus-base-feature/pom.xml | 2 +- assemblies/nexus-base-template/pom.xml | 2 +- assemblies/nexus-boot-feature/pom.xml | 2 +- assemblies/nexus-core-feature/pom.xml | 2 +- assemblies/nexus-startup-feature/pom.xml | 2 +- assemblies/pom.xml | 6 +- buildsupport/all/pom.xml | 38 ++--- buildsupport/commons/pom.xml | 2 +- buildsupport/db/pom.xml | 2 +- buildsupport/extjs-maven-plugin/pom.xml | 4 +- buildsupport/goodies/pom.xml | 2 +- buildsupport/groovy/pom.xml | 2 +- buildsupport/guice/pom.xml | 2 +- buildsupport/httpclient/pom.xml | 2 +- buildsupport/internal/pom.xml | 2 +- buildsupport/jetty/pom.xml | 2 +- buildsupport/jruby/pom.xml | 2 +- buildsupport/logging/pom.xml | 2 +- buildsupport/maven/pom.xml | 2 +- buildsupport/metrics/pom.xml | 2 +- buildsupport/osgi/pom.xml | 2 +- buildsupport/other/pom.xml | 2 +- buildsupport/pom.xml | 2 +- buildsupport/rest/pom.xml | 2 +- buildsupport/scripts/pom.xml | 4 +- buildsupport/security/pom.xml | 2 +- buildsupport/testing/pom.xml | 2 +- buildsupport/ui/pom.xml | 2 +- components/nexus-analytics-api/pom.xml | 2 +- components/nexus-audit/pom.xml | 2 +- components/nexus-base/pom.xml | 2 +- .../nexus/internal/web/ErrorPageServlet.java | 14 +- components/nexus-blobstore-api/pom.xml | 2 +- .../nexus/blobstore/api/BlobStore.java | 2 +- components/nexus-blobstore-file/pom.xml | 2 +- .../file/internal/BlobAttributes.java | 14 ++ .../file/internal/BlobCollisionException.java | 39 +++++ .../file/internal/FileBlobStore.java | 74 +++++++--- .../internal/FileBlobStoreConcurrencyIT.java | 2 +- .../file/internal/FileBlobStoreIT.java | 8 +- .../file/internal/FileBlobStoreTest.java | 37 +++++ components/nexus-bootstrap/pom.xml | 2 +- components/nexus-cache/pom.xml | 2 +- components/nexus-capability/pom.xml | 2 +- components/nexus-commands/pom.xml | 2 +- components/nexus-common/pom.xml | 2 +- components/nexus-core/pom.xml | 2 +- components/nexus-crypto/pom.xml | 2 +- components/nexus-elasticsearch/pom.xml | 2 +- components/nexus-email/pom.xml | 2 +- components/nexus-extdirect/pom.xml | 2 +- components/nexus-extender/pom.xml | 2 +- components/nexus-formfields/pom.xml | 2 +- components/nexus-guice-servlet/pom.xml | 2 +- components/nexus-httpclient/pom.xml | 2 +- components/nexus-jmx/pom.xml | 2 +- components/nexus-main/pom.xml | 2 +- components/nexus-mime/pom.xml | 2 +- components/nexus-orient-console/pom.xml | 2 +- components/nexus-orient/pom.xml | 2 +- components/nexus-oss-edition/pom.xml | 2 +- components/nexus-pax-exam/pom.xml | 2 +- components/nexus-pax-logging/pom.xml | 2 +- components/nexus-plugin-api/pom.xml | 2 +- components/nexus-quartz/pom.xml | 2 +- components/nexus-rapture/pom.xml | 2 +- components/nexus-repository/pom.xml | 2 +- .../repository/proxy/ProxyFacetSupport.java | 20 ++- .../nexus/repository/storage/AssetBlob.java | 84 +++++++++-- .../nexus/repository/storage/BlobTx.java | 55 ++++--- .../repository/storage/BucketDeleter.java | 2 +- .../storage/MissingBlobException.java | 7 + .../repository/storage/StorageTxImpl.java | 136 ++++++++++++------ .../proxy/ProxyFacetSupportTest.java | 23 +++ .../repository/storage/BlobTxTest.groovy | 6 +- .../storage/BucketDeleterTest.groovy | 12 +- .../storage/StorageTxImplTest.groovy | 21 ++- components/nexus-rest-client/pom.xml | 2 +- components/nexus-rest-jackson2/pom.xml | 2 +- components/nexus-rest/pom.xml | 2 +- components/nexus-scheduling/pom.xml | 2 +- components/nexus-script/pom.xml | 2 +- components/nexus-security/pom.xml | 2 +- components/nexus-selector/pom.xml | 2 +- components/nexus-servlet/pom.xml | 2 +- components/nexus-siesta/pom.xml | 2 +- components/nexus-ssl/pom.xml | 2 +- components/nexus-supportzip-api/pom.xml | 2 +- components/nexus-swagger/pom.xml | 2 +- components/nexus-test-common/pom.xml | 2 +- components/nexus-thread/pom.xml | 2 +- components/nexus-transaction/pom.xml | 2 +- components/nexus-upgrade/pom.xml | 2 +- components/nexus-validation/pom.xml | 2 +- components/nexus-webhooks/pom.xml | 2 +- components/nexus-webresources-api/pom.xml | 2 +- components/pom.xml | 6 +- plugins/nexus-audit-plugin/pom.xml | 2 +- plugins/nexus-coreui-plugin/pom.xml | 2 +- plugins/nexus-repository-httpbridge/pom.xml | 2 +- plugins/nexus-repository-maven/pom.xml | 2 +- .../maven/internal/MavenFacetImpl.java | 12 +- plugins/nexus-repository-raw/pom.xml | 2 +- plugins/nexus-script-plugin/pom.xml | 2 +- plugins/nexus-ssl-plugin/pom.xml | 2 +- plugins/pom.xml | 34 ++--- pom.xml | 120 ++++++++-------- revision.txt | 2 +- thirdparty-bundles/elasticsearch/pom.xml | 2 +- thirdparty-bundles/pom.xml | 6 +- 110 files changed, 631 insertions(+), 321 deletions(-) create mode 100644 components/nexus-blobstore-file/src/main/java/org/sonatype/nexus/blobstore/file/internal/BlobCollisionException.java diff --git a/assemblies/nexus-base-feature/pom.xml b/assemblies/nexus-base-feature/pom.xml index 79141be4c7..a956e07ae7 100644 --- a/assemblies/nexus-base-feature/pom.xml +++ b/assemblies/nexus-base-feature/pom.xml @@ -19,7 +19,7 @@ org.sonatype.nexus.assemblies nexus-assemblies - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-base-feature diff --git a/assemblies/nexus-base-template/pom.xml b/assemblies/nexus-base-template/pom.xml index 636f21ef97..60a4d116a1 100644 --- a/assemblies/nexus-base-template/pom.xml +++ b/assemblies/nexus-base-template/pom.xml @@ -21,7 +21,7 @@ org.sonatype.nexus.assemblies nexus-assemblies - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-base-template diff --git a/assemblies/nexus-boot-feature/pom.xml b/assemblies/nexus-boot-feature/pom.xml index 9bb0c7430c..a17605cd9d 100644 --- a/assemblies/nexus-boot-feature/pom.xml +++ b/assemblies/nexus-boot-feature/pom.xml @@ -19,7 +19,7 @@ org.sonatype.nexus.assemblies nexus-assemblies - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-boot-feature diff --git a/assemblies/nexus-core-feature/pom.xml b/assemblies/nexus-core-feature/pom.xml index 0b601bf96d..281f28c075 100644 --- a/assemblies/nexus-core-feature/pom.xml +++ b/assemblies/nexus-core-feature/pom.xml @@ -19,7 +19,7 @@ org.sonatype.nexus.assemblies nexus-assemblies - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-core-feature diff --git a/assemblies/nexus-startup-feature/pom.xml b/assemblies/nexus-startup-feature/pom.xml index 403bcc1e16..ac95897072 100644 --- a/assemblies/nexus-startup-feature/pom.xml +++ b/assemblies/nexus-startup-feature/pom.xml @@ -19,7 +19,7 @@ org.sonatype.nexus.assemblies nexus-assemblies - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-startup-feature diff --git a/assemblies/pom.xml b/assemblies/pom.xml index 2b9da04ad6..2239a17aa8 100644 --- a/assemblies/pom.xml +++ b/assemblies/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-parent - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus.assemblies @@ -45,7 +45,7 @@ org.sonatype.nexus nexus-components pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -53,7 +53,7 @@ org.sonatype.nexus.plugins nexus-plugins pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import diff --git a/buildsupport/all/pom.xml b/buildsupport/all/pom.xml index c325641b51..99b7a37adb 100644 --- a/buildsupport/all/pom.xml +++ b/buildsupport/all/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-all @@ -35,7 +35,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-commons pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -43,7 +43,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-db pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -51,7 +51,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-goodies pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -59,7 +59,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-groovy pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -67,7 +67,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-guice pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -75,7 +75,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-httpclient pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -83,7 +83,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-internal pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -91,7 +91,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-jetty pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -99,7 +99,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-jruby pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -107,7 +107,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-logging pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -115,7 +115,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-maven pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -123,7 +123,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-metrics pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -131,7 +131,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-osgi pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -139,7 +139,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-other pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -147,7 +147,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-rest pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -155,7 +155,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-security pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -163,7 +163,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-testing pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -171,7 +171,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-ui pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import diff --git a/buildsupport/commons/pom.xml b/buildsupport/commons/pom.xml index 79edc3474d..6609c200a0 100644 --- a/buildsupport/commons/pom.xml +++ b/buildsupport/commons/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-commons diff --git a/buildsupport/db/pom.xml b/buildsupport/db/pom.xml index 25d08db6a9..0259057623 100644 --- a/buildsupport/db/pom.xml +++ b/buildsupport/db/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-db diff --git a/buildsupport/extjs-maven-plugin/pom.xml b/buildsupport/extjs-maven-plugin/pom.xml index 4878bc2d42..b026cef4ee 100644 --- a/buildsupport/extjs-maven-plugin/pom.xml +++ b/buildsupport/extjs-maven-plugin/pom.xml @@ -21,7 +21,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT extjs-maven-plugin @@ -37,7 +37,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-all pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import diff --git a/buildsupport/goodies/pom.xml b/buildsupport/goodies/pom.xml index 1cd759901b..aa2cce0dd8 100644 --- a/buildsupport/goodies/pom.xml +++ b/buildsupport/goodies/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-goodies diff --git a/buildsupport/groovy/pom.xml b/buildsupport/groovy/pom.xml index b656a7108d..358a384f53 100644 --- a/buildsupport/groovy/pom.xml +++ b/buildsupport/groovy/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-groovy diff --git a/buildsupport/guice/pom.xml b/buildsupport/guice/pom.xml index e0abfba88e..e32388e4b6 100644 --- a/buildsupport/guice/pom.xml +++ b/buildsupport/guice/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-guice diff --git a/buildsupport/httpclient/pom.xml b/buildsupport/httpclient/pom.xml index c664f4ff0d..54cb0afabe 100644 --- a/buildsupport/httpclient/pom.xml +++ b/buildsupport/httpclient/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-httpclient diff --git a/buildsupport/internal/pom.xml b/buildsupport/internal/pom.xml index 940e62fa2b..01c766f0ea 100644 --- a/buildsupport/internal/pom.xml +++ b/buildsupport/internal/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-internal diff --git a/buildsupport/jetty/pom.xml b/buildsupport/jetty/pom.xml index b3baa4503b..dfa492a575 100644 --- a/buildsupport/jetty/pom.xml +++ b/buildsupport/jetty/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-jetty diff --git a/buildsupport/jruby/pom.xml b/buildsupport/jruby/pom.xml index 376de2b2a4..d5b3378143 100644 --- a/buildsupport/jruby/pom.xml +++ b/buildsupport/jruby/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-jruby diff --git a/buildsupport/logging/pom.xml b/buildsupport/logging/pom.xml index 780fd5f3d0..c5a256e3d0 100644 --- a/buildsupport/logging/pom.xml +++ b/buildsupport/logging/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-logging diff --git a/buildsupport/maven/pom.xml b/buildsupport/maven/pom.xml index c5615b5d43..2861f3cf5c 100644 --- a/buildsupport/maven/pom.xml +++ b/buildsupport/maven/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-maven diff --git a/buildsupport/metrics/pom.xml b/buildsupport/metrics/pom.xml index 7802ad0670..f1a31bd8a7 100644 --- a/buildsupport/metrics/pom.xml +++ b/buildsupport/metrics/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-metrics diff --git a/buildsupport/osgi/pom.xml b/buildsupport/osgi/pom.xml index 08f034d496..85c1a98fd4 100644 --- a/buildsupport/osgi/pom.xml +++ b/buildsupport/osgi/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-osgi diff --git a/buildsupport/other/pom.xml b/buildsupport/other/pom.xml index e05d36ca3f..50e8a97b09 100644 --- a/buildsupport/other/pom.xml +++ b/buildsupport/other/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-other diff --git a/buildsupport/pom.xml b/buildsupport/pom.xml index 6a50270e9e..22f51fa3e3 100644 --- a/buildsupport/pom.xml +++ b/buildsupport/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-parent - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus.buildsupport diff --git a/buildsupport/rest/pom.xml b/buildsupport/rest/pom.xml index a296cfbfd2..f8beba1bc0 100644 --- a/buildsupport/rest/pom.xml +++ b/buildsupport/rest/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-rest diff --git a/buildsupport/scripts/pom.xml b/buildsupport/scripts/pom.xml index eedd85c2a3..8983b510a9 100644 --- a/buildsupport/scripts/pom.xml +++ b/buildsupport/scripts/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-scripts @@ -36,7 +36,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-all pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import diff --git a/buildsupport/security/pom.xml b/buildsupport/security/pom.xml index efad8d7aca..2c10774535 100644 --- a/buildsupport/security/pom.xml +++ b/buildsupport/security/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-security diff --git a/buildsupport/testing/pom.xml b/buildsupport/testing/pom.xml index 4fa826020f..5c06e4eb48 100644 --- a/buildsupport/testing/pom.xml +++ b/buildsupport/testing/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-testing diff --git a/buildsupport/ui/pom.xml b/buildsupport/ui/pom.xml index de391753aa..c8f3402619 100644 --- a/buildsupport/ui/pom.xml +++ b/buildsupport/ui/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-buildsupport-ui diff --git a/components/nexus-analytics-api/pom.xml b/components/nexus-analytics-api/pom.xml index dc1a4a32ea..d93e0454bf 100644 --- a/components/nexus-analytics-api/pom.xml +++ b/components/nexus-analytics-api/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-analytics-api diff --git a/components/nexus-audit/pom.xml b/components/nexus-audit/pom.xml index dd7974c075..9e9ab3f0e9 100644 --- a/components/nexus-audit/pom.xml +++ b/components/nexus-audit/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-audit diff --git a/components/nexus-base/pom.xml b/components/nexus-base/pom.xml index a24259a922..b3265a0554 100644 --- a/components/nexus-base/pom.xml +++ b/components/nexus-base/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-base diff --git a/components/nexus-base/src/main/java/org/sonatype/nexus/internal/web/ErrorPageServlet.java b/components/nexus-base/src/main/java/org/sonatype/nexus/internal/web/ErrorPageServlet.java index 552001f588..af982aedbf 100644 --- a/components/nexus-base/src/main/java/org/sonatype/nexus/internal/web/ErrorPageServlet.java +++ b/components/nexus-base/src/main/java/org/sonatype/nexus/internal/web/ErrorPageServlet.java @@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Throwables.getRootCause; import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; /** @@ -152,8 +153,19 @@ protected void service(final HttpServletRequest request, final HttpServletRespon * @since 3.0 */ static void attachCause(final HttpServletRequest request, final Throwable cause) { - log.debug("Attaching cause", cause); + if (isJavaLangError(cause)) { + // Log java.lang.Error exceptions at error level + log.error("Unexpected exception", getRootCause(cause)); + } + else { + log.debug("Attaching cause", cause); + } request.setAttribute(ERROR_EXCEPTION_TYPE, cause.getClass()); request.setAttribute(ERROR_EXCEPTION, cause); } + + private static boolean isJavaLangError(final Throwable e) { + return getRootCause(e) instanceof Error; + } + } diff --git a/components/nexus-blobstore-api/pom.xml b/components/nexus-blobstore-api/pom.xml index 70e5ddaed9..eb4ee18a5d 100644 --- a/components/nexus-blobstore-api/pom.xml +++ b/components/nexus-blobstore-api/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-blobstore-api diff --git a/components/nexus-blobstore-api/src/main/java/org/sonatype/nexus/blobstore/api/BlobStore.java b/components/nexus-blobstore-api/src/main/java/org/sonatype/nexus/blobstore/api/BlobStore.java index d41dc33a08..0065b03290 100644 --- a/components/nexus-blobstore-api/src/main/java/org/sonatype/nexus/blobstore/api/BlobStore.java +++ b/components/nexus-blobstore-api/src/main/java/org/sonatype/nexus/blobstore/api/BlobStore.java @@ -99,7 +99,7 @@ public interface BlobStore * * @return {@code true} if the blob has been deleted, {@code false} if no blob was found by that ID. */ - boolean delete(BlobId blobId); + boolean delete(BlobId blobId, String reason); /** * Removes a blob from the blob store immediately, disregarding any locking or concurrent access by other threads. diff --git a/components/nexus-blobstore-file/pom.xml b/components/nexus-blobstore-file/pom.xml index b2fef2f2dc..a0a8424d72 100644 --- a/components/nexus-blobstore-file/pom.xml +++ b/components/nexus-blobstore-file/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-blobstore-file diff --git a/components/nexus-blobstore-file/src/main/java/org/sonatype/nexus/blobstore/file/internal/BlobAttributes.java b/components/nexus-blobstore-file/src/main/java/org/sonatype/nexus/blobstore/file/internal/BlobAttributes.java index 23b7feafbe..c976bf4cae 100644 --- a/components/nexus-blobstore-file/src/main/java/org/sonatype/nexus/blobstore/file/internal/BlobAttributes.java +++ b/components/nexus-blobstore-file/src/main/java/org/sonatype/nexus/blobstore/file/internal/BlobAttributes.java @@ -26,6 +26,7 @@ import org.joda.time.DateTime; import static com.google.common.base.Preconditions.checkNotNull; +import static java.util.Optional.of; /** * A data holder for the content of each blob's .attribs file. @@ -42,6 +43,8 @@ public class BlobAttributes private static final String DELETED_ATTRIBUTE = "deleted"; + private static final String DELETED_REASON_ATTRIBUTE = "deletedReason"; + public static final String HEADER_PREFIX = "@"; private Map headers; @@ -49,6 +52,8 @@ public class BlobAttributes private BlobMetrics metrics; private boolean deleted = false; + + private String deletedReason; private final PropertiesFile propertiesFile; @@ -80,6 +85,14 @@ public void setDeleted(final boolean deleted) { this.deleted = deleted; } + public void setDeletedReason(final String deletedReason) { + this.deletedReason = deletedReason; + } + + public String getDeletedReason() { + return deletedReason; + } + /** * @since 3.2 */ @@ -132,6 +145,7 @@ private Properties writeTo(final Properties properties) { if (deleted) { properties.put(DELETED_ATTRIBUTE, Boolean.toString(deleted)); + properties.put(DELETED_REASON_ATTRIBUTE, of(deletedReason).orElse("No reason supplied")); } return properties; } diff --git a/components/nexus-blobstore-file/src/main/java/org/sonatype/nexus/blobstore/file/internal/BlobCollisionException.java b/components/nexus-blobstore-file/src/main/java/org/sonatype/nexus/blobstore/file/internal/BlobCollisionException.java new file mode 100644 index 0000000000..d8ef4835b9 --- /dev/null +++ b/components/nexus-blobstore-file/src/main/java/org/sonatype/nexus/blobstore/file/internal/BlobCollisionException.java @@ -0,0 +1,39 @@ +/* + * Sonatype Nexus (TM) Open Source Version + * Copyright (c) 2008-present 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.blobstore.file.internal; + +import org.sonatype.nexus.blobstore.api.BlobId; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Thrown when a blob already exists for the generated {@link BlobId}. + * + * @since 3.4 + */ +public class BlobCollisionException + extends RuntimeException +{ + private final BlobId blobId; + + public BlobCollisionException(final BlobId blobId) { + this.blobId = checkNotNull(blobId); + } + + /** + * The BlobId of the blob related to this exception. + */ + public BlobId getBlobId() { + return blobId; + } +} diff --git a/components/nexus-blobstore-file/src/main/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStore.java b/components/nexus-blobstore-file/src/main/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStore.java index b65c6262a6..dc5c380fca 100644 --- a/components/nexus-blobstore-file/src/main/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStore.java +++ b/components/nexus-blobstore-file/src/main/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStore.java @@ -46,6 +46,7 @@ import org.sonatype.nexus.common.io.DirectoryHelper; import org.sonatype.nexus.common.node.NodeAccess; import org.sonatype.nexus.common.property.PropertiesFile; +import org.sonatype.nexus.common.property.SystemPropertiesHelper; import org.sonatype.nexus.common.stateguard.Guarded; import org.sonatype.nexus.common.stateguard.StateGuardLifecycleSupport; @@ -108,6 +109,12 @@ public class FileBlobStore @VisibleForTesting public static final String TEMPORARY_BLOB_ID_PREFIX = "tmp$"; + private static final boolean RETRY_ON_COLLISION = + SystemPropertiesHelper.getBoolean("nexus.blobstore.retryOnCollision", true); + + @VisibleForTesting + static final int MAX_COLLISION_RETRIES = 8; + private Path contentDir; private final LocationStrategy permanentLocationStrategy; @@ -293,6 +300,21 @@ private Blob create(final Map headers, final BlobIngester ingest checkArgument(headers.containsKey(BLOB_NAME_HEADER), "Missing header: %s", BLOB_NAME_HEADER); checkArgument(headers.containsKey(CREATED_BY_HEADER), "Missing header: %s", CREATED_BY_HEADER); + for (int retries = 0; retries <= MAX_COLLISION_RETRIES; retries++) { + try { + return tryCreate(headers, ingester); + } + catch (BlobCollisionException e) { // NOSONAR + log.warn("BlobId collision: {} already exists{}", e.getBlobId(), + retries < MAX_COLLISION_RETRIES ? ", retrying with new BlobId" : "!"); + } + } + + throw new BlobStoreException("Cannot find free BlobId", null); + } + + private Blob tryCreate(final Map headers, final BlobIngester ingester) { + // Generate a new blobId BlobId blobId; if (headers.containsKey(TEMPORARY_BLOB_HEADER)) { @@ -313,31 +335,36 @@ private Blob create(final Map headers, final BlobIngester ingest Lock lock = blob.lock(); try { - log.debug("Writing blob {} to {}", blobId, blobPath); + if (RETRY_ON_COLLISION && fileOperations.exists(blobPath)) { + throw new BlobCollisionException(blobId); + } + try { + log.debug("Writing blob {} to {}", blobId, blobPath); - final StreamMetrics streamMetrics = ingester.ingestTo(temporaryBlobPath); - final BlobMetrics metrics = new BlobMetrics(new DateTime(), streamMetrics.getSha1(), streamMetrics.getSize()); - blob.refresh(headers, metrics); + final StreamMetrics streamMetrics = ingester.ingestTo(temporaryBlobPath); + final BlobMetrics metrics = new BlobMetrics(new DateTime(), streamMetrics.getSha1(), streamMetrics.getSize()); + blob.refresh(headers, metrics); - // Write the blob attribute file - BlobAttributes blobAttributes = new BlobAttributes(temporaryAttributePath, headers, metrics); - blobAttributes.store(); + // Write the blob attribute file + BlobAttributes blobAttributes = new BlobAttributes(temporaryAttributePath, headers, metrics); + blobAttributes.store(); - // Move the temporary files into their final location - move(temporaryBlobPath, blobPath); - move(temporaryAttributePath, attributePath); + // Move the temporary files into their final location + move(temporaryBlobPath, blobPath); + move(temporaryAttributePath, attributePath); - storeMetrics.recordAddition(blobAttributes.getMetrics().getContentSize()); + storeMetrics.recordAddition(blobAttributes.getMetrics().getContentSize()); - return blob; - } - catch (Exception e) { - // Something went wrong, clean up the files we created - deleteQuietly(temporaryAttributePath); - deleteQuietly(temporaryBlobPath); - deleteQuietly(attributePath); - deleteQuietly(blobPath); - throw new BlobStoreException(e, blobId); + return blob; + } + catch (Exception e) { + // Something went wrong, clean up the files we created + deleteQuietly(temporaryAttributePath); + deleteQuietly(temporaryBlobPath); + deleteQuietly(attributePath); + deleteQuietly(blobPath); + throw new BlobStoreException(e, blobId); + } } finally { lock.unlock(); @@ -392,7 +419,7 @@ public Blob get(final BlobId blobId) { } if (blobAttributes.isDeleted()) { - log.warn("Attempt to access soft-deleted blob {} ({})", blobId, blobAttributes.getPath()); + log.warn("Attempt to access soft-deleted blob {} ({}), reason: {}", blobId, blobAttributes.getPath(), blobAttributes.getDeletedReason()); return null; } @@ -414,7 +441,7 @@ public Blob get(final BlobId blobId) { @Override @Guarded(by = STARTED) - public boolean delete(final BlobId blobId) { + public boolean delete(final BlobId blobId, final String reason) { checkNotNull(blobId); final FileBlob blob = liveBlobs.getUnchecked(blobId); @@ -439,6 +466,7 @@ else if (blobAttributes.isDeleted()) { } blobAttributes.setDeleted(true); + blobAttributes.setDeletedReason(reason); blobAttributes.store(); // record blob for hard-deletion when the next compact task runs @@ -595,7 +623,7 @@ private void move(final Path source, final Path target) throws IOException { } catch (AtomicMoveNotSupportedException e) { // NOSONAR supportsAtomicMove = false; - log.warn("Disabling atomic moves for blob store {}, could not move {} to {}, reason: {}", + log.warn("Disabling atomic moves for blob store {}, could not move {} to {}, reason deleted: {}", blobStoreConfiguration.getName(), source, target, e.getReason()); } } diff --git a/components/nexus-blobstore-file/src/test/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStoreConcurrencyIT.java b/components/nexus-blobstore-file/src/test/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStoreConcurrencyIT.java index 28ad5d6553..5ed3db5291 100644 --- a/components/nexus-blobstore-file/src/test/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStoreConcurrencyIT.java +++ b/components/nexus-blobstore-file/src/test/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStoreConcurrencyIT.java @@ -166,7 +166,7 @@ public void concurrencyTest() throws Exception { // There's a race condition here, we need to note that we're attempting to delete this before the deletion // goes through, otherwise we may fail the check, above. deletedIds.add(blobId); - underTest.delete(blobId); + underTest.delete(blobId, "Testing concurrency"); } ); diff --git a/components/nexus-blobstore-file/src/test/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStoreIT.java b/components/nexus-blobstore-file/src/test/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStoreIT.java index 4259107b9e..fcc49f6c75 100644 --- a/components/nexus-blobstore-file/src/test/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStoreIT.java +++ b/components/nexus-blobstore-file/src/test/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStoreIT.java @@ -167,7 +167,7 @@ public void basicSmokeTest() throws Exception { assertThat(storeMetrics.getAvailableSpace(), is(greaterThan(0L))); - final boolean deleted = underTest.delete(blob.getId()); + final boolean deleted = underTest.delete(blob.getId(), "basicSmokeTest"); assertThat(deleted, is(equalTo(true))); underTest.compact(); await().atMost(METRICS_FLUSH_TIMEOUT, SECONDS).until(() -> underTest.getMetrics().getBlobCount(), is(0L)); @@ -216,7 +216,7 @@ public void testSoftDeleteMetricsOnlyUpdateOnCompact() { .until(() -> underTest.getMetrics().getBlobCount(), is(initialBlobCount + 1)); //Standard delete will not update metrics - underTest.delete(blob.getId()); + underTest.delete(blob.getId(), "testSoftDeleteMetricsOnlyUpdateOnCompact"); assertThat(underTest.getMetrics().getBlobCount(), is(initialBlobCount + 1)); //Compact triggers hard delete, so metrics will be updated @@ -299,7 +299,7 @@ public void blobCopyingPreservesBytesUsingHardLink() throws Exception { BlobId copyId = underTest.copy(temp.getId(), TEST_HEADERS).getId(); - underTest.delete(temp.getId()); + underTest.delete(temp.getId(), "blobCopyingPreservesBytesUsingHardLink"); Blob copy = underTest.get(copyId); @@ -337,7 +337,7 @@ public void blobCopyingPreservesBytesUsingInputStream() throws Exception { BlobId copyId = underTest.copy(temp.getId(), TEST_HEADERS).getId(); - underTest.delete(temp.getId()); + underTest.delete(temp.getId(), "blobCopyingPreservesBytesUsingInputStream"); Blob copy = underTest.get(copyId); diff --git a/components/nexus-blobstore-file/src/test/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStoreTest.java b/components/nexus-blobstore-file/src/test/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStoreTest.java index 72c9884464..19d5dbe016 100644 --- a/components/nexus-blobstore-file/src/test/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStoreTest.java +++ b/components/nexus-blobstore-file/src/test/java/org/sonatype/nexus/blobstore/file/internal/FileBlobStoreTest.java @@ -41,8 +41,11 @@ import static java.nio.file.Files.write; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.sonatype.nexus.blobstore.api.BlobStore.BLOB_NAME_HEADER; import static org.sonatype.nexus.blobstore.api.BlobStore.CREATED_BY_HEADER; @@ -133,6 +136,40 @@ public void hardLinkWithPrecalculatedInformation() throws Exception { assertThat(blob.getMetrics().getSha1Hash(), is("356a192b7913b04c54574d18c28d46e6395428ab")); } + @Test + public void blobIdCollisionCausesRetry() throws Exception { + + long size = 100L; + HashCode sha1 = HashCode.fromString("356a192b7913b04c54574d18c28d46e6395428ab"); + + Path path = util.createTempFile().toPath(); + + when(fileOperations.exists(any())).thenReturn(true, true, true, false); + + underTest.create(path, TEST_HEADERS, size, sha1); + + verify(fileOperations, times(4)).exists(any()); + } + + @Test + public void blobIdCollisionThrowsExceptionOnRetryLimit() throws Exception { + + long size = 100L; + HashCode sha1 = HashCode.fromString("356a192b7913b04c54574d18c28d46e6395428ab"); + + Path path = util.createTempFile().toPath(); + + when(fileOperations.exists(any())).thenReturn(true); + + try { + underTest.create(path, TEST_HEADERS, size, sha1); + fail("Expected BlobStoreException"); + } + catch (BlobStoreException e) { + verify(fileOperations, times(FileBlobStore.MAX_COLLISION_RETRIES + 1)).exists(any()); + } + } + byte[] deletedBlobStoreProperties = ("deleted = true\n" + "@BlobStore.created-by = admin\n" + "size = 40\n" + diff --git a/components/nexus-bootstrap/pom.xml b/components/nexus-bootstrap/pom.xml index 25ca36aa0e..9f5f8563ca 100644 --- a/components/nexus-bootstrap/pom.xml +++ b/components/nexus-bootstrap/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-bootstrap diff --git a/components/nexus-cache/pom.xml b/components/nexus-cache/pom.xml index cda5381798..81aa5591f7 100644 --- a/components/nexus-cache/pom.xml +++ b/components/nexus-cache/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-cache diff --git a/components/nexus-capability/pom.xml b/components/nexus-capability/pom.xml index 9dd542c5b0..a73ae5dc96 100644 --- a/components/nexus-capability/pom.xml +++ b/components/nexus-capability/pom.xml @@ -21,7 +21,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-capability diff --git a/components/nexus-commands/pom.xml b/components/nexus-commands/pom.xml index 70d16bbf04..e87da2d3e9 100644 --- a/components/nexus-commands/pom.xml +++ b/components/nexus-commands/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-commands diff --git a/components/nexus-common/pom.xml b/components/nexus-common/pom.xml index 1dac0305c3..da2a9c326b 100644 --- a/components/nexus-common/pom.xml +++ b/components/nexus-common/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-common diff --git a/components/nexus-core/pom.xml b/components/nexus-core/pom.xml index 003d4c65de..2a9cafd8a9 100644 --- a/components/nexus-core/pom.xml +++ b/components/nexus-core/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-core diff --git a/components/nexus-crypto/pom.xml b/components/nexus-crypto/pom.xml index 6e62bb22e4..31d48c008b 100644 --- a/components/nexus-crypto/pom.xml +++ b/components/nexus-crypto/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-crypto diff --git a/components/nexus-elasticsearch/pom.xml b/components/nexus-elasticsearch/pom.xml index af6fe02f42..969430f988 100644 --- a/components/nexus-elasticsearch/pom.xml +++ b/components/nexus-elasticsearch/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-elasticsearch diff --git a/components/nexus-email/pom.xml b/components/nexus-email/pom.xml index 50f5a14945..ca188972bc 100644 --- a/components/nexus-email/pom.xml +++ b/components/nexus-email/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-email diff --git a/components/nexus-extdirect/pom.xml b/components/nexus-extdirect/pom.xml index cd22a06877..5811ecf5a7 100644 --- a/components/nexus-extdirect/pom.xml +++ b/components/nexus-extdirect/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-extdirect diff --git a/components/nexus-extender/pom.xml b/components/nexus-extender/pom.xml index 9ec522a979..52548d6d7c 100644 --- a/components/nexus-extender/pom.xml +++ b/components/nexus-extender/pom.xml @@ -19,7 +19,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-extender diff --git a/components/nexus-formfields/pom.xml b/components/nexus-formfields/pom.xml index ae23cac75b..70d5507ab3 100644 --- a/components/nexus-formfields/pom.xml +++ b/components/nexus-formfields/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-formfields diff --git a/components/nexus-guice-servlet/pom.xml b/components/nexus-guice-servlet/pom.xml index 3a344a25a1..b59baa1b98 100644 --- a/components/nexus-guice-servlet/pom.xml +++ b/components/nexus-guice-servlet/pom.xml @@ -19,7 +19,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-guice-servlet diff --git a/components/nexus-httpclient/pom.xml b/components/nexus-httpclient/pom.xml index 2b555c1a67..f1b6f9cc10 100644 --- a/components/nexus-httpclient/pom.xml +++ b/components/nexus-httpclient/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-httpclient diff --git a/components/nexus-jmx/pom.xml b/components/nexus-jmx/pom.xml index 3033adf349..f3cda927e0 100644 --- a/components/nexus-jmx/pom.xml +++ b/components/nexus-jmx/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-jmx diff --git a/components/nexus-main/pom.xml b/components/nexus-main/pom.xml index 50120f5203..5e7bd6de9d 100644 --- a/components/nexus-main/pom.xml +++ b/components/nexus-main/pom.xml @@ -21,7 +21,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-main diff --git a/components/nexus-mime/pom.xml b/components/nexus-mime/pom.xml index ca7eb17361..faa8af9a4b 100644 --- a/components/nexus-mime/pom.xml +++ b/components/nexus-mime/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-mime diff --git a/components/nexus-orient-console/pom.xml b/components/nexus-orient-console/pom.xml index 10ec548a8b..ce810523f1 100644 --- a/components/nexus-orient-console/pom.xml +++ b/components/nexus-orient-console/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-orient-console diff --git a/components/nexus-orient/pom.xml b/components/nexus-orient/pom.xml index a0f3105584..ae52ea8913 100644 --- a/components/nexus-orient/pom.xml +++ b/components/nexus-orient/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-orient diff --git a/components/nexus-oss-edition/pom.xml b/components/nexus-oss-edition/pom.xml index c03bab75c7..865b21c869 100644 --- a/components/nexus-oss-edition/pom.xml +++ b/components/nexus-oss-edition/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-oss-edition diff --git a/components/nexus-pax-exam/pom.xml b/components/nexus-pax-exam/pom.xml index 2b81c0ef9a..7be20f28ae 100644 --- a/components/nexus-pax-exam/pom.xml +++ b/components/nexus-pax-exam/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-pax-exam diff --git a/components/nexus-pax-logging/pom.xml b/components/nexus-pax-logging/pom.xml index 5352d4aaa8..399f1a616c 100644 --- a/components/nexus-pax-logging/pom.xml +++ b/components/nexus-pax-logging/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-pax-logging diff --git a/components/nexus-plugin-api/pom.xml b/components/nexus-plugin-api/pom.xml index f27e0e9cf3..8634396a8e 100644 --- a/components/nexus-plugin-api/pom.xml +++ b/components/nexus-plugin-api/pom.xml @@ -19,7 +19,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-plugin-api diff --git a/components/nexus-quartz/pom.xml b/components/nexus-quartz/pom.xml index eec9f4054b..0d8db3dfdb 100644 --- a/components/nexus-quartz/pom.xml +++ b/components/nexus-quartz/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-quartz diff --git a/components/nexus-rapture/pom.xml b/components/nexus-rapture/pom.xml index 824a26f363..b09c3c7a39 100644 --- a/components/nexus-rapture/pom.xml +++ b/components/nexus-rapture/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-rapture diff --git a/components/nexus-repository/pom.xml b/components/nexus-repository/pom.xml index 6425b501e9..946a24ac47 100644 --- a/components/nexus-repository/pom.xml +++ b/components/nexus-repository/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-repository diff --git a/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/proxy/ProxyFacetSupport.java b/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/proxy/ProxyFacetSupport.java index 02b67ede6f..d8380c6d7d 100644 --- a/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/proxy/ProxyFacetSupport.java +++ b/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/proxy/ProxyFacetSupport.java @@ -32,6 +32,8 @@ import org.sonatype.nexus.repository.config.ConfigurationFacet; import org.sonatype.nexus.repository.httpclient.HttpClientFacet; import org.sonatype.nexus.repository.httpclient.RemoteBlockedIOException; +import org.sonatype.nexus.repository.storage.MissingBlobException; +import org.sonatype.nexus.repository.storage.RetryDeniedException; import org.sonatype.nexus.repository.view.Content; import org.sonatype.nexus.repository.view.Context; import org.sonatype.nexus.repository.view.payloads.HttpEntityPayload; @@ -163,7 +165,7 @@ public URI getRemoteUrl() { public Content get(final Context context) throws IOException { checkNotNull(context); - Content content = getCachedContent(context); + Content content = maybeGetCachedContent(context); if (isStale(context, content)) { Content remote = null; @@ -220,6 +222,22 @@ public void invalidateProxyCaches() { cacheControllerHolder.invalidateCaches(); } + private Content maybeGetCachedContent(Context context) throws IOException { + try { + return getCachedContent(context); + } + catch (RetryDeniedException e) { + if (e.getCause() instanceof MissingBlobException) { + log.warn("Unable to find blob {} for {}, will check remote", ((MissingBlobException) e.getCause()).getBlobRef(), + getUrl(context)); + return null; + } + else { + throw e; + } + } + } + /** * If we have the content cached locally already, return that along with applicable cache controller - otherwise * {@code null}. diff --git a/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/AssetBlob.java b/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/AssetBlob.java index ed256e0c3e..dfa0e0d488 100644 --- a/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/AssetBlob.java +++ b/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/AssetBlob.java @@ -13,12 +13,15 @@ package org.sonatype.nexus.repository.storage; import java.util.Map; +import java.util.function.Function; import javax.annotation.Nonnull; import org.sonatype.nexus.blobstore.api.Blob; import org.sonatype.nexus.blobstore.api.BlobRef; +import org.sonatype.nexus.blobstore.api.BlobStore; import org.sonatype.nexus.common.hash.HashAlgorithm; +import org.sonatype.nexus.common.node.NodeAccess; import com.google.common.hash.HashCode; @@ -34,36 +37,80 @@ */ public class AssetBlob { - private final BlobRef blobRef; + private final NodeAccess nodeAccess; - private final Blob blob; + private final BlobStore blobStore; - private final long size; + private final Function blobFunction; private final String contentType; private final Map hashes; + private final boolean hashesVerified; + private boolean attached; - private boolean hashesVerified; + private Blob canonicalBlob; + + private Blob ingestedBlob; - public AssetBlob(final BlobRef blobRef, - final Blob blob, - final long size, + public AssetBlob(final NodeAccess nodeAccess, + final BlobStore blobStore, + final Function blobFunction, final String contentType, final Map hashes, final boolean hashesVerified) { - this.blobRef = checkNotNull(blobRef); - this.blob = checkNotNull(blob); - this.size = size; + this.nodeAccess = checkNotNull(nodeAccess); + this.blobStore = checkNotNull(blobStore); + this.blobFunction = checkNotNull(blobFunction); this.contentType = checkNotNull(contentType); this.hashes = checkNotNull(hashes); - this.attached = false; this.hashesVerified = hashesVerified; } + /** + * Returns {@code true} if this {@link AssetBlob} duplicates the old asset's blob. + * + * @since 3.4 + */ + public boolean isDuplicate() { + return canonicalBlob != null; + } + + /** + * Redirects this temporary {@link AssetBlob} to a canonical (de-duplicated) blob. + * + * @since 3.4 + */ + void setDuplicate(final Blob canonicalBlob) { + this.canonicalBlob = checkNotNull(canonicalBlob); + } + + /** + * Deletes this temporary {@link AssetBlob} by clearing any locally ingested blobs. + * + * Note this shouldn't stop the current response from serving back temporary content, + * it just makes sure non-persisted content is eventually cleaned up from the store. + * + * @since 3.4 + */ + void delete(final String reason) { + if (ingestedBlob != null) { + if (canonicalBlob != null) { + // canonical redirect is in place, so it's safe to hard-delete the temp blob + blobStore.deleteHard(ingestedBlob.getId()); + } + else { + // no redirect, so the temp blob is all we have - use soft-delete so the bytes + // will still be available on disk for streaming back in the current response, + // while making sure it gets cleaned up on the next compact + blobStore.delete(ingestedBlob.getId(), reason); + } + } + } + /** * Returns {@code true} if this instance is attached to an {@link Asset}. If {@code false} returned, the blob * referenced by this instance is considered "orphan" and will be deleted at the end of TX (whatever outcome is, @@ -86,19 +133,28 @@ void setAttached(final boolean attached) { */ @Nonnull public BlobRef getBlobRef() { - return blobRef; + return new BlobRef( + nodeAccess.getId(), + blobStore.getBlobStoreConfiguration().getName(), + getBlob().getId().asUniqueString()); } @Nonnull public Blob getBlob() { - return blob; + if (canonicalBlob != null) { + return canonicalBlob; + } + if (ingestedBlob == null) { + ingestedBlob = checkNotNull(blobFunction.apply(blobStore)); + } + return ingestedBlob; } /** * The blob size in bytes. */ public long getSize() { - return size; + return getBlob().getMetrics().getContentSize(); } /** diff --git a/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/BlobTx.java b/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/BlobTx.java index 62efad599a..c6eb81af56 100644 --- a/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/BlobTx.java +++ b/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/BlobTx.java @@ -15,7 +15,9 @@ import java.io.InputStream; import java.nio.file.Path; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; +import java.util.function.Function; import javax.annotation.Nullable; @@ -28,6 +30,7 @@ import org.sonatype.nexus.common.node.NodeAccess; import org.sonatype.nexus.common.text.Strings2; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.google.common.hash.HashCode; import org.slf4j.Logger; @@ -53,7 +56,7 @@ class BlobTx private final Set newlyCreatedBlobs = Sets.newHashSet(); - private final Set deletionRequests = Sets.newHashSet(); + private final Map deletionRequests = Maps.newHashMap(); public BlobTx(final NodeAccess nodeAccess, final BlobStore blobStore) { this.nodeAccess = checkNotNull(nodeAccess); @@ -66,8 +69,12 @@ public AssetBlob create(final InputStream inputStream, final String contentType) { MultiHashingInputStream hashingStream = new MultiHashingInputStream(hashAlgorithms, inputStream); - Blob blob = blobStore.create(hashingStream, headers); - return createAssetBlob(blob, hashingStream.hashes(), true, contentType); + Blob streamedBlob = blobStore.create(hashingStream, headers); // pre-fetch to populate hashes + return createAssetBlob( + store -> streamedBlob, + hashingStream.hashes(), + true, + contentType); } /** @@ -86,8 +93,11 @@ public AssetBlob createByHardLinking(final Path sourceFile, final String contentType, final long size) { - Blob blob = blobStore.create(sourceFile, headers, size, hashes.get(SHA1)); - return createAssetBlob(blob, hashes, false, contentType); + return createAssetBlob( + store -> store.create(sourceFile, headers, size, hashes.get(SHA1)), + hashes, + false, + contentType); } /** @@ -107,19 +117,26 @@ public AssetBlob createByCopying(final BlobId blobId, checkArgument(!Strings2.isBlank(headers.get(BlobStore.CONTENT_TYPE_HEADER)), "Blob content type is required"); // This might be a place where we might consider passing in a BlobRef instead of a BlobId, for a post-fabric world // where repositories could be writing/reading from multiple blob stores. - Blob blob = blobStore.copy(blobId, headers); - return createAssetBlob(blob, hashes, hashesVerified, headers.get(BlobStore.CONTENT_TYPE_HEADER)); + return createAssetBlob( + store -> store.copy(blobId, headers), + hashes, + hashesVerified, + headers.get(BlobStore.CONTENT_TYPE_HEADER)); } - private AssetBlob createAssetBlob(final Blob blob, + private AssetBlob createAssetBlob(final Function blobFunction, final Map hashes, final boolean hashesVerified, final String contentType) { - BlobRef blobRef = new BlobRef(nodeAccess.getId(), blobStore.getBlobStoreConfiguration().getName(), - blob.getId().asUniqueString()); - long bytes = blob.getMetrics().getContentSize(); - AssetBlob assetBlob = new AssetBlob(blobRef, blob, bytes, contentType, hashes, hashesVerified); + AssetBlob assetBlob = new AssetBlob( + nodeAccess, + blobStore, + blobFunction, + contentType, + hashes, + hashesVerified); + newlyCreatedBlobs.add(assetBlob); return assetBlob; } @@ -129,23 +146,23 @@ public Blob get(BlobRef blobRef) { return blobStore.get(blobRef.getBlobId()); } - public void delete(BlobRef blobRef) { - deletionRequests.add(blobRef); + public void delete(BlobRef blobRef, final String reason) { + deletionRequests.put(blobRef, reason); } public void commit() { - for (BlobRef blobRef : deletionRequests) { + for (Entry deletionRequestEntry : deletionRequests.entrySet()) { try { - blobStore.delete(blobRef.getBlobId()); + blobStore.delete(deletionRequestEntry.getKey().getBlobId(), deletionRequestEntry.getValue()); } catch (Throwable t) { - log.warn("Unable to delete old blob {} while committing transaction", blobRef, t); + log.warn("Unable to delete old blob {} while committing transaction", deletionRequestEntry.getKey(), t); } } for (AssetBlob assetBlob : newlyCreatedBlobs) { try { if (!assetBlob.isAttached()) { - blobStore.delete(assetBlob.getBlobRef().getBlobId()); + assetBlob.delete("Removing unattached asset"); } } catch (Throwable t) { @@ -158,7 +175,7 @@ public void commit() { public void rollback() { for (AssetBlob assetBlob : newlyCreatedBlobs) { try { - blobStore.delete(assetBlob.getBlobRef().getBlobId()); + assetBlob.delete("Rolling back new asset"); } catch (Throwable t) { log.warn("Unable to delete new blob {} while rolling back transaction", assetBlob.getBlobRef(), t); diff --git a/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/BucketDeleter.java b/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/BucketDeleter.java index 27fb2219f6..75ce967e19 100644 --- a/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/BucketDeleter.java +++ b/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/BucketDeleter.java @@ -177,7 +177,7 @@ private void deleteBlob(final Set deletedBlobStores, final BlobRef blobR } try { - blobStore.delete(blobRef.getBlobId()); + blobStore.delete(blobRef.getBlobId(), "Deleting Bucket"); } catch (InvalidStateException e) { if (deletedBlobStores.add(blobStoreName)) { diff --git a/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/MissingBlobException.java b/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/MissingBlobException.java index fe2f81fb2f..3eb2dda29b 100644 --- a/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/MissingBlobException.java +++ b/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/MissingBlobException.java @@ -22,7 +22,14 @@ public class MissingBlobException extends IllegalStateException { + private final BlobRef blobRef; + public MissingBlobException(final BlobRef blobRef) { super(String.format("Blob %s exists in metadata, but is missing from the blobstore", blobRef)); + this.blobRef = blobRef; + } + + public BlobRef getBlobRef() { + return blobRef; } } diff --git a/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/StorageTxImpl.java b/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/StorageTxImpl.java index 556dba62a0..b08e03ce99 100644 --- a/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/StorageTxImpl.java +++ b/components/nexus-repository/src/main/java/org/sonatype/nexus/repository/storage/StorageTxImpl.java @@ -18,6 +18,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import javax.annotation.Nonnull; @@ -58,6 +59,7 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static java.lang.String.format; import static org.sonatype.nexus.common.entity.EntityHelper.id; import static org.sonatype.nexus.repository.storage.Asset.CHECKSUM; import static org.sonatype.nexus.repository.storage.Asset.HASHES_NOT_VERIFIED; @@ -208,7 +210,7 @@ public boolean allowRetry(final Exception cause) throws RetryDeniedException { return true; } - String message = String.format("Reached max retries: %d/%d", retries, MAX_RETRIES); + String message = format("Reached max retries: %d/%d", retries, MAX_RETRIES); log.warn(message); throw new RetryDeniedException(message, cause); @@ -504,7 +506,7 @@ private void deleteAsset(final Asset asset, @Nullable final WritePolicy effectiv BlobRef blobRef = asset.blobRef(); if (blobRef != null) { - deleteBlob(blobRef, effectiveWritePolicy); + deleteBlob(blobRef, effectiveWritePolicy, format("Deleting asset %s", EntityHelper.id(asset))); } assetEntityAdapter.deleteEntity(db, asset); } @@ -631,71 +633,111 @@ public void attachBlob(final Asset asset, final AssetBlob assetBlob) throw new IllegalOperationException("Repository is read only: " + bucket.getRepositoryName()); } - if (!maybeDeleteBlob(asset, assetBlob, effectiveWritePolicy)) { - DateTime now = DateTime.now(); - asset.blobCreated(now); - asset.blobUpdated(now); - } + NestedAttributesMap checksums = asset.attributes().child(CHECKSUM); - asset.blobRef(assetBlob.getBlobRef()); - asset.size(assetBlob.getSize()); - asset.contentType(assetBlob.getContentType()); + if (!isDuplicateBlob(asset, assetBlob, effectiveWritePolicy, checksums)) { + maybeDeleteBlob(asset, effectiveWritePolicy); - // Set attributes map to contain computed checksum metadata - NestedAttributesMap checksums = asset.attributes().child(CHECKSUM); - for (HashAlgorithm algorithm : assetBlob.getHashes().keySet()) { - checksums.set(algorithm.name(), assetBlob.getHashes().get(algorithm).toString()); + asset.blobRef(assetBlob.getBlobRef()); + asset.size(assetBlob.getSize()); + asset.contentType(assetBlob.getContentType()); + + // Set attributes map to contain computed checksum metadata + for (Entry entry : assetBlob.getHashes().entrySet()) { + HashAlgorithm algorithm = entry.getKey(); + HashCode checksum = entry.getValue(); + checksums.set(algorithm.name(), checksum.toString()); + } + + // Mark assets whose checksums were not verified locally, for possible later verification + asset.attributes().child(PROVENANCE).set(HASHES_NOT_VERIFIED, !assetBlob.getHashesVerified()); + + assetBlob.setAttached(true); } + } - // Mark assets whose checksums were not verified locally, for possible later verification - asset.attributes().child(PROVENANCE).set(HASHES_NOT_VERIFIED, !assetBlob.getHashesVerified()); + /** + * Returns {@code true} when at least one incoming hash has the same algorithm as an existing checksum. + */ + private boolean checksumExists(final NestedAttributesMap checksums, final AssetBlob assetBlob) { + if (!checksums.isEmpty()) { + for (HashAlgorithm algorithm : assetBlob.getHashes().keySet()) { + if (checksums.contains(algorithm.name())) { + return true; + } + } + } + return false; + } - assetBlob.setAttached(true); + /** + * Returns {@code true} when incoming hashes all match existing checksums. + */ + private boolean compareChecksums(final NestedAttributesMap checksums, final AssetBlob assetBlob) { + for (Entry entry : assetBlob.getHashes().entrySet()) { + HashAlgorithm algorithm = entry.getKey(); + HashCode checksum = entry.getValue(); + if (!checksum.toString().equals(checksums.get(algorithm.name()))) { + return false; + } + } + return true; } /** - * Deletes the existing blob for the asset if one exists, updating the blob updated field if necessary. The - * write policy will be enforced for this operation and will throw an exception if updates are not supported. + * Checks whether incoming blob is a duplicate of existing asset blob; if so it re-uses the old blob. */ - private boolean maybeDeleteBlob(final Asset asset, + private boolean isDuplicateBlob(final Asset asset, final AssetBlob assetBlob, - final WritePolicy effectiveWritePolicy) + final WritePolicy effectiveWritePolicy, + final NestedAttributesMap checksums) { - checkNotNull(asset); - checkNotNull(assetBlob); - checkNotNull(effectiveWritePolicy); if (asset.blobRef() != null) { - if (!effectiveWritePolicy.checkUpdateAllowed()) { - throw new IllegalOperationException("Repository does not allow updating assets: " + bucket.getRepositoryName()); + Blob oldBlob = blobTx.get(asset.blobRef()); + if (oldBlob != null) { + boolean checksumsMatch; + if (assetBlob.getHashesVerified() && checksumExists(checksums, assetBlob)) { + // we have verified hashes, use those to avoid touching blob metrics + checksumsMatch = compareChecksums(checksums, assetBlob); + } + else { + // fall back to blob metrics, which involves fetching the new blob + String oldBlobSha1 = oldBlob.getMetrics().getSha1Hash(); + String newBlobSha1 = assetBlob.getBlob().getMetrics().getSha1Hash(); + checksumsMatch = oldBlobSha1.equalsIgnoreCase(newBlobSha1); + } + if (checksumsMatch) { + // still respect write policy even when de-duplicating + if (!effectiveWritePolicy.checkUpdateAllowed()) { + throw new IllegalOperationException( + "Repository does not allow updating assets: " + bucket.getRepositoryName()); + } + assetBlob.setDuplicate(oldBlob); + return true; + } } - maybeUpdateBlobUpdated(asset, assetBlob, DateTime.now()); - deleteBlob(asset.blobRef(), effectiveWritePolicy); - return true; } return false; } /** - * Updates the blob updated timestamp if the old blob and new blob do not share the same SHA1 hash. Assumes the blobs - * are different if the old blob has been lost for some reason. Note that this method only supports assets with a - * previously attached blob. + * Deletes the existing blob for the asset if one exists, updating the blob updated field if necessary. The + * write policy will be enforced for this operation and will throw an exception if updates are not supported. */ - private void maybeUpdateBlobUpdated(final Asset asset, final AssetBlob assetBlob, final DateTime now) { - checkNotNull(asset); - checkNotNull(assetBlob); - checkNotNull(now); - BlobRef oldBlobRef = checkNotNull(asset.blobRef()); - Blob oldBlob = blobTx.get(oldBlobRef); - if (oldBlob != null) { - String oldBlobSha1 = oldBlob.getMetrics().getSha1Hash(); - String newBlobSha1 = assetBlob.getBlob().getMetrics().getSha1Hash(); - if (!oldBlobSha1.equalsIgnoreCase(newBlobSha1)) { - asset.blobUpdated(now); + private void maybeDeleteBlob(final Asset asset, final WritePolicy effectiveWritePolicy) + { + DateTime now = DateTime.now(); + if (asset.blobRef() != null) { + // updating old blob + if (!effectiveWritePolicy.checkUpdateAllowed()) { + throw new IllegalOperationException("Repository does not allow updating assets: " + bucket.getRepositoryName()); } + asset.blobUpdated(now); + deleteBlob(asset.blobRef(), effectiveWritePolicy, format("Updating asset %s", EntityHelper.id(asset))); } else { - log.warn("Could not access attached blob for asset {} and blob ref {} in repository {}, assuming updated", asset, - oldBlobRef, bucket.getRepositoryName()); + // creating new blob + asset.blobCreated(now); asset.blobUpdated(now); } } @@ -825,13 +867,13 @@ private String determineContentType(final Supplier inputStreamSuppl /** * Deletes a blob w/ enforcing {@link WritePolicy} if not {@code null}. otherwise write policy will NOT be checked. */ - private void deleteBlob(final BlobRef blobRef, @Nullable WritePolicy effectiveWritePolicy) { + private void deleteBlob(final BlobRef blobRef, @Nullable WritePolicy effectiveWritePolicy, final String reason) { checkNotNull(blobRef); if (effectiveWritePolicy != null && !effectiveWritePolicy.checkDeleteAllowed()) { throw new IllegalOperationException( "Repository does not allow deleting assets: " + bucket.getRepositoryName()); } - blobTx.delete(blobRef); + blobTx.delete(blobRef, reason); } /** diff --git a/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/proxy/ProxyFacetSupportTest.java b/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/proxy/ProxyFacetSupportTest.java index 81a89fd84e..a23ca63431 100644 --- a/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/proxy/ProxyFacetSupportTest.java +++ b/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/proxy/ProxyFacetSupportTest.java @@ -24,6 +24,8 @@ import org.sonatype.nexus.repository.cache.CacheControllerHolder; import org.sonatype.nexus.repository.cache.CacheInfo; import org.sonatype.nexus.repository.httpclient.RemoteBlockedIOException; +import org.sonatype.nexus.repository.storage.MissingBlobException; +import org.sonatype.nexus.repository.storage.RetryDeniedException; import org.sonatype.nexus.repository.view.Content; import org.sonatype.nexus.repository.view.Context; @@ -206,4 +208,25 @@ public void testGet_IOException_thrownIfNotCached() throws IOException { underTest.get(missingContext); } + + @Test + public void testGet_MissingBlobException() throws IOException { + RetryDeniedException e = new RetryDeniedException("Denied", new MissingBlobException(null)); + doThrow(e).when(underTest).getCachedContent(cachedContext); + + doReturn(reFetchedContent).when(underTest).fetch(cachedContext, null); + doReturn(reFetchedContent).when(underTest).store(cachedContext, reFetchedContent); + + Content foundContent = underTest.get(cachedContext); + + assertThat(foundContent, is(reFetchedContent)); + } + + @Test(expected = RetryDeniedException.class) + public void testGet_differentRetryReason() throws IOException { + RetryDeniedException e = new RetryDeniedException("Denied", new IOException()); + doThrow(e).when(underTest).getCachedContent(cachedContext); + + underTest.get(cachedContext); + } } diff --git a/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/storage/BlobTxTest.groovy b/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/storage/BlobTxTest.groovy index d012f07ed2..01fc462cf8 100644 --- a/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/storage/BlobTxTest.groovy +++ b/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/storage/BlobTxTest.groovy @@ -74,7 +74,7 @@ class BlobTxTest assertThat(assetBlob.size, is(equalTo(blobSize))) assertThat(assetBlob.hashesVerified, is(true)) assertThat(assetBlob.hashes, hasEntry(SHA1, HashCode.fromString('6adfb183a4a2c94a2f92dab5ade762a47889a5a1'))) - assertThat(assetBlob.blob, is(blob)) + assertThat(assetBlob.ingestedBlob, is(blob)) } @Test @@ -112,7 +112,7 @@ class BlobTxTest assertThat(assetBlob.size, is(equalTo(blobSize))) assertThat(assetBlob.hashesVerified, is(false)) assertThat(assetBlob.hashes, hasEntry(SHA1, HashCode.fromString('356a192b7913b04c54574d18c28d46e6395428ab'))) - assertThat(assetBlob.blob, is(blob)) + assertThat(assetBlob.ingestedBlob, is(blob)) } @Test @@ -151,6 +151,6 @@ class BlobTxTest assertThat(assetBlob.size, is(equalTo(blobSize))) assertThat(assetBlob.hashesVerified, is(true)) assertThat(assetBlob.hashes, hasEntry(SHA1, HashCode.fromString('356a192b7913b04c54574d18c28d46e6395428ab'))) - assertThat(assetBlob.blob, is(blob)) + assertThat(assetBlob.ingestedBlob, is(blob)) } } diff --git a/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/storage/BucketDeleterTest.groovy b/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/storage/BucketDeleterTest.groovy index 52e6b2fa42..a0a458463f 100644 --- a/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/storage/BucketDeleterTest.groovy +++ b/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/storage/BucketDeleterTest.groovy @@ -116,7 +116,7 @@ class BucketDeleterTest componentsWithAssets.each { component -> verify(componentEntityAdapter).deleteEntity(db, component) } allAssets.each { asset -> verify(assetEntityAdapter).deleteEntity(db, asset) } - allBlobIds.each { blobId -> verify(blobStore).delete(blobId) } + allBlobIds.each { blobId -> verify(blobStore).delete(blobId, 'Deleting Bucket') } verify(bucketEntityAdapter).deleteEntity(db, bucket) verify(db, times(8)).commit() } @@ -134,7 +134,7 @@ class BucketDeleterTest underTest.deleteBucket(bucket) assets.each { asset -> verify(assetEntityAdapter).deleteEntity(db, asset) } - verify(blobStore, never()).delete(any(BlobId)) + verify(blobStore, never()).delete(any(BlobId), any(String)) verify(bucketEntityAdapter).deleteEntity(db, bucket) verify(db, times(4)).commit() } @@ -146,14 +146,14 @@ class BucketDeleterTest List assets = blobRefs.collect { blobRef -> mockAsset(blobRef) } when(blobStoreManager.get(BLOB_STORE_NAME)).thenReturn(blobStore) - doThrow(new InvalidStateException(STOPPED, STARTED)).when(blobStore).delete(any(BlobId)) + doThrow(new InvalidStateException(STOPPED, STARTED)).when(blobStore).delete(any(BlobId), any(String)) when(componentEntityAdapter.browseByBucket(db, bucket)).thenReturn([]) when(assetEntityAdapter.browseByBucket(db, bucket)).thenReturn(assets) underTest.deleteBucket(bucket) assets.each { asset -> verify(assetEntityAdapter).deleteEntity(db, asset) } - verify(blobStore, times(1)).delete(any(BlobId)) + verify(blobStore, times(1)).delete(any(BlobId), any(String)) verify(bucketEntityAdapter).deleteEntity(db, bucket) verify(db, times(4)).commit() } @@ -165,13 +165,13 @@ class BucketDeleterTest List assets = blobRefs.collect { blobRef -> mockAsset(blobRef) } when(blobStoreManager.get(BLOB_STORE_NAME)).thenReturn(blobStore) - doThrow(new RuntimeException()).when(blobStore).delete(any(BlobId)) + doThrow(new RuntimeException()).when(blobStore).delete(any(BlobId), any(String)) when(componentEntityAdapter.browseByBucket(db, bucket)).thenReturn([]) when(assetEntityAdapter.browseByBucket(db, bucket)).thenReturn(assets) underTest.deleteBucket(bucket) - blobIds.each { blobId -> verify(blobStore).delete(blobId) } + blobIds.each { blobId -> verify(blobStore).delete(blobId, 'Deleting Bucket') } assets.each { asset -> verify(assetEntityAdapter).deleteEntity(db, asset) } verify(bucketEntityAdapter).deleteEntity(db, bucket) verify(db, times(4)).commit() diff --git a/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/storage/StorageTxImplTest.groovy b/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/storage/StorageTxImplTest.groovy index 31ce72450c..2fb72abc9f 100644 --- a/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/storage/StorageTxImplTest.groovy +++ b/components/nexus-repository/src/test/java/org/sonatype/nexus/repository/storage/StorageTxImplTest.groovy @@ -18,6 +18,8 @@ import org.sonatype.nexus.blobstore.api.BlobMetrics import org.sonatype.nexus.blobstore.api.BlobRef import org.sonatype.nexus.blobstore.api.BlobStore import org.sonatype.nexus.common.collect.NestedAttributesMap +import org.sonatype.nexus.common.entity.EntityId +import org.sonatype.nexus.common.entity.EntityMetadata import org.sonatype.nexus.common.hash.HashAlgorithm import org.sonatype.nexus.mime.MimeRulesSource import org.sonatype.nexus.repository.IllegalOperationException @@ -69,6 +71,10 @@ extends TestSupport private AssetEntityAdapter assetEntityAdapter @Mock private Asset asset + @Mock + private EntityMetadata entityMetadata; + @Mock + private EntityId entityId; private Supplier supplier = new Supplier(){ @Override @@ -84,6 +90,9 @@ extends TestSupport @Before void prepare() { + when(asset.getEntityMetadata()).thenReturn(entityMetadata); + when(entityMetadata.getId()).thenReturn(entityId); + when(defaultContentValidator.determineContentType(anyBoolean(), any(Supplier), eq(MimeRulesSource.NOOP), anyString(), anyString())).thenReturn("text/plain") when(db.getTransaction()).thenReturn(tx) } @@ -108,7 +117,7 @@ extends TestSupport assertThat 'Expected IllegalOperationException', false } catch (IllegalOperationException e) {} - verify(blobTx, never()).delete(any(BlobRef)) + verify(blobTx, never()).delete(any(BlobRef), any(String)) verify(assetEntityAdapter, never()).deleteEntity(db, asset) } @@ -161,7 +170,7 @@ extends TestSupport def blobRef = mock(BlobRef) when(asset.blobRef()).thenReturn(blobRef) new StorageTxImpl('test', blobTx, db, bucket, writePolicy, WritePolicySelector.DEFAULT, bucketEntityAdapter, componentEntityAdapter, assetEntityAdapter, false, defaultContentValidator, MimeRulesSource.NOOP).deleteAsset(asset) - verify(blobTx, times(1)).delete(blobRef) + verify(blobTx, times(1)).delete(eq(blobRef), any(String)) verify(assetEntityAdapter, times(1)).deleteEntity(db, asset) } @@ -189,7 +198,7 @@ extends TestSupport assertThat 'Expected IllegalOperationException', false } catch (IllegalOperationException e) {} - verify(blobTx, never()).delete(any(BlobRef)) + verify(blobTx, never()).delete(any(BlobRef), any(String)) verify(blobTx, never()).create(any(InputStream), any(Map), any(Iterable), anyString()) verify(asset, never()).blobRef(any(BlobRef)) } @@ -213,7 +222,7 @@ extends TestSupport assertThat 'Expected IllegalOperationException', false } catch (IllegalOperationException e) {} - verify(blobTx, never()).delete(any(BlobRef)) + verify(blobTx, never()).delete(any(BlobRef), any(String)) verify(blobTx, never()).create(any(InputStream), any(Map), any(Iterable), anyString()) verify(asset, never()).blobRef(any(BlobRef)) } @@ -244,7 +253,7 @@ extends TestSupport assertThat 'Expected IllegalOperationException', false } catch (IllegalOperationException e) {} - verify(blobTx, never()).delete(any(BlobRef)) + verify(blobTx, never()).delete(any(BlobRef), any(String)) verify(blobTx, never()).create(any(InputStream), any(Map), any(Iterable), anyString()) verify(asset, never()).blobRef(any(BlobRef)) } @@ -298,7 +307,7 @@ extends TestSupport when(blobTx.create(any(InputStream), any(Map), any(Iterable), eq(ContentTypes.TEXT_PLAIN))).thenReturn(newAssetBlob) def underTest = new StorageTxImpl('test', blobTx, db, bucket, WritePolicy.ALLOW, WritePolicySelector.DEFAULT, bucketEntityAdapter, componentEntityAdapter, assetEntityAdapter, false, defaultContentValidator, MimeRulesSource.NOOP) underTest.setBlob(asset, 'testBlob.txt', supplier, hashAlgorithms, headers, 'text/plain', false) - verify(blobTx, times(1)).delete(blobRef) + verify(blobTx, times(1)).delete(eq(blobRef), any(String)) verify(blobTx, times(1)).create(any(InputStream), eq(expectedHeaders), any(Iterable), eq(ContentTypes.TEXT_PLAIN)) verify(asset, times(1)).blobRef(newBlobRef) } diff --git a/components/nexus-rest-client/pom.xml b/components/nexus-rest-client/pom.xml index b899aff876..cf7d5f4b06 100644 --- a/components/nexus-rest-client/pom.xml +++ b/components/nexus-rest-client/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-rest-client diff --git a/components/nexus-rest-jackson2/pom.xml b/components/nexus-rest-jackson2/pom.xml index 21e93491de..6332b8ffba 100644 --- a/components/nexus-rest-jackson2/pom.xml +++ b/components/nexus-rest-jackson2/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-rest-jackson2 diff --git a/components/nexus-rest/pom.xml b/components/nexus-rest/pom.xml index a4081bd09b..147a21d7e5 100644 --- a/components/nexus-rest/pom.xml +++ b/components/nexus-rest/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-rest diff --git a/components/nexus-scheduling/pom.xml b/components/nexus-scheduling/pom.xml index fcd00ea6c8..b75573394e 100644 --- a/components/nexus-scheduling/pom.xml +++ b/components/nexus-scheduling/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-scheduling diff --git a/components/nexus-script/pom.xml b/components/nexus-script/pom.xml index 8fb16dd66c..c88f9bf592 100644 --- a/components/nexus-script/pom.xml +++ b/components/nexus-script/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-script diff --git a/components/nexus-security/pom.xml b/components/nexus-security/pom.xml index 2d7977c6d3..0ca3410479 100644 --- a/components/nexus-security/pom.xml +++ b/components/nexus-security/pom.xml @@ -21,7 +21,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-security diff --git a/components/nexus-selector/pom.xml b/components/nexus-selector/pom.xml index 51669cf9f3..b6de3f0bb6 100644 --- a/components/nexus-selector/pom.xml +++ b/components/nexus-selector/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-selector diff --git a/components/nexus-servlet/pom.xml b/components/nexus-servlet/pom.xml index 6378fe0901..fc99a54fe1 100644 --- a/components/nexus-servlet/pom.xml +++ b/components/nexus-servlet/pom.xml @@ -19,7 +19,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-servlet diff --git a/components/nexus-siesta/pom.xml b/components/nexus-siesta/pom.xml index 37844aa825..78256dafbe 100644 --- a/components/nexus-siesta/pom.xml +++ b/components/nexus-siesta/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-siesta diff --git a/components/nexus-ssl/pom.xml b/components/nexus-ssl/pom.xml index 78eac679f6..5120a6b8bb 100644 --- a/components/nexus-ssl/pom.xml +++ b/components/nexus-ssl/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-ssl diff --git a/components/nexus-supportzip-api/pom.xml b/components/nexus-supportzip-api/pom.xml index c8963fc67b..15d60347af 100644 --- a/components/nexus-supportzip-api/pom.xml +++ b/components/nexus-supportzip-api/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-supportzip-api diff --git a/components/nexus-swagger/pom.xml b/components/nexus-swagger/pom.xml index 5fae0d200c..76cb63a972 100644 --- a/components/nexus-swagger/pom.xml +++ b/components/nexus-swagger/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-swagger diff --git a/components/nexus-test-common/pom.xml b/components/nexus-test-common/pom.xml index 8734cbfed9..f0293158f1 100644 --- a/components/nexus-test-common/pom.xml +++ b/components/nexus-test-common/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-test-common diff --git a/components/nexus-thread/pom.xml b/components/nexus-thread/pom.xml index 39565ae664..bcd7a81208 100644 --- a/components/nexus-thread/pom.xml +++ b/components/nexus-thread/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-thread diff --git a/components/nexus-transaction/pom.xml b/components/nexus-transaction/pom.xml index f9df8d4289..5c6f55d59d 100644 --- a/components/nexus-transaction/pom.xml +++ b/components/nexus-transaction/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-transaction diff --git a/components/nexus-upgrade/pom.xml b/components/nexus-upgrade/pom.xml index 75d1a331fc..e62c5f7787 100644 --- a/components/nexus-upgrade/pom.xml +++ b/components/nexus-upgrade/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-upgrade diff --git a/components/nexus-validation/pom.xml b/components/nexus-validation/pom.xml index 126e764962..435123e53c 100644 --- a/components/nexus-validation/pom.xml +++ b/components/nexus-validation/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-validation diff --git a/components/nexus-webhooks/pom.xml b/components/nexus-webhooks/pom.xml index a6c7d8800d..8461f4d0d7 100644 --- a/components/nexus-webhooks/pom.xml +++ b/components/nexus-webhooks/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-webhooks diff --git a/components/nexus-webresources-api/pom.xml b/components/nexus-webresources-api/pom.xml index d708fda039..f5d99ed202 100644 --- a/components/nexus-webresources-api/pom.xml +++ b/components/nexus-webresources-api/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-components - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-webresources-api diff --git a/components/pom.xml b/components/pom.xml index 65a8ef78ec..a7f0fd7c0d 100644 --- a/components/pom.xml +++ b/components/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-parent - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-components @@ -89,7 +89,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-all pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -97,7 +97,7 @@ org.sonatype.nexus.bundles nexus-thirdparty-bundles pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import diff --git a/plugins/nexus-audit-plugin/pom.xml b/plugins/nexus-audit-plugin/pom.xml index 654d453b0a..936977b90a 100644 --- a/plugins/nexus-audit-plugin/pom.xml +++ b/plugins/nexus-audit-plugin/pom.xml @@ -21,7 +21,7 @@ org.sonatype.nexus.plugins nexus-plugins - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-audit-plugin diff --git a/plugins/nexus-coreui-plugin/pom.xml b/plugins/nexus-coreui-plugin/pom.xml index a8ab2cc1d4..4e720feffe 100644 --- a/plugins/nexus-coreui-plugin/pom.xml +++ b/plugins/nexus-coreui-plugin/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.plugins nexus-plugins - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-coreui-plugin diff --git a/plugins/nexus-repository-httpbridge/pom.xml b/plugins/nexus-repository-httpbridge/pom.xml index d56adbcd1f..100390208d 100644 --- a/plugins/nexus-repository-httpbridge/pom.xml +++ b/plugins/nexus-repository-httpbridge/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.plugins nexus-plugins - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-repository-httpbridge diff --git a/plugins/nexus-repository-maven/pom.xml b/plugins/nexus-repository-maven/pom.xml index 666f228bde..4693d8ece7 100644 --- a/plugins/nexus-repository-maven/pom.xml +++ b/plugins/nexus-repository-maven/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.plugins nexus-plugins - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-repository-maven diff --git a/plugins/nexus-repository-maven/src/main/java/org/sonatype/nexus/repository/maven/internal/MavenFacetImpl.java b/plugins/nexus-repository-maven/src/main/java/org/sonatype/nexus/repository/maven/internal/MavenFacetImpl.java index 123a7ddf0f..4f93225430 100644 --- a/plugins/nexus-repository-maven/src/main/java/org/sonatype/nexus/repository/maven/internal/MavenFacetImpl.java +++ b/plugins/nexus-repository-maven/src/main/java/org/sonatype/nexus/repository/maven/internal/MavenFacetImpl.java @@ -308,6 +308,7 @@ private Asset putArtifact(final StorageTx tx, final Coordinates coordinates = checkNotNull(path.getCoordinates()); final Bucket bucket = tx.findBucket(getRepository()); Component component = findComponent(tx, getRepository(), path); + boolean updatePomModel = false; if (component == null) { // Create and set top-level properties component = tx.createComponent(bucket, getRepository().getFormat()) @@ -327,8 +328,9 @@ private Asset putArtifact(final StorageTx tx, tx.saveComponent(component); } else if (path.isPom()) { - fillInFromModel(path, assetBlob, component.formatAttributes()); - tx.saveComponent(component); + // reduce copying by deferring update of pom.xml attributes (which involves reading the blob) + // until after putAssetPayload, in case the blob is a duplicate and the model has not changed + updatePomModel = true; } Asset asset = findAsset(tx, bucket, path); @@ -354,6 +356,12 @@ else if (path.isPom()) { asset.markAsDownloaded(); tx.saveAsset(asset); + // avoid re-reading pom.xml if it's a duplicate of the old asset + if (updatePomModel && !assetBlob.isDuplicate()) { + fillInFromModel(path, assetBlob, component.formatAttributes()); + tx.saveComponent(component); + } + return asset; } diff --git a/plugins/nexus-repository-raw/pom.xml b/plugins/nexus-repository-raw/pom.xml index 2d48314a52..7495522731 100644 --- a/plugins/nexus-repository-raw/pom.xml +++ b/plugins/nexus-repository-raw/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.plugins nexus-plugins - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-repository-raw diff --git a/plugins/nexus-script-plugin/pom.xml b/plugins/nexus-script-plugin/pom.xml index 60be8557a4..bc0adada29 100644 --- a/plugins/nexus-script-plugin/pom.xml +++ b/plugins/nexus-script-plugin/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.plugins nexus-plugins - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-script-plugin diff --git a/plugins/nexus-ssl-plugin/pom.xml b/plugins/nexus-ssl-plugin/pom.xml index 2688d885ac..7204aef408 100644 --- a/plugins/nexus-ssl-plugin/pom.xml +++ b/plugins/nexus-ssl-plugin/pom.xml @@ -21,7 +21,7 @@ org.sonatype.nexus.plugins nexus-plugins - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT nexus-ssl-plugin diff --git a/plugins/pom.xml b/plugins/pom.xml index 57ed7fa69f..7b5a2831a4 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-parent - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus.plugins @@ -47,7 +47,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-all pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -58,13 +58,13 @@ org.sonatype.nexus.plugins nexus-audit-plugin - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus.plugins nexus-audit-plugin - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT features xml @@ -74,13 +74,13 @@ org.sonatype.nexus.plugins nexus-coreui-plugin - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus.plugins nexus-coreui-plugin - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT features xml @@ -89,7 +89,7 @@ org.sonatype.nexus.plugins nexus-coreui-plugin sources - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT @@ -97,13 +97,13 @@ org.sonatype.nexus.plugins nexus-repository-httpbridge - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus.plugins nexus-repository-httpbridge - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT features xml @@ -113,13 +113,13 @@ org.sonatype.nexus.plugins nexus-repository-maven - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus.plugins nexus-repository-maven - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT features xml @@ -129,13 +129,13 @@ org.sonatype.nexus.plugins nexus-repository-raw - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus.plugins nexus-repository-raw - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT features xml @@ -145,13 +145,13 @@ org.sonatype.nexus.plugins nexus-ssl-plugin - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus.plugins nexus-ssl-plugin - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT features xml @@ -161,13 +161,13 @@ org.sonatype.nexus.plugins nexus-script-plugin - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus.plugins nexus-script-plugin - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT features xml diff --git a/pom.xml b/pom.xml index 22b03688fa..c896d0b61a 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ ${project.groupId}:${project.artifactId} pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT 2008 http://nexus.sonatype.org/ @@ -88,7 +88,7 @@ Define nexus versions. The 'nexus.version' property always refers to the version of the current project. These values must always be constants; 'nexus.version' will get update automatically by set-version. --> - 3.3.0-SNAPSHOT + 3.3.0-01 INFO @@ -141,163 +141,163 @@ org.sonatype.nexus nexus-analytics-api - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-audit - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-base - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-blobstore-api - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-blobstore-file - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-bootstrap - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-capability - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-commands - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-common - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-core - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-crypto - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-orient - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-orient-console - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-cache - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-elasticsearch - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-email - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-extdirect - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-extender - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-httpclient - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-jmx - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-scheduling - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-formfields - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-guice-servlet - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-main - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-mime - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-oss-edition - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-oss-edition - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT features xml @@ -305,140 +305,140 @@ org.sonatype.nexus nexus-pax-logging - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-plugin-api - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-quartz - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-rapture - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-rapture - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT sources org.sonatype.nexus nexus-repository - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-rest - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-rest-client - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-rest-jackson2 - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-script - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-security - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-selector - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-servlet - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-siesta - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-ssl - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-supportzip-api - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-swagger - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-thread - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-transaction - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-upgrade - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-validation - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-webhooks - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-webresources-api - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT @@ -446,13 +446,13 @@ org.sonatype.nexus nexus-pax-exam - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus nexus-test-common - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT @@ -460,7 +460,7 @@ org.sonatype.nexus.assemblies nexus-startup-feature - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT features xml @@ -468,7 +468,7 @@ org.sonatype.nexus.assemblies nexus-boot-feature - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT features xml @@ -476,7 +476,7 @@ org.sonatype.nexus.assemblies nexus-base-feature - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT features xml @@ -484,7 +484,7 @@ org.sonatype.nexus.assemblies nexus-core-feature - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT features xml @@ -492,7 +492,7 @@ org.sonatype.nexus.assemblies nexus-base-template - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT zip @@ -764,7 +764,7 @@ org.sonatype.nexus.buildsupport extjs-maven-plugin - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT diff --git a/revision.txt b/revision.txt index 646e20d517..5d5610558b 100644 --- a/revision.txt +++ b/revision.txt @@ -1 +1 @@ -b=master,r=d2a592382fa343d6cd13c45b69a9edffe39c68c1,t=2017-04-07-1629-26139 \ No newline at end of file +b=3.3.1-release-branch,r=5b4aa3b1cb7aa5f63c971f1a462689a502615595,t=2017-04-27-1557-35442 \ No newline at end of file diff --git a/thirdparty-bundles/elasticsearch/pom.xml b/thirdparty-bundles/elasticsearch/pom.xml index 230fc96172..006a511628 100644 --- a/thirdparty-bundles/elasticsearch/pom.xml +++ b/thirdparty-bundles/elasticsearch/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus.bundles nexus-thirdparty-bundles - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus.bundles.elasticsearch diff --git a/thirdparty-bundles/pom.xml b/thirdparty-bundles/pom.xml index 85d31bec18..59f87110a1 100644 --- a/thirdparty-bundles/pom.xml +++ b/thirdparty-bundles/pom.xml @@ -20,7 +20,7 @@ org.sonatype.nexus nexus-parent - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT org.sonatype.nexus.bundles @@ -41,7 +41,7 @@ org.sonatype.nexus.buildsupport nexus-buildsupport-all pom - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT import @@ -50,7 +50,7 @@ org.sonatype.nexus.bundles org.sonatype.nexus.bundles.elasticsearch - 3.3.0-SNAPSHOT + 3.3.1-SNAPSHOT