Index: modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java
===================================================================
--- modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java (revision 1893)
+++ modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java (working copy)
@@ -1734,19 +1734,6 @@ 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(JcrI18n.requiresVersionable.text());
- }
- }
-
- /**
* Throw a {@link ConstraintViolationException} if this node is protected (based on the its node definition).
*
* @throws ConstraintViolationException if this node's definition indicates that the node is protected
@@ -1779,9 +1766,6 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node
* @see javax.jcr.Node#checkin()
*/
public final Version checkin() throws RepositoryException {
- checkSession();
- checkVersionable();
-
return versionManager().checkin(this);
}
@@ -1791,9 +1775,6 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node
* @see javax.jcr.Node#checkout()
*/
public final void checkout() throws UnsupportedRepositoryOperationException, LockException, RepositoryException {
- checkSession();
- checkVersionable();
-
versionManager().checkout(this);
}
@@ -1806,10 +1787,9 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node
boolean bestEffort ) throws ConstraintViolationException, RepositoryException {
CheckArg.isNotNull(srcWorkspace, "source workspace name");
- checkSession();
checkNotProtected();
- return versionManager().merge(this, srcWorkspace, bestEffort);
+ return versionManager().merge(this, srcWorkspace, bestEffort, false);
}
/**
@@ -1818,9 +1798,6 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node
* @see javax.jcr.Node#cancelMerge(javax.jcr.version.Version)
*/
public final void cancelMerge( Version version ) throws RepositoryException {
- checkSession();
- checkVersionable();
-
versionManager().cancelMerge(this, version);
}
@@ -1830,9 +1807,6 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node
* @see javax.jcr.Node#doneMerge(javax.jcr.version.Version)
*/
public final void doneMerge( Version version ) throws RepositoryException {
- checkSession();
- checkVersionable();
-
versionManager().doneMerge(this, version);
}
@@ -1842,9 +1816,6 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node
* @see javax.jcr.Node#getVersionHistory()
*/
public final JcrVersionHistoryNode getVersionHistory() throws RepositoryException {
- checkSession();
- checkVersionable();
-
return versionManager().getVersionHistory(this);
}
@@ -1855,7 +1826,6 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node
*/
public final JcrVersionNode getBaseVersion() throws RepositoryException {
checkSession();
- checkVersionable();
// This can happen if the versionable type was added to the node, but it hasn't been saved yet
if (!hasProperty(JcrLexicon.BASE_VERSION)) {
@@ -1882,7 +1852,6 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node
*/
public final void restore( Version version,
boolean removeExisting ) throws RepositoryException {
- checkSession();
try {
checkNotProtected();
} catch (ConstraintViolationException cve) {
@@ -1899,7 +1868,6 @@ abstract class AbstractJcrNode extends AbstractJcrItem implements javax.jcr.Node
public final void restore( Version version,
String relPath,
boolean removeExisting ) throws RepositoryException {
- checkSession();
checkNotProtected();
PathFactory pathFactory = context().getValueFactories().getPathFactory();
Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrLexicon.java
===================================================================
--- modeshape-jcr/src/main/java/org/modeshape/jcr/JcrLexicon.java (revision 1893)
+++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrLexicon.java (working copy)
@@ -36,6 +36,7 @@ public class JcrLexicon extends org.modeshape.graph.JcrLexicon {
public static final Name BASE_VERSION = new BasicName(Namespace.URI, "baseVersion");
public static final Name CHILD_VERSION_HISTORY = new BasicName(Namespace.URI, "childVersionHistory");
public static final Name CONTENT = new BasicName(Namespace.URI, "content");
+ public static final Name COPIED_FROM = new BasicName(Namespace.URI, "copiedFrom");
public static final Name CREATED = new BasicName(Namespace.URI, "created");
public static final Name DATA = new BasicName(Namespace.URI, "data");
public static final Name ENCODING = new BasicName(Namespace.URI, "encoding");
Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrRepository.java
===================================================================
--- modeshape-jcr/src/main/java/org/modeshape/jcr/JcrRepository.java (revision 1893)
+++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrRepository.java (working copy)
@@ -1257,7 +1257,6 @@ public class JcrRepository implements Repository {
repoDescriptors.put(Repository.OPTION_JOURNALED_OBSERVATION_SUPPORTED, valueFor(factories, false));
repoDescriptors.put(Repository.OPTION_RETENTION_SUPPORTED, valueFor(factories, false));
repoDescriptors.put(Repository.OPTION_LIFECYCLE_SUPPORTED, valueFor(factories, false));
- repoDescriptors.put(Repository.OPTION_TRANSACTIONS_SUPPORTED, valueFor(factories, false));
repoDescriptors.put(Repository.OPTION_WORKSPACE_MANAGEMENT_SUPPORTED, valueFor(factories, false));
repoDescriptors.put(Repository.OPTION_NODE_AND_PROPERTY_WITH_SAME_NAME_SUPPORTED, valueFor(factories, true));
repoDescriptors.put(Repository.OPTION_UPDATE_PRIMARY_NODE_TYPE_SUPPORTED, valueFor(factories, false));
@@ -1284,7 +1283,7 @@ public class JcrRepository implements Repository {
repoDescriptors.put(Repository.QUERY_FULL_TEXT_SEARCH_SUPPORTED, valueFor(factories, true));
repoDescriptors.put(Repository.QUERY_JOINS, valueFor(factories, Repository.QUERY_JOINS_INNER_OUTER));
repoDescriptors.put(Repository.SPEC_NAME_DESC, valueFor(factories, JcrI18n.SPEC_NAME_DESC.text()));
- repoDescriptors.put(Repository.SPEC_VERSION_DESC, valueFor(factories, "1.0"));
+ repoDescriptors.put(Repository.SPEC_VERSION_DESC, valueFor(factories, "2.0"));
if (!repoDescriptors.containsKey(Repository.REP_NAME_DESC)) {
repoDescriptors.put(Repository.REP_NAME_DESC,
Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrSession.java
===================================================================
--- modeshape-jcr/src/main/java/org/modeshape/jcr/JcrSession.java (revision 1893)
+++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrSession.java (working copy)
@@ -264,6 +264,16 @@ class JcrSession implements Session {
return this.repository.getRepositorySourceName();
}
+ Path pathFor( String path,
+ String parameterName ) throws RepositoryException {
+ try {
+ return this.executionContext.getValueFactories().getPathFactory().create(path);
+
+ } catch (org.modeshape.graph.property.ValueFormatException vfe) {
+ throw new RepositoryException(JcrI18n.invalidPathParameter.text(path, parameterName), vfe);
+ }
+ }
+
/**
* {@inheritDoc}
*
@@ -774,7 +784,7 @@ class JcrSession implements Session {
* @see javax.jcr.Session#getNodeByIdentifier(java.lang.String)
*/
@Override
- public Node getNodeByIdentifier( String id ) throws ItemNotFoundException, RepositoryException {
+ public AbstractJcrNode getNodeByIdentifier( String id ) throws ItemNotFoundException, RepositoryException {
// Attempt to create a UUID from the identifier ...
try {
return cache.findJcrNode(Location.create(UUID.fromString(id)));
Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionHistoryNode.java
===================================================================
--- modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionHistoryNode.java (revision 1893)
+++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionHistoryNode.java (working copy)
@@ -24,10 +24,12 @@
package org.modeshape.jcr;
import java.util.Collection;
+import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import javax.jcr.AccessDeniedException;
+import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.PathNotFoundException;
import javax.jcr.Property;
@@ -324,22 +326,36 @@ class JcrVersionHistoryNode extends JcrNode implements VersionHistory {
@Override
public NodeIterator getAllFrozenNodes() throws RepositoryException {
- throw new UnsupportedRepositoryOperationException();
+ return new FrozenNodeIterator(getAllVersions());
}
@Override
public NodeIterator getAllLinearFrozenNodes() throws RepositoryException {
- throw new UnsupportedRepositoryOperationException();
+ return new FrozenNodeIterator(getAllLinearVersions());
}
@Override
public VersionIterator getAllLinearVersions() throws RepositoryException {
- throw new UnsupportedRepositoryOperationException();
+ AbstractJcrNode existingNode = session().getNodeByIdentifier(getVersionableIdentifier());
+ if (existingNode == null) return getAllVersions();
+
+ assert existingNode.isNodeType(JcrMixLexicon.VERSIONABLE);
+
+ LinkedList versions = new LinkedList();
+ JcrVersionNode baseVersion = existingNode.getBaseVersion();
+
+ while (baseVersion != null) {
+ versions.addFirst(baseVersion);
+ baseVersion = baseVersion.getLinearPredecessor();
+ }
+
+ return new LinearVersionIterator(versions, versions.size());
}
@Override
public String getVersionableIdentifier() throws RepositoryException {
- throw new UnsupportedRepositoryOperationException();
+ // ModeShape uses a node's UUID as it's identifier
+ return getVersionableUUID();
}
/**
@@ -457,4 +473,110 @@ class JcrVersionHistoryNode extends JcrNode implements VersionHistory {
throw new UnsupportedOperationException();
}
}
+
+ /**
+ * An implementation of {@link VersionIterator} that iterates over a given set of versions. This differs from
+ * {@link JcrVersionIterator} in that it expects an exact list of versions to iterate over whereas {@code JcrVersionIterator}
+ * expects list of children for a {@code nt:versionHistory} node and filters out the label child.
+ */
+ class LinearVersionIterator implements VersionIterator {
+
+ private final Iterator extends Version> versions;
+ private final int size;
+ private int pos;
+
+ protected LinearVersionIterator( Iterable extends Version> versions,
+ int size ) {
+ this.versions = versions.iterator();
+ this.size = size;
+ this.pos = 0;
+ }
+
+ @Override
+ public long getPosition() {
+ return pos;
+ }
+
+ @Override
+ public long getSize() {
+ return this.size;
+ }
+
+ @Override
+ public void skip( long skipNum ) {
+ while (skipNum-- > 0 && versions.hasNext()) {
+ versions.next();
+ pos++;
+ }
+
+ }
+
+ @Override
+ public Version nextVersion() {
+ return versions.next();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return versions.hasNext();
+ }
+
+ @Override
+ public Object next() {
+ return nextVersion();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ class FrozenNodeIterator implements NodeIterator {
+ private final VersionIterator versions;
+
+ FrozenNodeIterator( VersionIterator versionIter ) {
+ this.versions = versionIter;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return versions.hasNext();
+ }
+
+ @Override
+ public Object next() {
+ return nextNode();
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Node nextNode() {
+ try {
+ return versions.nextVersion().getFrozenNode();
+ } catch (RepositoryException re) {
+ // ModeShape doesn't throw a RepositoryException on getFrozenNode() from a valid version node
+ throw new IllegalStateException(re);
+ }
+ }
+
+ @Override
+ public long getPosition() {
+ return versions.getPosition();
+ }
+
+ @Override
+ public long getSize() {
+ return versions.getSize();
+ }
+
+ @Override
+ public void skip( long skipNum ) {
+ versions.skip(skipNum);
+ }
+ }
}
Index: modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionManager.java
===================================================================
--- modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionManager.java (revision 1893)
+++ modeshape-jcr/src/main/java/org/modeshape/jcr/JcrVersionManager.java (working copy)
@@ -64,6 +64,7 @@ import net.jcip.annotations.NotThreadSafe;
import org.modeshape.common.i18n.I18n;
import org.modeshape.common.text.Jsr283Encoder;
import org.modeshape.common.text.TextEncoder;
+import org.modeshape.common.util.CheckArg;
import org.modeshape.common.util.Logger;
import org.modeshape.graph.ExecutionContext;
import org.modeshape.graph.Graph;
@@ -196,6 +197,8 @@ final class JcrVersionManager implements VersionManager {
*/
JcrVersionHistoryNode getVersionHistory( AbstractJcrNode node ) throws RepositoryException {
session.checkLive();
+ checkVersionable(node);
+
Location historyLocation = Location.create(versionHistoryPathFor(node.uuid()));
try {
return (JcrVersionHistoryNode)cache().findJcrNode(historyLocation);
@@ -234,6 +237,9 @@ final class JcrVersionManager implements VersionManager {
*/
JcrVersionNode checkin( AbstractJcrNode node ) throws RepositoryException {
+ session.checkLive();
+ checkVersionable(node);
+
if (node.isNew() || node.isModified()) {
throw new InvalidItemStateException(JcrI18n.noPendingChangesAllowed.text());
}
@@ -269,20 +275,13 @@ final class JcrVersionManager implements VersionManager {
Path versionPath = path(historyPath, name(NODE_ENCODER.encode(now.getString())));
AbstractJcrProperty predecessorsProp = node.getProperty(JcrLexicon.PREDECESSORS);
- systemBatch.create(versionPath)
- .with(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.VERSION)
- .and(JcrLexicon.CREATED, now)
- .and(JcrLexicon.UUID, versionUuid)
- .and(predecessorsProp.property())
- .and();
+ systemBatch.create(versionPath).with(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.VERSION).and(JcrLexicon.CREATED, now).and(JcrLexicon.UUID,
+ versionUuid).and(predecessorsProp.property()).and();
Path frozenVersionPath = path(versionPath, JcrLexicon.FROZEN_NODE);
- systemBatch.create(frozenVersionPath)
- .with(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.FROZEN_NODE)
- .and(JcrLexicon.FROZEN_UUID, jcrUuid)
- .and(JcrLexicon.FROZEN_PRIMARY_TYPE, primaryTypeName)
- .and(JcrLexicon.FROZEN_MIXIN_TYPES, mixinTypeNames)
- .and(versionedPropertiesFor(node))
- .and();
+ systemBatch.create(frozenVersionPath).with(JcrLexicon.PRIMARY_TYPE, JcrNtLexicon.FROZEN_NODE).and(JcrLexicon.FROZEN_UUID,
+ jcrUuid).and(JcrLexicon.FROZEN_PRIMARY_TYPE,
+ primaryTypeName).and(JcrLexicon.FROZEN_MIXIN_TYPES,
+ mixinTypeNames).and(versionedPropertiesFor(node)).and();
int onParentVersion = node.getDefinition().getOnParentVersion();
for (NodeIterator childNodes = node.getNodes(); childNodes.hasNext();) {
@@ -295,21 +294,24 @@ final class JcrVersionManager implements VersionManager {
for (Object ob : predecessorsProp.property()) {
UUID predUuid = uuid(ob);
- org.modeshape.graph.property.Property successorsProp = systemGraph.getNodeAt(predUuid)
- .getProperty(JcrLexicon.SUCCESSORS);
+ org.modeshape.graph.property.Property successorsProp = systemGraph.getNodeAt(predUuid).getProperty(JcrLexicon.SUCCESSORS);
List