Return-Path: Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: (qmail 94791 invoked from network); 19 Jul 2009 00:09:12 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 19 Jul 2009 00:09:12 -0000 Received: (qmail 1398 invoked by uid 500); 19 Jul 2009 00:10:17 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 1323 invoked by uid 500); 19 Jul 2009 00:10:17 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 1314 invoked by uid 99); 19 Jul 2009 00:10:17 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 19 Jul 2009 00:10:17 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 19 Jul 2009 00:10:03 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 1997A23888CC; Sun, 19 Jul 2009 00:09:42 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r795452 [3/3] - in /jackrabbit/sandbox/tripod-JCR-2209: ./ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/ Date: Sun, 19 Jul 2009 00:09:41 -0000 To: commits@jackrabbit.apache.org From: tripod@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090719000942.1997A23888CC@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImplRestore.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImplRestore.java?rev=795452&view=auto ============================================================================== --- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImplRestore.java (added) +++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImplRestore.java Sun Jul 19 00:09:40 2009 @@ -0,0 +1,552 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.jackrabbit.core.version; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; + +import javax.jcr.ItemExistsException; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.version.OnParentVersionAction; +import javax.jcr.version.Version; +import javax.jcr.version.VersionException; +import javax.jcr.version.VersionManager; + +import org.apache.jackrabbit.core.BatchedItemOperations; +import org.apache.jackrabbit.core.HierarchyManager; +import org.apache.jackrabbit.core.ItemValidator; +import org.apache.jackrabbit.core.SessionImpl; +import org.apache.jackrabbit.core.id.NodeId; +import org.apache.jackrabbit.core.nodetype.PropDef; +import org.apache.jackrabbit.core.security.authorization.Permission; +import org.apache.jackrabbit.core.state.ChildNodeEntry; +import org.apache.jackrabbit.core.state.ItemStateException; +import org.apache.jackrabbit.core.state.PropertyState; +import org.apache.jackrabbit.core.state.UpdatableItemStateManager; +import org.apache.jackrabbit.core.value.InternalValue; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.spi.Path; +import org.apache.jackrabbit.spi.commons.name.NameConstants; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The JCR Version Manager impementation is split in several classes in order to + * group related methods together. + *

+ * this class provides methods for the restore operations. + */ +abstract public class JcrVersionManagerImplRestore extends JcrVersionManagerImplBase { + + /** + * default logger + */ + private static final Logger log = LoggerFactory.getLogger(JcrVersionManagerImplRestore.class); + + /** + * Creates a new version manager for the given session + * @param session workspace sesion + * @param stateMgr the underlying state manager + * @param hierMgr local hierarchy manager + */ + protected JcrVersionManagerImplRestore(SessionImpl session, + UpdatableItemStateManager stateMgr, + HierarchyManager hierMgr) { + super(session, stateMgr, hierMgr); + } + + /** + * @param state the state to restore + * @param version the version to restore + * @param removeExisting remove existing flag + * @throws RepositoryException if an error occurs + * + * @see javax.jcr.version.VersionManager#restore(String, Version, boolean) + */ + protected void restore(NodeStateEx state, Version version, boolean removeExisting) + throws RepositoryException { + checkVersionable(state); + InternalVersion v = getVersion(version); + // check if 'own' version + if (!v.getVersionHistory().equals(getVersionHistory(state))) { + throw new VersionException("Unable to restore version. Not same version history."); + } + WriteOperation ops = startWriteOperation(); + try { + internalRestore(state, v, new DateVersionSelector(version.getCreated()), removeExisting); + ops.save(); + } catch (ItemStateException e) { + throw new RepositoryException(e); + } finally { + ops.close(); + } + } + + /** + * @param state the state to restore + * @param versionName the name of the version to restore + * @param removeExisting remove existing flag + * @throws RepositoryException if an error occurs + * + * @see VersionManager#restore(String, String, boolean) + */ + protected void restore(NodeStateEx state, Name versionName, boolean removeExisting) + throws RepositoryException { + checkVersionable(state); + InternalVersion v = getVersionHistory(state).getVersion(versionName); + DateVersionSelector gvs = new DateVersionSelector(v.getCreated()); + WriteOperation ops = startWriteOperation(); + try { + internalRestore(state, v, gvs, removeExisting); + ops.save(); + } catch (ItemStateException e) { + throw new RepositoryException(e); + } finally { + ops.close(); + } + } + + /** + * @param state the state to restore + * @param versionLabel the name of the version to restore + * @param removeExisting remove existing flag + * @throws RepositoryException if an error occurs + * + * @see VersionManager#restoreByLabel(String, String, boolean) + */ + protected void restoreByLabel(NodeStateEx state, Name versionLabel, boolean removeExisting) + throws RepositoryException { + checkVersionable(state); + InternalVersion v = getVersionHistory(state).getVersionByLabel(versionLabel); + if (v == null) { + throw new VersionException("No version for label " + versionLabel + " found."); + } + WriteOperation ops = startWriteOperation(); + try { + internalRestore(state, v, new LabelVersionSelector(versionLabel), removeExisting); + ops.save(); + } catch (ItemStateException e) { + throw new RepositoryException(e); + } finally { + ops.close(); + } + } + + /** + * Restores the version below the parent node + * using the indicated name + * + * @param parent parent node + * @param name desired name + * @param version version to restore + * @param removeExisting remove exiting flag + * @throws RepositoryException if an error occurs + */ + protected void restore(NodeStateEx parent, Name name, Version version, boolean removeExisting) + throws RepositoryException { + // check if versionable node exists + InternalFrozenNode fn = ((VersionImpl) version).getInternalFrozenNode(); + if (stateMgr.hasItemState(fn.getFrozenId())) { + if (removeExisting) { + NodeStateEx existing = parent.getNode(fn.getFrozenId()); + checkVersionable(existing); + InternalVersion v = getVersion(version); + + // move versionable node below this one using the given "name" + WriteOperation ops = startWriteOperation(); + try { + NodeStateEx exParent = existing.getParent(); + NodeStateEx state = parent.moveFrom(existing, name, false); + exParent.store(); + parent.store(); + // and restore it + internalRestore(state, v, new DateVersionSelector(v.getCreated()), removeExisting); + ops.save(); + } catch (ItemStateException e) { + throw new RepositoryException(e); + } finally { + ops.close(); + } + } else { + throw new ItemExistsException("Unable to restore version. Versionable node already exists."); + } + } else { + // create new node below parent + NodeStateEx state = parent.addNode(name, fn.getFrozenPrimaryType(), fn.getFrozenId()); + state.setMixins(fn.getFrozenMixinTypes()); + restore(state, version, removeExisting); + } + } + + /** + * @param versions Versions to restore + * @param removeExisting remove existing flag + * @throws RepositoryException if an error occurs + * + * @see VersionManager#restore(Version[], boolean) + * @see VersionManager#restore(Version, boolean) + */ + protected void restore(final Map versions, + boolean removeExisting) + throws RepositoryException { + + // create a version selector to the set of versions + VersionSelector vsel = new VersionSelector() { + public InternalVersion select(InternalVersionHistory versionHistory) throws RepositoryException { + // try to select version as specified + InternalVersion v = versions.get(versionHistory.getId()); + if (v == null) { + // select latest one + v = DateVersionSelector.selectByDate(versionHistory, null); + } + return v; + } + }; + + WriteOperation ops = startWriteOperation(); + try { + // now restore all versions that have a node in the workspace + int numRestored = 0; + while (versions.size() > 0) { + Set restored = null; + for (InternalVersion v : versions.values()) { + NodeStateEx state = getNodeStateEx(v.getFrozenNode().getFrozenId()); + if (state != null) { + // todo: check should operate on workspace states, too + int options = ItemValidator.CHECK_LOCK | ItemValidator.CHECK_HOLD; + checkModify(state, options, Permission.NONE); + restored = internalRestore(state, v, vsel, removeExisting); + // remove restored versions from set + for (InternalVersion r : restored) { + versions.remove(r.getVersionHistory().getId()); + } + numRestored += restored.size(); + break; + } + } + if (restored == null) { + if (numRestored == 0) { + throw new VersionException("Unable to restore. At least one version needs" + + " existing versionable node in workspace."); + } else { + throw new VersionException("Unable to restore. All versions with non" + + " existing versionable nodes need parent."); + } + } + } + ops.save(); + } catch (ItemStateException e) { + log.error("Error while reverting changes applied during restore.", e); + throw new RepositoryException(e); + } finally { + ops.close(); + } + } + + /** + * Internal method to restore a version. + * + * @param state the state to restore + * @param version version to restore + * @param vsel the version selector that will select the correct version for + * OPV=Version child nodes. + * @param removeExisting remove existing flag + * @return set of restored versions + * @throws RepositoryException if an error occurs + * @throws ItemStateException if an error occurs + */ + protected Set internalRestore(NodeStateEx state, + InternalVersion version, + VersionSelector vsel, + boolean removeExisting) + throws RepositoryException, ItemStateException { + + // fail if root version + if (version.isRootVersion()) { + throw new VersionException("Restore of root version not allowed."); + } + + boolean isFull = checkVersionable(state); + + // check permission + Path path = hierMgr.getPath(state.getNodeId()); + session.getAccessManager().checkPermission(path, Permission.VERSION_MNGMT); + + // 1. The child node and properties of N will be changed, removed or + // added to, depending on their corresponding copies in V and their + // own OnParentVersion attributes (see 7.2.8, below, for details). + Set restored = new HashSet(); + restoreFrozenState(state, version.getFrozenNode(), vsel, restored, removeExisting); + restored.add(version); + + if (isFull) { + // 2. N's jcr:baseVersion property will be changed to point to V. + state.setPropertyValue( + NameConstants.JCR_BASEVERSION, InternalValue.create(version.getId())); + + // 4. N's jcr:predecessor property is set to null + state.setPropertyValues(NameConstants.JCR_PREDECESSORS, PropertyType.REFERENCE, InternalValue.EMPTY_ARRAY); + + // also clear mergeFailed + state.removeProperty(NameConstants.JCR_MERGEFAILED); + + } else { + // with simple versioning, the node is checked in automatically, + // thus not allowing any branches + vMgr.checkin(session, state); + } + // 3. N's jcr:isCheckedOut property is set to false. + state.setPropertyValue(NameConstants.JCR_ISCHECKEDOUT, InternalValue.create(false)); + state.store(); + return restored; + } + + /** + * Restores the properties and child nodes from the frozen state. + * + * @param state state to restore + * @param freeze the frozen node + * @param vsel version selector + * @param restored set of restored versions + * @param removeExisting remove existing flag + * @throws RepositoryException if an error occurs + * @throws ItemStateException if an error occurs + */ + protected void restoreFrozenState(NodeStateEx state, InternalFrozenNode freeze, VersionSelector vsel, + Set restored, boolean removeExisting) + throws RepositoryException, ItemStateException { + + // check uuid + if (state.getEffectiveNodeType().includesNodeType(NameConstants.MIX_REFERENCEABLE)) { + if (!state.getNodeId().equals(freeze.getFrozenId())) { + throw new ItemExistsException("Unable to restore version of " + safeGetJCRPath(state) + ". UUID changed."); + } + } + + // check primary type + if (!freeze.getFrozenPrimaryType().equals(state.getState().getNodeTypeName())) { + // todo: implement + throw new UnsupportedRepositoryOperationException("Unable to restore version of " + safeGetJCRPath(state) + ". PrimaryType change not supported yet."); + } + + // adjust mixins + state.setMixins(freeze.getFrozenMixinTypes()); + + // copy frozen properties + PropertyState[] props = freeze.getFrozenProperties(); + HashSet propNames = new HashSet(); + for (PropertyState prop : props) { + // skip properties that should not to be reverted back + if (prop.getName().equals(NameConstants.JCR_ACTIVITY)) { + continue; + } + propNames.add(prop.getName()); + state.copyFrom(prop); + } + // remove properties that do not exist in the frozen representation + for (PropertyState prop: state.getProperties()) { + // ignore some props that are not well guarded by the OPV + Name propName = prop.getName(); + if (propName.equals(NameConstants.JCR_VERSIONHISTORY)) { + // ignore + } else if (propName.equals(NameConstants.JCR_PREDECESSORS)) { + // ignore + } else if (!propNames.contains(propName)) { + int opv = state.getDefinition(prop).getOnParentVersion(); + if (opv == OnParentVersionAction.COPY || opv == OnParentVersionAction.VERSION) { + state.removeProperty(propName); + } + } + } + + // add 'auto-create' properties that do not exist yet + for (PropDef def: state.getEffectiveNodeType().getAutoCreatePropDefs()) { + if (!state.hasProperty(def.getName())) { + // compute system generated values if necessary + // todo: use NodeTypeInstanceHandler + InternalValue[] values = + BatchedItemOperations.computeSystemGeneratedPropertyValues(state.getState(), def); + if (values == null) { + values = def.getDefaultValues(); + } + if (values != null) { + state.setPropertyValues(def.getName(), def.getRequiredType(), values, def.isMultiple()); + } + } + } + + // first delete some of the child nodes. this is a bit tricky, in case + // the child node index changed. mark an sweep + LinkedList toDelete = new LinkedList(); + for (ChildNodeEntry entry: state.getState().getChildNodeEntries()) { + NodeStateEx child = state.getNode(entry.getName(), entry.getIndex()); + int opv = child.getDefinition().getOnParentVersion(); + if (opv == OnParentVersionAction.COPY) { + // only remove OPV=Copy nodes + toDelete.addFirst(entry); + } else if (opv == OnParentVersionAction.VERSION) { + // only remove, if node to be restored does not contain child, + // or if restored child is not versionable + NodeId vhId = child.hasProperty(NameConstants.JCR_VERSIONHISTORY) + ? child.getPropertyValue(NameConstants.JCR_VERSIONHISTORY).getNodeId() + : null; + if (vhId == null || !freeze.hasFrozenHistory(vhId)) { + toDelete.addFirst(entry); + } + } + } + for (ChildNodeEntry entry: toDelete) { + state.removeNode(entry.getName(), entry.getIndex()); + } + // need to sync with state manager + state.store(); + + // restore the frozen nodes + InternalFreeze[] frozenNodes = freeze.getFrozenChildNodes(); + for (InternalFreeze child : frozenNodes) { + NodeStateEx restoredChild = null; + if (child instanceof InternalFrozenNode) { + InternalFrozenNode f = (InternalFrozenNode) child; + // check for existing + if (f.getFrozenId() != null) { + if (stateMgr.hasItemState(f.getFrozenId())) { + NodeStateEx existing = state.getNode(f.getFrozenId()); + if (removeExisting) { + NodeStateEx parent = existing.getParent(); + parent.removeNode(existing); + parent.store(); + } else if (existing.getState().isShareable()) { + // if existing node is shareable, then clone it + restoredChild = state.moveFrom(existing, existing.getName(), true); + } else { + // since we delete the OPV=Copy children beforehand, all + // found nodes must be outside of this tree + throw new ItemExistsException( + "Unable to restore node, item already" + + " exists outside of restored tree: " + + existing); + } + + } + } + if (restoredChild == null) { + restoredChild = state.addNode(f.getName(), f.getFrozenPrimaryType(), f.getFrozenId()); + restoredChild.setMixins(f.getFrozenMixinTypes()); + restoreFrozenState(restoredChild, f, vsel, restored, removeExisting); + } + + } else if (child instanceof InternalFrozenVersionHistory) { + InternalFrozenVersionHistory fh = (InternalFrozenVersionHistory) child; + InternalVersionHistory vh = vMgr.getVersionHistory(fh.getVersionHistoryId()); + Name oldVersion = null; + + // check if representing versionable already exists somewhere + NodeId nodeId = vh.getVersionableId(); + if (stateMgr.hasItemState(nodeId)) { + NodeStateEx existing = state.getNode(nodeId); + if (existing.getParentId() == state.getNodeId()) { + // remove + state.removeNode(existing); + } else if (removeExisting) { + NodeStateEx parent = existing.getNode(existing.getNodeId()); + state.moveFrom(existing, fh.getName(), false); + parent.store(); + + // get old version name + oldVersion = getBaseVersion(existing).getName(); + } else { + // since we delete the OPV=Copy children beforehand, all + // found nodes must be outside of this tree + throw new ItemExistsException( + "Unable to restore node, item already exists" + + " outside of restored tree: " + existing); + } + } + // get desired version from version selector + InternalVersion v = vsel.select(vh); + + // check existing version of item exists + if (!stateMgr.hasItemState(nodeId)) { + if (v == null) { + // if version selector was unable to select version, + // choose the initial one + InternalVersion[] vs = vh.getRootVersion().getSuccessors(); + if (vs.length == 0) { + String msg = "Unable to select appropariate version for " + + child.getName() + " using " + vsel; + log.error(msg); + throw new VersionException(msg); + } + v = vs[0]; + } + InternalFrozenNode f = v.getFrozenNode(); + restoredChild = state.addNode(fh.getName(), f.getFrozenPrimaryType(), f.getFrozenId()); + restoredChild.setMixins(f.getFrozenMixinTypes()); + } else { + restoredChild = state.getNode(nodeId); + if (v == null || oldVersion == null || v.getName().equals(oldVersion)) { + v = null; + } + } + if (v != null) { + try { + internalRestore(restoredChild, v, vsel, removeExisting); + } catch (RepositoryException e) { + log.error("Error while restoring node: " + e); + log.error(" child path: " + restoredChild); + log.error(" selected version: " + v.getName()); + StringBuffer avail = new StringBuffer(); + for (Name name: vh.getVersionNames()) { + avail.append(name); + avail.append(", "); + } + log.error(" available versions: " + avail); + log.error(" versionselector: " + vsel); + throw e; + } + // add this version to set + restored.add(v); + } + } + // ensure proper ordering (issue JCR-469) + if (restoredChild != null && state.getEffectiveNodeType().hasOrderableChildNodes()) { + // order at end + ArrayList list = new ArrayList(state.getState().getChildNodeEntries()); + ChildNodeEntry toReorder = null; + boolean isLast = true; + for (ChildNodeEntry e: list) { + if (e.getId().equals(restoredChild.getNodeId())) { + toReorder = e; + } else if (toReorder != null) { + isLast = false; + } + } + if (toReorder != null && !isLast) { + list.remove(toReorder); + list.add(toReorder); + state.getState().setChildNodeEntries(list); + } + } + } + } + +} \ No newline at end of file Propchange: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImplRestore.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/JcrVersionManagerImplRestore.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev Url Modified: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/LabelVersionSelector.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/LabelVersionSelector.java?rev=795452&r1=795451&r2=795452&view=diff ============================================================================== --- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/LabelVersionSelector.java (original) +++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/LabelVersionSelector.java Sun Jul 19 00:09:40 2009 @@ -17,9 +17,8 @@ package org.apache.jackrabbit.core.version; import javax.jcr.RepositoryException; -import javax.jcr.version.Version; -import javax.jcr.version.VersionException; -import javax.jcr.version.VersionHistory; + +import org.apache.jackrabbit.spi.Name; /** * This Class implements a version selector that selects a version by label. @@ -38,15 +37,15 @@ /** * a versionlabel hint */ - private String label = null; + private Name label = null; /** * Creates a LabelVersionSelector that will try to select a * version with the given label. * - * @param label + * @param label label hint */ - public LabelVersionSelector(String label) { + public LabelVersionSelector(Name label) { this.label = label; } @@ -55,28 +54,26 @@ * * @return the label hint. */ - public String getLabel() { + public Name getLabel() { return label; } /** * Sets the label hint * - * @param label + * @param label label hint */ - public void setLabel(String label) { + public void setLabel(Name label) { this.label = label; } /** + * {@inheritDoc} + * * Selects a version from the given version history using the previously * assigned hint in the following order: name, label, date, latest. - * - * @param versionHistory - * @return - * @throws RepositoryException */ - public Version select(VersionHistory versionHistory) + public InternalVersion select(InternalVersionHistory versionHistory) throws RepositoryException { return selectByLabel(versionHistory, label); } @@ -84,18 +81,14 @@ /** * Selects a version by label * - * @param history - * @param label + * @param history history to select from + * @param label desired label * @return the version with the given label or null - * @throws RepositoryException + * @throws RepositoryException if an error occurs */ - public static Version selectByLabel(VersionHistory history, String label) + public static InternalVersion selectByLabel(InternalVersionHistory history, Name label) throws RepositoryException { - try { - return history.getVersionByLabel(label); - } catch (VersionException e) { - return null; - } + return history.getVersionByLabel(label); } /** Modified: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java?rev=795452&r1=795451&r2=795452&view=diff ============================================================================== --- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java (original) +++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/NodeStateEx.java Sun Jul 19 00:09:40 2009 @@ -16,32 +16,34 @@ */ package org.apache.jackrabbit.core.version; +import java.util.List; +import java.util.Set; + +import javax.jcr.ItemExistsException; +import javax.jcr.PropertyType; +import javax.jcr.RepositoryException; +import javax.jcr.UnsupportedRepositoryOperationException; +import javax.jcr.nodetype.ConstraintViolationException; +import javax.jcr.nodetype.NoSuchNodeTypeException; + +import org.apache.jackrabbit.core.PropertyImpl; import org.apache.jackrabbit.core.id.NodeId; import org.apache.jackrabbit.core.id.PropertyId; -import org.apache.jackrabbit.core.PropertyImpl; import org.apache.jackrabbit.core.nodetype.EffectiveNodeType; import org.apache.jackrabbit.core.nodetype.NodeDef; import org.apache.jackrabbit.core.nodetype.NodeTypeConflictException; import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry; import org.apache.jackrabbit.core.nodetype.PropDef; +import org.apache.jackrabbit.core.state.ChildNodeEntry; import org.apache.jackrabbit.core.state.ItemState; import org.apache.jackrabbit.core.state.ItemStateException; import org.apache.jackrabbit.core.state.NodeState; import org.apache.jackrabbit.core.state.PropertyState; import org.apache.jackrabbit.core.state.UpdatableItemStateManager; -import org.apache.jackrabbit.core.state.ChildNodeEntry; import org.apache.jackrabbit.core.value.InternalValue; import org.apache.jackrabbit.spi.Name; import org.apache.jackrabbit.spi.commons.name.NameConstants; -import java.util.List; -import java.util.Set; - -import javax.jcr.RepositoryException; -import javax.jcr.PropertyType; -import javax.jcr.nodetype.ConstraintViolationException; -import javax.jcr.nodetype.NoSuchNodeTypeException; - /** * This Class provides some basic node operations directly on the node state. */ @@ -70,8 +72,10 @@ /** * Creates a new persistent node * - * @param stateMgr - * @param nodeState + * @param stateMgr state manager + * @param ntReg node type registry + * @param nodeState underlying node state + * @param name name (can be null) */ public NodeStateEx(UpdatableItemStateManager stateMgr, NodeTypeRegistry ntReg, @@ -82,6 +86,26 @@ this.name = name; } + /** + * Creates a new persistent node + * + * @param stateMgr state manager + * @param ntReg node type registry + * @param nodeId node id + * @throws RepositoryException if the node state can't be loaded + */ + public NodeStateEx(UpdatableItemStateManager stateMgr, + NodeTypeRegistry ntReg, + NodeId nodeId) throws RepositoryException { + try { + this.ntReg = ntReg; + this.stateMgr = stateMgr; + this.nodeState = (NodeState) stateMgr.getItemState(nodeId); + } catch (ItemStateException e) { + throw new RepositoryException(e); + } + } + /** * returns the name of this node @@ -95,7 +119,7 @@ NodeState parent = (NodeState) stateMgr.getItemState(parentId); name = parent.getChildNodeEntry(nodeState.getNodeId()).getName(); } catch (ItemStateException e) { - // should never occurr + // should never occur throw new IllegalStateException(e.toString()); } } @@ -121,6 +145,19 @@ } /** + * Returns the parent node of this node + * + * @return the parent node of this node or null if root node + * @throws RepositoryException if an error occurs + */ + public NodeStateEx getParent() throws RepositoryException { + if (nodeState.getParentId() == null) { + return null; + } + return getNode(nodeState.getParentId()); + } + + /** * Returns the underlaying node state. * @return the underlaying node state. */ @@ -132,6 +169,7 @@ * Returns the properties of this node * * @return the properties of this node + * @throws ItemStateException if an error occurs */ public PropertyState[] getProperties() throws ItemStateException { Set set = nodeState.getPropertyNames(); @@ -147,7 +185,7 @@ /** * Checks if the given property exists * - * @param name + * @param name name of the property * @return true if the given property exists. */ public boolean hasProperty(Name name) { @@ -158,7 +196,7 @@ /** * Returns the values of the given property of null * - * @param name + * @param name name of the property * @return the values of the given property. */ public InternalValue[] getPropertyValues(Name name) { @@ -174,7 +212,7 @@ /** * Returns the value of the given property or null * - * @param name + * @param name name of the property * @return the value of the given property. */ public InternalValue getPropertyValue(Name name) { @@ -190,9 +228,9 @@ /** * Sets the property value * - * @param name - * @param value - * @throws RepositoryException + * @param name name of the property + * @param value value to set + * @throws RepositoryException if an error occurs */ public void setPropertyValue(Name name, InternalValue value) throws RepositoryException { @@ -202,10 +240,10 @@ /** * Sets the property values * - * @param name - * @param type - * @param values - * @throws RepositoryException + * @param name name of the property + * @param type property type + * @param values values to set + * @throws RepositoryException if an error occurs */ public void setPropertyValues(Name name, int type, InternalValue[] values) throws RepositoryException { @@ -215,56 +253,43 @@ /** * Sets the property values * - * @param name - * @param type - * @param values - * @throws RepositoryException - */ - public void setPropertyValues(Name name, int type, InternalValue[] values, boolean multiple) - throws RepositoryException { - - PropertyState prop = getOrCreatePropertyState(name, type, multiple); - prop.setValues(values); - } - - - /** - * Retrieves or creates a new property state as child property of this node - * - * @param name - * @param type - * @param multiValued - * @return the property state - * @throws RepositoryException + * @param name name of the property + * @param type type of the values + * @param values values to set + * @param multiple truefor MV properties + * @return the modified property state + * @throws RepositoryException if an error occurs */ - private PropertyState getOrCreatePropertyState(Name name, int type, boolean multiValued) + public PropertyState setPropertyValues(Name name, int type, InternalValue[] values, boolean multiple) throws RepositoryException { - PropertyId propId = new PropertyId(nodeState.getNodeId(), name); if (stateMgr.hasItemState(propId)) { try { PropertyState propState = (PropertyState) stateMgr.getItemState(propId); - // someone calling this method will always alter the property state, so set status to modified if (propState.getStatus() == ItemState.STATUS_EXISTING) { propState.setStatus(ItemState.STATUS_EXISTING_MODIFIED); } - // although this is not quite correct, we mark node as modified aswell + // although this is not quite correct, we mark node as modified as well if (nodeState.getStatus() == ItemState.STATUS_EXISTING) { nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED); } + propState.setType(type); + propState.setValues(values); return propState; } catch (ItemStateException e) { throw new RepositoryException("Unable to create property: " + e.toString()); } } else { + + PropDef pd = getEffectiveNodeType().getApplicablePropertyDef(name, type, multiple); + PropertyState propState = stateMgr.createNew(name, nodeState.getNodeId()); propState.setType(type); - propState.setMultiValued(multiValued); - - PropDef pd = getEffectiveNodeType().getApplicablePropertyDef(name, type, multiValued); + propState.setMultiValued(multiple); propState.setDefinitionId(pd.getId()); + propState.setValues(values); - // need to store nodestate + // need to store node state nodeState.addPropertyName(name); if (nodeState.getStatus() == ItemState.STATUS_EXISTING) { nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED); @@ -278,7 +303,7 @@ * of this node's primary and mixin node types. * * @return the effective node type - * @throws RepositoryException + * @throws RepositoryException if an error occurs */ public EffectiveNodeType getEffectiveNodeType() throws RepositoryException { try { @@ -293,7 +318,7 @@ /** * checks if the given child node exists. * - * @param name + * @param name name of the node * @return true if the given child exists. */ public boolean hasNode(Name name) { @@ -303,30 +328,53 @@ /** * removes the (first) child node with the given name. * - * @param name + * @param name name of hte node * @return true if the child was removed - * @throws RepositoryException + * @throws RepositoryException if an error occurs */ public boolean removeNode(Name name) throws RepositoryException { return removeNode(name, 1); } /** + * removes the given child node + * + * @param node child node to remove + * @return true if the child was removed + * @throws RepositoryException if an error occurs + */ + public boolean removeNode(NodeStateEx node) throws RepositoryException { + // locate child node entry + return removeNode(nodeState.getChildNodeEntry(node.getNodeId())); + } + + + /** * removes the child node with the given name and 1-based index * - * @param name - * @param index + * @param name name of the child node + * @param index index of the child node * @return true if the child was removed. - * @throws RepositoryException + * @throws RepositoryException if an error occurs */ public boolean removeNode(Name name, int index) throws RepositoryException { + return removeNode(nodeState.getChildNodeEntry(name, index)); + } + + /** + * removes the child node with the given child node entry + * + * @param entry entry to remove + * @return true if the child was removed. + * @throws RepositoryException if an error occurs + */ + public boolean removeNode(ChildNodeEntry entry) throws RepositoryException { try { - ChildNodeEntry entry = nodeState.getChildNodeEntry(name, index); if (entry == null) { return false; } else { removeNode(entry.getId()); - nodeState.removeChildNodeEntry(name, index); + nodeState.removeChildNodeEntry(entry.getId()); nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED); return true; } @@ -338,8 +386,8 @@ /** * removes recursively the node with the given id * - * @param id - * @throws ItemStateException + * @param id node id + * @throws ItemStateException if an error occurs */ private void removeNode(NodeId id) throws ItemStateException { NodeState state = (NodeState) stateMgr.getItemState(id); @@ -365,9 +413,9 @@ /** * removes the property with the given name * - * @param name + * @param name name of the property * @return true if the property was removed. - * @throws RepositoryException + * @throws RepositoryException if an error occurs */ public boolean removeProperty(Name name) throws RepositoryException { try { @@ -390,10 +438,10 @@ * retrieves the child node with the given name and 1-base index or * null if the node does not exist. * - * @param name - * @param index + * @param name name of hte child node + * @param index index of thechild node * @return the node state. - * @throws RepositoryException + * @throws RepositoryException if an error occurs */ public NodeStateEx getNode(Name name, int index) throws RepositoryException { ChildNodeEntry entry = nodeState.getChildNodeEntry(name, index); @@ -409,14 +457,57 @@ } /** + * Returns the node with the given id. + * @param id node id + * @return the new node state + * @throws RepositoryException if an error occurs + */ + public NodeStateEx getNode(NodeId id) throws RepositoryException { + try { + NodeState state = (NodeState) stateMgr.getItemState(id); + return new NodeStateEx(stateMgr, ntReg, state, name); + } catch (ItemStateException e) { + throw new RepositoryException("Unable to getNode: " + e.toString()); + } + } + + /** + * Checks if the given node state exists + * @param id node id + * @return true if the node state exists + */ + public boolean hasNode(NodeId id) { + return stateMgr.hasItemState(id); + } + + /** * Adds a new child node with the given name * - * @param nodeName - * @param nodeTypeName + * @param nodeName name of the new node + * @param nodeTypeName node type name + * @param id id of the new node * @return the node state - * @throws NoSuchNodeTypeException - * @throws ConstraintViolationException - * @throws RepositoryException + * @throws NoSuchNodeTypeException if the node type does not exist + * @throws ConstraintViolationException if there is a constraint violation + * @throws RepositoryException if an error occurs + */ + public NodeStateEx addNode(Name nodeName, Name nodeTypeName, NodeId id) + throws NoSuchNodeTypeException, ConstraintViolationException, RepositoryException { + return addNode(nodeName, nodeTypeName, id, + ntReg.getEffectiveNodeType(nodeTypeName).includesNodeType(NameConstants.MIX_REFERENCEABLE)); + } + + /** + * Adds a new child node with the given name + * + * @param nodeName name of the new node + * @param nodeTypeName node type name + * @param id id of the new node + * @param referenceable if true, a UUID property is created + * @return the node state + * @throws NoSuchNodeTypeException if the node type does not exist + * @throws ConstraintViolationException if there is a constraint violation + * @throws RepositoryException if an error occurs */ public NodeStateEx addNode(Name nodeName, Name nodeTypeName, NodeId id, boolean referenceable) @@ -445,9 +536,11 @@ /** * creates a new child node * - * @param name - * @param id + * @param name name + * @param nodeTypeName node type name + * @param id id * @return the newly created node. + * @throws RepositoryException if an error occurs */ private NodeStateEx createChildNode(Name name, Name nodeTypeName, NodeId id) throws RepositoryException { @@ -475,10 +568,119 @@ } /** + * Moves the source node to this node using the given name. + * @param src shareable source node + * @param name name of new node + * @param createShare if true a share is created instead. + * @return child node + * @throws RepositoryException if an error occurs + */ + public NodeStateEx moveFrom(NodeStateEx src, Name name, boolean createShare) + throws RepositoryException { + if (name == null) { + name = src.getName(); + } + // (4) check for name collisions + NodeDef def; + try { + def = getEffectiveNodeType().getApplicableChildNodeDef(name, nodeState.getNodeTypeName(), ntReg); + } catch (RepositoryException re) { + String msg = "no definition found in parent node's node type for new node"; + throw new ConstraintViolationException(msg, re); + } + ChildNodeEntry cne = nodeState.getChildNodeEntry(name, 1); + if (cne != null) { + // there's already a child node entry with that name; + // check same-name sibling setting of new node + if (!def.allowsSameNameSiblings()) { + throw new ItemExistsException(getNodeId() + "/" + name); + } + NodeState existingChild; + try { + // check same-name sibling setting of existing node + existingChild = (NodeState) stateMgr.getItemState(cne.getId()); + } catch (ItemStateException e) { + throw new RepositoryException(e); + } + if (!ntReg.getNodeDef(existingChild.getDefinitionId()).allowsSameNameSiblings()) { + throw new ItemExistsException(existingChild.toString()); + } + } else { + // check if 'add' is allowed + if (getDefinition().isProtected()) { + String msg = "not allowed to modify a protected node"; + throw new ConstraintViolationException(msg); + } + } + + if (createShare) { + // (5) do clone operation + NodeId parentId = getNodeId(); + src.addShareParent(parentId); + // attach to this parent + nodeState.addChildNodeEntry(name, src.getNodeId()); + if (nodeState.getStatus() == ItemState.STATUS_EXISTING) { + nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED); + } + return new NodeStateEx(stateMgr, ntReg, src.getState(), name); + } else { + // detach from parent + NodeStateEx parent = getNode(src.getParentId()); + parent.nodeState.removeChildNodeEntry(src.getNodeId()); + if (parent.nodeState.getStatus() == ItemState.STATUS_EXISTING) { + parent.nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED); + } + // attach to this parent + nodeState.addChildNodeEntry(name, src.getNodeId()); + if (nodeState.getStatus() == ItemState.STATUS_EXISTING) { + nodeState.setStatus(ItemState.STATUS_EXISTING_MODIFIED); + } + NodeState srcState = src.getState(); + srcState.setParentId(getNodeId()); + srcState.setDefinitionId(def.getId()); + + if (srcState.getStatus() == ItemState.STATUS_EXISTING) { + srcState.setStatus(ItemState.STATUS_EXISTING_MODIFIED); + } + return new NodeStateEx(stateMgr, ntReg, srcState, name); + } + } + + /** + * Adds a share parent id + * @param parentId the parent id + * @throws RepositoryException if an error occurs + */ + private void addShareParent(NodeId parentId) throws RepositoryException { + // verify that we're shareable + if (!nodeState.isShareable()) { + String msg = this + " is not shareable."; + throw new RepositoryException(msg); + } + + // detect share cycle (TODO) + // NodeId srcId = getNodeId(); + //HierarchyManager hierMgr = session.getHierarchyManager(); + //if (parentId.equals(srcId) || hierMgr.isAncestor(srcId, parentId)) { + // String msg = "This would create a share cycle."; + // log.debug(msg); + // throw new RepositoryException(msg); + //} + + if (!nodeState.containsShare(parentId)) { + if (nodeState.addShare(parentId)) { + return; + } + } + String msg = "Adding a shareable node twice to the same parent is not supported."; + throw new UnsupportedRepositoryOperationException(msg); + } + + /** * returns all child nodes * * @return the child nodes. - * @throws RepositoryException + * @throws RepositoryException if an error occurs */ public NodeStateEx[] getChildNodes() throws RepositoryException { try { @@ -498,7 +700,7 @@ /** * stores the persistent state recursively * - * @throws RepositoryException + * @throws RepositoryException if an error occurs */ public void store() throws RepositoryException { try { @@ -511,8 +713,8 @@ /** * stores the given persistent state recursively * - * @param state - * @throws ItemStateException + * @param state node state to store + * @throws ItemStateException if an error occurs */ private void store(NodeState state) throws ItemStateException { @@ -539,12 +741,12 @@ /** * reloads the persistent state recursively * - * @throws RepositoryException + * @throws RepositoryException if an error occurs */ public void reload() throws RepositoryException { try { reload(nodeState); - // refetch nodestate if discarded + // refetch node state if discarded nodeState = (NodeState) stateMgr.getItemState(nodeState.getNodeId()); } catch (ItemStateException e) { throw new RepositoryException(e); @@ -554,8 +756,8 @@ /** * reloads the given persistent state recursively * - * @param state - * @throws ItemStateException + * @param state node state + * @throws ItemStateException if an error occurs */ private void reload(NodeState state) throws ItemStateException { if (state.getStatus() != ItemState.STATUS_EXISTING) { @@ -580,8 +782,8 @@ /** * copies a property * - * @param prop - * @throws RepositoryException + * @param prop source property + * @throws RepositoryException if an error occurs */ public void copyFrom(PropertyImpl prop) throws RepositoryException { if (prop.getDefinition().isMultiple()) { @@ -596,4 +798,36 @@ } } + /** + * copies a property + * + * @param prop source property + * @throws RepositoryException if an error occurs + */ + public void copyFrom(PropertyState prop) throws RepositoryException { + InternalValue[] values = prop.getValues(); + InternalValue[] copiedValues = new InternalValue[values.length]; + for (int i = 0; i < values.length; i++) { + copiedValues[i] = values[i].createCopy(); + } + setPropertyValues(prop.getName(), prop.getType(), copiedValues, prop.isMultiValued()); + } + + /** + * Returns the NodeDef for this state + * @return the node def + */ + public NodeDef getDefinition() { + return ntReg.getNodeDef(nodeState.getDefinitionId()); + } + + /** + * Returns the property definition for the property state + * @param prop the property state + * @return the prop def + */ + public PropDef getDefinition(PropertyState prop) { + return ntReg.getPropDef(prop.getDefinitionId()); + } + } Modified: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManager.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManager.java?rev=795452&r1=795451&r2=795452&view=diff ============================================================================== --- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManager.java (original) +++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManager.java Sun Jul 19 00:09:40 2009 @@ -62,20 +62,22 @@ * invokes the checkin() on the persistent version manager and remaps the * newly created version objects. * + * @param session session that invokes the checkin * @param node node to checkin * @return the newly created version * @throws RepositoryException if an error occurs */ - Version checkin(NodeImpl node) throws RepositoryException; + InternalVersion checkin(Session session, NodeStateEx node) throws RepositoryException; /** * invokes the checkout() on the persistent version manager. * - * @param node node to checkout - * @return the base version + * @param state node to checkout + * @param activityId node id if the current activity + * @return the base version id * @throws RepositoryException if an error occurs */ - Version checkout(NodeImpl node) throws RepositoryException; + NodeId canCheckout(NodeStateEx state, NodeId activityId) throws RepositoryException; /** * Removes the specified version from the given version history. Modified: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java?rev=795452&r1=795451&r2=795452&view=diff ============================================================================== --- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java (original) +++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionManagerImpl.java Sun Jul 19 00:09:40 2009 @@ -23,20 +23,19 @@ import javax.jcr.PropertyType; import javax.jcr.RepositoryException; import javax.jcr.Session; +import javax.jcr.version.ActivityViolationException; import javax.jcr.version.Version; import javax.jcr.version.VersionException; import javax.jcr.version.VersionHistory; -import javax.jcr.version.ActivityViolationException; import org.apache.commons.collections.map.ReferenceMap; -import org.apache.jackrabbit.core.id.ItemId; -import org.apache.jackrabbit.core.id.NodeId; -import org.apache.jackrabbit.core.NodeImpl; -import org.apache.jackrabbit.core.id.PropertyId; import org.apache.jackrabbit.core.SessionImpl; import org.apache.jackrabbit.core.cluster.UpdateEventChannel; import org.apache.jackrabbit.core.cluster.UpdateEventListener; import org.apache.jackrabbit.core.fs.FileSystem; +import org.apache.jackrabbit.core.id.ItemId; +import org.apache.jackrabbit.core.id.NodeId; +import org.apache.jackrabbit.core.id.PropertyId; import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry; import org.apache.jackrabbit.core.observation.DelegatingObservationDispatcher; import org.apache.jackrabbit.core.observation.EventState; @@ -51,10 +50,10 @@ import org.apache.jackrabbit.core.state.ItemStateException; import org.apache.jackrabbit.core.state.ItemStateListener; import org.apache.jackrabbit.core.state.LocalItemStateManager; +import org.apache.jackrabbit.core.state.NodeReferences; import org.apache.jackrabbit.core.state.NodeState; import org.apache.jackrabbit.core.state.PropertyState; import org.apache.jackrabbit.core.state.SharedItemStateManager; -import org.apache.jackrabbit.core.state.NodeReferences; import org.apache.jackrabbit.core.value.InternalValue; import org.apache.jackrabbit.core.virtual.VirtualItemStateProvider; import org.apache.jackrabbit.spi.Name; @@ -357,10 +356,9 @@ * checks if the checkout is valid in respect to a possible activity set on * the session */ - public Version checkout(NodeImpl node) throws RepositoryException { - NodeId baseId = NodeId.valueOf(node.getProperty(NameConstants.JCR_BASEVERSION).getString()); - NodeImpl activity = (NodeImpl) node.getSession().getWorkspace().getVersionManager().getActivity(); - if (activity != null) { + public NodeId canCheckout(NodeStateEx state, NodeId activityId) throws RepositoryException { + NodeId baseId = state.getPropertyValue(NameConstants.JCR_BASEVERSION).getNodeId(); + if (activityId != null) { // If there exists another workspace with node N' where N' also has version // history H, N' is checked out and the jcr:activity property of N' // references A, then the checkout fails with an @@ -369,10 +367,9 @@ // we're currently leverage the fact, that only references to "real" // workspaces are recorded. - NodeId nodeId = activity.getNodeId(); - if (stateMgr.hasNodeReferences(nodeId)) { + if (stateMgr.hasNodeReferences(activityId)) { try { - NodeReferences refs = stateMgr.getNodeReferences(nodeId); + NodeReferences refs = stateMgr.getNodeReferences(activityId); if (refs.hasReferences()) { throw new ActivityViolationException("Unable to checkout. " + "Activity is already used for the same node in " + @@ -383,12 +380,11 @@ } } - // TODO: // If there is a version in H that is not an eventual predecessor of N but // whose jcr:activity references A, then the checkout fails with an // ActivityViolationException - InternalActivityImpl a = (InternalActivityImpl) getItem(nodeId); - NodeId historyId = NodeId.valueOf(node.getProperty(NameConstants.JCR_VERSIONHISTORY).getString()); + InternalActivityImpl a = (InternalActivityImpl) getItem(activityId); + NodeId historyId = state.getPropertyValue(NameConstants.JCR_VERSIONHISTORY).getNodeId(); InternalVersionHistory history = (InternalVersionHistory) getItem(historyId); InternalVersion version = a.getLatestVersion(history); if (version != null) { @@ -402,8 +398,7 @@ } } } - return (VersionImpl) - ((SessionImpl) node.getSession()).getNodeById(baseId); + return baseId; } /** @@ -412,16 +407,17 @@ * This method must not be synchronized since it could cause deadlocks with * item-reading listeners in the observation thread. */ - public Version checkin(final NodeImpl node) throws RepositoryException { - InternalVersion version = (InternalVersion) - escFactory.doSourced((SessionImpl) node.getSession(), new SourcedTarget() { + public InternalVersion checkin(final Session session, final NodeStateEx node) + throws RepositoryException { + return (InternalVersion) + escFactory.doSourced((SessionImpl) session, new SourcedTarget() { public Object run() throws RepositoryException { InternalVersionHistory vh; - if (node.isNodeType(NameConstants.MIX_VERSIONABLE)) { + if (node.getEffectiveNodeType().includesNodeType(NameConstants.MIX_VERSIONABLE)) { // in full versioning, the history id can be retrieved via // the property - String histUUID = node.getProperty(NameConstants.JCR_VERSIONHISTORY).getString(); - vh = getVersionHistory(NodeId.valueOf(histUUID)); + NodeId histId = node.getPropertyValue(NameConstants.JCR_VERSIONHISTORY).getNodeId(); + vh = getVersionHistory(histId); return internalCheckin((InternalVersionHistoryImpl) vh, node, false); } else { // in simple versioning the history id needs to be calculated @@ -430,9 +426,6 @@ } } }); - - return (VersionImpl) - ((SessionImpl) node.getSession()).getNodeById(version.getId()); } /** Modified: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionSelector.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionSelector.java?rev=795452&r1=795451&r2=795452&view=diff ============================================================================== --- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionSelector.java (original) +++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/VersionSelector.java Sun Jul 19 00:09:40 2009 @@ -17,8 +17,6 @@ package org.apache.jackrabbit.core.version; import javax.jcr.RepositoryException; -import javax.jcr.version.Version; -import javax.jcr.version.VersionHistory; /** * This Interface defines the version selector that needs to provide a version, @@ -42,10 +40,7 @@ * * @see DateVersionSelector * @see LabelVersionSelector - * @see org.apache.jackrabbit.core.NodeImpl#restore(String, boolean) - * @see org.apache.jackrabbit.core.NodeImpl#restore(Version, boolean) - * @see org.apache.jackrabbit.core.NodeImpl#restore(Version, String, boolean) - * @see org.apache.jackrabbit.core.NodeImpl#restoreByLabel(String, boolean) + * @see javax.jcr.version.VersionManager#restore * */ public interface VersionSelector { @@ -59,6 +54,6 @@ * @return A version or null. * @throws RepositoryException if an error occurs. */ - Version select(VersionHistory versionHistory) throws RepositoryException; + InternalVersion select(InternalVersionHistory versionHistory) throws RepositoryException; } Modified: jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java?rev=795452&r1=795451&r2=795452&view=diff ============================================================================== --- jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java (original) +++ jackrabbit/sandbox/tripod-JCR-2209/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/version/XAVersionManager.java Sun Jul 19 00:09:40 2009 @@ -208,31 +208,32 @@ /** * {@inheritDoc} */ - public Version checkout(NodeImpl node) throws RepositoryException { - return vMgr.checkout(node); + public NodeId canCheckout(NodeStateEx state, NodeId activityId) throws RepositoryException { + return vMgr.canCheckout(state, activityId); } /** * {@inheritDoc} */ - public Version checkin(NodeImpl node) throws RepositoryException { + public InternalVersion checkin(Session session, NodeStateEx node) throws RepositoryException { if (isInXA()) { InternalVersionHistory vh; InternalVersion version; - if (node.isNodeType(NameConstants.MIX_VERSIONABLE)) { + if (node.getEffectiveNodeType().includesNodeType(NameConstants.MIX_VERSIONABLE)) { // in full versioning, the history id can be retrieved via // the property - String histUUID = node.getProperty(NameConstants.JCR_VERSIONHISTORY).getString(); - vh = getVersionHistory(NodeId.valueOf(histUUID)); + NodeId histId = node.getPropertyValue(NameConstants.JCR_VERSIONHISTORY).getNodeId(); + vh = getVersionHistory(histId); version = internalCheckin((InternalVersionHistoryImpl) vh, node, false); } else { // in simple versioning the history id needs to be calculated vh = getVersionHistoryOfNode(node.getNodeId()); version = internalCheckin((InternalVersionHistoryImpl) vh, node, true); } - return (Version) ((SessionImpl) node.getSession()).getNodeById(version.getId()); + return version; + } else { + return vMgr.checkin(session, node); } - return vMgr.checkin(node); } /** @@ -449,7 +450,7 @@ * Before modifying version history given, make a local copy of it. */ protected InternalVersion internalCheckin(InternalVersionHistoryImpl history, - NodeImpl node, boolean simple) + NodeStateEx node, boolean simple) throws RepositoryException { if (history.getVersionManager() != this) { Modified: jackrabbit/sandbox/tripod-JCR-2209/pom.xml URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/tripod-JCR-2209/pom.xml?rev=795452&r1=795451&r2=795452&view=diff ============================================================================== --- jackrabbit/sandbox/tripod-JCR-2209/pom.xml (original) +++ jackrabbit/sandbox/tripod-JCR-2209/pom.xml Sun Jul 19 00:09:40 2009 @@ -55,7 +55,7 @@ jackrabbit-spi2jcr jackrabbit-spi2dav jackrabbit-jcr-client - jackrabbit-standalone +