You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2008/02/07 17:33:47 UTC
svn commit: r619489 -
/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
Author: stefan
Date: Thu Feb 7 08:33:46 2008
New Revision: 619489
URL: http://svn.apache.org/viewvc?rev=619489&view=rev
Log:
JCR-1104: JSR 283 support
work in (slow) progress...
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java?rev=619489&r1=619488&r2=619489&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java Thu Feb 7 08:33:46 2008
@@ -928,157 +928,7 @@
throws ItemExistsException, PathNotFoundException,
VersionException, ConstraintViolationException, LockException,
RepositoryException {
- // check sanity of this session
- sanityCheck();
-
- // check paths & get node instances
-
- Path srcPath;
- Path.Element srcName;
- Path srcParentPath;
- NodeImpl targetNode;
- NodeImpl srcParentNode;
- try {
- srcPath = getQPath(srcAbsPath).getNormalizedPath();
- if (!srcPath.isAbsolute()) {
- throw new RepositoryException("not an absolute path: " + srcAbsPath);
- }
- srcName = srcPath.getNameElement();
- srcParentPath = srcPath.getAncestor(1);
- targetNode = getItemManager().getNode(srcPath);
- srcParentNode = getItemManager().getNode(srcParentPath);
- } catch (AccessDeniedException ade) {
- throw new PathNotFoundException(srcAbsPath);
- } catch (NameException e) {
- String msg = srcAbsPath + ": invalid path";
- log.debug(msg);
- throw new RepositoryException(msg, e);
- }
-
- Path destPath;
- Path.Element destName;
- Path destParentPath;
- NodeImpl destParentNode;
- try {
- destPath = getQPath(destAbsPath).getNormalizedPath();
- if (!destPath.isAbsolute()) {
- throw new RepositoryException("not an absolute path: " + destAbsPath);
- }
- if (srcPath.isAncestorOf(destPath)) {
- String msg = destAbsPath + ": invalid destination path (cannot be descendant of source path)";
- log.debug(msg);
- throw new RepositoryException(msg);
- }
- destName = destPath.getNameElement();
- destParentPath = destPath.getAncestor(1);
- destParentNode = getItemManager().getNode(destParentPath);
- } catch (AccessDeniedException ade) {
- throw new PathNotFoundException(destAbsPath);
- } catch (NameException e) {
- String msg = destAbsPath + ": invalid path";
- log.debug(msg);
- throw new RepositoryException(msg, e);
- }
- int ind = destName.getIndex();
- if (ind > 0) {
- // subscript in name element
- String msg = destAbsPath + ": invalid destination path (subscript in name element is not allowed)";
- log.debug(msg);
- throw new RepositoryException(msg);
- }
-
- // verify that both source and destination parent nodes are checked-out
- if (!srcParentNode.internalIsCheckedOut()) {
- String msg = srcAbsPath + ": cannot move a child of a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
- if (!destParentNode.internalIsCheckedOut()) {
- String msg = destAbsPath + ": cannot move a target to a checked-in node";
- log.debug(msg);
- throw new VersionException(msg);
- }
-
- // check for name collisions
-
- NodeImpl existing = null;
- try {
- existing = getItemManager().getNode(destPath);
- // there's already a node with that name:
- // check same-name sibling setting of existing node
- if (!existing.getDefinition().allowsSameNameSiblings()) {
- throw new ItemExistsException(existing.safeGetJCRPath());
- }
- } catch (AccessDeniedException ade) {
- // FIXME by throwing ItemExistsException we're disclosing too much information
- throw new ItemExistsException(destAbsPath);
- } catch (PathNotFoundException pnfe) {
- // no name collision, fall through
- }
-
- // check constraints
-
- // get applicable definition of target node at new location
- NodeTypeImpl nt = (NodeTypeImpl) targetNode.getPrimaryNodeType();
- NodeDefinitionImpl newTargetDef;
- try {
- newTargetDef = destParentNode.getApplicableChildNodeDefinition(destName.getName(), nt.getQName());
- } catch (RepositoryException re) {
- String msg = destAbsPath + ": no definition found in parent node's node type for new node";
- log.debug(msg);
- throw new ConstraintViolationException(msg, re);
- }
- // if there's already a node with that name also check same-name sibling
- // setting of new node; just checking same-name sibling setting on
- // existing node is not sufficient since same-name sibling nodes don't
- // necessarily have identical definitions
- if (existing != null && !newTargetDef.allowsSameNameSiblings()) {
- throw new ItemExistsException(existing.safeGetJCRPath());
- }
-
- // check protected flag of old & new parent
- if (destParentNode.getDefinition().isProtected()) {
- String msg = destAbsPath + ": cannot add a child node to a protected node";
- log.debug(msg);
- throw new ConstraintViolationException(msg);
- }
- if (srcParentNode.getDefinition().isProtected()) {
- String msg = srcAbsPath + ": cannot remove a child node from a protected node";
- log.debug(msg);
- throw new ConstraintViolationException(msg);
- }
-
- // check lock status
- srcParentNode.checkLock();
- destParentNode.checkLock();
-
- NodeId targetId = targetNode.getNodeId();
- int index = srcName.getIndex();
- if (index == 0) {
- index = 1;
- }
-
- if (srcParentNode.isSame(destParentNode)) {
- // do rename
- destParentNode.renameChildNode(srcName.getName(), index, targetId, destName.getName());
- } else {
- // do move:
- // 1. remove child node entry from old parent
- NodeState srcParentState =
- (NodeState) srcParentNode.getOrCreateTransientItemState();
- srcParentState.removeChildNodeEntry(srcName.getName(), index);
- // 2. re-parent target node
- NodeState targetState =
- (NodeState) targetNode.getOrCreateTransientItemState();
- targetState.setParentId(destParentNode.getNodeId());
- // 3. add child node entry to new parent
- NodeState destParentState =
- (NodeState) destParentNode.getOrCreateTransientItemState();
- destParentState.addChildNodeEntry(destName.getName(), targetId);
- }
-
- // change definition of target
- targetNode.onRedefine(newTargetDef.unwrap().getId());
+ move283(srcAbsPath, destAbsPath);
}
/**
@@ -1555,6 +1405,243 @@
log.debug(msg);
throw new RepositoryException(msg, e);
}
+ }
+
+ //-----------------------------------< Session methods changed in JSR 283 >
+ /**
+ * Moves the node at <code>srcAbsPath</code> (and its entire subtree) to the
+ * new location at <code>destAbsPath</code>. Returns the path of the node at
+ * its new position. Note that the returned path will indicate the resulting
+ * same-name sibling index of the destination (if necessary), unlike the
+ * supplied <code>destAbsPath</code> parameter (see below).
+ * <p>
+ * In order to persist the change, a <code>save</code>
+ * must be called on either the session or a common ancestor to both the source and destination locations.
+ * <p/>
+ * The identifiers of referenceable nodes must not be changed by a
+ * <code>move</code>. The identifiers of non-referenceable nodes <i>may</i> change.
+ * <p/>
+ * A <code>ConstraintViolationException</code> is thrown either immediately or on <code>save</code>
+ * if performing this operation would violate a node type or implementation-specific constraint.
+ * Implementations may differ on when this validation is performed.
+ * <p>
+ * As well, a <code>ConstraintViolationException</code> will be thrown on
+ * <code>save</code> if an attempt is made to seperately <code>save</code>
+ * either the source or destination node.
+ * <p>
+ * Note that this behaviour differs from that of
+ * {@link Workspace#move}, which operates directly in the persistent
+ * workspace and does not require a <code>save</code>.
+ * <p/>
+ * The <code>destAbsPath</code> provided must not have an index on its final
+ * element. If it does then a <code>RepositoryException</code> is thrown.
+ * Strictly speaking, the <code>destAbsPath</code> parameter is actually an
+ * <i>absolute path</i> to the parent node of the new location, appended
+ * with the new <i>name</i> desired for the moved node. It does not specify
+ * a position within the child node ordering (if such ordering is
+ * supported). If ordering is supported by the node type of the parent node
+ * of the new location, then the newly moved node is appended to the end of
+ * the child node list. The resulting position within a same-name sibling set
+ * can, however, be determined from the path returned by this method, which
+ * will include an index if one is required.
+ * <p/>
+ * This method cannot be used to move just an individual property by itself.
+ * It moves an entire node and its subtree (including, of course, any properties
+ * contained therein).
+ * <p/>
+ * If no node exists at <code>srcAbsPath</code> or no node exists one level above <code>destAbsPath</code>
+ * (in other words, there is no node that will serve as the parent of the moved item) then a
+ * <code>PathNotFoundException</code> is thrown either immediately or on <code>save</code>.
+ * Implementations may differ on when this validation is performed.
+ * <p/>
+ * An <code>ItemExistsException</code> is thrown either immediately or on <code>save</code>
+ * if a node already exists at <code>destAbsPath</code> and same-name siblings are not allowed.
+ * Implementations may differ on when this validation is performed.
+ * <p/>
+ * Note that if a property already exists at <code>destAbsPath</code>, the
+ * operation succeeds, since a node may have a child node and property with
+ * the same name.
+ * <p/>
+ * A <code>VersionException</code> is thrown either immediately or on <code>save</code>
+ * if the parent node of <code>destAbsPath</code> or the parent node of <code>srcAbsPath] is versionable and
+ * checked-in, or is non-versionable and its nearest versionable ancestor is checked-in.
+ * Implementations may differ on when this validation is performed.
+ * <p/>
+ * A <code>LockException</code> is thrown either immediately or on <code>save</code>
+ * if a lock prevents the <code>move</code>. Implementations may differ on when this validation is performed.
+ *
+ * @param srcAbsPath the root of the subtree to be moved.
+ * @param destAbsPath the location to which the subtree is to be moved.
+ * @return the path of the node at its new position.
+ * @throws ItemExistsException if a node already exists at <code>destAbsPath</code>
+ * and same-name siblings are not allowed.
+ * @throws PathNotFoundException if either <code>srcAbsPath</code> or <code>destAbsPath</code> cannot be found and this
+ * implementation performs this validation immediately instead of waiting until <code>save</code>.
+ * @throws VersionException if the parent node of <code>destAbsPath</code> or the parent node of <code>srcAbsPath</code>
+ * is versionable and checked-in, or or is non-verionable and its nearest versionable ancestor is checked-in and this
+ * implementation performs this validation immediately instead of waiting until <code>save</code>.
+ * @throws ConstraintViolationException if a node-type or other constraint violation is detected immediately and this
+ * implementation performs this validation immediately instead of waiting until <code>save</code>.
+ * @throws LockException if the move operation would violate a lock and this
+ * implementation performs this validation immediately instead of waiting until <code>save</code>.
+ * @throws RepositoryException if the last element of <code>destAbsPath</code> has an index or if another error occurs.
+ */
+ public String move283(String srcAbsPath, String destAbsPath)
+ throws ItemExistsException, PathNotFoundException, VersionException,
+ ConstraintViolationException, LockException, RepositoryException {
+ // check sanity of this session
+ sanityCheck();
+
+ // check paths & get node instances
+
+ Path srcPath;
+ Path.Element srcName;
+ Path srcParentPath;
+ NodeImpl targetNode;
+ NodeImpl srcParentNode;
+ try {
+ srcPath = getQPath(srcAbsPath).getNormalizedPath();
+ if (!srcPath.isAbsolute()) {
+ throw new RepositoryException("not an absolute path: " + srcAbsPath);
+ }
+ srcName = srcPath.getNameElement();
+ srcParentPath = srcPath.getAncestor(1);
+ targetNode = getItemManager().getNode(srcPath);
+ srcParentNode = getItemManager().getNode(srcParentPath);
+ } catch (AccessDeniedException ade) {
+ throw new PathNotFoundException(srcAbsPath);
+ } catch (NameException e) {
+ String msg = srcAbsPath + ": invalid path";
+ log.debug(msg);
+ throw new RepositoryException(msg, e);
+ }
+
+ Path destPath;
+ Path.Element destName;
+ Path destParentPath;
+ NodeImpl destParentNode;
+ try {
+ destPath = getQPath(destAbsPath).getNormalizedPath();
+ if (!destPath.isAbsolute()) {
+ throw new RepositoryException("not an absolute path: " + destAbsPath);
+ }
+ if (srcPath.isAncestorOf(destPath)) {
+ String msg = destAbsPath + ": invalid destination path (cannot be descendant of source path)";
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+ destName = destPath.getNameElement();
+ destParentPath = destPath.getAncestor(1);
+ destParentNode = getItemManager().getNode(destParentPath);
+ } catch (AccessDeniedException ade) {
+ throw new PathNotFoundException(destAbsPath);
+ } catch (NameException e) {
+ String msg = destAbsPath + ": invalid path";
+ log.debug(msg);
+ throw new RepositoryException(msg, e);
+ }
+ int ind = destName.getIndex();
+ if (ind > 0) {
+ // subscript in name element
+ String msg = destAbsPath + ": invalid destination path (subscript in name element is not allowed)";
+ log.debug(msg);
+ throw new RepositoryException(msg);
+ }
+
+ // verify that both source and destination parent nodes are checked-out
+ if (!srcParentNode.internalIsCheckedOut()) {
+ String msg = srcAbsPath + ": cannot move a child of a checked-in node";
+ log.debug(msg);
+ throw new VersionException(msg);
+ }
+ if (!destParentNode.internalIsCheckedOut()) {
+ String msg = destAbsPath + ": cannot move a target to a checked-in node";
+ log.debug(msg);
+ throw new VersionException(msg);
+ }
+
+ // check for name collisions
+
+ NodeImpl existing = null;
+ try {
+ existing = getItemManager().getNode(destPath);
+ // there's already a node with that name:
+ // check same-name sibling setting of existing node
+ if (!existing.getDefinition().allowsSameNameSiblings()) {
+ throw new ItemExistsException(existing.safeGetJCRPath());
+ }
+ } catch (AccessDeniedException ade) {
+ // FIXME by throwing ItemExistsException we're disclosing too much information
+ throw new ItemExistsException(destAbsPath);
+ } catch (PathNotFoundException pnfe) {
+ // no name collision, fall through
+ }
+
+ // check constraints
+
+ // get applicable definition of target node at new location
+ NodeTypeImpl nt = (NodeTypeImpl) targetNode.getPrimaryNodeType();
+ NodeDefinitionImpl newTargetDef;
+ try {
+ newTargetDef = destParentNode.getApplicableChildNodeDefinition(destName.getName(), nt.getQName());
+ } catch (RepositoryException re) {
+ String msg = destAbsPath + ": no definition found in parent node's node type for new node";
+ log.debug(msg);
+ throw new ConstraintViolationException(msg, re);
+ }
+ // if there's already a node with that name also check same-name sibling
+ // setting of new node; just checking same-name sibling setting on
+ // existing node is not sufficient since same-name sibling nodes don't
+ // necessarily have identical definitions
+ if (existing != null && !newTargetDef.allowsSameNameSiblings()) {
+ throw new ItemExistsException(existing.safeGetJCRPath());
+ }
+
+ // check protected flag of old & new parent
+ if (destParentNode.getDefinition().isProtected()) {
+ String msg = destAbsPath + ": cannot add a child node to a protected node";
+ log.debug(msg);
+ throw new ConstraintViolationException(msg);
+ }
+ if (srcParentNode.getDefinition().isProtected()) {
+ String msg = srcAbsPath + ": cannot remove a child node from a protected node";
+ log.debug(msg);
+ throw new ConstraintViolationException(msg);
+ }
+
+ // check lock status
+ srcParentNode.checkLock();
+ destParentNode.checkLock();
+
+ NodeId targetId = targetNode.getNodeId();
+ int index = srcName.getIndex();
+ if (index == 0) {
+ index = 1;
+ }
+
+ if (srcParentNode.isSame(destParentNode)) {
+ // do rename
+ destParentNode.renameChildNode(srcName.getName(), index, targetId, destName.getName());
+ } else {
+ // do move:
+ // 1. remove child node entry from old parent
+ NodeState srcParentState =
+ (NodeState) srcParentNode.getOrCreateTransientItemState();
+ srcParentState.removeChildNodeEntry(srcName.getName(), index);
+ // 2. re-parent target node
+ NodeState targetState =
+ (NodeState) targetNode.getOrCreateTransientItemState();
+ targetState.setParentId(destParentNode.getNodeId());
+ // 3. add child node entry to new parent
+ NodeState destParentState =
+ (NodeState) destParentNode.getOrCreateTransientItemState();
+ destParentState.addChildNodeEntry(destName.getName(), targetId);
+ }
+
+ // change definition of target
+ targetNode.onRedefine(newTargetDef.unwrap().getId());
+
+ return targetNode.safeGetJCRPath();
}
//-------------------------------------------------------------< Dumpable >