You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2004/10/26 17:44:47 UTC
svn commit: rev 55615 - in incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core: . nodetype state util version virtual
Author: tripod
Date: Tue Oct 26 08:44:46 2004
New Revision: 55615
Added:
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ChildrenCollectorFilter.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/DefaultItemStateProvider.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java (contents, props changed)
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java (contents, props changed)
Removed:
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/NodeWrapper.java
Modified:
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/InternalValue.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemState.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeState.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PropertyState.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenVersionHistory.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentNode.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentProperty.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionIteratorImpl.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java
incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/package.html
Log:
- adapted versioning again to spec 0.15
- added VirtualItemStateManager for reflecting virtual content
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/InternalValue.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/InternalValue.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/InternalValue.java Tue Oct 26 08:44:46 2004
@@ -215,6 +215,30 @@
}
/**
+ * @param values
+ * @return
+ */
+ public static InternalValue[] create(QName[] values) {
+ InternalValue[] ret = new InternalValue[values.length];
+ for (int i=0; i<values.length; i++) {
+ ret[i] = new InternalValue(values[i]);
+ }
+ return ret;
+ }
+
+ /**
+ * @param values
+ * @return
+ */
+ public static InternalValue[] create(String[] values) {
+ InternalValue[] ret = new InternalValue[values.length];
+ for (int i=0; i<values.length; i++) {
+ ret[i] = new InternalValue(values[i]);
+ }
+ return ret;
+ }
+
+ /**
* @param value
* @return
*/
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemImpl.java Tue Oct 26 08:44:46 2004
@@ -314,7 +314,7 @@
*
* @return the primary path to this <code>Item</code>
*/
- protected Path getPrimaryPath() throws RepositoryException {
+ public Path getPrimaryPath() throws RepositoryException {
return session.getHierarchyManager().getPath(id);
}
@@ -782,7 +782,7 @@
if (itemState.isNode() && itemState.getStatus() == ItemState.STATUS_NEW) {
NodeImpl node = (NodeImpl) itemMgr.getItem(itemState.getId());
if (node.isNodeType(NodeTypeRegistry.MIX_VERSIONABLE)) {
- VersionHistory hist = rep.getVersionManager().createVersionHistory(node);
+ VersionHistory hist = session.versionMgr.createVersionHistory(node);
node.internalSetProperty(VersionManager.PROPNAME_VERSION_HISTORY, InternalValue.create(new UUID(hist.getUUID())));
node.internalSetProperty(VersionManager.PROPNAME_BASE_VERSION, InternalValue.create(new UUID(hist.getRootVersion().getUUID())));
node.internalSetProperty(VersionManager.PROPNAME_IS_CHECKED_OUT, InternalValue.create(true));
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/ItemManager.java Tue Oct 26 08:44:46 2004
@@ -18,16 +18,14 @@
import org.apache.commons.collections.ReferenceMap;
import org.apache.jackrabbit.core.state.*;
import org.apache.jackrabbit.core.util.IteratorHelper;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
import org.apache.log4j.Logger;
import javax.jcr.*;
import javax.jcr.nodetype.NodeDef;
import javax.jcr.nodetype.PropertyDef;
import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Map;
+import java.util.*;
/**
* There's one <code>ItemManager</code> instance per <code>Session</code>
@@ -156,6 +154,7 @@
}
/**
+ * Checks if the item with the given id exists
* @param id
* @return
*/
@@ -335,6 +334,8 @@
}
}
+ // not need to add virtual properties
+
return new IteratorHelper(Collections.unmodifiableList(children));
}
@@ -368,8 +369,17 @@
// in order to maintain item cache consistency
ItemLifeCycleListener[] listeners = new ItemLifeCycleListener[]{this};
- // create node object
- return new NodeImpl(this, session, id, state, def, listeners);
+
+ // check spezial nodes
+ if (state.getNodeTypeName().equals(NodeTypeRegistry.NT_VERSION)) {
+ return session.versionMgr.createVersionInstance(session, state, def, this, listeners);
+ } else if (state.getNodeTypeName().equals(NodeTypeRegistry.NT_VERSION_HISTORY)) {
+ return session.versionMgr.createVersionHistoryInstance(session, state, def, this, listeners);
+ } else {
+ // create node object
+ return new NodeImpl(this, session, id, state, def, listeners);
+ }
+
}
NodeImpl createNodeInstance(NodeState state) throws RepositoryException {
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/NodeImpl.java Tue Oct 26 08:44:46 2004
@@ -19,6 +19,7 @@
import org.apache.jackrabbit.core.state.*;
import org.apache.jackrabbit.core.util.ChildrenCollector;
import org.apache.jackrabbit.core.util.IteratorHelper;
+import org.apache.jackrabbit.core.util.ChildrenCollectorFilter;
import org.apache.jackrabbit.core.util.uuid.UUID;
import org.apache.jackrabbit.core.version.*;
import org.apache.log4j.Logger;
@@ -27,7 +28,6 @@
import javax.jcr.lock.Lock;
import javax.jcr.lock.LockException;
import javax.jcr.nodetype.*;
-import javax.jcr.util.TraversingItemVisitor;
import javax.jcr.version.Version;
import javax.jcr.version.VersionException;
import javax.jcr.version.VersionHistory;
@@ -482,16 +482,16 @@
// check for name collisions
try {
- ItemImpl item = itemMgr.getItem(nodePath);
+ Item item = itemMgr.getItem(nodePath);
if (!item.isNode()) {
// there's already a property with that name
- throw new ItemExistsException(item.safeGetJCRPath());
+ throw new ItemExistsException(itemMgr.safeGetJCRPath(nodePath));
} else {
// there's already a node with that name
// check same-name sibling setting of both new and existing node
if (!def.allowSameNameSibs()
|| !((NodeImpl) item).getDefinition().allowSameNameSibs()) {
- throw new ItemExistsException(item.safeGetJCRPath());
+ throw new ItemExistsException(itemMgr.safeGetJCRPath(nodePath));
}
}
} catch (PathNotFoundException pnfe) {
@@ -1655,7 +1655,7 @@
if (!entExisting.includesNodeType(NodeTypeRegistry.MIX_VERSIONABLE) &&
entNew.includesNodeType(NodeTypeRegistry.MIX_VERSIONABLE)) {
// node has become 'versionable', initialize version history
- VersionHistory hist = rep.getVersionManager().createVersionHistory(this);
+ VersionHistory hist = session.versionMgr.createVersionHistory(this);
internalSetProperty(VersionManager.PROPNAME_VERSION_HISTORY, InternalValue.create(new UUID(hist.getUUID())));
internalSetProperty(VersionManager.PROPNAME_BASE_VERSION, InternalValue.create(new UUID(hist.getRootVersion().getUUID())));
internalSetProperty(VersionManager.PROPNAME_IS_CHECKED_OUT, InternalValue.create(true));
@@ -2010,7 +2010,7 @@
log.debug(msg);
throw new IllegalStateException(msg);
}
- Version v = rep.getVersionManager().checkin(this);
+ Version v = session.versionMgr.checkin(this);
Property prop = internalSetProperty(VersionManager.PROPNAME_IS_CHECKED_OUT, InternalValue.create(false));
prop.save();
prop = internalSetProperty(VersionManager.PROPNAME_BASE_VERSION, InternalValue.create(new UUID(v.getUUID())));
@@ -2563,7 +2563,7 @@
restoreFrozenState(version.getFrozenNode(), vsel);
// 2. N�s jcr:baseVersion property will be changed to point to V.
- internalSetProperty(VersionManager.PROPNAME_BASE_VERSION, InternalValue.create(new UUID(version.getUUID())));
+ internalSetProperty(VersionManager.PROPNAME_BASE_VERSION, InternalValue.create(new UUID(version.getId())));
// 3. N�s jcr:isCheckedOut property is set to false.
internalSetProperty(VersionManager.PROPNAME_IS_CHECKED_OUT, InternalValue.create(false));
@@ -2632,11 +2632,10 @@
internalSetProperty(props[i].getName(), prop.getValues()[0]);
continue;
} catch (RepositoryException e) {
-// ignore and try multiple below
+ // ignore and try multiple below
}
}
internalSetProperty(props[i].getName(), prop.getValues());
-
}
// restore the frozen nodes
@@ -2658,7 +2657,7 @@
// do nothing
} else {
// get desired version from version selector
- VersionHistory history = ((InternalFrozenVersionHistory) child).getVersionHistory(session);
+ VersionHistory history = (VersionHistory) session.getNodeByUUID(((InternalFrozenVersionHistory) child).getVersionHistoryId());
InternalVersion v = ((VersionImpl) vsel.select(history)).getInternalVersion();
NodeImpl node = addNode(child.getName(), v.getFrozenNode());
node.internalRestore(v, vsel);
@@ -2673,7 +2672,7 @@
public VersionHistory getVersionHistory()
throws UnsupportedRepositoryOperationException, RepositoryException {
checkVersionable();
- return rep.getVersionManager().getVersionHistory(this);
+ return session.versionMgr.getVersionHistory(this);
}
/**
@@ -2682,7 +2681,7 @@
public Version getBaseVersion()
throws UnsupportedRepositoryOperationException, RepositoryException {
checkVersionable();
- return rep.getVersionManager().getBaseVersion(this);
+ return session.versionMgr.getBaseVersion(this);
}
/**
@@ -2772,151 +2771,5 @@
public boolean isLocked() throws RepositoryException {
// @todo implement locking support
return false;
- }
-}
-
-/**
- * <code>ChildrenCollectorFilter</code> is a utility class
- * which can be used to 'collect' child items of a
- * node whose names match a certain pattern. It implements the
- * <code>ItemVisitor</code> interface.
- */
-class ChildrenCollectorFilter extends TraversingItemVisitor.Default {
- static final char WILDCARD_CHAR = '*';
- static final String OR = "|";
-
- private final Collection children;
- private final boolean collectNodes;
- private final boolean collectProperties;
- private final String namePattern;
-
- /**
- * Constructs a <code>ChildrenCollectorFilter</code>
- *
- * @param namePattern the pattern which should be applied to the names
- * of the children
- * @param children where the matching children should be added
- * @param collectNodes true, if child nodes should be collected; otherwise false
- * @param collectProperties true, if child properties should be collected; otherwise false
- * @param maxLevel umber of hierarchy levels to traverse
- * (e.g. 1 for direct children only, 2 for children and their children, and so on)
- */
- ChildrenCollectorFilter(String namePattern, Collection children, boolean collectNodes, boolean collectProperties, int maxLevel) {
- super(false, maxLevel);
- this.namePattern = namePattern;
- this.children = children;
- this.collectNodes = collectNodes;
- this.collectProperties = collectProperties;
- }
-
- /**
- * @see TraversingItemVisitor#entering(Node, int)
- */
- protected void entering(Node node, int level)
- throws RepositoryException {
- if (level > 0 && collectNodes) {
- if (matches(node.getName(), namePattern)) {
- children.add(node);
- }
- }
- }
-
- /**
- * @see TraversingItemVisitor#entering(Property, int)
- */
- protected void entering(Property property, int level)
- throws RepositoryException {
- if (level > 0 && collectProperties) {
- if (matches(property.getName(), namePattern)) {
- children.add(property);
- }
- }
- }
-
- /**
- * Applies the name pattern against the specified name.
- * <p/>
- * The pattern may be a full name or a partial name with one or more
- * wildcard characters ("*"), or a disjunction (using the "|" character
- * to represent logical <i>OR</i>) of these. For example,
- * <p/>
- * <code>"jcr:*|foo:bar"</code>
- * <p/>
- * would match
- * <p/>
- * <code>"foo:bar"</code>, but also <code>"jcr:whatever"</code>.
- *
- * @param name the name to test the pattern with
- * @return true if the specified name matches the pattern
- */
- static boolean matches(String name, String pattern) {
- // split pattern
- StringTokenizer st = new StringTokenizer(pattern, OR, false);
- while (st.hasMoreTokens()) {
- if (internalMatches(name, st.nextToken(), 0, 0)) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Internal helper used to recursively match the pattern
- *
- * @param s The string to be tested
- * @param pattern The pattern
- * @param sOff offset within <code>s</code>
- * @param pOff offset within <code>pattern</code>.
- * @return true if <code>s</code> matched pattern, else false.
- */
- private static boolean internalMatches(String s, String pattern, int sOff, int pOff) {
- int pLen = pattern.length();
- int sLen = s.length();
-
- for (; ;) {
- if (pOff >= pLen) {
- if (sOff >= sLen) {
- return true;
- } else if (s.charAt(sOff) == '[') {
- // check for subscript notation (e.g. "whatever[1]")
-
- // the entire pattern matched up to the subscript:
- // -> ignore the subscript
- return true;
- } else {
- return false;
- }
- }
- if (sOff >= sLen && pattern.charAt(pOff) != WILDCARD_CHAR) {
- return false;
- }
-
- // check for a '*' as the next pattern char;
- // this is handled by a recursive call for
- // each postfix of the name.
- if (pattern.charAt(pOff) == WILDCARD_CHAR) {
- if (++pOff >= pLen) {
- return true;
- }
-
- for (; ;) {
- if (internalMatches(s, pattern, sOff, pOff)) {
- return true;
- }
- if (sOff >= sLen) {
- return false;
- }
- sOff++;
- }
- }
-
- if (pOff < pLen && sOff < sLen) {
- if (pattern.charAt(pOff) != s.charAt(sOff)) {
- return false;
- }
- }
- pOff++;
- sOff++;
- }
}
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java Tue Oct 26 08:44:46 2004
@@ -27,7 +27,7 @@
import org.apache.jackrabbit.core.state.tx.TransactionManager;
import org.apache.jackrabbit.core.state.tx.XASessionImpl;
import org.apache.jackrabbit.core.util.uuid.UUID;
-import org.apache.jackrabbit.core.version.VersionManager;
+import org.apache.jackrabbit.core.version.PersistentVersionManager;
import org.apache.log4j.Logger;
import javax.jcr.*;
@@ -79,7 +79,7 @@
private final NamespaceRegistryImpl nsReg;
private final NodeTypeRegistry ntReg;
- private final VersionManager vMgr;
+ private final PersistentVersionManager vMgr;
private final TransactionManager txMgr;
// configuration of the repository
@@ -295,7 +295,7 @@
log.error(msg, npde);
throw new RepositoryException(msg, npde);
}
- vMgr = new VersionManager(verSession);
+ vMgr = new PersistentVersionManager(verSession);
// load repository properties
repProps = new Properties();
@@ -375,7 +375,7 @@
return ntReg;
}
- VersionManager getVersionManager() {
+ PersistentVersionManager getPersistentVersionManager() {
// check state
if (disposed) {
throw new IllegalStateException("repository instance has been shut down");
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/SessionImpl.java Tue Oct 26 08:44:46 2004
@@ -22,6 +22,7 @@
import org.apache.jackrabbit.core.state.PersistentItemStateProvider;
import org.apache.jackrabbit.core.state.SessionItemStateManager;
import org.apache.jackrabbit.core.xml.ImportHandler;
+import org.apache.jackrabbit.core.version.VersionManager;
import org.apache.log4j.Logger;
import org.xml.sax.ContentHandler;
import org.xml.sax.InputSource;
@@ -105,6 +106,11 @@
protected final TransientNamespaceMappings nsMappings;
/**
+ * The version manager for this session
+ */
+ protected final VersionManager versionMgr;
+
+ /**
* Protected constructor.
*
* @param rep
@@ -145,6 +151,16 @@
hierMgr = itemStateMgr.getHierarchyMgr();
itemMgr = createItemManager(itemStateMgr, hierMgr);
accessMgr = createAccessManager(credentials, hierMgr);
+ versionMgr = rep.getPersistentVersionManager()==null?null:rep.getPersistentVersionManager().getVersionManager();
+
+ // add virtual item managers only for normal sessions
+ if (!(this instanceof SystemSession)) {
+ try {
+ itemStateMgr.addVirtualItemStateProvider(versionMgr.getVirtualItemStateProvider(itemStateMgr));
+ } catch (Exception e) {
+ log.error("Unable to add vmgr: " + e.toString(), e);
+ }
+ }
}
/**
@@ -169,6 +185,16 @@
itemStateMgr = new SessionItemStateManager(rep.getRootNodeUUID(), wsp.getPersistentStateManager(), getNamespaceResolver());
hierMgr = itemStateMgr.getHierarchyMgr();
itemMgr = createItemManager(itemStateMgr, hierMgr);
+ versionMgr = rep.getPersistentVersionManager()==null?null:rep.getPersistentVersionManager().getVersionManager();
+
+ // add virtual item managers only for normal sessions
+ if (!(this instanceof SystemSession)) {
+ try {
+ itemStateMgr.addVirtualItemStateProvider(versionMgr.getVirtualItemStateProvider(itemStateMgr));
+ } catch (Exception e) {
+ log.error("Unable to add vmgr: " + e.toString(), e);
+ }
+ }
}
/**
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/nodetype/builtin_nodetypes.xml Tue Oct 26 08:44:46 2004
@@ -139,7 +139,7 @@
<supertypes>
<supertype>nt:base</supertype>
</supertypes>
- <propertyDef name="jcr:name" type="Name" autoCreate="false" mandatory="true" onParentVersion="COPY" protected="false" primaryItem="false" multiple="false"/>
+ <propertyDef name="jcr:name" type="Name" autoCreate="false" mandatory="false" onParentVersion="COPY" protected="false" primaryItem="false" multiple="false"/>
<propertyDef name="jcr:type" type="String" autoCreate="false" mandatory="true" onParentVersion="COPY" protected="false" primaryItem="false" multiple="false"/>
<propertyDef name="jcr:valueConstraints" type="String" autoCreate="false" mandatory="true" onParentVersion="COPY" protected="false" primaryItem="false" multiple="true"/>
<propertyDef name="jcr:defaultValues" type="undefined" autoCreate="false" mandatory="true" onParentVersion="COPY" protected="false" primaryItem="false" multiple="true"/>
@@ -154,7 +154,7 @@
<supertypes>
<supertype>nt:base</supertype>
</supertypes>
- <propertyDef name="jcr:name" type="Name" autoCreate="false" mandatory="true" onParentVersion="COPY" protected="false" primaryItem="false" multiple="false"/>
+ <propertyDef name="jcr:name" type="Name" autoCreate="false" mandatory="false" onParentVersion="COPY" protected="false" primaryItem="false" multiple="false"/>
<propertyDef name="jcr:requiredPrimaryTypes" type="String" autoCreate="true" mandatory="true" onParentVersion="COPY" protected="false" primaryItem="false" multiple="true">
<defaultValues>
<defaultValue>nt:base</defaultValue>
@@ -199,28 +199,16 @@
</valueConstraints>
</propertyDef>
</nodeType>
- <nodeType name="nt:frozen" mixin="false" orderableChildNodes="false">
- <supertypes>
- <supertype>nt:base</supertype>
- </supertypes>
- <propertyDef name="jcr:frozenPrimaryType" type="Name" autoCreate="false" mandatory="true" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="false"/>
- <propertyDef name="jcr:frozenMixinTypes" type="Name" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="true"/>
- <propertyDef name="jcr:frozenUUID" type="String" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="false"/>
- <propertyDef name="*" type="undefined" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="true"/>
- <propertyDef name="*" type="undefined" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="false"/>
- <childNodeDef name="*" defaultPrimaryType="nt:frozen" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" sameNameSibs="true">
- <requiredPrimaryTypes>
- <requiredPrimaryType>nt:base</requiredPrimaryType>
- </requiredPrimaryTypes>
- </childNodeDef>
- </nodeType>
<nodeType name="nt:version" mixin="false" orderableChildNodes="false">
<supertypes>
- <supertype>nt:frozen</supertype>
+ <supertype>nt:base</supertype>
<supertype>mix:referenceable</supertype>
</supertypes>
<propertyDef name="jcr:versionLabels" type="String" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="true"/>
<propertyDef name="jcr:created" type="Date" autoCreate="true" mandatory="true" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="false"/>
+ <propertyDef name="jcr:frozenPrimaryType" type="Name" autoCreate="false" mandatory="true" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="false"/>
+ <propertyDef name="jcr:frozenMixinTypes" type="Name" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="true"/>
+ <propertyDef name="jcr:frozenUUID" type="String" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="false"/>
<propertyDef name="jcr:predecessors" type="Reference" autoCreate="true" mandatory="true" onParentVersion="ABORT" protected="true" primaryItem="false" multiple="true">
<valueConstraints>
<valueConstraint>nt:version</valueConstraint>
@@ -231,6 +219,11 @@
<valueConstraint>nt:version</valueConstraint>
</valueConstraints>
</propertyDef>
+ <childNodeDef name="jcr:frozen" defaultPrimaryType="nt:base" autoCreate="false" mandatory="false" onParentVersion="ABORT" protected="true" primaryItem="false" sameNameSibs="false">
+ <requiredPrimaryTypes>
+ <requiredPrimaryType>nt:base</requiredPrimaryType>
+ </requiredPrimaryTypes>
+ </childNodeDef>
</nodeType>
<nodeType name="nt:query" mixin="false" orderableChildNodes="false">
<supertypes>
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemState.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemState.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/ItemState.java Tue Oct 26 08:44:46 2004
@@ -65,6 +65,10 @@
* 'existing', i.e. persistent state that has been destroyed by somebody else
*/
public static final int STATUS_STALE_DESTROYED = 6;
+ /**
+ * 'virtual' status, i.e. persistent state is virtual
+ */
+ public static final int STATUS_EXISTING_VIRTUAL = 7;
protected int status = STATUS_UNDEFINED;
@@ -100,6 +104,10 @@
case STATUS_NEW:
status = initialStatus;
break;
+ case STATUS_EXISTING_VIRTUAL:
+ // todo: should be keep this state?
+ status = STATUS_EXISTING;
+ break;
default:
String msg = "illegal status: " + initialStatus;
log.error(msg);
@@ -125,6 +133,10 @@
case STATUS_EXISTING_MODIFIED:
case STATUS_EXISTING_REMOVED:
status = initialStatus;
+ break;
+ case STATUS_EXISTING_VIRTUAL:
+ // todo: should be keep this state?
+ status = STATUS_EXISTING;
break;
default:
String msg = "illegal status: " + initialStatus;
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeState.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeState.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/NodeState.java Tue Oct 26 08:44:46 2004
@@ -59,7 +59,7 @@
* @param overlayedState the backing node state being overlayed
* @param initialStatus the initial status of the node state object
*/
- NodeState(NodeState overlayedState, int initialStatus) {
+ protected NodeState(NodeState overlayedState, int initialStatus) {
super(overlayedState, initialStatus);
copy(overlayedState);
@@ -73,7 +73,7 @@
* @param parentUUID the UUID of the parent node
* @param initialStatus the initial status of the node state object
*/
- NodeState(String uuid, QName nodeTypeName, String parentUUID, int initialStatus) {
+ protected NodeState(String uuid, QName nodeTypeName, String parentUUID, int initialStatus) {
super(parentUUID, new NodeId(uuid), initialStatus);
if (parentUUID != null) {
parentUUIDs.add(parentUUID);
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PropertyState.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PropertyState.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/PropertyState.java Tue Oct 26 08:44:46 2004
@@ -58,7 +58,7 @@
* @param parentUUID the uuid of the parent node
* @param initialStatus the initial status of the property state object
*/
- PropertyState(QName name, String parentUUID, int initialStatus) {
+ protected PropertyState(QName name, String parentUUID, int initialStatus) {
super(parentUUID, new PropertyId(parentUUID, name), initialStatus);
this.name = name;
type = PropertyType.UNDEFINED;
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java Tue Oct 26 08:44:46 2004
@@ -16,6 +16,7 @@
package org.apache.jackrabbit.core.state;
import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider;
import org.apache.log4j.Logger;
import javax.jcr.RepositoryException;
@@ -30,6 +31,7 @@
private static Logger log = Logger.getLogger(SessionItemStateManager.class);
private final PersistentItemStateProvider persistentStateMgr;
+ private VirtualItemStateProvider[] virtualProviders = new VirtualItemStateProvider[0];
private final TransientItemStateManager transientStateMgr;
private final HierarchyManager hierMgr;
@@ -48,6 +50,17 @@
hierMgr = new HierarchyManagerImpl(rootNodeUUID, this, nsResolver);
}
+ /**
+ * Adds a new virtual item state provider
+ * @param prov
+ */
+ public synchronized void addVirtualItemStateProvider(VirtualItemStateProvider prov) {
+ VirtualItemStateProvider[] provs = new VirtualItemStateProvider[virtualProviders.length+1];
+ System.arraycopy(virtualProviders, 0, provs, 0, virtualProviders.length);
+ provs[virtualProviders.length] = prov;
+ virtualProviders = provs;
+ }
+
private synchronized void collectDescendantItemStates(ItemId id, List descendents) {
// XXX very inefficient implementation, especially if # of transient states
// is relatively small compared to the total # of persistent states
@@ -172,6 +185,13 @@
*/
public ItemState getItemState(ItemId id)
throws NoSuchItemStateException, ItemStateException {
+ // check if there is a virtual state for the specified item
+ for (int i=0; i<virtualProviders.length; i++) {
+ if (virtualProviders[i].hasItemState(id)) {
+ return virtualProviders[i].getItemState(id);
+ }
+ }
+
// first check if the specified item has been transiently removed
if (transientStateMgr.hasItemStateInAttic(id)) {
/**
@@ -183,25 +203,42 @@
*/
return transientStateMgr.getItemState(id);
}
- try {
- // check if there's transient state for the specified item
+
+ // check if there's transient state for the specified item
+ if (transientStateMgr.hasItemState(id)) {
return transientStateMgr.getItemState(id);
- } catch (NoSuchItemStateException nsise) {
- // check if there's persistent state for the specified item
+ }
+
+ // check if there's persistent state for the specified item
+ if (persistentStateMgr.hasItemState(id)) {
return persistentStateMgr.getItemState(id);
}
+
+ throw new NoSuchItemStateException(id.toString());
}
/**
* @see ItemStateProvider#hasItemState(ItemId)
*/
public boolean hasItemState(ItemId id) {
- try {
- getItemState(id);
- return true;
- } catch (ItemStateException ise) {
- return false;
+ return transientStateMgr.hasItemStateInAttic(id)
+ || transientStateMgr.hasItemState(id)
+ || persistentStateMgr.hasItemState(id)
+ || hasVirtualItemState(id);
+ }
+
+ /**
+ * Checks if there is a virtual item state
+ * @param id
+ * @return
+ */
+ private boolean hasVirtualItemState(ItemId id) {
+ for (int i=0; i<virtualProviders.length; i++) {
+ if (virtualProviders[i].hasItemState(id)) {
+ return true;
+ }
}
+ return false;
}
/**
@@ -216,12 +253,7 @@
* @see ItemStateProvider#hasItemStateInAttic(ItemId)
*/
public boolean hasItemStateInAttic(ItemId id) {
- try {
- getItemStateInAttic(id);
- return true;
- } catch (ItemStateException ise) {
- return false;
- }
+ return transientStateMgr.hasItemStateInAttic(id);
}
//< more methods for listing and retrieving transient ItemState instances >
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ChildrenCollectorFilter.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/util/ChildrenCollectorFilter.java Tue Oct 26 08:44:46 2004
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.jackrabbit.core.util;
+
+import javax.jcr.util.TraversingItemVisitor;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Property;
+import java.util.Collection;
+import java.util.StringTokenizer;
+
+/**
+ * <code>ChildrenCollectorFilter</code> is a utility class
+ * which can be used to 'collect' child items of a
+ * node whose names match a certain pattern. It implements the
+ * <code>ItemVisitor</code> interface.
+ */
+public class ChildrenCollectorFilter extends TraversingItemVisitor.Default {
+ static final char WILDCARD_CHAR = '*';
+ static final String OR = "|";
+
+ private final Collection children;
+ private final boolean collectNodes;
+ private final boolean collectProperties;
+ private final String namePattern;
+
+ /**
+ * Constructs a <code>ChildrenCollectorFilter</code>
+ *
+ * @param namePattern the pattern which should be applied to the names
+ * of the children
+ * @param children where the matching children should be added
+ * @param collectNodes true, if child nodes should be collected; otherwise false
+ * @param collectProperties true, if child properties should be collected; otherwise false
+ * @param maxLevel umber of hierarchy levels to traverse
+ * (e.g. 1 for direct children only, 2 for children and their children, and so on)
+ */
+ public ChildrenCollectorFilter(String namePattern, Collection children, boolean collectNodes, boolean collectProperties, int maxLevel) {
+ super(false, maxLevel);
+ this.namePattern = namePattern;
+ this.children = children;
+ this.collectNodes = collectNodes;
+ this.collectProperties = collectProperties;
+ }
+
+ /**
+ * @see TraversingItemVisitor#entering(javax.jcr.Node, int)
+ */
+ protected void entering(Node node, int level)
+ throws RepositoryException {
+ if (level > 0 && collectNodes) {
+ if (matches(node.getName(), namePattern)) {
+ children.add(node);
+ }
+ }
+ }
+
+ /**
+ * @see TraversingItemVisitor#entering(javax.jcr.Property, int)
+ */
+ protected void entering(Property property, int level)
+ throws RepositoryException {
+ if (level > 0 && collectProperties) {
+ if (matches(property.getName(), namePattern)) {
+ children.add(property);
+ }
+ }
+ }
+
+ /**
+ * Applies the name pattern against the specified name.
+ * <p/>
+ * The pattern may be a full name or a partial name with one or more
+ * wildcard characters ("*"), or a disjunction (using the "|" character
+ * to represent logical <i>OR</i>) of these. For example,
+ * <p/>
+ * <code>"jcr:*|foo:bar"</code>
+ * <p/>
+ * would match
+ * <p/>
+ * <code>"foo:bar"</code>, but also <code>"jcr:whatever"</code>.
+ *
+ * @param name the name to test the pattern with
+ * @return true if the specified name matches the pattern
+ */
+ static boolean matches(String name, String pattern) {
+ // split pattern
+ StringTokenizer st = new StringTokenizer(pattern, OR, false);
+ while (st.hasMoreTokens()) {
+ if (internalMatches(name, st.nextToken(), 0, 0)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Internal helper used to recursively match the pattern
+ *
+ * @param s The string to be tested
+ * @param pattern The pattern
+ * @param sOff offset within <code>s</code>
+ * @param pOff offset within <code>pattern</code>.
+ * @return true if <code>s</code> matched pattern, else false.
+ */
+ private static boolean internalMatches(String s, String pattern, int sOff, int pOff) {
+ int pLen = pattern.length();
+ int sLen = s.length();
+
+ for (; ;) {
+ if (pOff >= pLen) {
+ if (sOff >= sLen) {
+ return true;
+ } else if (s.charAt(sOff) == '[') {
+ // check for subscript notation (e.g. "whatever[1]")
+
+ // the entire pattern matched up to the subscript:
+ // -> ignore the subscript
+ return true;
+ } else {
+ return false;
+ }
+ }
+ if (sOff >= sLen && pattern.charAt(pOff) != WILDCARD_CHAR) {
+ return false;
+ }
+
+ // check for a '*' as the next pattern char;
+ // this is handled by a recursive call for
+ // each postfix of the name.
+ if (pattern.charAt(pOff) == WILDCARD_CHAR) {
+ if (++pOff >= pLen) {
+ return true;
+ }
+
+ for (; ;) {
+ if (internalMatches(s, pattern, sOff, pOff)) {
+ return true;
+ }
+ if (sOff >= sLen) {
+ return false;
+ }
+ sOff++;
+ }
+ }
+
+ if (pOff < pLen && sOff < sLen) {
+ if (pattern.charAt(pOff) != s.charAt(sOff)) {
+ return false;
+ }
+ }
+ pOff++;
+ sOff++;
+ }
+ }
+}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFreeze.java Tue Oct 26 08:44:46 2004
@@ -23,10 +23,33 @@
*/
public abstract class InternalFreeze {
+ /** the parent 'freeze' */
+ private final InternalFreeze parent;
+
+ /**
+ * Creates a new 'Freeze'
+ * @param parent
+ */
+ protected InternalFreeze(InternalFreeze parent) {
+ this.parent = parent;
+ }
+
/**
* Returns the name of the frozen node
*
* @return
*/
public abstract QName getName();
+
+ /**
+ * returns the version manager
+ * @return
+ */
+ public PersistentVersionManager getVersionManager() {
+ return parent==null ? null : parent.getVersionManager();
+ }
+
+ public InternalFreeze getParent() {
+ return parent;
+ }
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenNode.java Tue Oct 26 08:44:46 2004
@@ -18,7 +18,6 @@
import org.apache.jackrabbit.core.*;
import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
-import org.apache.jackrabbit.core.util.uuid.UUID;
import javax.jcr.NodeIterator;
import javax.jcr.PropertyIterator;
@@ -73,7 +72,8 @@
* @param node
* @throws RepositoryException
*/
- protected InternalFrozenNode(PersistentNode node) throws RepositoryException {
+ protected InternalFrozenNode(InternalFreeze parent, PersistentNode node) throws RepositoryException {
+ super(parent);
this.node = node;
// init the frozen properties
@@ -120,9 +120,9 @@
frozenChildNodes = new InternalFreeze[childNodes.length];
for (int i = 0; i < childNodes.length; i++) {
if (childNodes[i].hasProperty(VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE)) {
- frozenChildNodes[i] = new InternalFrozenNode(childNodes[i]);
+ frozenChildNodes[i] = new InternalFrozenNode(this, childNodes[i]);
} else if (childNodes[i].hasProperty(VersionManager.PROPNAME_VERSION_HISTORY)) {
- frozenChildNodes[i] = new InternalFrozenVersionHistory(childNodes[i]);
+ frozenChildNodes[i] = new InternalFrozenVersionHistory(this, childNodes[i]);
} else {
// unkown ?
}
@@ -206,7 +206,7 @@
* @return
* @throws RepositoryException
*/
- protected static InternalFrozenNode checkin(PersistentNode parent, QName name, NodeImpl src)
+ protected static PersistentNode checkin(PersistentNode parent, QName name, NodeImpl src, boolean initOnly)
throws RepositoryException {
// create new node
@@ -229,61 +229,63 @@
node.setPropertyValues(VersionManager.PROPNAME_FROZEN_MIXIN_TYPES, PropertyType.NAME, ivalues);
}
- // add the properties
- PropertyIterator piter = src.getProperties();
- while (piter.hasNext()) {
- PropertyImpl prop = (PropertyImpl) piter.nextProperty();
-// ignore some properties that not have a OPV=Ignore yet
- if (prop.getQName().equals(VersionManager.PROPNAME_VERSION_HISTORY)) {
- continue;
- }
- if (prop.getQName().equals(VersionManager.PROPNAME_PREDECESSORS)) {
- continue;
- }
- switch (prop.getDefinition().getOnParentVersion()) {
- case OnParentVersionAction.ABORT:
- parent.reload();
- throw new RepositoryException("Checkin aborted due to OPV in " + prop.safeGetJCRPath());
- case OnParentVersionAction.COMPUTE:
- case OnParentVersionAction.IGNORE:
- case OnParentVersionAction.INITIALIZE:
- break;
- case OnParentVersionAction.VERSION:
- case OnParentVersionAction.COPY:
- node.copyFrom(prop);
- break;
+ if (!initOnly) {
+ // add the properties
+ PropertyIterator piter = src.getProperties();
+ while (piter.hasNext()) {
+ PropertyImpl prop = (PropertyImpl) piter.nextProperty();
+ // ignore some properties that not have a OPV=Ignore yet
+ if (prop.getQName().equals(VersionManager.PROPNAME_VERSION_HISTORY)) {
+ continue;
+ }
+ if (prop.getQName().equals(VersionManager.PROPNAME_PREDECESSORS)) {
+ continue;
+ }
+ switch (prop.getDefinition().getOnParentVersion()) {
+ case OnParentVersionAction.ABORT:
+ parent.reload();
+ throw new RepositoryException("Checkin aborted due to OPV in " + prop.safeGetJCRPath());
+ case OnParentVersionAction.COMPUTE:
+ case OnParentVersionAction.IGNORE:
+ case OnParentVersionAction.INITIALIZE:
+ break;
+ case OnParentVersionAction.VERSION:
+ case OnParentVersionAction.COPY:
+ node.copyFrom(prop);
+ break;
+ }
}
- }
- // add the frozen children and vistories
- NodeIterator niter = src.getNodes();
- while (niter.hasNext()) {
- NodeImpl child = (NodeImpl) niter.nextNode();
- switch (child.getDefinition().getOnParentVersion()) {
- case OnParentVersionAction.ABORT:
- throw new RepositoryException("Checkin aborted due to OPV in " + child.safeGetJCRPath());
- case OnParentVersionAction.COMPUTE:
- case OnParentVersionAction.IGNORE:
- case OnParentVersionAction.INITIALIZE:
- break;
- case OnParentVersionAction.VERSION:
- if (child.isNodeType(NodeTypeRegistry.MIX_VERSIONABLE)) {
-// create frozen versionable child
- PersistentNode newChild = node.addNode(child.getQName(), NodeTypeRegistry.NT_UNSTRUCTURED);
- newChild.setPropertyValue(VersionManager.PROPNAME_VERSION_HISTORY,
- InternalValue.create(new UUID(child.getVersionHistory().getUUID())));
- newChild.setPropertyValue(VersionManager.PROPNAME_BASE_VERSION,
- InternalValue.create(new UUID(child.getBaseVersion().getUUID())));
- }
- // else ignore
- break;
- case OnParentVersionAction.COPY:
- checkin(node, child.getQName(), child);
- break;
+ // add the frozen children and vistories
+ NodeIterator niter = src.getNodes();
+ while (niter.hasNext()) {
+ NodeImpl child = (NodeImpl) niter.nextNode();
+ switch (child.getDefinition().getOnParentVersion()) {
+ case OnParentVersionAction.ABORT:
+ throw new RepositoryException("Checkin aborted due to OPV in " + child.safeGetJCRPath());
+ case OnParentVersionAction.COMPUTE:
+ case OnParentVersionAction.IGNORE:
+ case OnParentVersionAction.INITIALIZE:
+ break;
+ case OnParentVersionAction.VERSION:
+ if (child.isNodeType(NodeTypeRegistry.MIX_VERSIONABLE)) {
+ // create frozen versionable child
+ PersistentNode newChild = node.addNode(child.getQName(), NodeTypeRegistry.NT_UNSTRUCTURED);
+ newChild.setPropertyValue(VersionManager.PROPNAME_VERSION_HISTORY,
+ InternalValue.create(child.getVersionHistory().getUUID()));
+ newChild.setPropertyValue(VersionManager.PROPNAME_BASE_VERSION,
+ InternalValue.create(child.getBaseVersion().getUUID()));
+ }
+ // else ignore
+ break;
+ case OnParentVersionAction.COPY:
+ checkin(node, child.getQName(), child, false);
+ break;
+ }
}
}
parent.store();
- return new InternalFrozenNode(node);
+ return node;
}
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenVersionHistory.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenVersionHistory.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalFrozenVersionHistory.java Tue Oct 26 08:44:46 2004
@@ -16,11 +16,8 @@
package org.apache.jackrabbit.core.version;
import org.apache.jackrabbit.core.QName;
-import org.apache.jackrabbit.core.util.uuid.UUID;
import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.version.VersionHistory;
/**
* This Class represents a frozen versionable child node, that was created
@@ -38,7 +35,8 @@
*
* @param node
*/
- protected InternalFrozenVersionHistory(PersistentNode node) {
+ protected InternalFrozenVersionHistory(InternalFreeze parent, PersistentNode node) {
+ super(parent);
this.node = node;
}
@@ -54,16 +52,31 @@
/**
* Returns the version history that was versioned with this node.
*
- * @param session
* @return
* @throws RepositoryException
*/
- public VersionHistory getVersionHistory(Session session)
+ public String getVersionHistoryId()
throws RepositoryException {
- String historyId = ((UUID) node.getPropertyValue(VersionManager.PROPNAME_VERSION_HISTORY).internalValue()).toString();
- PersistentNode hNode = node.getNodeByUUID(historyId);
- return new VersionHistoryImpl(session, new InternalVersionHistory(hNode));
+ return (String) node.getPropertyValue(VersionManager.PROPNAME_VERSION_HISTORY).internalValue();
}
+ /**
+ * Returns the version history that was versioned with this node.
+ *
+ * @return
+ * @throws RepositoryException
+ */
+ public InternalVersionHistory getVersionHistory()
+ throws RepositoryException {
+ return getVersionManager().getVersionHistory(getVersionHistoryId());
+ }
+
+ public String getBaseVersionId() throws RepositoryException {
+ return (String) node.getPropertyValue(VersionManager.PROPNAME_BASE_VERSION).internalValue();
+ }
+ public InternalVersion getBaseVesion()
+ throws RepositoryException {
+ return getVersionManager().getVersion(getVersionHistoryId(), getBaseVersionId());
+ }
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersion.java Tue Oct 26 08:44:46 2004
@@ -30,7 +30,7 @@
/**
* This Class implements the Version representation of the node.
*/
-public final class InternalVersion {
+public final class InternalVersion extends InternalFreeze {
/**
* the list/cache of predecessors (values == InternalVersion)
@@ -68,6 +68,16 @@
private InternalFrozenNode frozen;
/**
+ * the id of this version
+ */
+ private String versionId;
+
+ /**
+ * specifies if this is the root version
+ */
+ private final boolean isRoot;
+
+ /**
* Creates a new internal version with the given version history and
* persistance node
*
@@ -76,11 +86,19 @@
* @throws RepositoryException
*/
InternalVersion(InternalVersionHistory vh, PersistentNode node) throws RepositoryException {
+ super(null);
this.versionHistory = vh;
this.node = node;
+
+ // check name
+ isRoot = node.getName().equals(VersionManager.NODENAME_ROOTVERSION);
+
+ // get id
+ versionId = (String) node.getPropertyValue(PersistentVersionManager.PROPNAME_VERSION_ID).internalValue();
+
// get frozen node
- PersistentNode pNode = node.getNode(VersionManager.NODENAME_FROZEN, 1);
- frozen = pNode == null ? null : new InternalFrozenNode(pNode);
+ PersistentNode pNode = node.getNode(PersistentVersionManager.NODENAME_FROZEN, 1);
+ frozen = pNode == null ? null : new InternalFrozenNode(this, pNode);
// init internal values
InternalValue[] values = node.getPropertyValues(VersionManager.PROPNAME_CREATED);
@@ -94,8 +112,8 @@
*
* @return
*/
- public String getUUID() {
- return node.getUUID();
+ public String getId() {
+ return versionId;
}
/**
@@ -108,6 +126,14 @@
}
/**
+ * returns the version manager
+ * @return
+ */
+ public PersistentVersionManager getVersionManager() {
+ return versionHistory.getVersionManager();
+ }
+
+ /**
* Returns the frozen node
*
* @return
@@ -169,9 +195,9 @@
private void storePredecessors() throws RepositoryException {
InternalValue[] values = new InternalValue[predecessors.size()];
for (int i = 0; i < values.length; i++) {
- values[i] = InternalValue.create(new UUID(((InternalVersion) predecessors.get(i)).getUUID()));
+ values[i] = InternalValue.create(new UUID(((InternalVersion) predecessors.get(i)).getId()));
}
- node.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.REFERENCE, values);
+ node.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.STRING, values);
}
/**
@@ -289,4 +315,12 @@
return labelCache == null ? new String[0] : (String[]) labelCache.toArray(new String[labelCache.size()]);
}
+ /**
+ * checks if this is the root version.
+ * @return <code>true</code> if this version is the root version;
+ * <code>false</code> otherwise.
+ */
+ public boolean isRootVersion() {
+ return isRoot;
+ }
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/InternalVersionHistory.java Tue Oct 26 08:44:46 2004
@@ -16,7 +16,6 @@
package org.apache.jackrabbit.core.version;
import org.apache.jackrabbit.core.InternalValue;
-import org.apache.jackrabbit.core.ItemImpl;
import org.apache.jackrabbit.core.NodeImpl;
import org.apache.jackrabbit.core.QName;
import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
@@ -57,7 +56,7 @@
/**
* the hashmap of all versions
- * key = UUID (String)
+ * key = versionId (String)
* value = version
*/
private HashMap versionCache = new HashMap();
@@ -73,9 +72,20 @@
private PersistentNode labelNode;
/**
+ * the id of this history
+ */
+ private String historyId;
+
+ /**
+ * the version manager
+ */
+ private final PersistentVersionManager vMgr;
+
+ /**
* Creates a new VersionHistory object for the given node state.
*/
- InternalVersionHistory(PersistentNode node) throws RepositoryException {
+ InternalVersionHistory(PersistentVersionManager vMgr, PersistentNode node) throws RepositoryException {
+ this.vMgr = vMgr;
this.node = node;
init();
}
@@ -89,17 +99,20 @@
versionCache.clear();
labelCache.clear();
+ // get id
+ historyId = (String) node.getPropertyValue(PersistentVersionManager.PROPNAME_HISTORY_ID).internalValue();
+
// get entries
PersistentNode[] children = node.getChildNodes();
for (int i = 0; i < children.length; i++) {
PersistentNode child = children[i];
- if (child.getName().equals(VersionManager.NODENAME_VERSION_LABELS)) {
+ if (child.getName().equals(PersistentVersionManager.NODENAME_VERSION_LABELS)) {
labelNode = child;
continue;
}
InternalVersion v = new InternalVersion(this, child);
- versionCache.put(child.getUUID(), v);
- if (child.getName().equals(VersionManager.NODENAME_ROOTVERSION)) {
+ versionCache.put(v.getId(), v);
+ if (v.isRootVersion()) {
rootVersion = v;
}
}
@@ -115,8 +128,8 @@
PersistentNode labels[] = labelNode.getChildNodes();
for (int i = 0; i < labels.length; i++) {
PersistentNode lNode = labels[i];
- String name = (String) lNode.getPropertyValue(VersionManager.PROPNAME_NAME).internalValue();
- String ref = ((UUID) lNode.getPropertyValue(VersionManager.PROPNAME_VERSION).internalValue()).toString();
+ String name = (String) lNode.getPropertyValue(PersistentVersionManager.PROPNAME_NAME).internalValue();
+ String ref = (String) lNode.getPropertyValue(PersistentVersionManager.PROPNAME_VERSION).internalValue();
InternalVersion v = getVersion(ref);
labelCache.put(name, v);
v.internalAddLabel(name);
@@ -124,12 +137,20 @@
}
/**
- * Returns the uuid of this version history
+ * returns the version manager
+ * @return
+ */
+ public PersistentVersionManager getVersionManager() {
+ return vMgr;
+ }
+
+ /**
+ * Returns the id of this version history
*
* @return
*/
- public String getUUID() {
- return node.getUUID();
+ public String getId() {
+ return historyId;
}
/**
@@ -222,7 +243,7 @@
v.internalDetach();
// and remove from history
- versionCache.remove(v.getUUID());
+ versionCache.remove(v.getId());
store();
}
@@ -234,14 +255,15 @@
* @param label
* @throws RepositoryException
*/
- public void addVersionLabel(InternalVersion version, String label, boolean move) throws RepositoryException {
+ public void addVersionLabel(InternalVersion version, String label, boolean move)
+ throws VersionException, RepositoryException {
InternalVersion prev = (InternalVersion) labelCache.get(label);
if (version.equals(prev)) {
// ignore
return;
} else if (prev != null && !move) {
// already defined elsewhere, throw
- throw new RepositoryException("Version label " + label + " already defined for version " + prev);
+ throw new VersionException("Version label " + label + " already defined for version " + prev.getName());
} else if (prev != null) {
// if already defined, but move, remove old label first
removeVersionLabel(label);
@@ -250,10 +272,12 @@
version.internalAddLabel(label);
QName name = new QName("", Text.md5(label));
PersistentNode lNode = labelNode.addNode(name, NodeTypeRegistry.NT_UNSTRUCTURED);
- lNode.setPropertyValue(VersionManager.PROPNAME_NAME, InternalValue.create(label));
- lNode.setPropertyValue(VersionManager.PROPNAME_VERSION, InternalValue.create(new UUID(version.getUUID())));
- lNode.store();
+ lNode.setPropertyValue(PersistentVersionManager.PROPNAME_NAME, InternalValue.create(label));
+ lNode.setPropertyValue(PersistentVersionManager.PROPNAME_VERSION, InternalValue.create(version.getId()));
+ labelNode.store();
+ // inform manager
+ vMgr.onVersionModified(version);
}
/**
@@ -271,6 +295,9 @@
QName name = new QName("", Text.md5(label));
labelNode.removeNode(name);
labelNode.store();
+
+ // inform manager
+ vMgr.onVersionModified(v);
}
/**
@@ -289,25 +316,24 @@
Value[] preds = src.getProperty(VersionManager.PROPNAME_PREDECESSORS).getValues();
InternalValue[] predecessors = new InternalValue[preds.length];
for (int i = 0; i < preds.length; i++) {
- String uuid = preds[i].getString();
+ String predId = preds[i].getString();
// check if version exist
- if (!versionCache.containsKey(uuid)) {
+ if (!versionCache.containsKey(predId)) {
throw new RepositoryException("invalid predecessor in source node");
}
- predecessors[i] = InternalValue.create(new UUID(uuid));
+ predecessors[i] = InternalValue.create(predId);
}
PersistentNode vNode = node.addNode(name, NodeTypeRegistry.NT_UNSTRUCTURED);
- vNode.setPropertyValue(ItemImpl.PROPNAME_UUID, InternalValue.create(vNode.getUUID()));
- vNode.setMixinNodeTypes(new QName[]{NodeTypeRegistry.MIX_REFERENCEABLE});
+ String versionId = UUID.randomUUID().toString();
+ vNode.setPropertyValue(PersistentVersionManager.PROPNAME_VERSION_ID, InternalValue.create(versionId));
// initialize 'created' and 'predecessors'
vNode.setPropertyValue(VersionManager.PROPNAME_CREATED, InternalValue.create(Calendar.getInstance()));
- vNode.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.REFERENCE, predecessors);
-
+ vNode.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.STRING, predecessors);
// checkin source node
- InternalFrozenNode.checkin(vNode, VersionManager.NODENAME_FROZEN, src);
+ InternalFrozenNode.checkin(vNode, PersistentVersionManager.NODENAME_FROZEN, src, false);
// and store
store();
@@ -317,7 +343,7 @@
version.resolvePredecessors();
// update cache
- versionCache.put(version.getUUID(), version);
+ versionCache.put(version.getId(), version);
return version;
}
@@ -343,6 +369,14 @@
}
/**
+ * Returns an iterator over all versions (not ordered yet)
+ * @return
+ */
+ protected Iterator getVersions() {
+ return versionCache.values().iterator();
+ }
+
+ /**
* Creates a new <code>InternalVersionHistory</code> below the given parent
* node and with the given name.
*
@@ -351,28 +385,30 @@
* @return
* @throws RepositoryException
*/
- protected static InternalVersionHistory create(PersistentNode parent, QName name)
+ protected static InternalVersionHistory create(PersistentVersionManager vMgr, PersistentNode parent, String historyId, QName name, NodeImpl src)
throws RepositoryException {
// create history node
PersistentNode pNode = parent.addNode(name, NodeTypeRegistry.NT_UNSTRUCTURED);
- pNode.setPropertyValue(ItemImpl.PROPNAME_UUID, InternalValue.create(pNode.getUUID()));
- pNode.setMixinNodeTypes(new QName[]{NodeTypeRegistry.MIX_REFERENCEABLE});
+ pNode.setPropertyValue(PersistentVersionManager.PROPNAME_HISTORY_ID, InternalValue.create(historyId));
// create label node
- pNode.addNode(VersionManager.NODENAME_VERSION_LABELS, NodeTypeRegistry.NT_UNSTRUCTURED);
+ pNode.addNode(PersistentVersionManager.NODENAME_VERSION_LABELS, NodeTypeRegistry.NT_UNSTRUCTURED);
// create root version
+ String versionId = UUID.randomUUID().toString();
PersistentNode vNode = pNode.addNode(VersionManager.NODENAME_ROOTVERSION, NodeTypeRegistry.NT_UNSTRUCTURED);
- vNode.setPropertyValue(ItemImpl.PROPNAME_UUID, InternalValue.create(vNode.getUUID()));
- vNode.setMixinNodeTypes(new QName[]{NodeTypeRegistry.MIX_REFERENCEABLE});
+ vNode.setPropertyValue(PersistentVersionManager.PROPNAME_VERSION_ID, InternalValue.create(versionId));
// initialize 'created' and 'predecessors'
vNode.setPropertyValue(VersionManager.PROPNAME_CREATED, InternalValue.create(Calendar.getInstance()));
vNode.setPropertyValues(VersionManager.PROPNAME_PREDECESSORS, PropertyType.REFERENCE, new InternalValue[0]);
+ // add also an empty frozen node to the root version
+ InternalFrozenNode.checkin(vNode, PersistentVersionManager.NODENAME_FROZEN, src, true);
+
parent.store();
- return new InternalVersionHistory(pNode);
+ return new InternalVersionHistory(vMgr, pNode);
}
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentNode.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentNode.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentNode.java Tue Oct 26 08:44:46 2004
@@ -111,7 +111,8 @@
for (int i = 0; i < list.size(); i++) {
NodeState.PropertyEntry entry = (NodeState.PropertyEntry) list.get(i);
PropertyId propId = new PropertyId(nodeState.getUUID(), entry.getName());
- props[i] = new PersistentProperty((PropertyState) stateMgr.getItemState(propId));
+ PropertyState pState = (PropertyState) stateMgr.getItemState(propId);
+ props[i] = new PersistentProperty(pState, ntMgr.getPropDef(pState.getDefinitionId()).isMultiple());
}
return props;
} catch (ItemStateException e) {
@@ -171,7 +172,7 @@
*/
protected void setPropertyValue(QName name, InternalValue value)
throws RepositoryException {
- setPropertyValues(name, value.getType(), new InternalValue[]{value});
+ setPropertyValues(name, value.getType(), new InternalValue[]{value}, false);
}
/**
@@ -184,7 +185,20 @@
*/
protected void setPropertyValues(QName name, int type, InternalValue[] values)
throws RepositoryException {
- PersistentPropertyState prop = getOrCreatePropertyState(name, type, true);
+ setPropertyValues(name, type, values, true);
+ }
+
+ /**
+ * Sets the property values
+ *
+ * @param name
+ * @param type
+ * @param values
+ * @throws RepositoryException
+ */
+ protected void setPropertyValues(QName name, int type, InternalValue[] values, boolean multiple)
+ throws RepositoryException {
+ PersistentPropertyState prop = getOrCreatePropertyState(name, type, multiple);
prop.setValues(values);
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentProperty.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentProperty.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentProperty.java Tue Oct 26 08:44:46 2004
@@ -28,15 +28,21 @@
/**
* the underlaying persistent state
*/
- private PropertyState state;
+ private final PropertyState state;
+
+ /**
+ * flag if this is a multivalued propertery
+ */
+ private final boolean isMultiple;
/**
* Creates a new persistent property
*
* @param state
*/
- public PersistentProperty(PropertyState state) {
+ public PersistentProperty(PropertyState state, boolean isMultiple) {
this.state = state;
+ this.isMultiple = isMultiple;
}
/**
@@ -66,4 +72,11 @@
return state.getType();
}
+ /**
+ * returns <code>true</code> if this is a multivalue propererty
+ * @return
+ */
+ public boolean isMultiple() {
+ return isMultiple;
+ }
}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/PersistentVersionManager.java Tue Oct 26 08:44:46 2004
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.jackrabbit.core.version;
+
+import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
+import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.PersistentNodeState;
+import org.apache.jackrabbit.core.state.PersistentItemStateProvider;
+import org.apache.log4j.Logger;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * This Class provides general versioning functions.
+ */
+public class PersistentVersionManager {
+
+ /**
+ * the logger
+ */
+ private static Logger log = Logger.getLogger(PersistentVersionManager.class);
+
+ /**
+ * root path for version storage
+ */
+ public static final QName VERSION_HISTORY_ROOT_NAME = new QName(NamespaceRegistryImpl.NS_JCR_URI, "persistentVersionStorage");
+ /**
+ * name of the 'jcr:historyId' property
+ */
+ public static final QName PROPNAME_HISTORY_ID = new QName(NamespaceRegistryImpl.NS_JCR_URI, "historyId");
+ /**
+ * name of the 'jcr:versionId' property
+ */
+ public static final QName PROPNAME_VERSION_ID = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionId");
+ /**
+ * name of the 'jcr:versionLabels' node
+ */
+ public static final QName NODENAME_VERSION_LABELS = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionLabels");
+ /**
+ * name of the 'jcr:frozen' property
+ */
+ public static final QName NODENAME_FROZEN = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozen");
+ /**
+ * name of the 'jcr:name' property
+ */
+ public static final QName PROPNAME_NAME = new QName(NamespaceRegistryImpl.NS_JCR_URI, "name");
+ /**
+ * name of the 'jcr:version' property
+ */
+ public static final QName PROPNAME_VERSION = new QName(NamespaceRegistryImpl.NS_JCR_URI, "version");
+
+
+ /**
+ * the root node of the version histories
+ */
+ private final PersistentNode historyRoot;
+
+ /**
+ * the system root id
+ */
+ private final String systemRootId;
+
+ /**
+ * the state manager for the version storage
+ */
+ private PersistentItemStateProvider stateMgr;
+
+ /**
+ * the nodetype manager for the version storage
+ */
+ private NodeTypeManagerImpl ntMgr;
+
+ /**
+ * The representation version manager
+ */
+ private VersionManager versionManager;
+
+ /**
+ * the version histories
+ */
+ private HashMap histories = new HashMap();
+
+ /**
+ * Creates a new PersistentVersionManager.
+ *
+ * @param session
+ * @throws RepositoryException
+ */
+ public PersistentVersionManager(SessionImpl session) throws RepositoryException {
+ this.stateMgr = ((WorkspaceImpl) session.getWorkspace()).getPersistentStateManager();
+ this.ntMgr = session.getNodeTypeManager();
+
+ // check for versionhistory root
+ NodeImpl systemRoot = ((RepositoryImpl) session.getRepository()).getSystemRootNode(session);
+ systemRootId = systemRoot.internalGetUUID();
+ if (!systemRoot.hasNode(VERSION_HISTORY_ROOT_NAME)) {
+ // if not exist, create
+ systemRoot.addNode(VERSION_HISTORY_ROOT_NAME, NodeTypeRegistry.NT_UNSTRUCTURED);
+ systemRoot.save();
+ }
+
+ try {
+ PersistentNodeState nodeState = (PersistentNodeState) stateMgr.getItemState(new NodeId(systemRoot.getNode(VERSION_HISTORY_ROOT_NAME).internalGetUUID()));
+ historyRoot = new PersistentNode(stateMgr, ntMgr, nodeState);
+ } catch (ItemStateException e) {
+ throw new RepositoryException("Unable to initialize PersistentVersionManager: " + e.toString());
+ }
+ }
+
+ /**
+ * Creates a new Version History..
+ *
+ * @param node the node for which the version history is to be initialized
+ * @return the newly created version history.
+ * @throws RepositoryException
+ */
+ public synchronized InternalVersionHistory createVersionHistory(NodeImpl node)
+ throws RepositoryException {
+
+ // create deep path
+ String uuid = UUID.randomUUID().toString();
+ QName historyNodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, uuid);
+ if (historyRoot.hasNode(historyNodeName)) {
+ historyRoot.removeNode(historyNodeName);
+ }
+ historyRoot.store();
+
+ // create new history node in the persistent state
+ InternalVersionHistory hist = InternalVersionHistory.create(this, historyRoot, uuid, historyNodeName, node);
+ histories.put(hist.getId(), hist);
+ return hist;
+ }
+
+ /**
+ * returns the internal version history for the id
+ *
+ * @param histId the id of the history
+ * @return
+ * @throws RepositoryException
+ */
+ public synchronized InternalVersionHistory getVersionHistory(String histId)
+ throws RepositoryException {
+
+ InternalVersionHistory hist = (InternalVersionHistory) histories.get(histId);
+ if (hist==null) {
+ // we cannot used the uuid, since the persistent state do not share the same ids
+ QName historyNodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, histId);
+ PersistentNode hNode = historyRoot.getNode(historyNodeName, 1);
+ hist = new InternalVersionHistory(this, hNode);
+ histories.put(histId, hist);
+ }
+ return hist;
+ }
+
+ /**
+ * returns an iterator over all existing version histories
+ * @return
+ * @throws RepositoryException
+ */
+ public synchronized Iterator getVersionHistories() throws RepositoryException {
+ PersistentNode[] ph = historyRoot.getChildNodes();
+ ArrayList list = new ArrayList(ph.length);
+ for (int i=0; i<ph.length; i++) {
+ list.add(getVersionHistory(ph[i].getName().getLocalName()));
+ }
+ return list.iterator();
+ }
+
+ /**
+ * returns the internal version for the id
+ *
+ * @param versionId
+ * @return
+ * @throws RepositoryException
+ */
+ public synchronized InternalVersion getVersion(String histId, String versionId)
+ throws RepositoryException {
+ InternalVersionHistory history = getVersionHistory(histId);
+ return history.getVersion(versionId);
+ }
+
+ /**
+ * is informed by the versions if they were modified
+ * @param version
+ */
+ protected void onVersionModified(InternalVersion version) throws RepositoryException {
+ // check if version manager already generated item states
+ if (versionManager!=null) {
+ versionManager.onVersionModified(version);
+ }
+ }
+
+ /**
+ * Checks in a node
+ *
+ * @param node
+ * @return
+ * @throws RepositoryException
+ * @see Node#checkin()
+ */
+ public synchronized InternalVersion checkin(NodeImpl node) throws RepositoryException {
+ // assuming node is versionable and checkout (check in nodeimpl)
+ // To create a new version of a versionable node N, the client calls N.checkin.
+ // This causes the following series of events:
+ String histUUID = node.getProperty(VersionManager.PROPNAME_VERSION_HISTORY).getString();
+ InternalVersionHistory history = getVersionHistory(histUUID);
+
+ // 0. resolve the predecessors
+ Value[] values = node.getProperty(VersionManager.PROPNAME_PREDECESSORS).getValues();
+ InternalVersion[] preds = new InternalVersion[values.length];
+ for (int i = 0; i < values.length; i++) {
+ preds[i] = history.getVersion(values[i].getString());
+ }
+
+ // 0.1 search a predecessor, suitable for generating the new name
+ String versionName = null;
+ int maxDots = Integer.MAX_VALUE;
+ for (int i = 0; i < preds.length; i++) {
+ // take the first pred. without a successor
+ if (preds[i].getSuccessors().length == 0) {
+ versionName = preds[i].getName().getLocalName(); //assuming no namespaces in version names
+ // need to count the dots
+ int pos = -1;
+ int numDots = 0;
+ while (versionName.indexOf('.', pos + 1) >= 0) {
+ pos = versionName.indexOf('.', pos + 1);
+ numDots++;
+ }
+ if (numDots < maxDots) {
+ maxDots = numDots;
+ versionName = pos < 0 ? "1.0" : versionName.substring(0, pos + 1) + (Integer.parseInt(versionName.substring(pos + 1)) + 1);
+ }
+ break;
+ }
+ }
+ // if no empty found, generate new name
+ if (versionName == null) {
+ versionName = preds[0].getName().getLocalName();
+ do {
+ versionName += ".1";
+ } while (history.hasVersion(new QName("", versionName)));
+ }
+
+ return history.checkin(new QName("", versionName), node);
+ }
+
+ /**
+ * returns the version manager
+ * @return
+ */
+ public synchronized VersionManager getVersionManager() {
+ if (versionManager==null) {
+ versionManager = new VersionManager(this, systemRootId);
+ }
+ return versionManager;
+ }
+
+ /**
+ * returns the node type manager of the version storage
+ * @return
+ */
+ public NodeTypeManagerImpl getNodeTypeManager(){
+ return ntMgr;
+ }
+}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionHistoryImpl.java Tue Oct 26 08:44:46 2004
@@ -16,11 +16,12 @@
package org.apache.jackrabbit.core.version;
import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.state.NodeState;
import javax.jcr.Item;
import javax.jcr.RepositoryException;
-import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.nodetype.NodeDef;
import javax.jcr.version.Version;
import javax.jcr.version.VersionHistory;
import javax.jcr.version.VersionIterator;
@@ -29,7 +30,7 @@
/**
* This Class implements a version history that extends a node.
*/
-public class VersionHistoryImpl extends NodeWrapper implements VersionHistory {
+public class VersionHistoryImpl extends NodeImpl implements VersionHistory {
/**
* the internal version history
@@ -37,16 +38,21 @@
private final InternalVersionHistory history;
/**
- * creates a new version history implementation for the given session and
- * internal version history
- *
+ * creates a new version history node.
+ * @param itemMgr
* @param session
+ * @param id
+ * @param state
+ * @param definition
+ * @param listeners
* @param history
* @throws RepositoryException
*/
- protected VersionHistoryImpl(Session session, InternalVersionHistory history)
- throws RepositoryException {
- super((NodeImpl) session.getNodeByUUID(history.getUUID()));
+ protected VersionHistoryImpl(ItemManager itemMgr, SessionImpl session, NodeId id,
+ NodeState state, NodeDef definition,
+ ItemLifeCycleListener[] listeners,
+ InternalVersionHistory history) throws RepositoryException {
+ super(itemMgr, session, id, state, definition, listeners);
this.history = history;
}
@@ -54,14 +60,14 @@
* @see VersionHistory#getRootVersion()
*/
public Version getRootVersion() throws RepositoryException {
- return new VersionImpl(unwrap().getSession(), history.getRootVersion());
+ return (Version) session.getNodeByUUID(history.getRootVersion().getId());
}
/**
* @see VersionHistory#getAllVersions()
*/
public VersionIterator getAllVersions() throws RepositoryException {
- return new VersionIteratorImpl(unwrap().getSession(), history.getRootVersion());
+ return new VersionIteratorImpl(session, history.getRootVersion());
}
/**
@@ -69,9 +75,9 @@
*/
public Version getVersion(String versionName) throws RepositoryException {
try {
- QName name = QName.fromJCRName(versionName, ((SessionImpl) unwrap().getSession()).getNamespaceResolver());
+ QName name = QName.fromJCRName(versionName, session.getNamespaceResolver());
InternalVersion v = history.getVersion(name);
- return v == null ? null : new VersionImpl(unwrap().getSession(), v);
+ return v == null ? null : (Version) session.getNodeByUUID(v.getId());
} catch (IllegalNameException e) {
throw new RepositoryException(e);
} catch (UnknownPrefixException e) {
@@ -84,40 +90,48 @@
*/
public Version getVersionByLabel(String label) throws RepositoryException {
InternalVersion v = history.getVersionByLabel(label);
- return v == null ? null : new VersionImpl(unwrap().getSession(), v);
+ return v == null ? null : (Version) session.getNodeByUUID(v.getId());
}
/**
* @see VersionHistory#addVersionLabel(String, String)
*/
- public void addVersionLabel(String versionName, String label) throws VersionException, RepositoryException {
- InternalVersion v;
+ public void addVersionLabel(String version, String label) throws VersionException, RepositoryException {
+ addVersionLabel(version, label, false);
+ }
+
+ /**
+ * @see VersionHistory#addVersionLabel(String, String, boolean)
+ */
+ public void addVersionLabel(String version, String label, boolean move)
+ throws VersionException, RepositoryException {
try {
- QName name = QName.fromJCRName(versionName, ((SessionImpl) unwrap().getSession()).getNamespaceResolver());
- v = history.getVersion(name);
+ QName name = QName.fromJCRName(version, session.getNamespaceResolver());
+ InternalVersion v = history.getVersion(name);
+ if (v==null) {
+ throw new VersionException("Version " + version + " does not exist in this version history.");
+ }
+ history.addVersionLabel(v, label, move);
} catch (IllegalNameException e) {
throw new RepositoryException(e);
} catch (UnknownPrefixException e) {
throw new RepositoryException(e);
}
- if (v == null) {
- throw new VersionException("specified version does not exist");
- }
- history.addVersionLabel(v, label, false);
}
/**
* @see VersionHistory#removeVersionLabel(String)
*/
- public void removeVersionLabel(String label) throws VersionException, RepositoryException {
+ public void removeVersionLabel(String label) throws RepositoryException {
history.removeVersionLabel(label);
}
+
/**
* @see javax.jcr.Node#getUUID()
*/
public String getUUID() throws UnsupportedRepositoryOperationException, RepositoryException {
- return history.getUUID();
+ return history.getId();
}
/**
@@ -126,7 +140,7 @@
public boolean isSame(Item otherItem) {
if (otherItem instanceof VersionHistoryImpl) {
// since all version histories live in the same workspace, we can compare the uuids
- return ((VersionHistoryImpl) otherItem).history.getUUID().equals(history.getUUID());
+ return ((VersionHistoryImpl) otherItem).history.getId().equals(history.getId());
} else {
return false;
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionImpl.java Tue Oct 26 08:44:46 2004
@@ -15,19 +15,20 @@
*/
package org.apache.jackrabbit.core.version;
-import org.apache.jackrabbit.core.NodeImpl;
+import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.state.NodeState;
import javax.jcr.Item;
import javax.jcr.RepositoryException;
-import javax.jcr.Session;
import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.nodetype.NodeDef;
import javax.jcr.version.Version;
import java.util.Calendar;
/**
* This Class implements a Version that extends the node interface
*/
-public class VersionImpl extends NodeWrapper implements Version {
+public class VersionImpl extends NodeImpl implements Version {
/**
* the internal version
@@ -35,15 +36,21 @@
protected final InternalVersion version;
/**
- * Creates a new version implementation
- *
+ * creates a new version node
+ * @param itemMgr
* @param session
+ * @param id
+ * @param state
+ * @param definition
+ * @param listeners
* @param version
* @throws RepositoryException
*/
- protected VersionImpl(Session session, InternalVersion version)
+ protected VersionImpl(ItemManager itemMgr, SessionImpl session, NodeId id,
+ NodeState state, NodeDef definition,
+ ItemLifeCycleListener[] listeners, InternalVersion version)
throws RepositoryException {
- super((NodeImpl) session.getNodeByUUID(version.getUUID()));
+ super(itemMgr, session, id, state, definition, listeners);
this.version = version;
}
@@ -76,7 +83,7 @@
InternalVersion[] suc = version.getSuccessors();
Version[] ret = new Version[suc.length];
for (int i = 0; i < suc.length; i++) {
- ret[i] = new VersionImpl(unwrap().getSession(), suc[i]);
+ ret[i] = (Version) session.getNodeByUUID(suc[i].getId());
}
return ret;
}
@@ -89,7 +96,7 @@
InternalVersion[] pred = version.getPredecessors();
Version[] ret = new Version[pred.length];
for (int i = 0; i < pred.length; i++) {
- ret[i] = new VersionImpl(unwrap().getSession(), pred[i]);
+ ret[i] = (Version) session.getNodeByUUID(pred[i].getId());
}
return ret;
}
@@ -98,7 +105,7 @@
* @see javax.jcr.Node#getUUID()
*/
public String getUUID() throws UnsupportedRepositoryOperationException, RepositoryException {
- return version.getUUID();
+ return version.getId();
}
/**
@@ -126,9 +133,10 @@
public boolean isSame(Item otherItem) {
if (otherItem instanceof VersionImpl) {
// since all versions live in the same workspace, we can compare the uuids
- return ((VersionImpl) otherItem).version.getUUID().equals(version.getUUID());
+ return ((VersionImpl) otherItem).version.getId().equals(version.getId());
} else {
return false;
}
}
+
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionIteratorImpl.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionIteratorImpl.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionIteratorImpl.java Tue Oct 26 08:44:46 2004
@@ -75,7 +75,7 @@
push(ret.getSuccessors());
try {
- return new VersionImpl(session, ret);
+ return (Version) session.getNodeByUUID(ret.getId());
} catch (RepositoryException e) {
throw new NoSuchElementException("Unable to provide element: " + e.toString());
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/VersionManager.java Tue Oct 26 08:44:46 2004
@@ -16,177 +16,152 @@
package org.apache.jackrabbit.core.version;
import org.apache.jackrabbit.core.*;
-import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
+import org.apache.jackrabbit.core.state.*;
import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
+import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.jackrabbit.core.virtual.*;
import org.apache.jackrabbit.core.state.ItemStateException;
-import org.apache.jackrabbit.core.state.PersistentItemStateProvider;
-import org.apache.jackrabbit.core.state.PersistentNodeState;
import org.apache.log4j.Logger;
-import javax.jcr.Node;
import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import javax.jcr.version.Version;
+import javax.jcr.PropertyType;
+import javax.jcr.nodetype.NodeDef;
import javax.jcr.version.VersionHistory;
+import javax.jcr.version.Version;
+import java.util.Iterator;
/**
- * This Class provides general versioning functions.
+ * This Class implements the session tied version manager. It is also repsonsible
+ * for mapping the internal versions to the presentation layer using virtual
+ * nodes and items.
+ *
+ * @author tripod
+ * @version $Revision:$, $Date:$
*/
public class VersionManager {
+ /**
+ * the default logger
+ */
private static Logger log = Logger.getLogger(VersionManager.class);
/**
* root path for version storage
*/
public static final QName VERSION_HISTORY_ROOT_NAME = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionStorage");
-
/**
* name of the 'jcr:frozenUUID' property
*/
public static final QName PROPNAME_FROZEN_UUID = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozenUUID");
-
/**
* name of the 'jcr:frozenPrimaryType' property
*/
public static final QName PROPNAME_FROZEN_PRIMARY_TYPE = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozenPrimaryType");
-
/**
* name of the 'jcr:frozenMixinTypes' property
*/
public static final QName PROPNAME_FROZEN_MIXIN_TYPES = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozenMixinTypes");
-
- /**
- * name of the 'jcr:versionLabels' node
- */
- public static final QName NODENAME_VERSION_LABELS = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionLabels");
-
- /**
- * name of the 'jcr:frozen' property
- */
- public static final QName NODENAME_FROZEN = new QName(NamespaceRegistryImpl.NS_JCR_URI, "frozen");
-
/**
* name of the 'jcr:predecessors' property
*/
public static final QName PROPNAME_PREDECESSORS = new QName(NamespaceRegistryImpl.NS_JCR_URI, "predecessors");
-
/**
- * name of the 'jcr:successors' property
+ * name of the 'jcr:versionLabels' property
*/
- public static final QName PROPNAME_SUCCESSORS = new QName(NamespaceRegistryImpl.NS_JCR_URI, "successors");
-
- /**
- * name of the 'jcr:name' property
- */
- public static final QName PROPNAME_NAME = new QName(NamespaceRegistryImpl.NS_JCR_URI, "name");
-
+ public static final QName PROPNAME_VERSION_LABELS= new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionLabels");
/**
- * name of the 'jcr:version' property
+ * name of the 'jcr:successors' property
*/
- public static final QName PROPNAME_VERSION = new QName(NamespaceRegistryImpl.NS_JCR_URI, "version");
-
+ public static final QName PROPNAME_SUCCESSORS = new QName(NamespaceRegistryImpl.NS_JCR_URI, "successors");
/**
* name of the 'jcr:isCheckedOut' property
*/
public static final QName PROPNAME_IS_CHECKED_OUT = new QName(NamespaceRegistryImpl.NS_JCR_URI, "isCheckedOut");
-
/**
* name of the 'jcr:versionHistory' property
*/
public static final QName PROPNAME_VERSION_HISTORY = new QName(NamespaceRegistryImpl.NS_JCR_URI, "versionHistory");
-
/**
* name of the 'jcr:baseVersion' property
*/
public static final QName PROPNAME_BASE_VERSION = new QName(NamespaceRegistryImpl.NS_JCR_URI, "baseVersion");
-
/**
* name of the 'jcr:created' property
*/
public static final QName PROPNAME_CREATED = new QName(NamespaceRegistryImpl.NS_JCR_URI, "created");
-
/**
* the name of the 'jcr:rootVersion' node
*/
public static final QName NODENAME_ROOTVERSION = new QName(NamespaceRegistryImpl.NS_JCR_URI, "rootVersion");
/**
- * the root node of the version histories
+ * The version manager of the internal versions
*/
- private final PersistentNode historyRoot;
+ private final PersistentVersionManager vMgr;
/**
- * the state manager for the version storage
+ * the uuid of the system root node
*/
- private PersistentItemStateProvider stateMgr;
+ private final String rootId;
/**
- * the nodetype manager for the version storage
+ * The virtual item manager that exposes the versions to the content
*/
- private NodeTypeManagerImpl ntMgr;
+ private DefaultItemStateProvider virtProvider;
/**
- * Creates a new VersionManager.
- *
- * @param session
- * @throws RepositoryException
+ * The virtual history root
*/
- public VersionManager(SessionImpl session) throws RepositoryException {
- this.stateMgr = ((WorkspaceImpl) session.getWorkspace()).getPersistentStateManager();
- this.ntMgr = session.getNodeTypeManager();
-
- // check for versionhistory root
- NodeImpl systemRoot = ((RepositoryImpl) session.getRepository()).getSystemRootNode(session);
- if (!systemRoot.hasNode(VERSION_HISTORY_ROOT_NAME)) {
- // if not exist, create
- systemRoot.addNode(VERSION_HISTORY_ROOT_NAME, NodeTypeRegistry.NT_UNSTRUCTURED);
- systemRoot.save();
- }
+ private VirtualNodeState historyRoot;
- try {
- PersistentNodeState nodeState = (PersistentNodeState) stateMgr.getItemState(new NodeId(systemRoot.getNode(VERSION_HISTORY_ROOT_NAME).internalGetUUID()));
- historyRoot = new PersistentNode(stateMgr, ntMgr, nodeState);
- } catch (ItemStateException e) {
- throw new RepositoryException("Unable to initialize VersionManager: " + e.toString());
+
+ /**
+ * @param vMgr
+ */
+ protected VersionManager(PersistentVersionManager vMgr, String rootId) {
+ this.vMgr = vMgr;
+ this.rootId = rootId;
+ }
+
+ /**
+ * returns the virtual item state provider that exposes the internal versions
+ * as items.
+ * @param base
+ * @return
+ */
+ public VirtualItemStateProvider getVirtualItemStateProvider(ItemStateProvider base) {
+ if (virtProvider==null) {
+ try {
+ NodeState rootState = (NodeState) base.getItemState(new NodeId(rootId));
+ virtProvider = new DefaultItemStateProvider(vMgr.getNodeTypeManager(), rootState);
+ historyRoot = virtProvider.addNode(virtProvider.getRootState(), VERSION_HISTORY_ROOT_NAME, null, NodeTypeRegistry.NT_UNSTRUCTURED, null);
+ Iterator iter = vMgr.getVersionHistories();
+ while (iter.hasNext()) {
+ InternalVersionHistory vh = (InternalVersionHistory) iter.next();
+ mapVersionHistory(vh);
+ }
+ } catch (Exception e) {
+ // todo: better error handling
+ log.error("Error while initializing virtual items.", e);
+ throw new IllegalStateException(e.toString());
+ }
}
+ return virtProvider;
}
/**
- * Creates a new Version History..
+ * Creates a new version history. This action is needed either when creating
+ * a new 'mix:versionable' node or when adding the 'mix:versionalbe' mixin
+ * to a node.
*
- * @param node the node for which the version history is to be initialized
- * @return the newly created version history.
+ * @param node
+ * @return
* @throws RepositoryException
*/
- public VersionHistory createVersionHistory(NodeImpl node)
- throws RepositoryException {
-
- // create deep path
- String uuid = node.getUUID();
- PersistentNode parent = historyRoot;
- QName historyNodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, uuid.substring(0, 2));
- if (!parent.hasNode(historyNodeName)) {
- parent = parent.addNode(historyNodeName, NodeTypeRegistry.NT_UNSTRUCTURED);
- } else {
- parent = parent.getNode(historyNodeName, 1);
- }
- historyNodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, uuid.substring(2, 4));
- if (!parent.hasNode(historyNodeName)) {
- parent = parent.addNode(historyNodeName, NodeTypeRegistry.NT_UNSTRUCTURED);
- } else {
- parent = parent.getNode(historyNodeName, 1);
- }
-
- historyNodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, uuid.substring(4));
- if (parent.hasNode(historyNodeName)) {
- parent.removeNode(historyNodeName);
- }
- historyRoot.store();
-
- // create new history node in the persistent state
- InternalVersionHistory history = InternalVersionHistory.create(parent, historyNodeName);
- return new VersionHistoryImpl(node.getSession(), history);
+ public VersionHistory createVersionHistory(NodeImpl node) throws RepositoryException {
+ InternalVersionHistory history = vMgr.createVersionHistory(node);
+ mapVersionHistory(history);
+ return (VersionHistory) node.getSession().getNodeByUUID(history.getId());
}
/**
@@ -197,9 +172,10 @@
* @throws RepositoryException
*/
public Version getBaseVersion(NodeImpl node) throws RepositoryException {
- InternalVersionHistory history = getInternalVersionHistory(node);
+ String histUUID = node.getProperty(VersionManager.PROPNAME_VERSION_HISTORY).getString();
+ InternalVersionHistory history = vMgr.getVersionHistory(histUUID);
InternalVersion version = history.getVersion(node.getProperty(PROPNAME_BASE_VERSION).getString());
- return version == null ? null : new VersionImpl(node.getSession(), version);
+ return version == null ? null : (Version) node.getSession().getNodeByUUID(version.getId());
}
/**
@@ -212,81 +188,230 @@
*/
public VersionHistory getVersionHistory(NodeImpl node)
throws RepositoryException {
- InternalVersionHistory history = getInternalVersionHistory(node);
- return new VersionHistoryImpl(node.getSession(), history);
+ String histUUID = node.getProperty(VersionManager.PROPNAME_VERSION_HISTORY).getString();
+ InternalVersionHistory history = vMgr.getVersionHistory(histUUID);
+ return (VersionHistory) node.getSession().getNodeByUUID(history.getId());
}
+
/**
- * returns the internal version history for the given node
- *
- * @param node
+ * Creates a new VersionHistoryImpl instance. this is usually called by
+ * the {@link ItemManager}.
+ * @param session
+ * @param state
+ * @param def
+ * @param itemMgr
+ * @param listeners
* @return
* @throws RepositoryException
*/
- private InternalVersionHistory getInternalVersionHistory(NodeImpl node)
+ public VersionHistoryImpl createVersionHistoryInstance(SessionImpl session,
+ NodeState state, NodeDef def,
+ ItemManager itemMgr,
+ ItemLifeCycleListener[] listeners)
throws RepositoryException {
- String histUUID = node.getProperty(PROPNAME_VERSION_HISTORY).getString();
- try {
- PersistentNodeState state = (PersistentNodeState) stateMgr.getItemState(new NodeId(histUUID));
- PersistentNode hNode = new PersistentNode(stateMgr, ntMgr, state);
- return new InternalVersionHistory(hNode);
- } catch (ItemStateException e) {
- throw new RepositoryException(e);
+ if (!state.getNodeTypeName().equals(NodeTypeRegistry.NT_VERSION_HISTORY)) {
+ throw new RepositoryException("node not nt:versionhistory");
}
+ NodeId nodeId = (NodeId) state.getId();
+ InternalVersionHistory history = vMgr.getVersionHistory(nodeId.getUUID());
+ return new VersionHistoryImpl(itemMgr, session, nodeId, state, def, listeners, history);
}
/**
- * Checks in a node
- *
+ * Creates a new VersionImpl instance. this is usually called by
+ * the {@link ItemManager}.
+ * @param session
+ * @param state
+ * @param def
+ * @param itemMgr
+ * @param listeners
+ * @return
+ * @throws RepositoryException
+ */
+ public VersionImpl createVersionInstance(SessionImpl session,
+ NodeState state, NodeDef def,
+ ItemManager itemMgr,
+ ItemLifeCycleListener[] listeners)
+ throws RepositoryException {
+ if (!state.getNodeTypeName().equals(NodeTypeRegistry.NT_VERSION)) {
+ throw new RepositoryException("node not nt:version");
+ }
+ NodeId nodeId = (NodeId) state.getId();
+ String historyId = state.getParentUUID();
+ InternalVersionHistory history = vMgr.getVersionHistory(historyId);
+ InternalVersion version = history.getVersion(nodeId.getUUID());
+ return new VersionImpl(itemMgr, session, nodeId, state, def, listeners, version);
+ }
+
+ /**
+ * invokes the checkin() on the persistent version manager and remaps the
+ * newly created version objects.
* @param node
* @return
* @throws RepositoryException
- * @see Node#checkin()
*/
public Version checkin(NodeImpl node) throws RepositoryException {
- // assuming node is versionable and checkout (check in nodeimpl)
- // To create a new version of a versionable node N, the client calls N.checkin.
- // This causes the following series of events:
- InternalVersionHistory history = getInternalVersionHistory(node);
-
- // 0. resolve the predecessors
- Value[] values = node.getProperty(PROPNAME_PREDECESSORS).getValues();
- InternalVersion[] preds = new InternalVersion[values.length];
- for (int i = 0; i < values.length; i++) {
- preds[i] = history.getVersion(values[i].getString());
+ try {
+ InternalVersion version = vMgr.checkin(node);
+ VirtualNodeState vhNode = (VirtualNodeState) virtProvider.getItemState(new NodeId(version.getVersionHistory().getId()));
+ mapVersion(vhNode, version);
+ // invalidate predecessors 'sucessors' properties
+ InternalVersion[] pred = version.getPredecessors();
+ for (int i=0; i<pred.length; i++) {
+ onVersionModified(pred[i]);
+ }
+ return (Version) node.getSession().getNodeByUUID(version.getId());
+ } catch (NoSuchItemStateException e) {
+ throw new RepositoryException(e);
}
+ }
- // 0.1 search a predecessor, suitable for generating the new name
- String versionName = null;
- int maxDots = Integer.MAX_VALUE;
- for (int i = 0; i < preds.length; i++) {
- // take the first pred. without a successor
- if (preds[i].getSuccessors().length == 0) {
- versionName = preds[i].getName().getLocalName(); //assuming no namespaces in version names
- // need to count the dots
- int pos = -1;
- int numDots = 0;
- while (versionName.indexOf('.', pos + 1) >= 0) {
- pos = versionName.indexOf('.', pos + 1);
- numDots++;
- }
- if (numDots < maxDots) {
- maxDots = numDots;
- versionName = pos < 0 ? "1.0" : versionName.substring(0, pos + 1) + (Integer.parseInt(versionName.substring(pos + 1)) + 1);
- }
- break;
+ /**
+ * Called when a internal version has changed its internal structure, and
+ * some of the properties has to be remapped to the content.
+ * @param v
+ * @throws RepositoryException
+ */
+ protected void onVersionModified(InternalVersion v) throws RepositoryException {
+ try {
+ VirtualNodeState ns = (VirtualNodeState) virtProvider.getItemState(new NodeId(v.getId()));
+ mapDynamicProperties(ns, v);
+ } catch (NoSuchItemStateException e) {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ * Maps the version history and it's versions to the content representation.
+ * @param vh
+ * @throws RepositoryException
+ */
+ private void mapVersionHistory(InternalVersionHistory vh)
+ throws RepositoryException {
+ try {
+ String uuid = vh.getId();
+ VirtualNodeState parent = historyRoot;
+ QName historyNodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, uuid.substring(0, 2));
+ if (!parent.hasChildNodeEntry(historyNodeName)) {
+ parent = virtProvider.addNode(parent, historyNodeName, null, NodeTypeRegistry.NT_UNSTRUCTURED, null);
+ } else {
+ parent = virtProvider.getNode(parent, historyNodeName, 1);
+ }
+ historyNodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, uuid.substring(2, 4));
+ if (!parent.hasChildNodeEntry(historyNodeName)) {
+ parent = virtProvider.addNode(parent, historyNodeName, null, NodeTypeRegistry.NT_UNSTRUCTURED, null);
+ } else {
+ parent = virtProvider.getNode(parent, historyNodeName, 1);
+ }
+
+ historyNodeName = new QName(NamespaceRegistryImpl.NS_DEFAULT_URI, uuid.substring(4));
+ VirtualNodeState vhNode = virtProvider.addNode(parent, historyNodeName, vh.getId(), NodeTypeRegistry.NT_VERSION_HISTORY, null);
+
+ // add the versions
+ Iterator iter = vh.getVersions();
+ while (iter.hasNext()) {
+ InternalVersion v = (InternalVersion) iter.next();
+ mapVersion(vhNode, v);
+ }
+
+ } catch (ItemStateException e) {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ * Maps the internal version to its respective content representation
+ * @param vhNode
+ * @param version
+ * @throws RepositoryException
+ */
+ private void mapVersion(VirtualNodeState vhNode, InternalVersion version)
+ throws RepositoryException {
+ try {
+ VirtualNodeState vNode = virtProvider.addNode(vhNode, version.getName(), version.getId(), NodeTypeRegistry.NT_VERSION, null);
+
+ // initialize the version
+ virtProvider.setPropertyValue(vNode, VersionManager.PROPNAME_CREATED, InternalValue.create(version.getCreated()));
+
+ // initialize the primary properties
+ InternalFrozenNode fNode = version.getFrozenNode();
+ virtProvider.setPropertyValue(vNode, VersionManager.PROPNAME_FROZEN_UUID, InternalValue.create(fNode.getFrozenUUID()));
+ virtProvider.setPropertyValue(vNode, VersionManager.PROPNAME_FROZEN_PRIMARY_TYPE, InternalValue.create(fNode.getFrozenPrimaryType()));
+ virtProvider.setPropertyValues(vNode, VersionManager.PROPNAME_FROZEN_MIXIN_TYPES, PropertyType.NAME, InternalValue.create(fNode.getFrozenMixinTypes()));
+
+ // map dynamic ones
+ mapDynamicProperties(vNode, version);
+
+ if (!version.isRootVersion()) {
+ // don't map for root verion
+ mapFrozenNode(vNode, PersistentVersionManager.NODENAME_FROZEN, fNode);
}
+
+ } catch (ItemStateException e) {
+ throw new RepositoryException(e);
}
- // if no empty found, generate new name
- if (versionName == null) {
- versionName = preds[0].getName().getLocalName();
- do {
- versionName += ".1";
- } while (history.hasVersion(new QName("", versionName)));
+ }
+
+ /**
+ * Maps those properties of the internal version to the content that might
+ * change over time. such as labels and successors.
+ * @param vNode
+ * @param version
+ * @throws RepositoryException
+ */
+ private void mapDynamicProperties(VirtualNodeState vNode, InternalVersion version) throws RepositoryException {
+ // add version labels
+ virtProvider.setPropertyValues(vNode, VersionManager.PROPNAME_VERSION_LABELS, PropertyType.STRING, InternalValue.create(version.internalGetLabels()));
+
+ // add predecessors
+ InternalVersion[] preds = version.getPredecessors();
+ InternalValue[] predV = new InternalValue[preds.length];
+ for (int i=0; i<preds.length; i++) {
+ predV[i] = InternalValue.create(new UUID(preds[i].getId()));
}
+ virtProvider.setPropertyValues(vNode, VersionManager.PROPNAME_PREDECESSORS, PropertyType.REFERENCE, predV);
- InternalVersion v = history.checkin(new QName("", versionName), node);
- return new VersionImpl(node.getSession(), v);
+ // add successors
+ InternalVersion[] succ= version.getSuccessors();
+ InternalValue[] succV = new InternalValue[succ.length];
+ for (int i=0; i<succ.length; i++) {
+ succV[i] = InternalValue.create(new UUID(succ[i].getId()));
+ }
+ virtProvider.setPropertyValues(vNode, VersionManager.PROPNAME_SUCCESSORS, PropertyType.REFERENCE, succV);
}
+ /**
+ * Maps the frozen content of an internal version to the content
+ * representation.
+ * @param parent
+ * @param name
+ * @param fNode
+ * @throws RepositoryException
+ */
+ private void mapFrozenNode(VirtualNodeState parent, QName name, InternalFrozenNode fNode) throws RepositoryException {
+ try {
+ VirtualNodeState node = virtProvider.addNode(parent, name, null, fNode.getFrozenPrimaryType(), fNode.getFrozenMixinTypes());
+
+ // initialize the content
+ PersistentProperty[] props = fNode.getFrozenProperties();
+ for (int i=0; i<props.length; i++) {
+ virtProvider.setPropertyValues(node, props[i].getName(), props[i].getType(), props[i].getValues(), props[i].isMultiple());
+ }
+ InternalFreeze[] freezes = fNode.getFrozenChildNodes();
+ for (int i=0; i<freezes.length; i++) {
+ if (freezes[i] instanceof InternalFrozenVersionHistory) {
+ InternalFrozenVersionHistory vh = (InternalFrozenVersionHistory) freezes[i];
+ VirtualNodeState fChild = virtProvider.addNode(node.getId(), vh.getName(), null, NodeTypeRegistry.NT_FROZEN_VERSIONABLE_CHILD);
+ virtProvider.setPropertyValue(fChild, VersionManager.PROPNAME_VERSION_HISTORY, InternalValue.create(UUID.fromString(vh.getVersionHistoryId())));
+ } else { // instance of InternalFrozenNode
+ InternalFrozenNode fn = (InternalFrozenNode) freezes[i];
+ mapFrozenNode(node, fn.getName(), fn);
+ }
+ }
+ } catch (ItemStateException e) {
+ throw new RepositoryException(e);
+ }
+
+ }
}
Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/package.html
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/package.html (original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/version/package.html Tue Oct 26 08:44:46 2004
@@ -1,14 +1,25 @@
<body>
-The version storage is currently implement using the normal storage of the
-repository. For performance and scalability reasons, it will be probably
-stored externally later.<br>
-A lot of the versioning functionality is handled in the NodeImpl or VersionImpl
-itself, since it operates on internal properties and node of that nodes. This
-also might move to another class, eg. the VersionManager later.<br>
+The versioning framework in jackrabbit consists of 3 layers. A persistence layer,
+an application layer and an presentation layer.<p>
+The persistence layer uses a 'normal' workspace as storage. The storage can later
+be exchanged by a more scaleable one. The application layer operates on the
+persistent one and provides the internal view of the version storage. It is
+manifested through the <code>InternalVersion</code> and
+<code>InternalVersionHistory</code> objects. The
+<code>PersistentVersionManager</code> is responsible for those 2 layers.<p>
+The internal versions are also mapped to the content and exposed through the
+API (i.e. the <code>Version</code> extends <code>Node</code> and can be inspected
+with normal Node methods). Furthermore the version store is also exposed below
+<code>/jcr:system/jcr:versionStorage</code>. The exact structure of it is not
+defined yet, so applications should not relay on it and rather use
+<code>Node.getVersionHistory()</code> to access a particular version history or
+use the search mechanisms to find the respective versions.<p>
+The presentation layer is managed by the <code>VersionManager</code>. it is
+responsible for mapping the version storage to the content.
<p>
Open issues:
<ul>
<li>consider multi-threading behaviour
</ul>
-</body>
\ No newline at end of file
+</body>
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/DefaultItemStateProvider.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/DefaultItemStateProvider.java Tue Oct 26 08:44:46 2004
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.jackrabbit.core.virtual;
+
+import org.apache.jackrabbit.core.state.*;
+import org.apache.jackrabbit.core.*;
+import org.apache.jackrabbit.core.nodetype.*;
+import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.log4j.Logger;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Arrays;
+
+/**
+ * This Class implements a virtual item state provider.
+ *
+ * @author tripod
+ * @version $Revision:$, $Date:$
+ */
+public class DefaultItemStateProvider implements VirtualItemStateProvider {
+
+ /**
+ * the default logger
+ */
+ private static Logger log = Logger.getLogger(DefaultItemStateProvider.class);
+
+ /**
+ * the nodetype manager that is used by this provider
+ */
+ private final NodeTypeManagerImpl ntMgr;
+
+ /**
+ * the virtual root state of this provider (does not have to be /)
+ */
+ private final VirtualNodeState rootState;
+
+ /**
+ * the items of this provider
+ */
+ private final HashMap items = new HashMap();
+
+ /**
+ * Creates a new item state provider.
+ * @param ntMgr the nodetype manager
+ * @param overlayedRoot the node state that is overlayed
+ */
+ public DefaultItemStateProvider(NodeTypeManagerImpl ntMgr, NodeState overlayedRoot) {
+ this.ntMgr = ntMgr;
+ rootState = new VirtualNodeState(overlayedRoot);
+ items.put(rootState.getId(), rootState);
+ }
+
+ /**
+ * Returns the nodestate of the relative root of this provider
+ * @return
+ */
+ public VirtualNodeState getRootState() {
+ return rootState;
+ }
+
+ /**
+ * @see ItemStateProvider#getItemState(org.apache.jackrabbit.core.ItemId)
+ */
+ public ItemState getItemState(ItemId id) throws NoSuchItemStateException {
+ ItemState state = (ItemState) items.get(id);
+ if (state==null) {
+ throw new NoSuchItemStateException(id.toString());
+ }
+ return state;
+ }
+
+ /**
+ * @see ItemStateProvider#hasItemState(org.apache.jackrabbit.core.ItemId)
+ */
+ public boolean hasItemState(ItemId id) {
+ return items.containsKey(id);
+ }
+
+ /**
+ * virtual item state provider do not have attics.
+ * @throws NoSuchItemStateException always
+ */
+ public ItemState getItemStateInAttic(ItemId id) throws NoSuchItemStateException {
+ // never has states in attic
+ throw new NoSuchItemStateException(id.toString());
+ }
+
+ /**
+ * virtual item state provider do not have attics.
+ * @return <code>false</code>
+ */
+ public boolean hasItemStateInAttic(ItemId id) {
+ // never has states in attic
+ return false;
+ }
+
+ /**
+ * Adds a node state
+ * @param parentId
+ * @param name
+ * @param id
+ * @param nodeType
+ * @return
+ * @throws ItemStateException
+ * @throws RepositoryException
+ */
+ public VirtualNodeState addNode(ItemId parentId, QName name, String id, QName nodeType)
+ throws ItemStateException, RepositoryException {
+ if (!(parentId instanceof NodeId)) {
+ throw new ItemStateException("Parent must be a node");
+ }
+ VirtualNodeState parent = (VirtualNodeState) getItemState(parentId);
+ return addNode(parent, name, id, nodeType, null);
+ }
+
+ /**
+ * Adds a node state
+ * @param parent
+ * @param name
+ * @param id
+ * @param nodeTypeName
+ * @param mixins
+ * @return
+ * @throws ItemStateException
+ * @throws RepositoryException
+ */
+ public VirtualNodeState addNode(VirtualNodeState parent, QName name, String id, QName nodeTypeName, QName[] mixins)
+ throws ItemStateException, RepositoryException {
+ NodeTypeImpl nodeType = nodeTypeName==null ? null : ntMgr.getNodeType(nodeTypeName);
+ NodeDefImpl def;
+ try {
+ def = getApplicableChildNodeDef(parent, name, nodeType == null ? null : nodeType.getQName());
+ } catch (RepositoryException re) {
+ String msg = "no definition found in parent node's node type for new node";
+ throw new ConstraintViolationException(msg, re);
+ }
+ if (nodeType == null) {
+ // use default node type
+ nodeType = (NodeTypeImpl) def.getDefaultPrimaryType();
+ }
+
+ // default properties
+ VirtualNodeState ns = createChildNode(parent, name, def, nodeType, id);
+ setPropertyValue(ns, ItemImpl.PROPNAME_PRIMARYTYPE, InternalValue.create(nodeType.getQName()));
+ if (mixins!=null) {
+ ns.setMixinTypeNames(new HashSet(Arrays.asList(mixins)));
+ }
+ if (getEffectiveNodeType(ns).includesNodeType(NodeTypeRegistry.MIX_REFERENCEABLE)) {
+ setPropertyValue(ns, ItemImpl.PROPNAME_UUID, InternalValue.create(ns.getUUID()));
+ }
+ items.put(ns.getId(), ns);
+ return ns;
+ }
+
+ /**
+ * returns the child node of the given parent
+ * @param parent
+ * @param name
+ * @param index
+ * @return
+ * @throws NoSuchItemStateException
+ */
+ public VirtualNodeState getNode(VirtualNodeState parent, QName name, int index) throws NoSuchItemStateException {
+ NodeState.ChildNodeEntry entry = parent.getChildNodeEntry(name, index);
+ if (entry==null) {
+ throw new NoSuchItemStateException(name.toString());
+ }
+ return (VirtualNodeState) getItemState(new NodeId(entry.getUUID()));
+ }
+
+ /**
+ * Sets the property value
+ *
+ * @param name
+ * @param value
+ * @throws RepositoryException
+ */
+ public void setPropertyValue(VirtualNodeState parentState, QName name, InternalValue value)
+ throws RepositoryException {
+ setPropertyValues(parentState, name, value.getType(), new InternalValue[]{value}, false);
+ }
+
+ /**
+ * Sets the property values
+ *
+ * @param name
+ * @param type
+ * @param values
+ * @throws RepositoryException
+ */
+ public void setPropertyValues(VirtualNodeState parentState, QName name, int type, InternalValue[] values)
+ throws RepositoryException {
+ setPropertyValues(parentState, name, type, values, true);
+ }
+
+ /**
+ * Sets the property values
+ *
+ * @param name
+ * @param type
+ * @param values
+ * @throws RepositoryException
+ */
+ public void setPropertyValues(VirtualNodeState parentState, QName name, int type, InternalValue[] values, boolean multiple)
+ throws RepositoryException {
+ VirtualPropertyState prop = getOrCreatePropertyState(parentState, name, type, multiple);
+ prop.setValues(values);
+ }
+
+ /**
+ * creates a new child node
+ *
+ * @param name
+ * @param def
+ * @param nodeType
+ * @param uuid
+ * @return
+ */
+ private VirtualNodeState createChildNode(VirtualNodeState parentState,
+ QName name, NodeDefImpl def,
+ NodeTypeImpl nodeType, String uuid) {
+
+ String parentUUID = parentState.getUUID();
+ // create a new node state
+ VirtualNodeState state = null;
+ if (uuid == null) {
+ uuid = UUID.randomUUID().toString();
+ }
+ state = new VirtualNodeState(uuid, nodeType.getQName(), parentUUID);
+ state.setDefinitionId(new NodeDefId(def.unwrap()));
+
+ // add new child node entry
+ parentState.addChildNodeEntry(name, state.getUUID());
+
+ return state;
+ }
+
+ /**
+ * Retrieves or creates a new property state as child property of this node
+ *
+ * @param name
+ * @param type
+ * @param multiValued
+ * @return
+ * @throws RepositoryException
+ */
+ private VirtualPropertyState getOrCreatePropertyState(VirtualNodeState parentState, QName name, int type, boolean multiValued)
+ throws RepositoryException {
+
+ PropertyId propId = new PropertyId(parentState.getUUID(), name);
+ if (hasItemState(propId)) {
+ try {
+ return (VirtualPropertyState) getItemState(propId);
+ } catch (ItemStateException e) {
+ throw new RepositoryException("Unable to create property: " + e.toString());
+ }
+ } else {
+ try {
+ PropertyDefImpl def = getApplicablePropertyDef(parentState, name, type, multiValued);
+ VirtualPropertyState propState = createPropertyState(parentState.getUUID(), name);
+ propState.setType(type);
+ propState.setDefinitionId(new PropDefId(def.unwrap()));
+ parentState.addPropertyEntry(name);
+ return propState;
+ } catch (ItemStateException e) {
+ throw new RepositoryException("Unable to store property: " + e.toString());
+ }
+ }
+ }
+
+ /**
+ * Creates a property state
+ * @param parentUUID
+ * @param propName
+ * @return
+ * @throws ItemStateException
+ */
+ private VirtualPropertyState createPropertyState(String parentUUID, QName propName) throws ItemStateException {
+ PropertyId id = new PropertyId(parentUUID, propName);
+ // check cache
+ if (hasItemState(id)) {
+ String msg = "there's already a property state instance with id " + id;
+ log.error(msg);
+ throw new ItemStateException(msg);
+ }
+
+ VirtualPropertyState propState = new VirtualPropertyState(propName, parentUUID);
+ items.put(id, propState);
+ return propState;
+
+ }
+ /**
+ * retrieves the property definition for the given contraints
+ *
+ * @param propertyName
+ * @param type
+ * @param multiValued
+ * @return
+ * @throws javax.jcr.RepositoryException
+ */
+ protected PropertyDefImpl getApplicablePropertyDef(VirtualNodeState parentState, QName propertyName,
+ int type, boolean multiValued)
+ throws RepositoryException {
+ PropDef pd = getEffectiveNodeType(parentState).getApplicablePropertyDef(propertyName, type, multiValued);
+ return ntMgr.getPropDef(new PropDefId(pd));
+ }
+
+ /**
+ * Retrieves the node definition for the given contraints.
+ *
+ * @param nodeName
+ * @param nodeTypeName
+ * @return
+ * @throws RepositoryException
+ */
+ protected NodeDefImpl getApplicableChildNodeDef(VirtualNodeState parentState, QName nodeName, QName nodeTypeName)
+ throws RepositoryException {
+ ChildNodeDef cnd = getEffectiveNodeType(parentState).getApplicableChildNodeDef(nodeName, nodeTypeName);
+ return ntMgr.getNodeDef(new NodeDefId(cnd));
+ }
+
+ /**
+ * Returns the effective (i.e. merged and resolved) node type representation
+ * of this node's primary and mixin node types.
+ *
+ * @return the effective node type
+ * @throws RepositoryException
+ */
+ protected EffectiveNodeType getEffectiveNodeType(VirtualNodeState nodeState) throws RepositoryException {
+ // build effective node type of mixins & primary type
+ NodeTypeRegistry ntReg = ntMgr.getNodeTypeRegistry();
+ // existing mixin's
+ HashSet set = new HashSet(nodeState.getMixinTypeNames());
+ // primary type
+ set.add(nodeState.getNodeTypeName());
+ try {
+ return ntReg.buildEffectiveNodeType((QName[]) set.toArray(new QName[set.size()]));
+ } catch (NodeTypeConflictException ntce) {
+ String msg = "internal error: failed to build effective node type for node " + nodeState.getUUID();
+ throw new RepositoryException(msg, ntce);
+ }
+ }
+
+}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualItemStateProvider.java Tue Oct 26 08:44:46 2004
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.jackrabbit.core.virtual;
+
+import org.apache.jackrabbit.core.state.ItemStateProvider;
+/**
+ * This Interface defines a virtual item state provide.
+ *
+ * @author tripod
+ * @version $Revision:$, $Date:$
+ */
+public interface VirtualItemStateProvider extends ItemStateProvider {
+
+}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualNodeState.java Tue Oct 26 08:44:46 2004
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.jackrabbit.core.virtual;
+
+import org.apache.jackrabbit.core.state.*;
+import org.apache.jackrabbit.core.QName;
+
+/**
+ * This Class implements a virtual node state
+ *
+ * @author tripod
+ * @version $Revision:$, $Date:$
+ */
+public class VirtualNodeState extends NodeState {
+
+ /**
+ *
+ * @param uuid
+ * @param nodeTypeName
+ * @param parentUUID
+ */
+ protected VirtualNodeState(String uuid, QName nodeTypeName, String parentUUID) {
+ super(uuid, nodeTypeName, parentUUID, ItemState.STATUS_EXISTING_VIRTUAL);
+ }
+
+ /**
+ *
+ * @param overlayedState
+ */
+ protected VirtualNodeState(NodeState overlayedState) {
+ super(overlayedState, ItemState.STATUS_EXISTING_VIRTUAL);
+ }
+}
Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/virtual/VirtualPropertyState.java Tue Oct 26 08:44:46 2004
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ *
+ * Licensed 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.jackrabbit.core.virtual;
+
+import org.apache.jackrabbit.core.state.PropertyState;
+import org.apache.jackrabbit.core.state.ItemState;
+import org.apache.jackrabbit.core.QName;
+
+/**
+ * This Class implements a virtual property state
+ *
+ * @author tripod
+ * @version $Revision:$, $Date:$
+ */
+public class VirtualPropertyState extends PropertyState {
+
+ /**
+ *
+ * @param name
+ * @param parentUUID
+ */
+ public VirtualPropertyState(QName name, String parentUUID) {
+ super(name, parentUUID, ItemState.STATUS_EXISTING);
+ }
+
+}