Index: modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrItem.java =================================================================== --- modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrItem.java (revision 1691) +++ modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrItem.java (working copy) @@ -75,6 +75,10 @@ abstract class AbstractJcrItem implements Item { return context().getValueFactories().getPathFactory().createSegment(segment); } + final Path.Segment segmentFrom( Name segment ) { + return context().getValueFactories().getPathFactory().createSegment(segment); + } + final NamespaceRegistry namespaces() { return context().getNamespaceRegistry(); } Index: modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java =================================================================== --- modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java (revision 1691) +++ modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java (working copy) @@ -660,7 +660,7 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node * @throws IllegalArgumentException if relativePath is empty or null. * @see javax.jcr.Node#getNode(java.lang.String) */ - public final javax.jcr.Node getNode( String relativePath ) throws RepositoryException { + public final AbstractJcrNode getNode( String relativePath ) throws RepositoryException { CheckArg.isNotEmpty(relativePath, "relativePath"); if (relativePath.equals(".")) return this; if (relativePath.equals("..")) return this.getParent(); @@ -681,7 +681,7 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node if (path.size() > 1) { AbstractJcrItem item = cache.findJcrNode(nodeId, location.getPath(), path); if (item instanceof javax.jcr.Node) { - return (javax.jcr.Node)item; + return (AbstractJcrNode)item; } I18n msg = JcrI18n.nodeNotFoundAtPathRelativeToReferenceNode; throw new PathNotFoundException(msg.text(relativePath, getPath(), cache.workspaceName())); @@ -1371,6 +1371,18 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node } /** + * Throw an {@link UnsupportedRepositoryOperationException} if this node is not versionable (i.e., + * isNodeType(JcrMixLexicon.VERSIONABLE) == false). + * @throws UnsupportedRepositoryOperationException if !isNodeType({@link JcrMixLexicon#VERSIONABLE}) + * @throws RepositoryException if an error occurs reading the node types for this node + */ + private void checkVersionable() throws UnsupportedRepositoryOperationException, RepositoryException { + if (!isNodeType(JcrMixLexicon.VERSIONABLE)) { + throw new UnsupportedRepositoryOperationException("TODO: Add message"); + } + } + + /** * {@inheritDoc} * * @return false @@ -1386,8 +1398,11 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node * @throws UnsupportedRepositoryOperationException always * @see javax.jcr.Node#checkin() */ - public final Version checkin() throws UnsupportedRepositoryOperationException { - throw new UnsupportedRepositoryOperationException(); + public final Version checkin() throws UnsupportedRepositoryOperationException, RepositoryException { + checkVersionable(); + + return null; + //throw new UnsupportedRepositoryOperationException(); } /** @@ -1396,13 +1411,111 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node * @throws UnsupportedRepositoryOperationException always * @see javax.jcr.Node#checkout() */ - public final void checkout() throws UnsupportedRepositoryOperationException { + public final void checkout() throws UnsupportedRepositoryOperationException, RepositoryException { + checkVersionable(); + + // throw new UnsupportedRepositoryOperationException(); + } + + /** + * {@inheritDoc} + * + * @throws UnsupportedOperationException always + * @see javax.jcr.Node#merge(java.lang.String, boolean) + */ + public final NodeIterator merge( String srcWorkspace, + boolean bestEffort ) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + * + * @throws UnsupportedOperationException always + * @see javax.jcr.Node#cancelMerge(javax.jcr.version.Version) + */ + public final void cancelMerge( Version version ) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + * + * @throws UnsupportedOperationException always + * @see javax.jcr.Node#doneMerge(javax.jcr.version.Version) + */ + public final void doneMerge( Version version ) { + throw new UnsupportedOperationException(); + } + + /** + * {@inheritDoc} + * + * @throws UnsupportedRepositoryOperationException always + * @see javax.jcr.Node#getVersionHistory() + */ + public final VersionHistory getVersionHistory() throws UnsupportedRepositoryOperationException { throw new UnsupportedRepositoryOperationException(); } /** * {@inheritDoc} * + * @throws UnsupportedRepositoryOperationException always + * @see javax.jcr.Node#getBaseVersion() + */ + public final Version getBaseVersion() throws UnsupportedRepositoryOperationException { + throw new UnsupportedRepositoryOperationException(); + } + + /** + * {@inheritDoc} + * + * @throws UnsupportedRepositoryOperationException always + * @see javax.jcr.Node#restore(java.lang.String, boolean) + */ + public final void restore( String versionName, + boolean removeExisting ) throws UnsupportedRepositoryOperationException { + throw new UnsupportedRepositoryOperationException(); + } + + /** + * {@inheritDoc} + * + * @throws UnsupportedRepositoryOperationException always + * @see javax.jcr.Node#restore(javax.jcr.version.Version, boolean) + */ + public final void restore( Version version, + boolean removeExisting ) throws UnsupportedRepositoryOperationException { + throw new UnsupportedRepositoryOperationException(); + } + + /** + * {@inheritDoc} + * + * @throws UnsupportedRepositoryOperationException always + * @see javax.jcr.Node#restore(javax.jcr.version.Version, java.lang.String, boolean) + */ + public final void restore( Version version, + String relPath, + boolean removeExisting ) throws UnsupportedRepositoryOperationException { + throw new UnsupportedRepositoryOperationException(); + } + + /** + * {@inheritDoc} + * + * @throws UnsupportedRepositoryOperationException always + * @see javax.jcr.Node#restoreByLabel(java.lang.String, boolean) + */ + public final void restoreByLabel( String versionLabel, + boolean removeExisting ) throws UnsupportedRepositoryOperationException { + throw new UnsupportedRepositoryOperationException(); + } + + /** + * {@inheritDoc} + * * @return false * @see javax.jcr.Node#holdsLock() */ @@ -1546,37 +1659,6 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node /** * {@inheritDoc} * - * @throws UnsupportedOperationException always - * @see javax.jcr.Node#merge(java.lang.String, boolean) - */ - public final NodeIterator merge( String srcWorkspace, - boolean bestEffort ) { - throw new UnsupportedOperationException(); - } - - /** - * {@inheritDoc} - * - * @throws UnsupportedOperationException always - * @see javax.jcr.Node#cancelMerge(javax.jcr.version.Version) - */ - public final void cancelMerge( Version version ) { - throw new UnsupportedOperationException(); - } - - /** - * {@inheritDoc} - * - * @throws UnsupportedOperationException always - * @see javax.jcr.Node#doneMerge(javax.jcr.version.Version) - */ - public final void doneMerge( Version version ) { - throw new UnsupportedOperationException(); - } - - /** - * {@inheritDoc} - * * @see javax.jcr.Node#getCorrespondingNodePath(java.lang.String) */ public final String getCorrespondingNodePath( String workspaceName ) @@ -1632,71 +1714,6 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node * {@inheritDoc} * * @throws UnsupportedRepositoryOperationException always - * @see javax.jcr.Node#getVersionHistory() - */ - public final VersionHistory getVersionHistory() throws UnsupportedRepositoryOperationException { - throw new UnsupportedRepositoryOperationException(); - } - - /** - * {@inheritDoc} - * - * @throws UnsupportedRepositoryOperationException always - * @see javax.jcr.Node#getBaseVersion() - */ - public final Version getBaseVersion() throws UnsupportedRepositoryOperationException { - throw new UnsupportedRepositoryOperationException(); - } - - /** - * {@inheritDoc} - * - * @throws UnsupportedRepositoryOperationException always - * @see javax.jcr.Node#restore(java.lang.String, boolean) - */ - public final void restore( String versionName, - boolean removeExisting ) throws UnsupportedRepositoryOperationException { - throw new UnsupportedRepositoryOperationException(); - } - - /** - * {@inheritDoc} - * - * @throws UnsupportedRepositoryOperationException always - * @see javax.jcr.Node#restore(javax.jcr.version.Version, boolean) - */ - public final void restore( Version version, - boolean removeExisting ) throws UnsupportedRepositoryOperationException { - throw new UnsupportedRepositoryOperationException(); - } - - /** - * {@inheritDoc} - * - * @throws UnsupportedRepositoryOperationException always - * @see javax.jcr.Node#restore(javax.jcr.version.Version, java.lang.String, boolean) - */ - public final void restore( Version version, - String relPath, - boolean removeExisting ) throws UnsupportedRepositoryOperationException { - throw new UnsupportedRepositoryOperationException(); - } - - /** - * {@inheritDoc} - * - * @throws UnsupportedRepositoryOperationException always - * @see javax.jcr.Node#restoreByLabel(java.lang.String, boolean) - */ - public final void restoreByLabel( String versionLabel, - boolean removeExisting ) throws UnsupportedRepositoryOperationException { - throw new UnsupportedRepositoryOperationException(); - } - - /** - * {@inheritDoc} - * - * @throws UnsupportedRepositoryOperationException always * @see javax.jcr.Node#orderBefore(java.lang.String, java.lang.String) */ public final void orderBefore( String srcChildRelPath, Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrNode.java =================================================================== --- modeshape-jcr/src/main/java/org/modeshape/jcr/JcrNode.java (revision 1691) +++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrNode.java (working copy) @@ -38,7 +38,7 @@ import org.modeshape.graph.session.GraphSession.NodeId; * @see JcrRootNode */ @NotThreadSafe -final class JcrNode extends AbstractJcrNode { +class JcrNode extends AbstractJcrNode { JcrNode( SessionCache cache, NodeId nodeId, @@ -52,7 +52,7 @@ final class JcrNode extends AbstractJcrNode { * @see org.modeshape.jcr.AbstractJcrNode#isRoot() */ @Override - boolean isRoot() { + final boolean isRoot() { return false; } Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrRepository.java =================================================================== --- modeshape-jcr/src/main/java/org/modeshape/jcr/JcrRepository.java (revision 1691) +++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrRepository.java (working copy) @@ -452,7 +452,7 @@ public class JcrRepository implements Repository { modifiableDescriptors.put(Repository.OPTION_OBSERVATION_SUPPORTED, "true"); modifiableDescriptors.put(Repository.OPTION_QUERY_SQL_SUPPORTED, "false"); // not JCR 1.0 SQL modifiableDescriptors.put(Repository.OPTION_TRANSACTIONS_SUPPORTED, "false"); - modifiableDescriptors.put(Repository.OPTION_VERSIONING_SUPPORTED, "false"); + modifiableDescriptors.put(Repository.OPTION_VERSIONING_SUPPORTED, "true"); modifiableDescriptors.put(Repository.QUERY_XPATH_DOC_ORDER, "false"); // see MODE-613 if (!modifiableDescriptors.containsKey(Repository.QUERY_XPATH_POS_INDEX)) { // don't override what was supplied ... Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrSession.java =================================================================== --- modeshape-jcr/src/main/java/org/modeshape/jcr/JcrSession.java (revision 1691) +++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrSession.java (working copy) @@ -568,7 +568,7 @@ class JcrSession implements Session { * * @see javax.jcr.Session#getNodeByUUID(java.lang.String) */ - public Node getNodeByUUID( String uuid ) throws ItemNotFoundException, RepositoryException { + public AbstractJcrNode getNodeByUUID( String uuid ) throws ItemNotFoundException, RepositoryException { return cache.findJcrNode(Location.create(UUID.fromString(uuid))); } Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionHistoryNode.java new file mode 100644 =================================================================== --- /dev/null (revision 1691) +++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionHistoryNode.java (working copy) @@ -0,0 +1,275 @@ +package org.modeshape.jcr; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.NoSuchElementException; +import javax.jcr.AccessDeniedException; +import javax.jcr.NodeIterator; +import javax.jcr.PathNotFoundException; +import javax.jcr.Property; +import javax.jcr.PropertyIterator; +import javax.jcr.ReferentialIntegrityException; +import javax.jcr.RepositoryException; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.version.Version; +import javax.jcr.version.VersionException; +import javax.jcr.version.VersionHistory; +import javax.jcr.version.VersionIterator; +import org.modeshape.graph.connector.RepositorySourceException; +import org.modeshape.graph.property.Name; +import org.modeshape.graph.property.Path.Segment; + +/** + * Convenience wrapper around a version history {@link JcrNode node}. + * + */ +public class JcrVersionHistoryNode extends JcrNode implements VersionHistory { + + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + + public JcrVersionHistoryNode( AbstractJcrNode node ) { + super(node.cache, node.nodeId, node.location); + + assert !node.isRoot() : "Version histories should always be located in the /jcr:system/jcr:versionStorage subgraph"; + } + + /** + * @return a reference to the {@code jcr:versionLabels} child node of this history node. + * @throws RepositoryException if an error occurs accessing this node + */ + private AbstractJcrNode versionLabels() throws RepositoryException { + Segment segment = segmentFrom(JcrLexicon.VERSION_LABELS); + return nodeInfo().getChild(segment).getPayload().getJcrNode(); + } + + @Override + public VersionIterator getAllVersions() throws RepositoryException { + return new JcrVersionIterator(getNodes()); + } + + @Override + public Version getRootVersion() throws RepositoryException { + // Copied from AbstractJcrNode.getNode(String) to avoid double conversion. Needs to be refactored. + Segment segment = context().getValueFactories().getPathFactory().createSegment(JcrLexicon.ROOT_VERSION); + try { + return new JcrVersionNode(nodeInfo().getChild(segment).getPayload().getJcrNode()); + } catch (org.modeshape.graph.property.PathNotFoundException e) { + String msg = JcrI18n.childNotFoundUnderNode.text(segment, getPath(), cache.workspaceName()); + throw new PathNotFoundException(msg); + } catch (RepositorySourceException e) { + throw new RepositoryException(e.getLocalizedMessage(), e); + } + } + + @Override + public Version getVersion( String versionName ) throws VersionException, RepositoryException { + AbstractJcrNode version = getNode(versionName); + if (version == null) return null; + + return new JcrVersionNode(version); + } + + @Override + public Version getVersionByLabel( String label ) throws VersionException, RepositoryException { + Property prop = versionLabels().getProperty(label); + if (prop == null) throw new VersionException(); + + AbstractJcrNode version = session().getNodeByUUID(prop.getString()); + + assert version != null; + + return new JcrVersionNode(version); + } + + @Override + public String[] getVersionLabels() throws RepositoryException { + PropertyIterator iter = versionLabels().getProperties(); + + String[] labels = new String[(int) iter.getSize()]; + for ( int i = 0; iter.hasNext(); i++) { + labels[i] = iter.nextProperty().getName(); + } + + return labels; + } + + /** + * Returns the version labels that point to the given version + * @param version the version for which the labels should be retrieved + * @return the version labels for that version + * @throws RepositoryException if an error occurs accessing the repository + */ + private Collection versionLabelsFor(Version version) throws RepositoryException { + String versionUuid = version.getUUID(); + + PropertyIterator iter = versionLabels().getProperties(); + + List labels = new LinkedList(); + for ( int i = 0; iter.hasNext(); i++) { + Property prop = iter.nextProperty(); + + if (versionUuid.equals(prop.getString())) { + labels.add(prop.getName()); + } + } + + return labels; + } + + @Override + public String[] getVersionLabels( Version version ) throws RepositoryException { + return versionLabelsFor(version).toArray(EMPTY_STRING_ARRAY); + } + + @Override + public String getVersionableUUID() throws RepositoryException { + return getProperty(JcrLexicon.VERSIONABLE_UUID).getString(); + } + + @Override + public boolean hasVersionLabel( String label ) throws RepositoryException { + return versionLabels().hasProperty(label); + } + + @Override + public boolean hasVersionLabel( Version version, + String label ) throws RepositoryException { + Collection labels = versionLabelsFor(version); + + return labels.contains(label); + } + + @Override + public void removeVersion( String versionName ) + throws ReferentialIntegrityException, AccessDeniedException, UnsupportedRepositoryOperationException, VersionException, + RepositoryException { + // TODO Auto-generated method stub + + } + + @Override + public void addVersionLabel( String versionName, + String label, + boolean moveLabel ) throws VersionException, RepositoryException { + AbstractJcrNode versionLabels = versionLabels(); + Property prop = versionLabels.getProperty(label); + Version version = getVersion(versionName); + + if (prop != null) { + if (!moveLabel) throw new VersionException(); + + prop.setValue(version); + } + else { + versionLabels.setProperty(label, version); + } + } + + @Override + public void removeVersionLabel( String label ) throws VersionException, RepositoryException { + Property prop = versionLabels().getProperty(label); + + if (prop == null) { + throw new VersionException(); + } + + prop.remove(); + } + + /** + * Iterator over the versions within a version history. + * This class wraps the {@link JcrChildNodeIterator node iterator} for all nodes of the {@link JcrVersionHistoryNode version history}, + * silently ignoring the {@code jcr:rootVersion} and {@code jcr:versionLabels} children. + * + */ + class JcrVersionIterator implements VersionIterator { + + private final NodeIterator nodeIterator; + private Version next; + private int position = 0; + + public JcrVersionIterator( NodeIterator nodeIterator ) { + super(); + this.nodeIterator = nodeIterator; + } + + @Override + public Version nextVersion() { + Version next = this.next; + + if (next != null) { + this.next = null; + return next; + } + + next = nextVersionIfPossible(); + + if (next == null) { + throw new NoSuchElementException(); + } + + position++; + return next; + } + + private JcrVersionNode nextVersionIfPossible() { + while (nodeIterator.hasNext()) { + AbstractJcrNode node = (AbstractJcrNode)nodeIterator.nextNode(); + + Name nodeName; + try { + nodeName = node.name(); + } catch (RepositoryException re) { + throw new IllegalStateException(re); + } + + if (!JcrLexicon.ROOT_VERSION.equals(nodeName) && !JcrLexicon.VERSION_LABELS.equals(nodeName)) { + return new JcrVersionNode(node); + } + } + + return null; + } + + @Override + public long getPosition() { + return position; + } + + @Override + public long getSize() { + // The number of version nodes is the number of child nodes of the version history - 2 + // (1 each for the jcr:rootVersion and jcr:versionLabels nodes) + return nodeIterator.getSize() - 2; + } + + @Override + public void skip( long count ) { + // Walk through the list to make sure that we don't accidentally count jcr:rootVersion or jcr:versionLabels as a + // skipped node + while (count-- > 0) { + nextVersion(); + } + } + + @Override + public boolean hasNext() { + if (this.next != null) return true; + + this.next = nextVersionIfPossible(); + + return this.next != null; + } + + @Override + public Object next() { + return nextVersion(); + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionNode.java new file mode 100644 =================================================================== --- /dev/null (revision 1691) +++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionNode.java (working copy) @@ -0,0 +1,69 @@ +package org.modeshape.jcr; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.version.Version; +import org.modeshape.graph.property.Name; + +public class JcrVersionNode extends JcrNode implements Version { + + private static final Version[] EMPTY_VERSION_ARRAY = new Version[0]; + + + public JcrVersionNode( AbstractJcrNode node ) { + super(node.cache, node.nodeId, node.location); + + assert !node.isRoot() : "Versions should always be located in the /jcr:system/jcr:versionStorage subgraph"; + } + + @Override + public JcrVersionHistoryNode getContainingHistory() throws RepositoryException { + return new JcrVersionHistoryNode(getParent()); + } + + @Override + public Calendar getCreated() throws RepositoryException { + return getProperty(JcrLexicon.CREATED).getDate(); + } + + @Override + public Version[] getPredecessors() throws RepositoryException { + return getNodesForProperty(JcrLexicon.PREDECESSORS); + } + + /** + * Returns the successor versions of this version. This corresponds to returning all the nt:version nodes referenced by the + * jcr:successors multi-value property in the nt:version node that represents this version. + */ + @Override + public Version[] getSuccessors() throws RepositoryException { + return getNodesForProperty(JcrLexicon.SUCCESSORS); + } + + private final Version[] getNodesForProperty(Name propertyName) throws RepositoryException { + assert JcrLexicon.SUCCESSORS.equals(propertyName) || JcrLexicon.PREDECESSORS.equals(propertyName); + + Property references = getProperty(propertyName); + + if (references == null) return EMPTY_VERSION_ARRAY; + + Value[] values = references.getValues(); + + List versions = new ArrayList(values.length); + + for (int i = 0; i < values.length; i++) { + String uuid = values[i].getString(); + + AbstractJcrNode node = session().getNodeByUUID(uuid); + versions.add(new JcrVersionNode(node)); + } + + return versions.toArray(EMPTY_VERSION_ARRAY); + + } + +} Index: modeshape-jcr/src/main/resources/org/modeshape/jcr/jsr_170_builtins.cnd =================================================================== --- modeshape-jcr/src/main/resources/org/modeshape/jcr/jsr_170_builtins.cnd (revision 1691) +++ modeshape-jcr/src/main/resources/org/modeshape/jcr/jsr_170_builtins.cnd (working copy) @@ -68,6 +68,13 @@ + jcr:propertyDefinition (nt:propertyDefinition) = nt:propertyDefinition multiple version + jcr:childNodeDefinition (nt:childNodeDefinition) = nt:childNodeDefinition multiple version +[mix:versionable] > mix:referenceable mixin + - jcr:versionHistory (reference) mandatory protected < 'nt:versionHistory' + - jcr:baseVersion (reference) mandatory protected ignore < 'nt:version' + - jcr:isCheckedOut (boolean) = 'true' mandatory autocreated protected ignore + - jcr:predecessors (reference) mandatory protected multiple < 'nt:version' + - jcr:mergeFailed (reference) protected multiple abort + [nt:versionLabels] - * (reference) protected abort < 'nt:version' Index: modeshape-jcr/src/test/java/org/modeshape/jcr/JcrTckTest.java =================================================================== --- modeshape-jcr/src/test/java/org/modeshape/jcr/JcrTckTest.java (revision 1691) +++ modeshape-jcr/src/test/java/org/modeshape/jcr/JcrTckTest.java (working copy) @@ -100,6 +100,35 @@ import org.apache.jackrabbit.test.api.query.GetPersistentQueryPathTest; import org.apache.jackrabbit.test.api.query.QueryResultNodeIteratorTest; import org.apache.jackrabbit.test.api.query.SaveTest; import org.apache.jackrabbit.test.api.query.XPathQueryLevel2Test; +import org.apache.jackrabbit.test.api.version.CheckinTest; +import org.apache.jackrabbit.test.api.version.CheckoutTest; +import org.apache.jackrabbit.test.api.version.GetContainingHistoryTest; +import org.apache.jackrabbit.test.api.version.GetCreatedTest; +import org.apache.jackrabbit.test.api.version.GetPredecessorsTest; +import org.apache.jackrabbit.test.api.version.GetReferencesNodeTest; +import org.apache.jackrabbit.test.api.version.GetVersionableUUIDTest; +import org.apache.jackrabbit.test.api.version.MergeCancelMergeTest; +import org.apache.jackrabbit.test.api.version.MergeCheckedoutSubNodeTest; +import org.apache.jackrabbit.test.api.version.MergeDoneMergeTest; +import org.apache.jackrabbit.test.api.version.MergeNodeIteratorTest; +import org.apache.jackrabbit.test.api.version.MergeNodeTest; +import org.apache.jackrabbit.test.api.version.MergeNonVersionableSubNodeTest; +import org.apache.jackrabbit.test.api.version.MergeSubNodeTest; +import org.apache.jackrabbit.test.api.version.OnParentVersionAbortTest; +import org.apache.jackrabbit.test.api.version.OnParentVersionComputeTest; +import org.apache.jackrabbit.test.api.version.OnParentVersionCopyTest; +import org.apache.jackrabbit.test.api.version.OnParentVersionIgnoreTest; +import org.apache.jackrabbit.test.api.version.OnParentVersionInitializeTest; +import org.apache.jackrabbit.test.api.version.RemoveVersionTest; +import org.apache.jackrabbit.test.api.version.RestoreTest; +import org.apache.jackrabbit.test.api.version.SessionMoveVersionExceptionTest; +import org.apache.jackrabbit.test.api.version.VersionGraphTest; +import org.apache.jackrabbit.test.api.version.VersionHistoryTest; +import org.apache.jackrabbit.test.api.version.VersionLabelTest; +import org.apache.jackrabbit.test.api.version.VersionStorageTest; +import org.apache.jackrabbit.test.api.version.VersionTest; +import org.apache.jackrabbit.test.api.version.WorkspaceMoveVersionExceptionTest; +import org.apache.jackrabbit.test.api.version.WorkspaceRestoreTest; /** * Test suite to wrap Apache Jackrabbit JCR technology compatibility kit (TCK) unit tests. Note that technically these are not the @@ -125,9 +154,11 @@ public class JcrTckTest { // Or uncomment the following lines to execute the different sets/suites of tests ... TestSuite suite = new TestSuite("JCR 1.0 API tests"); - suite.addTest(new LevelOneFeatureTests()); - suite.addTest(new LevelTwoFeatureTests()); - suite.addTest(new OptionalFeatureTests()); + //suite.addTest(new LevelOneFeatureTests()); + //suite.addTest(new LevelTwoFeatureTests()); + //suite.addTest(new OptionalFeatureTests()); + suite.addTest(new VersioningTests()); // remove this and the ObservationTests inner class when all tests pass and uncomment + return suite; } @@ -292,6 +323,7 @@ public class JcrTckTest { // See https://jira.jboss.org/jira/browse/ModeShape-285 addTest(new ObservationTests()); // remove this and the ObservationTests inner class when all tests pass and uncomment + addTest(new VersioningTests()); // remove this and the VersionTests inner class when all tests pass and uncomment // observation.TestAll // addTest(org.apache.jackrabbit.test.api.observation.TestAll.suite()); // addTest(org.apache.jackrabbit.test.api.version.TestAll.suite()); @@ -320,4 +352,43 @@ public class JcrTckTest { // addTestSuite(WorkspaceOperationTest.class); } } + + private static class VersioningTests extends TestSuite { + protected VersioningTests() { + super("JCR Versioning Tests"); + + addTestSuite(VersionTest.class); + addTestSuite(VersionHistoryTest.class); + addTestSuite(VersionStorageTest.class); + addTestSuite(VersionLabelTest.class); + addTestSuite(CheckoutTest.class); + addTestSuite(CheckinTest.class); + addTestSuite(VersionGraphTest.class); + addTestSuite(RemoveVersionTest.class); + addTestSuite(RestoreTest.class); + addTestSuite(WorkspaceRestoreTest.class); + addTestSuite(OnParentVersionAbortTest.class); + addTestSuite(OnParentVersionComputeTest.class); + addTestSuite(OnParentVersionCopyTest.class); + addTestSuite(OnParentVersionIgnoreTest.class); + addTestSuite(OnParentVersionInitializeTest.class); + addTestSuite(GetReferencesNodeTest.class); + addTestSuite(GetPredecessorsTest.class); + addTestSuite(GetCreatedTest.class); + addTestSuite(GetContainingHistoryTest.class); + addTestSuite(GetVersionableUUIDTest.class); + addTestSuite(SessionMoveVersionExceptionTest.class); + addTestSuite(WorkspaceMoveVersionExceptionTest.class); + addTestSuite(MergeCancelMergeTest.class); + addTestSuite(MergeCheckedoutSubNodeTest.class); + addTestSuite(MergeDoneMergeTest.class); + addTestSuite(MergeNodeIteratorTest.class); + addTestSuite(MergeNodeTest.class); + addTestSuite(MergeNonVersionableSubNodeTest.class); + addTestSuite(MergeSubNodeTest.class); + + // addTest(org.apache.jackrabbit.test.api.version.TestAll.suite()); + } + } + } Index: modeshape-jcr/src/test/resources/repositoryStubImpl.properties =================================================================== --- modeshape-jcr/src/test/resources/repositoryStubImpl.properties (revision 1691) +++ modeshape-jcr/src/test/resources/repositoryStubImpl.properties (working copy) @@ -50,6 +50,10 @@ javax.jcr.tck.NodeOrderableChildNodesTest.testOrderBeforeUnsupportedRepositoryOp javax.jcr.tck.SaveTest.nodetype=nt\:query javax.jcr.tck.SetPropertyAssumeTypeTest.nodetype=modetest\:setPropertyAssumeTypeTest +# version test types +javax.jcr.tck.versionableNodeType=modetest\:versionableUnstructured +javax.jcr.tck.propertyValue=31337 + # Test users javax.jcr.tck.superuser.name=superuser javax.jcr.tck.superuser.pwd=superuser Index: modeshape-jcr/src/test/resources/tck/tck_test_types.cnd =================================================================== --- modeshape-jcr/src/test/resources/tck/tck_test_types.cnd (revision 1691) +++ modeshape-jcr/src/test/resources/tck/tck_test_types.cnd (working copy) @@ -26,3 +26,5 @@ - prop1 (PATH) copy - * (*) copy - * (*) multiple copy + +[modetest:versionableUnstructured] > nt:unstructured, mix:versionable