NOTE: This article is for the legacy blob store layout only (3.82 and older).
Nexus Repository 3 stores blobs in a blobstore at a generated path location which is derived from the unique blob id.
Given you only have a native blobstore blob ID value, you can programmatically determine the relative blob path to the blob asset.
The logic to generate the path, excluding the file extension, inside a native blobstore is isolated to one class file:
/*
* 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;
import org.sonatype.nexus.blobstore.api.BlobId;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Stores blobs in a two-deep directory tree.
*
* The first layer, {@code vol}, having {@link #TIER_1_MODULO} directories,
* and the second {@code chap} having {@link #TIER_2_MODULO}.
*
* @since 3.0
*/
public class VolumeChapterLocationStrategy
extends LocationStrategySupport
{
private static final int TIER_1_MODULO = 43;
private static final int TIER_2_MODULO = 47;
@Override
public String location(final BlobId blobId) {
checkNotNull(blobId);
return String.format("vol-%02d/chap-%02d/%s",
tier(blobId, TIER_1_MODULO),
tier(blobId, TIER_2_MODULO),
escapeFilename(blobId.asUniqueString())
);
}
private int tier(final BlobId blobId, final int modulo) {
return Math.abs(blobId.hashCode() % modulo) + 1;
}
}
Sample Bash/Groovy Script Equivalent
Here is a sample Bash script invoking Java(Groovy) code that can convert Blob ID into a Blob Store Blob Paths:
#!/bin/bash
# input NXRM blob ID, output blobstore two deep dir, blob path location in the blobstore
# When viewing the asset in the UI, you may see a Blob reference of this form:
# npmjs@261713CC-58FF7EA7-0A42ABB7-153BCDD2-6528D0EE:c3b7d5e2-1d51-450f-aa5e-319cada6d973
#
# When querying an <format>_asset_blob table in PostgreSQl, there is a blob_ref column with the values reversed as:
# npmjs:c3b7d5e2-1d51-450f-aa5e-319cada6d973@261713CC-58FF7EA7-0A42ABB7-153BCDD2-6528D0EE
#
# Feed into this script the value after the colon ":" which is c3b7d5e2-1d51-450f-aa5e-319cada6d973
# The value after the colon is the Blob ID.
# result from
# > toblobstorelocationfromblobuuid.bash c3b7d5e2-1d51-450f-aa5e-319cada6d973
# is
# hashCode=1682551340,tier1=41,tier2=33
# vol-41/chap-33/c3b7d5e2-1d51-450f-aa5e-319cada6d973.bytes
# vol-41/chap-33/c3b7d5e2-1d51-450f-aa5e-319cada6d973.properties
# logic here replicates that in org.sonatype.nexus.blobstore.VolumeChapterLocationStrategy
groovy -e "new GroovyShell().evaluate(System.in.text)" <<EOF
def hc = '${1}'.hashCode()
def t1 = Math.abs(hc % 43) + 1
def t2 = Math.abs(hc % 47) + 1
println 'hashCode=' + hc + ',tier1=' + t1 + ',tier2=' + t2
def p = String.format('vol-%02d/chap-%02d/%s', t1, t2, '${1}')
println p + '.bytes'
println p + '.properties'
EOF