You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fm...@apache.org on 2014/03/24 13:49:01 UTC

svn commit: r1580826 - in /chemistry/opencmis/trunk: chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/ chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemi...

Author: fmui
Date: Mon Mar 24 12:49:00 2014
New Revision: 1580826

URL: http://svn.apache.org/r1580826
Log:
added support for CMIS extension: content stream hash 

Added:
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java   (with props)
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java   (with props)
Modified:
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java
    chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java
    chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java?rev=1580826&r1=1580825&r2=1580826&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java Mon Mar 24 12:49:00 2014
@@ -18,6 +18,10 @@
  */
 package org.apache.chemistry.opencmis.client.api;
 
+import java.util.List;
+
+import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
+
 /**
  * Accessors to CMIS document properties.
  * 
@@ -204,4 +208,16 @@ public interface DocumentProperties {
      * @cmis 1.0
      */
     String getContentStreamId();
+
+    /**
+     * Returns the content hashes or {@code null} if the document has no content
+     * (CMIS property {@code cmis:contentStreamHash}).
+     * 
+     * @return the list of content hashes or {@code null} if the property hasn't
+     *         been requested, hasn't been provided by the repository, or the
+     *         document has no content
+     * 
+     * @cmis Extension
+     */
+    List<ContentStreamHash> getContentStreamHashes();
 }

Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java?rev=1580826&r1=1580825&r2=1580826&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java Mon Mar 24 12:49:00 2014
@@ -38,6 +38,7 @@ import org.apache.chemistry.opencmis.cli
 import org.apache.chemistry.opencmis.commons.PropertyIds;
 import org.apache.chemistry.opencmis.commons.data.Ace;
 import org.apache.chemistry.opencmis.commons.data.ContentStream;
+import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
 import org.apache.chemistry.opencmis.commons.data.ObjectData;
 import org.apache.chemistry.opencmis.commons.data.PartialContentStream;
 import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
@@ -46,6 +47,7 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.enums.VersioningState;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamHashImpl;
 import org.apache.chemistry.opencmis.commons.spi.Holder;
 
 public class DocumentImpl extends AbstractFilableCmisObject implements Document {
@@ -122,6 +124,20 @@ public class DocumentImpl extends Abstra
         return getPropertyValue(PropertyIds.CONTENT_STREAM_ID);
     }
 
+    public List<ContentStreamHash> getContentStreamHashes() {
+        List<String> hashes = getPropertyValue(PropertyIds.CONTENT_STREAM_HASH);
+        if (hashes == null || hashes.size() == 0) {
+            return null;
+        }
+
+        List<ContentStreamHash> result = new ArrayList<ContentStreamHash>(hashes.size());
+        for (String hash : hashes) {
+            result.add(new ContentStreamHashImpl(hash));
+        }
+
+        return result;
+    }
+
     // operations
 
     public Document copy(ObjectId targetFolderId, Map<String, ?> properties, VersioningState versioningState,

Modified: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java?rev=1580826&r1=1580825&r2=1580826&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java Mon Mar 24 12:49:00 2014
@@ -343,7 +343,7 @@ public final class PropertyIds {
      */
     public static final String POLICY_TEXT = "cmis:policyText";
 
-    // ---- retention ---
+    // ---- retention ----
     /**
      * CMIS retention property {@code cmis:rm_expirationDate}: expiration date.
      * <p>
@@ -382,4 +382,16 @@ public final class PropertyIds {
      * @cmis 1.1
      */
     public static final String HOLD_IDS = "cmis:rm_holdIds";
+
+    // ---- extensions ----
+    /**
+     * Content Hash property {@code cmis:contentStreamHash} (multivalue): hashes
+     * of the content stream
+     * <p>
+     * CMIS data type: string<br>
+     * Java type: String
+     * 
+     * @cmis Extension
+     */
+    public static final String CONTENT_STREAM_HASH = "cmis:contentStreamHash";
 }

Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java?rev=1580826&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java Mon Mar 24 12:49:00 2014
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.chemistry.opencmis.commons.data;
+
+/**
+ * Content hash.
+ */
+public interface ContentStreamHash {
+
+    /**
+     * Returns the content hash property value ({@code cmis:contentStreamHash}).
+     * 
+     * @return the content hash property value
+     */
+    String getPropertyValue();
+
+    /**
+     * Returns the hash algorithm.
+     * 
+     * @return the hash algorithm or {@code null} if the property value is
+     *         invalid
+     */
+    String getAlgorithm();
+
+    /**
+     * Returns the hash value.
+     * 
+     * @return the hash value or {@code null} if the property value is invalid
+     */
+    String getHash();
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java?rev=1580826&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java Mon Mar 24 12:49:00 2014
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.chemistry.opencmis.commons.impl.dataobjects;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
+
+public class ContentStreamHashImpl implements ContentStreamHash {
+
+    public static final String ALGORITHM_MD5 = "md5";
+    public static final String ALGORITHM_SHA1 = "sha-1";
+    public static final String ALGORITHM_SHA224 = "sha-224";
+    public static final String ALGORITHM_SHA256 = "sha-256";
+    public static final String ALGORITHM_SHA384 = "sha-384";
+    public static final String ALGORITHM_SHA512 = "sha-512";
+    public static final String ALGORITHM_SHA3 = "sha-3";
+
+    private final static char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
+
+    private String propertyValue;
+    private String algorithm = null;
+    private String hash = null;
+
+    /**
+     * Constructs an object without values.
+     */
+    public ContentStreamHashImpl() {
+    }
+
+    /**
+     * Constructs an object from the {@code cmis:contentStreamHash} property
+     * value.
+     * 
+     * @param propertyValue
+     *            the property value
+     */
+    public ContentStreamHashImpl(String propertyValue) {
+        this.propertyValue = propertyValue;
+
+        if (propertyValue == null) {
+            return;
+        }
+
+        String pv = propertyValue.trim();
+        int algEnd = pv.indexOf('}');
+        if (pv.charAt(0) != '{' || algEnd < 1) {
+            return;
+        }
+
+        this.algorithm = pv.substring(1, algEnd).toLowerCase(Locale.ENGLISH);
+        this.hash = pv.substring(algEnd + 1).replaceAll("\\s", "").toLowerCase(Locale.ENGLISH);
+    }
+
+    /**
+     * Constructs an object from the algorithm and hash.
+     * 
+     * @param algorithm
+     *            the algorithm
+     * @param hash
+     *            the hash value
+     */
+    public ContentStreamHashImpl(String algorithm, String hash) {
+        if (algorithm == null || algorithm.trim().length() == 0) {
+            throw new IllegalArgumentException("Algorithm must be set!");
+        }
+
+        if (hash == null || hash.trim().length() == 0) {
+            throw new IllegalArgumentException("Hash must be set!");
+        }
+
+        this.algorithm = algorithm.toLowerCase(Locale.ENGLISH);
+        this.hash = hash.replaceAll("\\s", "").toLowerCase(Locale.ENGLISH);
+        this.propertyValue = "{" + algorithm + "}" + hash;
+    }
+
+    public String getPropertyValue() {
+        return propertyValue;
+    }
+
+    public String getAlgorithm() {
+        return algorithm;
+    }
+
+    public String getHash() {
+        return hash;
+    }
+
+    /**
+     * Creates a list of content hashes from a stream
+     * <p>
+     * This method consumes the stream but doesn't close it.
+     * 
+     * @param stream
+     *            the stream
+     * @param algorithm
+     *            the algorithms
+     * @return the list of content hashes
+     */
+    public static List<ContentStreamHash> createContentHashes(InputStream stream, String... algorithm)
+            throws IOException, NoSuchAlgorithmException {
+        if (stream == null) {
+            throw new IllegalArgumentException("Stream must be set!");
+        }
+
+        if (algorithm == null || algorithm.length == 0) {
+            throw new IllegalArgumentException("Algorithm must be set!");
+        }
+
+        MessageDigest[] md = new MessageDigest[algorithm.length];
+        for (int i = 0; i < algorithm.length; i++) {
+            md[i] = MessageDigest.getInstance(algorithm[i]);
+        }
+
+        int b;
+        byte[] buffer = new byte[64 * 1024];
+        while ((b = stream.read(buffer)) > -1) {
+            for (int j = 0; j < md.length; j++) {
+                md[j].update(buffer, 0, b);
+            }
+        }
+
+        List<ContentStreamHash> result = new ArrayList<ContentStreamHash>();
+
+        for (int i = 0; i < md.length; i++) {
+            result.add(new ContentStreamHashImpl(algorithm[i], byteArrayToHexString(md[i].digest())));
+        }
+
+        return result;
+    }
+
+    protected static String byteArrayToHexString(byte[] bytes) {
+        int n = bytes.length;
+        char[] hashHex = new char[n * 2];
+        for (int i = 0; i < n; i++) {
+            hashHex[i * 2] = HEX_DIGITS[(0xF0 & bytes[i]) >>> 4];
+            hashHex[i * 2 + 1] = HEX_DIGITS[0x0F & bytes[i]];
+        }
+
+        return new String(hashHex);
+    }
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java?rev=1580826&view=auto
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java (added)
+++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java Mon Mar 24 12:49:00 2014
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.chemistry.opencmis.commons.impl.misc;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.util.List;
+
+import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
+import org.apache.chemistry.opencmis.commons.impl.IOUtils;
+import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamHashImpl;
+import org.junit.Test;
+
+public class ContentStreamHashTest {
+
+    @Test
+    public void testHash() throws Exception {
+        ContentStreamHashImpl hash1 = new ContentStreamHashImpl("{alg}0123456789abcdef");
+        ContentStreamHashImpl hash2 = new ContentStreamHashImpl("alg", "0123456789abcdef");
+
+        assertEquals("alg", hash1.getAlgorithm());
+        assertEquals("0123456789abcdef", hash1.getHash());
+
+        assertEquals(hash1.getPropertyValue(), hash2.getPropertyValue());
+        assertEquals(hash2.getAlgorithm(), hash2.getAlgorithm());
+        assertEquals(hash2.getHash(), hash2.getHash());
+    }
+
+    @Test
+    public void testHashCorrected() throws Exception {
+        ContentStreamHashImpl hash1 = new ContentStreamHashImpl("{alg} 01 23 45 67 89 AB CD EF ");
+        ContentStreamHashImpl hash2 = new ContentStreamHashImpl("ALG", "0123 4567 89ab cdef");
+
+        assertEquals("alg", hash1.getAlgorithm());
+        assertEquals("0123456789abcdef", hash1.getHash());
+
+        assertEquals(hash2.getAlgorithm(), hash2.getAlgorithm());
+        assertEquals(hash2.getHash(), hash2.getHash());
+    }
+
+    @Test
+    public void testHashStreamMD5() throws Exception {
+        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
+        ByteArrayInputStream stream = new ByteArrayInputStream(content);
+
+        ContentStreamHash hash = ContentStreamHashImpl.createContentHashes(stream, ContentStreamHashImpl.ALGORITHM_MD5)
+                .get(0);
+
+        assertEquals(ContentStreamHashImpl.ALGORITHM_MD5, hash.getAlgorithm());
+        assertEquals("ed076287532e86365e841e92bfc50d8c", hash.getHash());
+        assertEquals("{md5}ed076287532e86365e841e92bfc50d8c", hash.getPropertyValue());
+
+        stream.close();
+    }
+
+    @Test
+    public void testHashStreamSHA1() throws Exception {
+        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
+        ByteArrayInputStream stream = new ByteArrayInputStream(content);
+
+        ContentStreamHash hash = ContentStreamHashImpl
+                .createContentHashes(stream, ContentStreamHashImpl.ALGORITHM_SHA1).get(0);
+
+        assertEquals(ContentStreamHashImpl.ALGORITHM_SHA1, hash.getAlgorithm());
+        assertEquals("2ef7bde608ce5404e97d5f042f95f89f1c232871", hash.getHash());
+        assertEquals("{sha-1}2ef7bde608ce5404e97d5f042f95f89f1c232871", hash.getPropertyValue());
+
+        stream.close();
+    }
+
+    @Test
+    public void testHashStreamSHA256() throws Exception {
+        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
+        ByteArrayInputStream stream = new ByteArrayInputStream(content);
+
+        ContentStreamHash hash = ContentStreamHashImpl.createContentHashes(stream,
+                ContentStreamHashImpl.ALGORITHM_SHA256).get(0);
+
+        assertEquals(ContentStreamHashImpl.ALGORITHM_SHA256, hash.getAlgorithm());
+        assertEquals("7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", hash.getHash());
+        assertEquals("{sha-256}7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069",
+                hash.getPropertyValue());
+
+        stream.close();
+    }
+
+    @Test
+    public void testHashStreamSHA512() throws Exception {
+        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
+        ByteArrayInputStream stream = new ByteArrayInputStream(content);
+
+        ContentStreamHash hash = ContentStreamHashImpl.createContentHashes(stream,
+                ContentStreamHashImpl.ALGORITHM_SHA512).get(0);
+
+        assertEquals(ContentStreamHashImpl.ALGORITHM_SHA512, hash.getAlgorithm());
+        assertEquals(
+                "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8",
+                hash.getHash());
+        assertEquals(
+                "{sha-512}"
+                        + "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8",
+                hash.getPropertyValue());
+
+        stream.close();
+    }
+
+    @Test
+    public void testHashStreams() throws Exception {
+        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
+        ByteArrayInputStream stream = new ByteArrayInputStream(content);
+
+        List<ContentStreamHash> hashes = ContentStreamHashImpl.createContentHashes(stream,
+                ContentStreamHashImpl.ALGORITHM_SHA1, ContentStreamHashImpl.ALGORITHM_SHA256,
+                ContentStreamHashImpl.ALGORITHM_SHA512);
+
+        assertNotNull(hashes);
+        assertEquals(3, hashes.size());
+
+        assertEquals("{sha-1}2ef7bde608ce5404e97d5f042f95f89f1c232871", hashes.get(0).getPropertyValue());
+        assertEquals("{sha-256}7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", hashes.get(1)
+                .getPropertyValue());
+        assertEquals(
+                "{sha-512}"
+                        + "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8",
+                hashes.get(2).getPropertyValue());
+
+        stream.close();
+    }
+}

Propchange: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



Re: svn commit: r1580826 - in /chemistry/opencmis/trunk: chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/ chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemi...

Posted by Florian Müller <fm...@apache.org>.
 Done: CMIS-770

 Florian


> Hi,
>
> Could you please open a JIRA ticket for this, and reference it in
> further commits?
>
> Thanks,
> Florent
>
>


Re: svn commit: r1580826 - in /chemistry/opencmis/trunk: chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/ chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemi...

Posted by Florent Guillaume <fg...@nuxeo.com>.
Hi,

Could you please open a JIRA ticket for this, and reference it in
further commits?

Thanks,
Florent


On Mon, Mar 24, 2014 at 1:49 PM,  <fm...@apache.org> wrote:
> Author: fmui
> Date: Mon Mar 24 12:49:00 2014
> New Revision: 1580826
>
> URL: http://svn.apache.org/r1580826
> Log:
> added support for CMIS extension: content stream hash
>
> Added:
>     chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java   (with props)
>     chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java   (with props)
>     chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java   (with props)
> Modified:
>     chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java
>     chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java
>     chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java
>
> Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java
> URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java?rev=1580826&r1=1580825&r2=1580826&view=diff
> ==============================================================================
> --- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java (original)
> +++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java Mon Mar 24 12:49:00 2014
> @@ -18,6 +18,10 @@
>   */
>  package org.apache.chemistry.opencmis.client.api;
>
> +import java.util.List;
> +
> +import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
> +
>  /**
>   * Accessors to CMIS document properties.
>   *
> @@ -204,4 +208,16 @@ public interface DocumentProperties {
>       * @cmis 1.0
>       */
>      String getContentStreamId();
> +
> +    /**
> +     * Returns the content hashes or {@code null} if the document has no content
> +     * (CMIS property {@code cmis:contentStreamHash}).
> +     *
> +     * @return the list of content hashes or {@code null} if the property hasn't
> +     *         been requested, hasn't been provided by the repository, or the
> +     *         document has no content
> +     *
> +     * @cmis Extension
> +     */
> +    List<ContentStreamHash> getContentStreamHashes();
>  }
>
> Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java
> URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java?rev=1580826&r1=1580825&r2=1580826&view=diff
> ==============================================================================
> --- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java (original)
> +++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java Mon Mar 24 12:49:00 2014
> @@ -38,6 +38,7 @@ import org.apache.chemistry.opencmis.cli
>  import org.apache.chemistry.opencmis.commons.PropertyIds;
>  import org.apache.chemistry.opencmis.commons.data.Ace;
>  import org.apache.chemistry.opencmis.commons.data.ContentStream;
> +import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
>  import org.apache.chemistry.opencmis.commons.data.ObjectData;
>  import org.apache.chemistry.opencmis.commons.data.PartialContentStream;
>  import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
> @@ -46,6 +47,7 @@ import org.apache.chemistry.opencmis.com
>  import org.apache.chemistry.opencmis.commons.enums.VersioningState;
>  import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
>  import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
> +import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamHashImpl;
>  import org.apache.chemistry.opencmis.commons.spi.Holder;
>
>  public class DocumentImpl extends AbstractFilableCmisObject implements Document {
> @@ -122,6 +124,20 @@ public class DocumentImpl extends Abstra
>          return getPropertyValue(PropertyIds.CONTENT_STREAM_ID);
>      }
>
> +    public List<ContentStreamHash> getContentStreamHashes() {
> +        List<String> hashes = getPropertyValue(PropertyIds.CONTENT_STREAM_HASH);
> +        if (hashes == null || hashes.size() == 0) {
> +            return null;
> +        }
> +
> +        List<ContentStreamHash> result = new ArrayList<ContentStreamHash>(hashes.size());
> +        for (String hash : hashes) {
> +            result.add(new ContentStreamHashImpl(hash));
> +        }
> +
> +        return result;
> +    }
> +
>      // operations
>
>      public Document copy(ObjectId targetFolderId, Map<String, ?> properties, VersioningState versioningState,
>
> Modified: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java
> URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java?rev=1580826&r1=1580825&r2=1580826&view=diff
> ==============================================================================
> --- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java (original)
> +++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java Mon Mar 24 12:49:00 2014
> @@ -343,7 +343,7 @@ public final class PropertyIds {
>       */
>      public static final String POLICY_TEXT = "cmis:policyText";
>
> -    // ---- retention ---
> +    // ---- retention ----
>      /**
>       * CMIS retention property {@code cmis:rm_expirationDate}: expiration date.
>       * <p>
> @@ -382,4 +382,16 @@ public final class PropertyIds {
>       * @cmis 1.1
>       */
>      public static final String HOLD_IDS = "cmis:rm_holdIds";
> +
> +    // ---- extensions ----
> +    /**
> +     * Content Hash property {@code cmis:contentStreamHash} (multivalue): hashes
> +     * of the content stream
> +     * <p>
> +     * CMIS data type: string<br>
> +     * Java type: String
> +     *
> +     * @cmis Extension
> +     */
> +    public static final String CONTENT_STREAM_HASH = "cmis:contentStreamHash";
>  }
>
> Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java
> URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java?rev=1580826&view=auto
> ==============================================================================
> --- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java (added)
> +++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java Mon Mar 24 12:49:00 2014
> @@ -0,0 +1,47 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.chemistry.opencmis.commons.data;
> +
> +/**
> + * Content hash.
> + */
> +public interface ContentStreamHash {
> +
> +    /**
> +     * Returns the content hash property value ({@code cmis:contentStreamHash}).
> +     *
> +     * @return the content hash property value
> +     */
> +    String getPropertyValue();
> +
> +    /**
> +     * Returns the hash algorithm.
> +     *
> +     * @return the hash algorithm or {@code null} if the property value is
> +     *         invalid
> +     */
> +    String getAlgorithm();
> +
> +    /**
> +     * Returns the hash value.
> +     *
> +     * @return the hash value or {@code null} if the property value is invalid
> +     */
> +    String getHash();
> +}
>
> Propchange: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java
> URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java?rev=1580826&view=auto
> ==============================================================================
> --- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java (added)
> +++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java Mon Mar 24 12:49:00 2014
> @@ -0,0 +1,164 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.chemistry.opencmis.commons.impl.dataobjects;
> +
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.security.MessageDigest;
> +import java.security.NoSuchAlgorithmException;
> +import java.util.ArrayList;
> +import java.util.List;
> +import java.util.Locale;
> +
> +import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
> +
> +public class ContentStreamHashImpl implements ContentStreamHash {
> +
> +    public static final String ALGORITHM_MD5 = "md5";
> +    public static final String ALGORITHM_SHA1 = "sha-1";
> +    public static final String ALGORITHM_SHA224 = "sha-224";
> +    public static final String ALGORITHM_SHA256 = "sha-256";
> +    public static final String ALGORITHM_SHA384 = "sha-384";
> +    public static final String ALGORITHM_SHA512 = "sha-512";
> +    public static final String ALGORITHM_SHA3 = "sha-3";
> +
> +    private final static char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
> +
> +    private String propertyValue;
> +    private String algorithm = null;
> +    private String hash = null;
> +
> +    /**
> +     * Constructs an object without values.
> +     */
> +    public ContentStreamHashImpl() {
> +    }
> +
> +    /**
> +     * Constructs an object from the {@code cmis:contentStreamHash} property
> +     * value.
> +     *
> +     * @param propertyValue
> +     *            the property value
> +     */
> +    public ContentStreamHashImpl(String propertyValue) {
> +        this.propertyValue = propertyValue;
> +
> +        if (propertyValue == null) {
> +            return;
> +        }
> +
> +        String pv = propertyValue.trim();
> +        int algEnd = pv.indexOf('}');
> +        if (pv.charAt(0) != '{' || algEnd < 1) {
> +            return;
> +        }
> +
> +        this.algorithm = pv.substring(1, algEnd).toLowerCase(Locale.ENGLISH);
> +        this.hash = pv.substring(algEnd + 1).replaceAll("\\s", "").toLowerCase(Locale.ENGLISH);
> +    }
> +
> +    /**
> +     * Constructs an object from the algorithm and hash.
> +     *
> +     * @param algorithm
> +     *            the algorithm
> +     * @param hash
> +     *            the hash value
> +     */
> +    public ContentStreamHashImpl(String algorithm, String hash) {
> +        if (algorithm == null || algorithm.trim().length() == 0) {
> +            throw new IllegalArgumentException("Algorithm must be set!");
> +        }
> +
> +        if (hash == null || hash.trim().length() == 0) {
> +            throw new IllegalArgumentException("Hash must be set!");
> +        }
> +
> +        this.algorithm = algorithm.toLowerCase(Locale.ENGLISH);
> +        this.hash = hash.replaceAll("\\s", "").toLowerCase(Locale.ENGLISH);
> +        this.propertyValue = "{" + algorithm + "}" + hash;
> +    }
> +
> +    public String getPropertyValue() {
> +        return propertyValue;
> +    }
> +
> +    public String getAlgorithm() {
> +        return algorithm;
> +    }
> +
> +    public String getHash() {
> +        return hash;
> +    }
> +
> +    /**
> +     * Creates a list of content hashes from a stream
> +     * <p>
> +     * This method consumes the stream but doesn't close it.
> +     *
> +     * @param stream
> +     *            the stream
> +     * @param algorithm
> +     *            the algorithms
> +     * @return the list of content hashes
> +     */
> +    public static List<ContentStreamHash> createContentHashes(InputStream stream, String... algorithm)
> +            throws IOException, NoSuchAlgorithmException {
> +        if (stream == null) {
> +            throw new IllegalArgumentException("Stream must be set!");
> +        }
> +
> +        if (algorithm == null || algorithm.length == 0) {
> +            throw new IllegalArgumentException("Algorithm must be set!");
> +        }
> +
> +        MessageDigest[] md = new MessageDigest[algorithm.length];
> +        for (int i = 0; i < algorithm.length; i++) {
> +            md[i] = MessageDigest.getInstance(algorithm[i]);
> +        }
> +
> +        int b;
> +        byte[] buffer = new byte[64 * 1024];
> +        while ((b = stream.read(buffer)) > -1) {
> +            for (int j = 0; j < md.length; j++) {
> +                md[j].update(buffer, 0, b);
> +            }
> +        }
> +
> +        List<ContentStreamHash> result = new ArrayList<ContentStreamHash>();
> +
> +        for (int i = 0; i < md.length; i++) {
> +            result.add(new ContentStreamHashImpl(algorithm[i], byteArrayToHexString(md[i].digest())));
> +        }
> +
> +        return result;
> +    }
> +
> +    protected static String byteArrayToHexString(byte[] bytes) {
> +        int n = bytes.length;
> +        char[] hashHex = new char[n * 2];
> +        for (int i = 0; i < n; i++) {
> +            hashHex[i * 2] = HEX_DIGITS[(0xF0 & bytes[i]) >>> 4];
> +            hashHex[i * 2 + 1] = HEX_DIGITS[0x0F & bytes[i]];
> +        }
> +
> +        return new String(hashHex);
> +    }
> +}
>
> Propchange: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java
> URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java?rev=1580826&view=auto
> ==============================================================================
> --- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java (added)
> +++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java Mon Mar 24 12:49:00 2014
> @@ -0,0 +1,147 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.chemistry.opencmis.commons.impl.misc;
> +
> +import static org.junit.Assert.assertEquals;
> +import static org.junit.Assert.assertNotNull;
> +
> +import java.io.ByteArrayInputStream;
> +import java.util.List;
> +
> +import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
> +import org.apache.chemistry.opencmis.commons.impl.IOUtils;
> +import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamHashImpl;
> +import org.junit.Test;
> +
> +public class ContentStreamHashTest {
> +
> +    @Test
> +    public void testHash() throws Exception {
> +        ContentStreamHashImpl hash1 = new ContentStreamHashImpl("{alg}0123456789abcdef");
> +        ContentStreamHashImpl hash2 = new ContentStreamHashImpl("alg", "0123456789abcdef");
> +
> +        assertEquals("alg", hash1.getAlgorithm());
> +        assertEquals("0123456789abcdef", hash1.getHash());
> +
> +        assertEquals(hash1.getPropertyValue(), hash2.getPropertyValue());
> +        assertEquals(hash2.getAlgorithm(), hash2.getAlgorithm());
> +        assertEquals(hash2.getHash(), hash2.getHash());
> +    }
> +
> +    @Test
> +    public void testHashCorrected() throws Exception {
> +        ContentStreamHashImpl hash1 = new ContentStreamHashImpl("{alg} 01 23 45 67 89 AB CD EF ");
> +        ContentStreamHashImpl hash2 = new ContentStreamHashImpl("ALG", "0123 4567 89ab cdef");
> +
> +        assertEquals("alg", hash1.getAlgorithm());
> +        assertEquals("0123456789abcdef", hash1.getHash());
> +
> +        assertEquals(hash2.getAlgorithm(), hash2.getAlgorithm());
> +        assertEquals(hash2.getHash(), hash2.getHash());
> +    }
> +
> +    @Test
> +    public void testHashStreamMD5() throws Exception {
> +        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
> +        ByteArrayInputStream stream = new ByteArrayInputStream(content);
> +
> +        ContentStreamHash hash = ContentStreamHashImpl.createContentHashes(stream, ContentStreamHashImpl.ALGORITHM_MD5)
> +                .get(0);
> +
> +        assertEquals(ContentStreamHashImpl.ALGORITHM_MD5, hash.getAlgorithm());
> +        assertEquals("ed076287532e86365e841e92bfc50d8c", hash.getHash());
> +        assertEquals("{md5}ed076287532e86365e841e92bfc50d8c", hash.getPropertyValue());
> +
> +        stream.close();
> +    }
> +
> +    @Test
> +    public void testHashStreamSHA1() throws Exception {
> +        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
> +        ByteArrayInputStream stream = new ByteArrayInputStream(content);
> +
> +        ContentStreamHash hash = ContentStreamHashImpl
> +                .createContentHashes(stream, ContentStreamHashImpl.ALGORITHM_SHA1).get(0);
> +
> +        assertEquals(ContentStreamHashImpl.ALGORITHM_SHA1, hash.getAlgorithm());
> +        assertEquals("2ef7bde608ce5404e97d5f042f95f89f1c232871", hash.getHash());
> +        assertEquals("{sha-1}2ef7bde608ce5404e97d5f042f95f89f1c232871", hash.getPropertyValue());
> +
> +        stream.close();
> +    }
> +
> +    @Test
> +    public void testHashStreamSHA256() throws Exception {
> +        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
> +        ByteArrayInputStream stream = new ByteArrayInputStream(content);
> +
> +        ContentStreamHash hash = ContentStreamHashImpl.createContentHashes(stream,
> +                ContentStreamHashImpl.ALGORITHM_SHA256).get(0);
> +
> +        assertEquals(ContentStreamHashImpl.ALGORITHM_SHA256, hash.getAlgorithm());
> +        assertEquals("7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", hash.getHash());
> +        assertEquals("{sha-256}7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069",
> +                hash.getPropertyValue());
> +
> +        stream.close();
> +    }
> +
> +    @Test
> +    public void testHashStreamSHA512() throws Exception {
> +        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
> +        ByteArrayInputStream stream = new ByteArrayInputStream(content);
> +
> +        ContentStreamHash hash = ContentStreamHashImpl.createContentHashes(stream,
> +                ContentStreamHashImpl.ALGORITHM_SHA512).get(0);
> +
> +        assertEquals(ContentStreamHashImpl.ALGORITHM_SHA512, hash.getAlgorithm());
> +        assertEquals(
> +                "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8",
> +                hash.getHash());
> +        assertEquals(
> +                "{sha-512}"
> +                        + "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8",
> +                hash.getPropertyValue());
> +
> +        stream.close();
> +    }
> +
> +    @Test
> +    public void testHashStreams() throws Exception {
> +        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
> +        ByteArrayInputStream stream = new ByteArrayInputStream(content);
> +
> +        List<ContentStreamHash> hashes = ContentStreamHashImpl.createContentHashes(stream,
> +                ContentStreamHashImpl.ALGORITHM_SHA1, ContentStreamHashImpl.ALGORITHM_SHA256,
> +                ContentStreamHashImpl.ALGORITHM_SHA512);
> +
> +        assertNotNull(hashes);
> +        assertEquals(3, hashes.size());
> +
> +        assertEquals("{sha-1}2ef7bde608ce5404e97d5f042f95f89f1c232871", hashes.get(0).getPropertyValue());
> +        assertEquals("{sha-256}7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", hashes.get(1)
> +                .getPropertyValue());
> +        assertEquals(
> +                "{sha-512}"
> +                        + "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8",
> +                hashes.get(2).getPropertyValue());
> +
> +        stream.close();
> +    }
> +}
>
> Propchange: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
>



-- 
Florent Guillaume, Director of R&D, Nuxeo
Open Source Content Management Platform for Business Apps
http://www.nuxeo.com   http://community.nuxeo.com

Re: svn commit: r1580826 - in /chemistry/opencmis/trunk: chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/ chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemi...

Posted by Florent Guillaume <fg...@nuxeo.com>.
Hi,

Could you please open a JIRA ticket for this, and reference it in
further commits?

Thanks,
Florent


On Mon, Mar 24, 2014 at 1:49 PM,  <fm...@apache.org> wrote:
> Author: fmui
> Date: Mon Mar 24 12:49:00 2014
> New Revision: 1580826
>
> URL: http://svn.apache.org/r1580826
> Log:
> added support for CMIS extension: content stream hash
>
> Added:
>     chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java   (with props)
>     chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java   (with props)
>     chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java   (with props)
> Modified:
>     chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java
>     chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java
>     chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java
>
> Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java
> URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java?rev=1580826&r1=1580825&r2=1580826&view=diff
> ==============================================================================
> --- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java (original)
> +++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-api/src/main/java/org/apache/chemistry/opencmis/client/api/DocumentProperties.java Mon Mar 24 12:49:00 2014
> @@ -18,6 +18,10 @@
>   */
>  package org.apache.chemistry.opencmis.client.api;
>
> +import java.util.List;
> +
> +import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
> +
>  /**
>   * Accessors to CMIS document properties.
>   *
> @@ -204,4 +208,16 @@ public interface DocumentProperties {
>       * @cmis 1.0
>       */
>      String getContentStreamId();
> +
> +    /**
> +     * Returns the content hashes or {@code null} if the document has no content
> +     * (CMIS property {@code cmis:contentStreamHash}).
> +     *
> +     * @return the list of content hashes or {@code null} if the property hasn't
> +     *         been requested, hasn't been provided by the repository, or the
> +     *         document has no content
> +     *
> +     * @cmis Extension
> +     */
> +    List<ContentStreamHash> getContentStreamHashes();
>  }
>
> Modified: chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java
> URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java?rev=1580826&r1=1580825&r2=1580826&view=diff
> ==============================================================================
> --- chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java (original)
> +++ chemistry/opencmis/trunk/chemistry-opencmis-client/chemistry-opencmis-client-impl/src/main/java/org/apache/chemistry/opencmis/client/runtime/DocumentImpl.java Mon Mar 24 12:49:00 2014
> @@ -38,6 +38,7 @@ import org.apache.chemistry.opencmis.cli
>  import org.apache.chemistry.opencmis.commons.PropertyIds;
>  import org.apache.chemistry.opencmis.commons.data.Ace;
>  import org.apache.chemistry.opencmis.commons.data.ContentStream;
> +import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
>  import org.apache.chemistry.opencmis.commons.data.ObjectData;
>  import org.apache.chemistry.opencmis.commons.data.PartialContentStream;
>  import org.apache.chemistry.opencmis.commons.enums.CmisVersion;
> @@ -46,6 +47,7 @@ import org.apache.chemistry.opencmis.com
>  import org.apache.chemistry.opencmis.commons.enums.VersioningState;
>  import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
>  import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
> +import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamHashImpl;
>  import org.apache.chemistry.opencmis.commons.spi.Holder;
>
>  public class DocumentImpl extends AbstractFilableCmisObject implements Document {
> @@ -122,6 +124,20 @@ public class DocumentImpl extends Abstra
>          return getPropertyValue(PropertyIds.CONTENT_STREAM_ID);
>      }
>
> +    public List<ContentStreamHash> getContentStreamHashes() {
> +        List<String> hashes = getPropertyValue(PropertyIds.CONTENT_STREAM_HASH);
> +        if (hashes == null || hashes.size() == 0) {
> +            return null;
> +        }
> +
> +        List<ContentStreamHash> result = new ArrayList<ContentStreamHash>(hashes.size());
> +        for (String hash : hashes) {
> +            result.add(new ContentStreamHashImpl(hash));
> +        }
> +
> +        return result;
> +    }
> +
>      // operations
>
>      public Document copy(ObjectId targetFolderId, Map<String, ?> properties, VersioningState versioningState,
>
> Modified: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java
> URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java?rev=1580826&r1=1580825&r2=1580826&view=diff
> ==============================================================================
> --- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java (original)
> +++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/PropertyIds.java Mon Mar 24 12:49:00 2014
> @@ -343,7 +343,7 @@ public final class PropertyIds {
>       */
>      public static final String POLICY_TEXT = "cmis:policyText";
>
> -    // ---- retention ---
> +    // ---- retention ----
>      /**
>       * CMIS retention property {@code cmis:rm_expirationDate}: expiration date.
>       * <p>
> @@ -382,4 +382,16 @@ public final class PropertyIds {
>       * @cmis 1.1
>       */
>      public static final String HOLD_IDS = "cmis:rm_holdIds";
> +
> +    // ---- extensions ----
> +    /**
> +     * Content Hash property {@code cmis:contentStreamHash} (multivalue): hashes
> +     * of the content stream
> +     * <p>
> +     * CMIS data type: string<br>
> +     * Java type: String
> +     *
> +     * @cmis Extension
> +     */
> +    public static final String CONTENT_STREAM_HASH = "cmis:contentStreamHash";
>  }
>
> Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java
> URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java?rev=1580826&view=auto
> ==============================================================================
> --- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java (added)
> +++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java Mon Mar 24 12:49:00 2014
> @@ -0,0 +1,47 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.chemistry.opencmis.commons.data;
> +
> +/**
> + * Content hash.
> + */
> +public interface ContentStreamHash {
> +
> +    /**
> +     * Returns the content hash property value ({@code cmis:contentStreamHash}).
> +     *
> +     * @return the content hash property value
> +     */
> +    String getPropertyValue();
> +
> +    /**
> +     * Returns the hash algorithm.
> +     *
> +     * @return the hash algorithm or {@code null} if the property value is
> +     *         invalid
> +     */
> +    String getAlgorithm();
> +
> +    /**
> +     * Returns the hash value.
> +     *
> +     * @return the hash value or {@code null} if the property value is invalid
> +     */
> +    String getHash();
> +}
>
> Propchange: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-api/src/main/java/org/apache/chemistry/opencmis/commons/data/ContentStreamHash.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java
> URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java?rev=1580826&view=auto
> ==============================================================================
> --- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java (added)
> +++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java Mon Mar 24 12:49:00 2014
> @@ -0,0 +1,164 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.chemistry.opencmis.commons.impl.dataobjects;
> +
> +import java.io.IOException;
> +import java.io.InputStream;
> +import java.security.MessageDigest;
> +import java.security.NoSuchAlgorithmException;
> +import java.util.ArrayList;
> +import java.util.List;
> +import java.util.Locale;
> +
> +import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
> +
> +public class ContentStreamHashImpl implements ContentStreamHash {
> +
> +    public static final String ALGORITHM_MD5 = "md5";
> +    public static final String ALGORITHM_SHA1 = "sha-1";
> +    public static final String ALGORITHM_SHA224 = "sha-224";
> +    public static final String ALGORITHM_SHA256 = "sha-256";
> +    public static final String ALGORITHM_SHA384 = "sha-384";
> +    public static final String ALGORITHM_SHA512 = "sha-512";
> +    public static final String ALGORITHM_SHA3 = "sha-3";
> +
> +    private final static char[] HEX_DIGITS = "0123456789abcdef".toCharArray();
> +
> +    private String propertyValue;
> +    private String algorithm = null;
> +    private String hash = null;
> +
> +    /**
> +     * Constructs an object without values.
> +     */
> +    public ContentStreamHashImpl() {
> +    }
> +
> +    /**
> +     * Constructs an object from the {@code cmis:contentStreamHash} property
> +     * value.
> +     *
> +     * @param propertyValue
> +     *            the property value
> +     */
> +    public ContentStreamHashImpl(String propertyValue) {
> +        this.propertyValue = propertyValue;
> +
> +        if (propertyValue == null) {
> +            return;
> +        }
> +
> +        String pv = propertyValue.trim();
> +        int algEnd = pv.indexOf('}');
> +        if (pv.charAt(0) != '{' || algEnd < 1) {
> +            return;
> +        }
> +
> +        this.algorithm = pv.substring(1, algEnd).toLowerCase(Locale.ENGLISH);
> +        this.hash = pv.substring(algEnd + 1).replaceAll("\\s", "").toLowerCase(Locale.ENGLISH);
> +    }
> +
> +    /**
> +     * Constructs an object from the algorithm and hash.
> +     *
> +     * @param algorithm
> +     *            the algorithm
> +     * @param hash
> +     *            the hash value
> +     */
> +    public ContentStreamHashImpl(String algorithm, String hash) {
> +        if (algorithm == null || algorithm.trim().length() == 0) {
> +            throw new IllegalArgumentException("Algorithm must be set!");
> +        }
> +
> +        if (hash == null || hash.trim().length() == 0) {
> +            throw new IllegalArgumentException("Hash must be set!");
> +        }
> +
> +        this.algorithm = algorithm.toLowerCase(Locale.ENGLISH);
> +        this.hash = hash.replaceAll("\\s", "").toLowerCase(Locale.ENGLISH);
> +        this.propertyValue = "{" + algorithm + "}" + hash;
> +    }
> +
> +    public String getPropertyValue() {
> +        return propertyValue;
> +    }
> +
> +    public String getAlgorithm() {
> +        return algorithm;
> +    }
> +
> +    public String getHash() {
> +        return hash;
> +    }
> +
> +    /**
> +     * Creates a list of content hashes from a stream
> +     * <p>
> +     * This method consumes the stream but doesn't close it.
> +     *
> +     * @param stream
> +     *            the stream
> +     * @param algorithm
> +     *            the algorithms
> +     * @return the list of content hashes
> +     */
> +    public static List<ContentStreamHash> createContentHashes(InputStream stream, String... algorithm)
> +            throws IOException, NoSuchAlgorithmException {
> +        if (stream == null) {
> +            throw new IllegalArgumentException("Stream must be set!");
> +        }
> +
> +        if (algorithm == null || algorithm.length == 0) {
> +            throw new IllegalArgumentException("Algorithm must be set!");
> +        }
> +
> +        MessageDigest[] md = new MessageDigest[algorithm.length];
> +        for (int i = 0; i < algorithm.length; i++) {
> +            md[i] = MessageDigest.getInstance(algorithm[i]);
> +        }
> +
> +        int b;
> +        byte[] buffer = new byte[64 * 1024];
> +        while ((b = stream.read(buffer)) > -1) {
> +            for (int j = 0; j < md.length; j++) {
> +                md[j].update(buffer, 0, b);
> +            }
> +        }
> +
> +        List<ContentStreamHash> result = new ArrayList<ContentStreamHash>();
> +
> +        for (int i = 0; i < md.length; i++) {
> +            result.add(new ContentStreamHashImpl(algorithm[i], byteArrayToHexString(md[i].digest())));
> +        }
> +
> +        return result;
> +    }
> +
> +    protected static String byteArrayToHexString(byte[] bytes) {
> +        int n = bytes.length;
> +        char[] hashHex = new char[n * 2];
> +        for (int i = 0; i < n; i++) {
> +            hashHex[i * 2] = HEX_DIGITS[(0xF0 & bytes[i]) >>> 4];
> +            hashHex[i * 2 + 1] = HEX_DIGITS[0x0F & bytes[i]];
> +        }
> +
> +        return new String(hashHex);
> +    }
> +}
>
> Propchange: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/main/java/org/apache/chemistry/opencmis/commons/impl/dataobjects/ContentStreamHashImpl.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
> Added: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java
> URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java?rev=1580826&view=auto
> ==============================================================================
> --- chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java (added)
> +++ chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java Mon Mar 24 12:49:00 2014
> @@ -0,0 +1,147 @@
> +/*
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements.  See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership.  The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License.  You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied.  See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + */
> +package org.apache.chemistry.opencmis.commons.impl.misc;
> +
> +import static org.junit.Assert.assertEquals;
> +import static org.junit.Assert.assertNotNull;
> +
> +import java.io.ByteArrayInputStream;
> +import java.util.List;
> +
> +import org.apache.chemistry.opencmis.commons.data.ContentStreamHash;
> +import org.apache.chemistry.opencmis.commons.impl.IOUtils;
> +import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamHashImpl;
> +import org.junit.Test;
> +
> +public class ContentStreamHashTest {
> +
> +    @Test
> +    public void testHash() throws Exception {
> +        ContentStreamHashImpl hash1 = new ContentStreamHashImpl("{alg}0123456789abcdef");
> +        ContentStreamHashImpl hash2 = new ContentStreamHashImpl("alg", "0123456789abcdef");
> +
> +        assertEquals("alg", hash1.getAlgorithm());
> +        assertEquals("0123456789abcdef", hash1.getHash());
> +
> +        assertEquals(hash1.getPropertyValue(), hash2.getPropertyValue());
> +        assertEquals(hash2.getAlgorithm(), hash2.getAlgorithm());
> +        assertEquals(hash2.getHash(), hash2.getHash());
> +    }
> +
> +    @Test
> +    public void testHashCorrected() throws Exception {
> +        ContentStreamHashImpl hash1 = new ContentStreamHashImpl("{alg} 01 23 45 67 89 AB CD EF ");
> +        ContentStreamHashImpl hash2 = new ContentStreamHashImpl("ALG", "0123 4567 89ab cdef");
> +
> +        assertEquals("alg", hash1.getAlgorithm());
> +        assertEquals("0123456789abcdef", hash1.getHash());
> +
> +        assertEquals(hash2.getAlgorithm(), hash2.getAlgorithm());
> +        assertEquals(hash2.getHash(), hash2.getHash());
> +    }
> +
> +    @Test
> +    public void testHashStreamMD5() throws Exception {
> +        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
> +        ByteArrayInputStream stream = new ByteArrayInputStream(content);
> +
> +        ContentStreamHash hash = ContentStreamHashImpl.createContentHashes(stream, ContentStreamHashImpl.ALGORITHM_MD5)
> +                .get(0);
> +
> +        assertEquals(ContentStreamHashImpl.ALGORITHM_MD5, hash.getAlgorithm());
> +        assertEquals("ed076287532e86365e841e92bfc50d8c", hash.getHash());
> +        assertEquals("{md5}ed076287532e86365e841e92bfc50d8c", hash.getPropertyValue());
> +
> +        stream.close();
> +    }
> +
> +    @Test
> +    public void testHashStreamSHA1() throws Exception {
> +        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
> +        ByteArrayInputStream stream = new ByteArrayInputStream(content);
> +
> +        ContentStreamHash hash = ContentStreamHashImpl
> +                .createContentHashes(stream, ContentStreamHashImpl.ALGORITHM_SHA1).get(0);
> +
> +        assertEquals(ContentStreamHashImpl.ALGORITHM_SHA1, hash.getAlgorithm());
> +        assertEquals("2ef7bde608ce5404e97d5f042f95f89f1c232871", hash.getHash());
> +        assertEquals("{sha-1}2ef7bde608ce5404e97d5f042f95f89f1c232871", hash.getPropertyValue());
> +
> +        stream.close();
> +    }
> +
> +    @Test
> +    public void testHashStreamSHA256() throws Exception {
> +        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
> +        ByteArrayInputStream stream = new ByteArrayInputStream(content);
> +
> +        ContentStreamHash hash = ContentStreamHashImpl.createContentHashes(stream,
> +                ContentStreamHashImpl.ALGORITHM_SHA256).get(0);
> +
> +        assertEquals(ContentStreamHashImpl.ALGORITHM_SHA256, hash.getAlgorithm());
> +        assertEquals("7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", hash.getHash());
> +        assertEquals("{sha-256}7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069",
> +                hash.getPropertyValue());
> +
> +        stream.close();
> +    }
> +
> +    @Test
> +    public void testHashStreamSHA512() throws Exception {
> +        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
> +        ByteArrayInputStream stream = new ByteArrayInputStream(content);
> +
> +        ContentStreamHash hash = ContentStreamHashImpl.createContentHashes(stream,
> +                ContentStreamHashImpl.ALGORITHM_SHA512).get(0);
> +
> +        assertEquals(ContentStreamHashImpl.ALGORITHM_SHA512, hash.getAlgorithm());
> +        assertEquals(
> +                "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8",
> +                hash.getHash());
> +        assertEquals(
> +                "{sha-512}"
> +                        + "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8",
> +                hash.getPropertyValue());
> +
> +        stream.close();
> +    }
> +
> +    @Test
> +    public void testHashStreams() throws Exception {
> +        byte[] content = IOUtils.toUTF8Bytes("Hello World!");
> +        ByteArrayInputStream stream = new ByteArrayInputStream(content);
> +
> +        List<ContentStreamHash> hashes = ContentStreamHashImpl.createContentHashes(stream,
> +                ContentStreamHashImpl.ALGORITHM_SHA1, ContentStreamHashImpl.ALGORITHM_SHA256,
> +                ContentStreamHashImpl.ALGORITHM_SHA512);
> +
> +        assertNotNull(hashes);
> +        assertEquals(3, hashes.size());
> +
> +        assertEquals("{sha-1}2ef7bde608ce5404e97d5f042f95f89f1c232871", hashes.get(0).getPropertyValue());
> +        assertEquals("{sha-256}7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069", hashes.get(1)
> +                .getPropertyValue());
> +        assertEquals(
> +                "{sha-512}"
> +                        + "861844d6704e8573fec34d967e20bcfef3d424cf48be04e6dc08f2bd58c729743371015ead891cc3cf1c9d34b49264b510751b1ff9e537937bc46b5d6ff4ecc8",
> +                hashes.get(2).getPropertyValue());
> +
> +        stream.close();
> +    }
> +}
>
> Propchange: chemistry/opencmis/trunk/chemistry-opencmis-commons/chemistry-opencmis-commons-impl/src/test/java/org/apache/chemistry/opencmis/commons/impl/misc/ContentStreamHashTest.java
> ------------------------------------------------------------------------------
>     svn:eol-style = native
>
>



-- 
Florent Guillaume, Director of R&D, Nuxeo
Open Source Content Management Platform for Business Apps
http://www.nuxeo.com   http://community.nuxeo.com