Author: chetanm
Date: Wed Mar 26 08:03:45 2014
New Revision: 1581730
URL: http://svn.apache.org/r1581730
Log:
OAK-1604 - Support for signed references in Blob (WIP)
Initialize referenceKey upon first use
Modified:
jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStore.java
Modified:
jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStore.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStore.java?rev=1581730&r1=1581729&r2=1581730&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStore.java
(original)
+++
jackrabbit/oak/trunk/oak-blob/src/main/java/org/apache/jackrabbit/oak/spi/blob/AbstractBlobStore.java
Wed Mar 26 08:03:45 2014
@@ -27,6 +27,7 @@ import java.lang.ref.WeakReference;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
@@ -49,6 +50,7 @@ import org.apache.jackrabbit.oak.commons
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
/**
@@ -186,12 +188,14 @@ public abstract class AbstractBlobStore
return new BlobStoreInputStream(this, blobId, 0);
}
+ //--------------------------------------------< Blob Reference >
+
@Override
public String getReference(String blobId) {
checkNotNull(blobId, "BlobId must be specified");
try {
Mac mac = Mac.getInstance(ALGORITHM);
- mac.init(new SecretKeySpec(referenceKey, ALGORITHM));
+ mac.init(new SecretKeySpec(getReferenceKey(), ALGORITHM));
byte[] hash = mac.doFinal(blobId.getBytes("UTF-8"));
return blobId + ':' + BaseEncoding.base32Hex().encode(hash);
} catch (NoSuchAlgorithmException e) {
@@ -218,7 +222,43 @@ public abstract class AbstractBlobStore
return null;
}
+ /**
+ * Returns the reference key of this blob store. If one does not already
+ * exist, it is automatically created in an implementation-specific way.
+ * The default implementation simply creates a temporary random key that's
+ * valid only until the data store gets restarted. Subclasses can override
+ * and/or decorate this method to support a more persistent reference key.
+ * <p>
+ * This method is called only once during the lifetime of a data store
+ * instance and the return value is cached in memory, so it's no problem
+ * if the implementation is slow.
+ *
+ * @return reference key
+ */
+ protected byte[] getOrCreateReferenceKey() {
+ byte[] referenceKeyValue = new byte[256];
+ new SecureRandom().nextBytes(referenceKeyValue);
+ log.info("Reference key is not specified for the BlobStore in use.
Generating a random key. For stable " +
+ "reference ensure that reference key is specified");
+ return referenceKeyValue;
+ }
+
+ /**
+ * Returns the reference key of this data store. Synchronized to
+ * control concurrent access to the cached {@link #referenceKey} value.
+ *
+ * @return reference key
+ */
+ private synchronized byte[] getReferenceKey() {
+ if (referenceKey == null) {
+ referenceKey = getOrCreateReferenceKey();
+ }
+ return referenceKey;
+ }
+
public void setReferenceKey(byte[] referenceKey) {
+ checkArgument(referenceKey == null, "Reference key already initialized
by default means. " +
+ "To explicitly set it, setReferenceKey must be invoked before
its first use");
this.referenceKey = referenceKey;
}
@@ -227,7 +267,7 @@ public abstract class AbstractBlobStore
* @param encodedKey base64 encoded key
*/
public void setReferenceKeyEncoded(String encodedKey) {
- this.referenceKey = BaseEncoding.base64().decode(encodedKey);
+ setReferenceKey(BaseEncoding.base64().decode(encodedKey));
}
/**
@@ -243,7 +283,7 @@ public abstract class AbstractBlobStore
* @see org.apache.jackrabbit.oak.commons.PropertiesUtil#populate(Object,
java.util.Map, boolean)
*/
public void setReferenceKeyPlainText(String textKey) {
- this.referenceKey = textKey.getBytes(Charsets.UTF_8);
+ setReferenceKey(textKey.getBytes(Charsets.UTF_8));
}
protected void usesBlobId(String blobId) {