001/*
002 * ModeShape (http://www.modeshape.org)
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *       http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.modeshape.cmis;
017
018import java.util.Iterator;
019import java.util.Set;
020import javax.jcr.Node;
021import javax.jcr.Property;
022import javax.jcr.RepositoryException;
023import javax.jcr.UnsupportedRepositoryOperationException;
024import javax.jcr.version.Version;
025import javax.jcr.version.VersionException;
026import javax.jcr.version.VersionHistory;
027import javax.jcr.version.VersionIterator;
028import org.apache.chemistry.opencmis.commons.PropertyIds;
029import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
030import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
031import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertiesImpl;
032import org.apache.chemistry.opencmis.commons.impl.server.ObjectInfoImpl;
033import org.apache.chemistry.opencmis.jcr.JcrTypeManager;
034import org.apache.chemistry.opencmis.jcr.JcrVersion;
035import org.apache.chemistry.opencmis.jcr.PathManager;
036import org.apache.chemistry.opencmis.jcr.type.JcrTypeHandlerManager;
037import org.modeshape.jcr.api.Binary;
038
039/**
040 * Modified
041 * <code>JcrVersion</code> class.
042 *
043 * @author kulikov
044 */
045public class JcrMsVersion extends JcrVersion {
046
047    private static final String HASH_ALGORITHM = "sha-1";
048
049    public JcrMsVersion(Node node, Version version, JcrTypeManager typeManager, PathManager pathManager,
050            JcrTypeHandlerManager typeHandlerManager) {
051
052        super(node, version, typeManager, pathManager, typeHandlerManager);
053    }
054
055    @Override
056    public Iterator<JcrVersion> getVersions() {
057        try {
058            VersionHistory versionHistory = getVersionHistory(getNode());
059            final VersionIterator versions = versionHistory.getAllLinearVersions();
060
061            return new Iterator<JcrVersion>() {
062                @Override
063                public boolean hasNext() {
064                    return versions.hasNext();
065                }
066
067                @Override
068                public JcrVersion next() {
069                    return new JcrMsVersionNode(getNode(), versions.nextVersion(), typeManager, pathManager,
070                            typeHandlerManager);
071                }
072
073                @Override
074                public void remove() {
075                    throw new UnsupportedOperationException();
076                }
077            };
078        } catch (RepositoryException e) {
079            throw new CmisRuntimeException(e.getMessage(), e);
080        }
081    }
082
083    @Override
084    public JcrVersion getVersion(String name) {
085        try {
086            Node node = getNode();
087            VersionHistory versionHistory = getVersionHistory(node);
088            Version version = versionHistory.getVersion(name);
089            return new JcrMsVersion(node, version, typeManager, pathManager, typeHandlerManager);
090        } catch (UnsupportedRepositoryOperationException | VersionException e) {
091            throw new CmisObjectNotFoundException(e.getMessage(), e);
092        } catch (RepositoryException e) {
093            throw new CmisRuntimeException(e.getMessage(), e);
094        }
095    }
096
097    @Override
098    protected void compileProperties(PropertiesImpl properties, Set<String> filter, ObjectInfoImpl objectInfo)
099            throws RepositoryException {
100        super.compileProperties(properties, filter, objectInfo);
101        //append cmis:contentStreamHash  property
102        addPropertyString(properties, getTypeIdInternal(), filter, PropertyIds.CONTENT_STREAM_HASH, getHash());
103    }
104
105    /**
106     * Get the hexadecimal form of the SHA-1 hash of the contents. 
107     * 
108     * @return the hexadecimal form of hash, or a null string if the hash could not be computed or is not known
109     */
110    private String getHash() {
111        try {
112            Node contentNode = getContextNode();
113            Property data = contentNode.getProperty(Property.JCR_DATA);
114            Binary bin = (Binary) data.getBinary();
115            return String.format("{%s}%s", HASH_ALGORITHM, bin.getHexHash());
116        } catch (RepositoryException e) {
117            return "";
118        }
119    }
120}