You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2009/09/08 18:09:45 UTC
svn commit: r812570 [7/24] - in /jackrabbit/sandbox/JCR-1456: ./
jackrabbit-api/ jackrabbit-api/src/main/appended-resources/
jackrabbit-api/src/main/appended-resources/META-INF/
jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/ jackrabbi...
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockInfo.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockInfo.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockInfo.java Tue Sep 8 16:09:28 2009
@@ -16,59 +16,188 @@
*/
package org.apache.jackrabbit.core.lock;
+import org.apache.jackrabbit.core.SessionImpl;
import org.apache.jackrabbit.core.id.NodeId;
+import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import javax.jcr.lock.LockException;
/**
- * Lock information interface.
+ * Internal lock information.
*/
-public interface LockInfo {
+public abstract class LockInfo {
+
+ /**
+ * The biggest possible timeout hint value (in seconds), used to avoid
+ * overflows when calculating the timeout. 100 years should be plenty
+ * enough for anyone...
+ */
+ private static final long MAXIMUM_TIMEOUT = 100L * 365L * 24L * 60L * 60L;
+
+ /**
+ * Lock holder node id. Used also as the lock token.
+ */
+ private final NodeId id;
+
+ /**
+ * Flag indicating whether lock is session scoped
+ */
+ private final boolean sessionScoped;
+
+ /**
+ * Flag indicating whether lock is deep
+ */
+ private final boolean deep;
+
+ /**
+ * Lock owner, determined on creation time
+ */
+ private final String lockOwner;
+
+ /**
+ * Lock timeout hint (in seconds) given when the lock was created.
+ * Guaranteed to be between 0 and {@link #MAXIMUM_TIMEOUT}. If the value
+ * is 0, then this lock will not timeout.
+ */
+ private final long timeoutHint;
+
+ /**
+ * Time (in seconds since epoch) when this lock will timeout. Set to
+ * {@link Long#MAX_VALUE} if this lock will not timeout.
+ */
+ private long timeoutTime;
+
+ /**
+ * Flag indicating whether this lock is live. See also {@link #timeoutTime}.
+ */
+ private boolean live;
+
+ /**
+ * Session currently holding lock
+ */
+ private SessionImpl lockHolder;
+
+ /**
+ * Create a new instance of this class.
+ *
+ * @param id lock holder node id
+ * @param sessionScoped whether lock token is session scoped
+ * @param deep whether lock is deep
+ * @param lockOwner owner of lock
+ * @param timeoutHint lock timeout hint in seconds
+ */
+ protected LockInfo(
+ NodeId id, boolean sessionScoped, boolean deep,
+ String lockOwner, long timeoutHint) {
+ this.id = id;
+ this.sessionScoped = sessionScoped;
+ this.deep = deep;
+ this.lockOwner = lockOwner;
+ this.timeoutHint = timeoutHint;
+
+ updateTimeoutTime();
+ }
+
+ protected LockInfo(LockInfo that) {
+ this.id = that.id;
+ this.sessionScoped = that.sessionScoped;
+ this.deep = that.deep;
+ this.lockOwner = that.lockOwner;
+ this.timeoutHint = that.timeoutHint;
+ this.timeoutTime = that.timeoutTime;
+ }
+
+ /**
+ * Return the lock token associated with this lock.
+ *
+ * @return lock token
+ */
+ public String getLockToken() {
+ String uuid = id.toString();
+ return uuid + "-" + getLockTokenCheckDigit(uuid);
+ }
/**
* Return the ID of the lock holding node
* @return the id
*/
- public NodeId getId();
-
+ public NodeId getId() {
+ return id;
+ }
+
/**
* Return the lock owner.
*
* @return lock owner
*/
- public String getLockOwner();
-
+ public String getLockOwner() {
+ return lockOwner;
+ }
+
/**
* Return a flag indicating whether the lock is deep.
*
* @return <code>true</code> if the lock is deep;
* <code>false</code> otherwise
*/
- public boolean isDeep();
-
+ public boolean isDeep() {
+ return deep;
+ }
+
/**
* Return a flag indicating whether the session given is lock holder.
*
* @param session session to compare with
*/
- public boolean isLockHolder(Session session);
+ public boolean isLockHolder(Session session) {
+ return lockHolder == session;
+ }
+
+ /**
+ * Return the session currently holding the lock
+ *
+ * @return session currently holding the lock
+ */
+ public SessionImpl getLockHolder() {
+ return lockHolder;
+ }
/**
- * Return the lock token as seen by the session passed as parameter. If
- * this session is currently holding the lock, it will get the lock token
- * itself, otherwise a <code>null</code> string.
+ * Set the session currently holding the lock
*
- * @param session The session asking for the lock token.
- * @return lock token.
+ * @param lockHolder session currently holding the lock
*/
- public String getLockToken(Session session);
+ public void setLockHolder(SessionImpl lockHolder) {
+ this.lockHolder = lockHolder;
+ }
/**
* Return a flag indicating whether the lock is live
*
* @return <code>true</code> if the lock is live; otherwise <code>false</code>
*/
- public boolean isLive();
+ public boolean isLive() {
+ return live;
+ }
+
+ /**
+ * Set the live flag
+ *
+ * @param live live flag
+ */
+ public void setLive(boolean live) {
+ this.live = live;
+ }
+
+ /**
+ * Return a flag indicating whether the lock information may still change.
+ *
+ * @return <code>true</code> if the lock is still alive.
+ */
+ public boolean mayChange() {
+ return live;
+ }
/**
* Return a flag indicating whether the lock is session-scoped
@@ -76,12 +205,155 @@
* @return <code>true</code> if the lock is session-scoped;
* otherwise <code>false</code>
*/
- public boolean isSessionScoped();
+ public boolean isSessionScoped() {
+ return sessionScoped;
+ }
+
+ /**
+ * Returns the timeout hint given when the lock was created.
+ *
+ * @return timeout hint (in seconds)
+ */
+ public long getTimeoutHint() {
+ return timeoutHint;
+ }
+
+ /**
+ * Returns the time when this lock will expire.
+ *
+ * @return timeout time in seconds after epoch
+ */
+ public long getTimeoutTime() {
+ return timeoutTime;
+ }
+
+ public boolean isExpired() {
+ return timeoutTime != Long.MAX_VALUE
+ && timeoutTime * 1000 > System.currentTimeMillis();
+ }
+
+ /**
+ * Updates the timeout time of this lock based on current time and
+ * the timeout hint specified for this lock. The timeout time is always
+ * rounded up.
+ */
+ public void updateTimeoutTime() {
+ if (timeoutHint > 0 && timeoutHint <= MAXIMUM_TIMEOUT) {
+ long now = (System.currentTimeMillis() + 999) / 1000; // round up
+ this.timeoutTime = now + timeoutHint;
+ } else {
+ this.timeoutTime = Long.MAX_VALUE;
+ }
+ }
/**
- * Return the number of seconds remaining until the lock expires.
+ * Utility method that throws a {@link LockException} with the
+ * "failure node path" set to the path of the node that holds this lock.
+ * The given session is used to resolve the path of the lock holder node.
*
- * @return number of seconds remaining until the lock expires.
+ * @param message exception message
+ * @param session session that the user was using for the failing operation
+ * @throws LockException always thrown, unless another error occurs
+ * @throws RepositoryException if the path of this lock can not be resolved
*/
- public long getSecondsRemaining();
+ public void throwLockException(String message, SessionImpl session)
+ throws LockException, RepositoryException {
+ String path;
+ try {
+ path = session.getJCRPath(
+ session.getHierarchyManager().getPath(id));
+ } catch (RepositoryException ignored) {
+ path = null;
+ }
+ if (path != null) {
+ throw new LockException(
+ message + " (lock held by node " + path + ")", null, path);
+ } else {
+ throw new LockException(message);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append('(');
+ if (deep) {
+ buffer.append("deep ");
+ }
+ if (sessionScoped) {
+ buffer.append("session ");
+ }
+ buffer.append("holder:");
+ if (lockHolder != null) {
+ buffer.append(lockHolder.getUserID());
+ } else {
+ buffer.append("none");
+ }
+ buffer.append("owner:").append(lockOwner);
+ buffer.append(')');
+ return buffer.toString();
+ }
+
+ /**
+ * Parse a lock token string representation and return the lock
+ * holder node id.
+ *
+ * @param token string representation of lock token
+ * @return lock holder node id
+ * @throws IllegalArgumentException if some field is illegal
+ */
+ public static NodeId parseLockToken(String token)
+ throws IllegalArgumentException {
+ int sep = token.lastIndexOf('-');
+ if (sep == -1 || sep == token.length() - 1) {
+ throw new IllegalArgumentException("Separator not found.");
+ }
+ String uuid = token.substring(0, sep);
+ if (getLockTokenCheckDigit(uuid) != token.charAt(token.length() - 1)) {
+ throw new IllegalArgumentException("Bad check digit.");
+ }
+ return NodeId.valueOf(uuid);
+ }
+
+ /**
+ * Return the check digit for a lock token, given by its UUID
+ * @param uuid uuid
+ * @return check digit
+ */
+ private static char getLockTokenCheckDigit(String uuid) {
+ int result = 0;
+
+ int multiplier = 36;
+ for (int i = 0; i < uuid.length(); i++) {
+ char c = uuid.charAt(i);
+ if (c >= '0' && c <= '9') {
+ int num = c - '0';
+ result += multiplier * num;
+ multiplier--;
+ } else if (c >= 'A' && c <= 'F') {
+ int num = c - 'A' + 10;
+ result += multiplier * num;
+ multiplier--;
+ } else if (c >= 'a' && c <= 'f') {
+ int num = c - 'a' + 10;
+ result += multiplier * num;
+ multiplier--;
+ }
+ }
+
+ int rem = result % 37;
+ if (rem != 0) {
+ rem = 37 - rem;
+ }
+ if (rem >= 0 && rem <= 9) {
+ return (char) ('0' + rem);
+ } else if (rem >= 10 && rem <= 35) {
+ return (char) ('A' + rem - 10);
+ } else {
+ return '+';
+ }
+ }
+
}
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java Tue Sep 8 16:09:28 2009
@@ -52,7 +52,6 @@
import org.slf4j.LoggerFactory;
import javax.jcr.ItemNotFoundException;
-import javax.jcr.Node;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
@@ -70,6 +69,9 @@
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
/**
* Provides the functionality needed for locking and unlocking nodes.
@@ -90,7 +92,7 @@
/**
* Path map containing all locks at the leaves.
*/
- private final PathMap lockMap = new PathMap();
+ private final PathMap<LockInfo> lockMap = new PathMap<LockInfo>();
private final ReentrantLock lockMapLock = new ReentrantLock(){
@@ -135,6 +137,11 @@
};
/**
+ * The periodically invoked lock timeout handler.
+ */
+ private final ScheduledFuture<?> timeoutHandler;
+
+ /**
* System session
*/
private final SessionImpl sysSession;
@@ -157,12 +164,14 @@
/**
* Create a new instance of this class.
*
- * @param session system session
- * @param fs file system for persisting locks
+ * @param session system session
+ * @param fs file system for persisting locks
+ * @param executor scheduled executor service for handling lock timeouts
* @throws RepositoryException if an error occurs
*/
- public LockManagerImpl(SessionImpl session, FileSystem fs)
- throws RepositoryException {
+ public LockManagerImpl(
+ SessionImpl session, FileSystem fs,
+ ScheduledExecutorService executor) throws RepositoryException {
this.sysSession = session;
this.locksFile = new FileSystemResource(fs, FileSystem.SEPARATOR + LOCKS_FILE);
@@ -179,16 +188,51 @@
throw new RepositoryException("I/O error while reading locks from '"
+ locksFile.getPath() + "'", e);
}
+
+ timeoutHandler = executor.scheduleWithFixedDelay(
+ new TimeoutHandler(), 1, 1, TimeUnit.SECONDS);
}
/**
* Close this lock manager. Writes back all changes.
*/
public void close() {
+ timeoutHandler.cancel(false);
save();
}
/**
+ * Periodically (at one second delay) invoked timeout handler. Traverses
+ * all locks and unlocks those that have expired.
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/JCR-1590">JCR-1590</a>:
+ * JSR 283: Locking
+ */
+ private class TimeoutHandler implements Runnable {
+ public void run() {
+ lockMap.traverse(new PathMap.ElementVisitor<LockInfo>() {
+ public void elementVisited(PathMap.Element<LockInfo> element) {
+ LockInfo info = element.get();
+ if (info != null && info.isLive() && info.isExpired()) {
+ NodeId id = info.getId();
+ SessionImpl holder = info.getLockHolder();
+ if (holder == null) {
+ info.setLockHolder(sysSession);
+ holder = sysSession;
+ }
+ try {
+ // FIXME: This session access is not thread-safe!
+ unlock(holder.getNodeById(id));
+ } catch (RepositoryException e) {
+ log.warn("Unable to expire the lock " + id, e);
+ }
+ }
+ }
+ }, false);
+ }
+ }
+
+ /**
* Read locks from locks file and populate path map
*/
private void load() throws FileSystemException {
@@ -202,7 +246,7 @@
if (s == null || s.equals("")) {
break;
}
- reapplyLock(LockToken.parse(s));
+ reapplyLock(s);
}
} catch (IOException e) {
throw new FileSystemException("error while reading locks file", e);
@@ -214,22 +258,35 @@
/**
* Reapply a lock given a lock token that was read from the locks file
*
- * @param lockToken lock token to apply
+ * @param lockTokenLine lock token to apply
*/
- private void reapplyLock(LockToken lockToken) {
+ private void reapplyLock(String lockTokenLine) {
+ String[] parts = lockTokenLine.split(",");
+ String token = parts[0];
+ long timeoutHint = Long.MAX_VALUE;
+ if (parts.length > 1) {
+ try {
+ timeoutHint = Long.parseLong(parts[1]);
+ } catch (NumberFormatException e) {
+ log.warn("Unexpected timeout hint "
+ + parts[1] + " for lock token " + token, e);
+ }
+ }
+
try {
- NodeImpl node = (NodeImpl)
- sysSession.getItemManager().getItem(lockToken.getId());
- Path path = getPath(sysSession, lockToken.getId());
+ NodeId id = LockInfo.parseLockToken(parts[0]);
+ NodeImpl node = (NodeImpl) sysSession.getItemManager().getItem(id);
+ Path path = getPath(sysSession, id);
- InternalLockInfo info = new InternalLockInfo(lockToken, false,
+ InternalLockInfo info = new InternalLockInfo(
+ id, false,
node.getProperty(NameConstants.JCR_LOCKISDEEP).getBoolean(),
- node.getProperty(NameConstants.JCR_LOCKOWNER).getString());
+ node.getProperty(NameConstants.JCR_LOCKOWNER).getString(),
+ timeoutHint);
info.setLive(true);
lockMap.put(path, info);
} catch (RepositoryException e) {
- log.warn("Unable to recreate lock '" + lockToken
- + "': " + e.getMessage());
+ log.warn("Unable to recreate lock '" + token + "': " + e.getMessage());
log.debug("Root cause: ", e);
}
}
@@ -242,11 +299,11 @@
return;
}
- final ArrayList<AbstractLockInfo> list = new ArrayList<AbstractLockInfo>();
+ final ArrayList<LockInfo> list = new ArrayList<LockInfo>();
- lockMap.traverse(new PathMap.ElementVisitor() {
- public void elementVisited(PathMap.Element element) {
- AbstractLockInfo info = (AbstractLockInfo) element.get();
+ lockMap.traverse(new PathMap.ElementVisitor<LockInfo>() {
+ public void elementVisited(PathMap.Element<LockInfo> element) {
+ LockInfo info = element.get();
if (!info.isSessionScoped()) {
list.add(info);
}
@@ -259,9 +316,15 @@
try {
writer = new BufferedWriter(
new OutputStreamWriter(locksFile.getOutputStream()));
- for (int i = 0; i < list.size(); i++) {
- AbstractLockInfo info = list.get(i);
+ for (LockInfo info : list) {
writer.write(info.getLockToken());
+
+ // Store the timeout hint, if one is specified
+ if (info.getTimeoutHint() != Long.MAX_VALUE) {
+ writer.write(',');
+ writer.write(Long.toString(info.getTimeoutHint()));
+ }
+
writer.newLine();
}
} catch (FileSystemException fse) {
@@ -295,15 +358,15 @@
* @throws LockException if the node is already locked
* @throws RepositoryException if another error occurs
*/
- AbstractLockInfo internalLock(NodeImpl node, boolean isDeep,
- boolean isSessionScoped, long timeoutHint,
- String ownerInfo)
+ LockInfo internalLock(
+ NodeImpl node, boolean isDeep, boolean isSessionScoped,
+ long timeoutHint, String ownerInfo)
throws LockException, RepositoryException {
SessionImpl session = (SessionImpl) node.getSession();
String lockOwner = (ownerInfo != null) ? ownerInfo : session.getUserID();
- InternalLockInfo info = new InternalLockInfo(new LockToken(node.getNodeId()),
- isSessionScoped, isDeep, lockOwner, timeoutHint);
+ InternalLockInfo info = new InternalLockInfo(
+ node.getNodeId(), isSessionScoped, isDeep, lockOwner, timeoutHint);
ClusterOperation operation = null;
boolean successful = false;
@@ -318,20 +381,21 @@
try {
// check whether node is already locked
Path path = getPath(session, node.getId());
- PathMap.Element element = lockMap.map(path, false);
+ PathMap.Element<LockInfo> element = lockMap.map(path, false);
- LockInfo other = (LockInfo) element.get();
+ LockInfo other = element.get();
if (other != null) {
if (element.hasPath(path)) {
- throw new LockException("Node already locked: " + node);
+ other.throwLockException(
+ "Node already locked: " + node, session);
} else if (other.isDeep()) {
- throw new LockException(
- "Parent node has a deep lock: " + node);
+ other.throwLockException(
+ "Parent node has a deep lock: " + node, session);
}
}
- if (info.deep && element.hasPath(path)
+ if (info.isDeep() && element.hasPath(path)
&& element.getChildrenCount() > 0) {
- throw new LockException("Some child node is locked.");
+ info.throwLockException("Some child node is locked", session);
}
// create lock token
@@ -378,17 +442,18 @@
try {
SessionImpl session = (SessionImpl) node.getSession();
// check whether node is locked by this session
- PathMap.Element element = lockMap.map(getPath(session, node.getId()), true);
+ PathMap.Element<LockInfo> element =
+ lockMap.map(getPath(session, node.getId()), true);
if (element == null) {
throw new LockException("Node not locked: " + node);
}
- AbstractLockInfo info = (AbstractLockInfo) element.get();
+ LockInfo info = element.get();
if (info == null) {
throw new LockException("Node not locked: " + node);
}
checkUnlock(info, session);
- getSessionLockManager(session).lockTokenRemoved(info.getLockToken(session));
+ getSessionLockManager(session).lockTokenRemoved(info.getLockToken());
element.set(null);
info.setLive(false);
@@ -408,23 +473,22 @@
}
/**
- * Package-private low-level helper method returning all
- * <code>AbstractLockInfo</code>s associated with the specified
- * session.
+ * Package-private low-level helper method returning all locks
+ * associated with the specified session.
* @param session session
* @return an array of <code>AbstractLockInfo</code>s
*/
- AbstractLockInfo[] getLockInfos(final SessionImpl session) {
+ LockInfo[] getLockInfos(final SessionImpl session) {
final ArrayList<LockInfo> infos = new ArrayList<LockInfo>();
- lockMap.traverse(new PathMap.ElementVisitor() {
- public void elementVisited(PathMap.Element element) {
- LockInfo info = (LockInfo) element.get();
+ lockMap.traverse(new PathMap.ElementVisitor<LockInfo>() {
+ public void elementVisited(PathMap.Element<LockInfo> element) {
+ LockInfo info = element.get();
if (info.isLive() && info.isLockHolder(session)) {
infos.add(info);
}
}
}, false);
- return infos.toArray(new AbstractLockInfo[infos.size()]);
+ return infos.toArray(new LockInfo[infos.size()]);
}
/**
@@ -434,7 +498,7 @@
* @return lock info or <code>null</code> if node is not locked
* @throws RepositoryException if an error occurs
*/
- public AbstractLockInfo getLockInfo(NodeId id) throws RepositoryException {
+ public LockInfo getLockInfo(NodeId id) throws RepositoryException {
Path path;
try {
path = getPath(sysSession, id);
@@ -444,8 +508,8 @@
acquire();
try {
- PathMap.Element element = lockMap.map(path, false);
- AbstractLockInfo info = (AbstractLockInfo) element.get();
+ PathMap.Element<LockInfo> element = lockMap.map(path, false);
+ LockInfo info = element.get();
if (info != null) {
if (element.hasPath(path) || info.isDeep()) {
return info;
@@ -464,13 +528,13 @@
*/
public Lock lock(NodeImpl node, boolean isDeep, boolean isSessionScoped)
throws LockException, RepositoryException {
- return lock(node, isDeep, isSessionScoped, AbstractLockInfo.TIMEOUT_INFINITE, null);
+ return lock(node, isDeep, isSessionScoped, Long.MAX_VALUE, null);
}
public Lock lock(NodeImpl node, boolean isDeep, boolean isSessionScoped, long timoutHint, String ownerInfo)
throws LockException, RepositoryException {
- AbstractLockInfo info = internalLock(node, isDeep, isSessionScoped, timoutHint, ownerInfo);
- writeLockProperties(node, info.lockOwner, info.deep);
+ LockInfo info = internalLock(node, isDeep, isSessionScoped, timoutHint, ownerInfo);
+ writeLockProperties(node, info.getLockOwner(), info.isDeep());
return new LockImpl(info, node);
}
@@ -487,10 +551,11 @@
SessionImpl session = (SessionImpl) node.getSession();
Path path = getPath(session, node.getId());
- PathMap.Element element = lockMap.map(path, false);
- AbstractLockInfo info = (AbstractLockInfo) element.get();
- if (info != null && (element.hasPath(path) || info.deep)) {
- Node lockHolder = (Node) session.getItemManager().getItem(info.getId());
+ PathMap.Element<LockInfo> element = lockMap.map(path, false);
+ LockInfo info = element.get();
+ if (info != null && (element.hasPath(path) || info.isDeep())) {
+ NodeImpl lockHolder = (NodeImpl)
+ session.getItemManager().getItem(info.getId());
return new LockImpl(info, lockHolder);
} else {
throw new LockException("Node not locked: " + node);
@@ -509,14 +574,14 @@
acquire();
- AbstractLockInfo[] infos = getLockInfos(session);
+ LockInfo[] infos = getLockInfos(session);
try {
Lock[] locks = new Lock[infos.length];
for (int i = 0; i < infos.length; i++) {
- AbstractLockInfo info = infos[i];
- Node holder = (Node) session.getItemManager().getItem(info.getId());
- locks[i] = new LockImpl(info, holder);
+ NodeImpl holder = (NodeImpl)
+ session.getItemManager().getItem(infos[i].getId());
+ locks[i] = new LockImpl(infos[i], holder);
}
return locks;
} finally {
@@ -544,7 +609,8 @@
try {
SessionImpl session = (SessionImpl) node.getSession();
- PathMap.Element element = lockMap.map(getPath(session, node.getId()), true);
+ PathMap.Element<LockInfo> element =
+ lockMap.map(getPath(session, node.getId()), true);
if (element == null) {
return false;
}
@@ -566,15 +632,15 @@
SessionImpl session = (SessionImpl) node.getSession();
Path path = getPath(session, node.getId());
- PathMap.Element element = lockMap.map(path, false);
- AbstractLockInfo info = (AbstractLockInfo) element.get();
+ PathMap.Element<LockInfo> element = lockMap.map(path, false);
+ LockInfo info = element.get();
if (info == null) {
return false;
}
if (element.hasPath(path)) {
return true;
} else {
- return info.deep;
+ return info.isDeep();
}
} catch (ItemNotFoundException e) {
return false;
@@ -599,8 +665,8 @@
public void checkLock(Path path, Session session)
throws LockException, RepositoryException {
- PathMap.Element element = lockMap.map(path, false);
- LockInfo info = (LockInfo) element.get();
+ PathMap.Element<LockInfo> element = lockMap.map(path, false);
+ LockInfo info = element.get();
if (info != null) {
if (element.hasPath(path) || info.isDeep()) {
checkLock(info, session);
@@ -635,12 +701,12 @@
throws LockException, RepositoryException {
// check whether node is locked by this session
- PathMap.Element element = lockMap.map(getPath((SessionImpl) session,
- node.getId()), true);
+ PathMap.Element<LockInfo> element =
+ lockMap.map(getPath((SessionImpl) session, node.getId()), true);
if (element == null) {
throw new LockException("Node not locked: " + node);
}
- AbstractLockInfo info = (AbstractLockInfo) element.get();
+ LockInfo info = element.get();
if (info == null) {
throw new LockException("Node not locked: " + node);
}
@@ -673,13 +739,13 @@
*/
public void addLockToken(SessionImpl session, String lt) throws LockException, RepositoryException {
try {
- LockToken lockToken = LockToken.parse(lt);
+ NodeId id = LockInfo.parseLockToken(lt);
- NodeImpl node = (NodeImpl)
- this.sysSession.getItemManager().getItem(lockToken.getId());
- PathMap.Element element = lockMap.map(node.getPrimaryPath(), true);
+ NodeImpl node = (NodeImpl) sysSession.getItemManager().getItem(id);
+ Path path = node.getPrimaryPath();
+ PathMap.Element<LockInfo> element = lockMap.map(path, true);
if (element != null) {
- AbstractLockInfo info = (AbstractLockInfo) element.get();
+ LockInfo info = element.get();
if (info != null) {
if (info.isLockHolder(session)) {
// nothing to do
@@ -691,7 +757,7 @@
} else {
String msg = "Cannot add lock token: lock already held by other session.";
log.warn(msg);
- throw new LockException(msg);
+ info.throwLockException(msg, session);
}
}
}
@@ -711,13 +777,13 @@
throws LockException, RepositoryException {
try {
- LockToken lockToken = LockToken.parse(lt);
+ NodeId id = LockInfo.parseLockToken(lt);
- NodeImpl node = (NodeImpl) this.sysSession.getItemManager()
- .getItem(lockToken.getId());
- PathMap.Element element = lockMap.map(node.getPrimaryPath(), true);
+ NodeImpl node = (NodeImpl) sysSession.getItemManager().getItem(id);
+ PathMap.Element<LockInfo> element =
+ lockMap.map(node.getPrimaryPath(), true);
if (element != null) {
- AbstractLockInfo info = (AbstractLockInfo) element.get();
+ LockInfo info = element.get();
if (info != null) {
if (info.isLockHolder(session)) {
info.setLockHolder(null);
@@ -726,7 +792,7 @@
} else {
String msg = "Cannot remove lock token: lock held by other session.";
log.warn(msg);
- throw new LockException(msg);
+ info.throwLockException(msg, session);
}
}
}
@@ -979,16 +1045,6 @@
}
/**
- * Return the event type. May be {@link Event#NODE_ADDED},
- * {@link Event#NODE_REMOVED} or a combination of both.\
- *
- * @return event type
- */
- public int getType() {
- return type;
- }
-
- /**
* Return the old path if this is a move operation
*
* @return old path
@@ -1011,9 +1067,9 @@
* {@inheritDoc}
*/
public void onEvent(EventIterator events) {
- Iterator iter = consolidateEvents(events);
+ Iterator<HierarchyEvent> iter = consolidateEvents(events);
while (iter.hasNext()) {
- HierarchyEvent event = (HierarchyEvent) iter.next();
+ HierarchyEvent event = iter.next();
if (event.type == Event.NODE_ADDED) {
nodeAdded(event.path);
} else if (event.type == Event.NODE_REMOVED) {
@@ -1029,7 +1085,7 @@
* add and remove operations on nodes with the same UUID into a move
* operation.
*/
- private Iterator consolidateEvents(EventIterator events) {
+ private Iterator<HierarchyEvent> consolidateEvents(EventIterator events) {
LinkedMap eventMap = new LinkedMap();
while (events.hasNext()) {
@@ -1062,15 +1118,14 @@
* Refresh a non-empty path element whose children might have changed
* its position.
*/
- private void refresh(PathMap.Element element) {
- final ArrayList<AbstractLockInfo> infos = new ArrayList<AbstractLockInfo>();
+ private void refresh(PathMap.Element<LockInfo> element) {
+ final ArrayList<LockInfo> infos = new ArrayList<LockInfo>();
boolean needsSave = false;
// save away non-empty children
- element.traverse(new PathMap.ElementVisitor() {
- public void elementVisited(PathMap.Element element) {
- AbstractLockInfo info = (AbstractLockInfo) element.get();
- infos.add(info);
+ element.traverse(new PathMap.ElementVisitor<LockInfo>() {
+ public void elementVisited(PathMap.Element<LockInfo> element) {
+ infos.add(element.get());
}
}, false);
@@ -1080,7 +1135,7 @@
// now re-insert at appropriate location or throw away if node
// does no longer exist
for (int i = 0; i < infos.size(); i++) {
- AbstractLockInfo info = infos.get(i);
+ LockInfo info = infos.get(i);
try {
NodeImpl node = (NodeImpl) sysSession.getItemManager().getItem(
info.getId());
@@ -1110,7 +1165,8 @@
acquire();
try {
- PathMap.Element parent = lockMap.map(path.getAncestor(1), true);
+ PathMap.Element<LockInfo> parent =
+ lockMap.map(path.getAncestor(1), true);
if (parent != null) {
refresh(parent);
}
@@ -1132,7 +1188,8 @@
acquire();
try {
- PathMap.Element parent = lockMap.map(oldPath.getAncestor(1), true);
+ PathMap.Element<LockInfo> parent =
+ lockMap.map(oldPath.getAncestor(1), true);
if (parent != null) {
refresh(parent);
}
@@ -1153,7 +1210,8 @@
acquire();
try {
- PathMap.Element parent = lockMap.map(path.getAncestor(1), true);
+ PathMap.Element<LockInfo> parent =
+ lockMap.map(path.getAncestor(1), true);
if (parent != null) {
refresh(parent);
}
@@ -1168,20 +1226,7 @@
* Contains information about a lock and gets placed inside the child
* information of a {@link org.apache.jackrabbit.spi.commons.name.PathMap}.
*/
- class InternalLockInfo extends AbstractLockInfo implements SessionListener {
-
- /**
- * Create a new instance of this class.
- *
- * @param lockToken lock token
- * @param sessionScoped whether lock token is session scoped
- * @param deep whether lock is deep
- * @param lockOwner owner of lock
- */
- public InternalLockInfo(LockToken lockToken, boolean sessionScoped,
- boolean deep, String lockOwner) {
- this(lockToken, sessionScoped, deep, lockOwner, TIMEOUT_INFINITE);
- }
+ class InternalLockInfo extends LockInfo implements SessionListener {
/**
* Create a new instance of this class.
@@ -1192,7 +1237,7 @@
* @param lockOwner owner of lock
* @param timeoutHint
*/
- public InternalLockInfo(LockToken lockToken, boolean sessionScoped,
+ public InternalLockInfo(NodeId lockToken, boolean sessionScoped,
boolean deep, String lockOwner, long timeoutHint) {
super(lockToken, sessionScoped, deep, lockOwner, timeoutHint);
}
@@ -1268,7 +1313,8 @@
Path path = getPath(sysSession, nodeId);
// create lock token
- InternalLockInfo info = new InternalLockInfo(new LockToken(nodeId), false, isDeep, lockOwner);
+ InternalLockInfo info = new InternalLockInfo(
+ nodeId, false, isDeep, lockOwner, Long.MAX_VALUE);
info.setLive(true);
lockMap.put(path, info);
@@ -1286,11 +1332,11 @@
try {
Path path = getPath(sysSession, nodeId);
- PathMap.Element element = lockMap.map(path, true);
+ PathMap.Element<LockInfo> element = lockMap.map(path, true);
if (element == null) {
throw new LockException("Node not locked: " + path.toString());
}
- AbstractLockInfo info = (AbstractLockInfo) element.get();
+ LockInfo info = element.get();
if (info == null) {
throw new LockException("Node not locked: " + path.toString());
}
@@ -1310,8 +1356,8 @@
* @param ps print stream to dump to
*/
public void dump(final PrintStream ps) {
- lockMap.traverse(new PathMap.ElementVisitor() {
- public void elementVisited(PathMap.Element element) {
+ lockMap.traverse(new PathMap.ElementVisitor<LockInfo>() {
+ public void elementVisited(PathMap.Element<LockInfo> element) {
StringBuffer line = new StringBuffer();
for (int i = 0; i < element.getDepth(); i++) {
line.append("--");
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java Tue Sep 8 16:09:28 2009
@@ -108,9 +108,9 @@
* @throws LockException if node is already locked
* @throws RepositoryException if an error occurs
*/
- public AbstractLockInfo lock(NodeImpl node, boolean isDeep, boolean isSessionScoped)
+ public LockInfo lock(NodeImpl node, boolean isDeep, boolean isSessionScoped)
throws LockException, RepositoryException {
- return lock(node, isDeep, isSessionScoped, AbstractLockInfo.TIMEOUT_INFINITE, null);
+ return lock(node, isDeep, isSessionScoped, Long.MAX_VALUE, null);
}
/**
@@ -125,7 +125,7 @@
* @throws LockException if node is already locked
* @throws RepositoryException if an error occurs
*/
- public AbstractLockInfo lock(NodeImpl node, boolean isDeep, boolean isSessionScoped, long timeoutHint, String ownerInfo)
+ public LockInfo lock(NodeImpl node, boolean isDeep, boolean isSessionScoped, long timeoutHint, String ownerInfo)
throws LockException, RepositoryException {
NodeId id = node.getNodeId();
@@ -134,7 +134,7 @@
XALockInfo info = unlockedNodesMap.get(id);
if (info != null) {
// if settings are compatible, this is effectively a no-op
- if (info.deep == isDeep && info.sessionScoped == isSessionScoped) {
+ if (info.isDeep() == isDeep && info.isSessionScoped() == isSessionScoped) {
unlockedNodesMap.remove(id);
operations.remove(info);
return lockMgr.getLockInfo(id);
@@ -148,12 +148,12 @@
// create a new lock info for this node
String lockOwner = (ownerInfo != null) ? ownerInfo : node.getSession().getUserID();
- info = new XALockInfo(node, new LockToken(id), isSessionScoped, isDeep, lockOwner);
+ info = new XALockInfo(node, isSessionScoped, isDeep, lockOwner);
SessionImpl session = (SessionImpl) node.getSession();
info.setLockHolder(session);
info.setLive(true);
- LockManagerImpl.getSessionLockManager(session).lockTokenAdded(info.lockToken.toString());
+ LockManagerImpl.getSessionLockManager(session).lockTokenAdded(info.getLockToken());
lockedNodesMap.put(id, info);
operations.add(info);
@@ -170,7 +170,7 @@
NodeId id = node.getNodeId();
// check positive set first
- AbstractLockInfo info = lockedNodesMap.get(id);
+ LockInfo info = lockedNodesMap.get(id);
if (info != null) {
lockedNodesMap.remove(id);
operations.remove(info);
@@ -207,7 +207,7 @@
* @return LockInfo lock info or <code>null</code> if node is not locked
* @throws RepositoryException if an error occurs
*/
- public AbstractLockInfo getLockInfo(NodeImpl node) throws RepositoryException {
+ public LockInfo getLockInfo(NodeImpl node) throws RepositoryException {
NodeId id = node.getNodeId();
// check negative set
@@ -221,7 +221,7 @@
for (;;) {
XALockInfo info = lockedNodesMap.get(current.getId());
if (info != null) {
- if (info.getId().equals(id) || info.deep) {
+ if (info.getId().equals(id) || info.isDeep()) {
return info;
}
break;
@@ -237,21 +237,17 @@
}
/**
- * Returns all <code>AbstractLockInfo</code>s associated with the specified
- * session.
+ * Returns all locks associated with the specified session.
* @param session session
- * @return an array of <code>AbstractLockInfo</code>s
+ * @return locks associated with the session
* @throws RepositoryException if an error occurs
*/
- public AbstractLockInfo[] getLockInfos(SessionImpl session)
+ public LockInfo[] getLockInfos(SessionImpl session)
throws RepositoryException {
-
- ArrayList<AbstractLockInfo> result = new ArrayList<AbstractLockInfo>();
+ ArrayList<LockInfo> result = new ArrayList<LockInfo>();
// get lock informations from global lock manager first
- AbstractLockInfo[] infos = lockMgr.getLockInfos(session);
- for (int i = 0; i < infos.length; i++) {
- AbstractLockInfo info = infos[i];
+ for (LockInfo info : lockMgr.getLockInfos(session)) {
// check negative set
if (!unlockedNodesMap.containsKey(info.getId())) {
result.add(info);
@@ -261,7 +257,7 @@
// add 'uncommitted' lock informations
result.addAll(lockedNodesMap.values());
- return (AbstractLockInfo[]) result.toArray(new AbstractLockInfo[result.size()]);
+ return (LockInfo[]) result.toArray(new LockInfo[result.size()]);
}
/**
@@ -272,9 +268,9 @@
*/
public void addLockToken(SessionImpl session, String lt) throws RepositoryException {
try {
- LockToken lockToken = LockToken.parse(lt);
- NodeImpl node = (NodeImpl) session.getItemManager().getItem(lockToken.getId());
- AbstractLockInfo info = getLockInfo(node);
+ NodeId id = LockInfo.parseLockToken(lt);
+ NodeImpl node = (NodeImpl) session.getItemManager().getItem(id);
+ LockInfo info = getLockInfo(node);
if (info != null) {
if (info.isLockHolder(session)) {
// nothing to do
@@ -303,10 +299,10 @@
*/
public void removeLockToken(SessionImpl session, String lt) throws RepositoryException {
try {
- LockToken lockToken = LockToken.parse(lt);
+ NodeId id = LockInfo.parseLockToken(lt);
- NodeImpl node = (NodeImpl) session.getItemManager().getItem(lockToken.getId());
- AbstractLockInfo info = getLockInfo(node);
+ NodeImpl node = (NodeImpl) session.getItemManager().getItem(id);
+ LockInfo info = getLockInfo(node);
if (info != null) {
if (info.isLockHolder(session)) {
info.setLockHolder(null);
@@ -416,7 +412,7 @@
* Return a flag indicating whether a lock info belongs to a different
* XA environment.
*/
- public boolean differentXAEnv(AbstractLockInfo info) {
+ public boolean differentXAEnv(LockInfo info) {
if (info instanceof XALockInfo) {
XALockInfo lockInfo = (XALockInfo) info;
return lockInfo.getXAEnv() != this;
@@ -427,7 +423,7 @@
/**
* Information about a lock used inside transactions.
*/
- class XALockInfo extends AbstractLockInfo {
+ class XALockInfo extends LockInfo {
/**
* Node being locked/unlocked.
@@ -441,30 +437,14 @@
/**
* Create a new instance of this class.
- * @param lockToken lock token
- * @param sessionScoped whether lock token is session scoped
- * @param deep whether lock is deep
- * @param lockOwner owner of lock
- */
- public XALockInfo(NodeImpl node, LockToken lockToken,
- boolean sessionScoped, boolean deep, String lockOwner) {
-
- this(node, lockToken, sessionScoped, deep, lockOwner,
- TIMEOUT_INFINITE);
- }
-
- /**
- * Create a new instance of this class.
- * @param lockToken lock token
* @param sessionScoped whether lock token is session scoped
* @param deep whether lock is deep
* @param lockOwner owner of lock
*/
- public XALockInfo(NodeImpl node, LockToken lockToken,
- boolean sessionScoped, boolean deep, String lockOwner,
- long timeoutHint) {
-
- super(lockToken, sessionScoped, deep, lockOwner, timeoutHint);
+ public XALockInfo(
+ NodeImpl node,
+ boolean sessionScoped, boolean deep, String lockOwner) {
+ super(node.getNodeId(), sessionScoped, deep, lockOwner, Long.MAX_VALUE);
this.node = node;
}
@@ -472,9 +452,8 @@
* Create a new instance of this class. Used to signal an
* unlock operation on some existing lock information.
*/
- public XALockInfo(NodeImpl node, AbstractLockInfo info) {
- super(info.lockToken, info.sessionScoped, info.deep, info.lockOwner, info.getSecondsRemaining());
-
+ public XALockInfo(NodeImpl node, LockInfo info) {
+ super(info);
this.node = node;
this.isUnlock = true;
}
@@ -495,8 +474,10 @@
if (isUnlock) {
lockMgr.internalUnlock(node);
} else {
- AbstractLockInfo internalLock = lockMgr.internalLock(node, deep, sessionScoped, getSecondsRemaining(), lockOwner);
- AbstractLockInfo xaEnvLock = getLockInfo(node);
+ LockInfo internalLock = lockMgr.internalLock(
+ node, isDeep(), isSessionScoped(),
+ getTimeoutTime(), getLockOwner());
+ LockInfo xaEnvLock = getLockInfo(node);
// Check if the lockToken has been removed in the transaction ...
if (xaEnvLock != null && xaEnvLock.getLockHolder() == null) {
internalLock.setLockHolder(null);
@@ -509,7 +490,9 @@
*/
public void undo() throws LockException, RepositoryException {
if (isUnlock) {
- lockMgr.internalLock(node, deep, sessionScoped, getSecondsRemaining(), lockOwner);
+ lockMgr.internalLock(
+ node, isDeep(), isSessionScoped(),
+ getTimeoutHint(), getLockOwner());
} else {
lockMgr.internalUnlock(node);
}
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockImpl.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockImpl.java Tue Sep 8 16:09:28 2009
@@ -18,7 +18,6 @@
import org.apache.jackrabbit.core.NodeImpl;
-import javax.jcr.Node;
import javax.jcr.RepositoryException;
/**
@@ -32,16 +31,17 @@
private final XALockManager lockMgr;
/**
- * Abstract lock info.
+ * The underlying lock info.
*/
- private final AbstractLockInfo info;
+ private final LockInfo info;
/**
* Create a new instance of this class.
* @param info lock information
* @param node node holding lock
*/
- public XALockImpl(XALockManager lockMgr, AbstractLockInfo info, Node node) {
+ public XALockImpl(
+ XALockManager lockMgr, LockInfo info, NodeImpl node) {
super(info, node);
this.info = info;
@@ -56,7 +56,7 @@
public boolean isLive() throws RepositoryException {
if (info.mayChange()) {
if (lockMgr.differentXAEnv(info)) {
- return lockMgr.holdsLock((NodeImpl) node);
+ return lockMgr.holdsLock(node);
}
}
return super.isLive();
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java Tue Sep 8 16:09:28 2009
@@ -65,7 +65,7 @@
*/
public Lock lock(NodeImpl node, boolean isDeep, boolean isSessionScoped)
throws LockException, RepositoryException {
- return lock(node, isDeep, isSessionScoped, AbstractLockInfo.TIMEOUT_INFINITE, null);
+ return lock(node, isDeep, isSessionScoped, Long.MAX_VALUE, null);
}
/**
@@ -73,13 +73,13 @@
*/
public Lock lock(NodeImpl node, boolean isDeep, boolean isSessionScoped, long timoutHint, String ownerInfo)
throws LockException, RepositoryException {
- AbstractLockInfo info;
+ LockInfo info;
if (isInXA()) {
info = xaEnv.lock(node, isDeep, isSessionScoped, timoutHint, ownerInfo);
} else {
info = lockMgr.internalLock(node, isDeep, isSessionScoped, timoutHint, ownerInfo);
}
- lockMgr.writeLockProperties(node, info.lockOwner, info.deep);
+ lockMgr.writeLockProperties(node, info.getLockOwner(), info.isDeep());
return new XALockImpl(this, info, node);
}
@@ -87,7 +87,7 @@
* {@inheritDoc}
*/
public Lock getLock(NodeImpl node) throws LockException, RepositoryException {
- AbstractLockInfo info;
+ LockInfo info;
if (isInXA()) {
info = xaEnv.getLockInfo(node);
} else {
@@ -105,7 +105,7 @@
* {@inheritDoc}
*/
public Lock[] getLocks(SessionImpl session) throws RepositoryException {
- AbstractLockInfo[] infos;
+ LockInfo[] infos;
if (isInXA()) {
infos = xaEnv.getLockInfos(session);
} else {
@@ -115,7 +115,7 @@
XALockImpl[] locks = new XALockImpl[infos.length];
for (int i = 0; i < infos.length; i++) {
- AbstractLockInfo info = infos[i];
+ LockInfo info = infos[i];
NodeImpl holder = (NodeImpl) session.getItemManager().getItem(info.getId());
locks[i] = new XALockImpl(this, info, holder);
}
@@ -138,7 +138,7 @@
* {@inheritDoc}
*/
public boolean holdsLock(NodeImpl node) throws RepositoryException {
- AbstractLockInfo info;
+ LockInfo info;
if (isInXA()) {
info = xaEnv.getLockInfo(node);
} else {
@@ -151,7 +151,7 @@
* {@inheritDoc}
*/
public boolean isLocked(NodeImpl node) throws RepositoryException {
- AbstractLockInfo info;
+ LockInfo info;
if (isInXA()) {
info = xaEnv.getLockInfo(node);
} else {
@@ -164,7 +164,7 @@
* {@inheritDoc}
*/
public void checkLock(NodeImpl node) throws LockException, RepositoryException {
- AbstractLockInfo info;
+ LockInfo info;
if (isInXA()) {
info = xaEnv.getLockInfo(node);
if (info != null && !info.isLockHolder(node.getSession())) {
@@ -196,7 +196,7 @@
throws LockException, RepositoryException {
if (isInXA()) {
- AbstractLockInfo info = xaEnv.getLockInfo(node);
+ LockInfo info = xaEnv.getLockInfo(node);
if (info == null || !info.getId().equals(node.getId())) {
throw new LockException("Node not locked: " + node);
}
@@ -297,7 +297,7 @@
* Return a flag indicating whether a lock info belongs to a different
* XA environment.
*/
- public boolean differentXAEnv(AbstractLockInfo info) {
+ public boolean differentXAEnv(LockInfo info) {
if (isInXA()) {
return xaEnv.differentXAEnv(info);
} else {
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/EffectiveNodeType.java Tue Sep 8 16:09:28 2009
@@ -1150,7 +1150,8 @@
clone.namedItemDefs.put(name, new ArrayList<ItemDef>(list));
}
clone.unnamedItemDefs.addAll(unnamedItemDefs);
-
+ clone.orderableChildNodes = orderableChildNodes;
+ clone.primaryItemName = primaryItemName;
return clone;
}
}
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java Tue Sep 8 16:09:28 2009
@@ -60,6 +60,7 @@
import org.apache.jackrabbit.spi.QNodeTypeDefinition;
import org.apache.jackrabbit.spi.QValueConstraint;
import org.apache.jackrabbit.spi.commons.conversion.NameException;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
import org.apache.jackrabbit.spi.commons.nodetype.AbstractNodeTypeManager;
import org.apache.jackrabbit.spi.commons.nodetype.InvalidConstraintException;
@@ -207,6 +208,13 @@
}
/**
+ * @see org.apache.jackrabbit.spi.commons.nodetype.AbstractNodeTypeManager#getNamePathResolver()
+ */
+ public NamePathResolver getNamePathResolver() {
+ return session;
+ }
+
+ /**
* @return the node type registry
*/
public NodeTypeRegistry getNodeTypeRegistry() {
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java Tue Sep 8 16:09:28 2009
@@ -1275,8 +1275,11 @@
// and do some preliminary checks
for (NodeTypeDef ntd : ntDefs) {
Name name = ntd.getName();
- if (name != null && registeredNTDefs.containsKey(name)) {
+ if (name != null && tmpNTDefCache.containsKey(name)) {
String msg = name + " already exists";
+ if (tmpNTDefCache.containsKey(name)) {
+ msg += " locally";
+ }
log.debug(msg);
throw new InvalidNodeTypeDefException(msg);
}
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventFilter.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventFilter.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventFilter.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventFilter.java Tue Sep 8 16:09:28 2009
@@ -27,6 +27,7 @@
import org.apache.jackrabbit.spi.Path;
import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
/**
* The <code>EventFilter</code> class implements the filter logic based
@@ -180,10 +181,10 @@
// check node types
if (nodeTypes != null) {
- Set eventTypes = eventState.getNodeTypes(session.getNodeTypeManager());
+ Set<NodeType> eventTypes = eventState.getNodeTypes(session.getNodeTypeManager());
boolean match = false;
for (int i = 0; i < nodeTypes.length && !match; i++) {
- for (Iterator iter = eventTypes.iterator(); iter.hasNext();) {
+ for (Iterator<NodeType> iter = eventTypes.iterator(); iter.hasNext();) {
NodeTypeImpl nodeType = (NodeTypeImpl) iter.next();
match |= nodeType.getQName().equals(nodeTypes[i].getQName())
|| nodeType.isDerivedFrom(nodeTypes[i].getQName());
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventImpl.java Tue Sep 8 16:09:28 2009
@@ -18,7 +18,6 @@
import java.util.Map;
import java.util.HashMap;
-import java.util.Iterator;
import org.apache.jackrabbit.api.observation.JackrabbitEvent;
import javax.jcr.observation.Event;
@@ -141,11 +140,10 @@
/**
* {@inheritDoc}
*/
- public Map getInfo() throws RepositoryException {
- Map info = new HashMap();
- for (Iterator it = eventState.getInfo().entrySet().iterator(); it.hasNext(); ) {
- Map.Entry entry = (Map.Entry) it.next();
- InternalValue value = (InternalValue) entry.getValue();
+ public Map<String, String> getInfo() throws RepositoryException {
+ Map<String, String> info = new HashMap<String, String>();
+ for (Map.Entry<String, InternalValue> entry : eventState.getInfo().entrySet()) {
+ InternalValue value = entry.getValue();
String strValue = null;
if (value != null) {
strValue = ValueFormat.getJCRString(value, session);
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventJournalImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventJournalImpl.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventJournalImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventJournalImpl.java Tue Sep 8 16:09:28 2009
@@ -67,7 +67,7 @@
* Each sorted map has the following structure:
* Key=Long (timestamp), Value=Long (revision)
*/
- private static final Map REVISION_SKIP_MAPS = new WeakHashMap();
+ private static final Map<Journal, SortedMap<Long, Long>> REVISION_SKIP_MAPS = new WeakHashMap<Journal, SortedMap<Long, Long>>();
/**
* Last revision seen by this event journal.
@@ -97,7 +97,7 @@
/**
* Buffer of {@link EventBundle}s.
*/
- private final List eventBundleBuffer = new LinkedList();
+ private final List<EventBundle> eventBundleBuffer = new LinkedList<EventBundle>();
/**
* The current position of this iterator.
@@ -129,12 +129,12 @@
long time = System.currentTimeMillis();
// get skip map for this journal
- SortedMap skipMap = getSkipMap();
+ SortedMap<Long, Long> skipMap = getSkipMap();
synchronized (skipMap) {
- SortedMap head = skipMap.headMap(new Long(time));
+ SortedMap<Long, Long> head = skipMap.headMap(new Long(time));
if (!head.isEmpty()) {
eventBundleBuffer.clear();
- lastRevision = (Long) head.get(head.lastKey());
+ lastRevision = head.get(head.lastKey());
}
}
@@ -267,7 +267,7 @@
* {@inheritDoc}
*/
public void process(ChangeLogRecord record) {
- List events = record.getEvents();
+ List<EventState> events = record.getEvents();
if (!events.isEmpty()) {
EventBundle bundle = new EventBundle(events,
record.getTimestamp(), record.getUserData(), filter);
@@ -304,7 +304,7 @@
*/
private EventBundle getCurrentBundle() {
while (!eventBundleBuffer.isEmpty()) {
- EventBundle bundle = (EventBundle) eventBundleBuffer.get(0);
+ EventBundle bundle = eventBundleBuffer.get(0);
if (bundle.events.hasNext()) {
return bundle;
} else {
@@ -346,7 +346,7 @@
if (processor.getNumEvents() >= MIN_BUFFER_SIZE) {
// remember in skip map
- SortedMap skipMap = getSkipMap();
+ SortedMap<Long, Long> skipMap = getSkipMap();
Long timestamp = new Long(processor.getLastTimestamp());
synchronized (skipMap) {
if (log.isDebugEnabled()) {
@@ -369,11 +369,11 @@
/**
* @return the revision skip map for this journal.
*/
- private SortedMap getSkipMap() {
+ private SortedMap<Long, Long> getSkipMap() {
synchronized (REVISION_SKIP_MAPS) {
- SortedMap map = (SortedMap) REVISION_SKIP_MAPS.get(journal);
+ SortedMap<Long, Long> map = REVISION_SKIP_MAPS.get(journal);
if (map == null) {
- map = new TreeMap();
+ map = new TreeMap<Long, Long>();
REVISION_SKIP_MAPS.put(journal, map);
}
return map;
@@ -403,7 +403,7 @@
* @param userData the user data associated with this event.
* @param filter the event filter.
*/
- private EventBundle(List eventStates,
+ private EventBundle(List<EventState> eventStates,
long timestamp,
String userData,
EventFilter filter) {
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventListenerIteratorImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventListenerIteratorImpl.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventListenerIteratorImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventListenerIteratorImpl.java Tue Sep 8 16:09:28 2009
@@ -48,7 +48,7 @@
/**
* Current position
*/
- private long pos = 0;
+ private long pos;
/**
* Creates a new <code>EventListenerIteratorImpl</code>.
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventState.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventState.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventState.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventState.java Tue Sep 8 16:09:28 2009
@@ -33,6 +33,8 @@
import javax.jcr.Session;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.nodetype.NodeType;
+
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
@@ -107,7 +109,7 @@
/**
* Set of mixin QNames assigned to the parent node.
*/
- private final Set mixins;
+ private final Set<Name> mixins;
/**
* Set of node types. This Set consists of the primary node type and all
@@ -116,7 +118,7 @@
* This <code>Set</code> is initialized when
* {@link #getNodeTypes(NodeTypeManagerImpl)} is called for the first time.
*/
- private Set allTypes;
+ private Set<NodeType> allTypes;
/**
* The session that caused this event.
@@ -142,13 +144,13 @@
/**
* The info Map associated with this event.
*/
- private Map info = Collections.EMPTY_MAP;
+ private Map<String, InternalValue> info = Collections.emptyMap();
/**
* If set to <code>true</code>, indicates that the child node of a node
* added or removed event is a shareable node.
*/
- private boolean shareableNode = false;
+ private boolean shareableNode;
/**
* Creates a new <code>EventState</code> instance.
@@ -169,7 +171,7 @@
*/
private EventState(int type, NodeId parentId, Path parentPath,
NodeId childId, Path.Element childPath, Name nodeType,
- Set mixins, Session session, boolean external) {
+ Set<Name> mixins, Session session, boolean external) {
int mask = (Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED);
if ((type & mask) > 0) {
@@ -214,7 +216,7 @@
NodeId childId,
Path.Element childPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session) {
return childNodeAdded(parentId, parentPath, childId,
@@ -242,7 +244,7 @@
NodeId childId,
Path.Element childPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session,
boolean external) {
@@ -270,7 +272,7 @@
NodeId childId,
Path.Element childPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session) {
return childNodeRemoved(parentId, parentPath, childId,
@@ -298,7 +300,7 @@
NodeId childId,
Path.Element childPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session,
boolean external) {
@@ -330,7 +332,7 @@
NodeId childId,
Path.Element childPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session,
boolean external) {
@@ -361,7 +363,7 @@
NodeId childId,
Path srcPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session,
boolean external)
throws ItemStateException {
@@ -369,7 +371,7 @@
EventState es = nodeMoved(parentId, destPath.getAncestor(1),
childId, destPath.getNameElement(), nodeType, mixins,
session, external);
- Map info = new HashMap();
+ Map<String, InternalValue> info = new HashMap<String, InternalValue>();
info.put(SRC_ABS_PATH, InternalValue.create(srcPath));
info.put(DEST_ABS_PATH, InternalValue.create(destPath));
es.setInfo(info);
@@ -412,12 +414,12 @@
Path.Element srcChildPath,
Path.Element beforeChildPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session,
boolean external) {
EventState es = nodeMoved(parentId, parentPath, childId, destChildPath,
nodeType, mixins, session, external);
- Map info = new HashMap();
+ Map<String, InternalValue> info = new HashMap<String, InternalValue>();
info.put(SRC_CHILD_REL_PATH, createValue(srcChildPath));
InternalValue value = null;
if (beforeChildPath != null) {
@@ -446,7 +448,7 @@
Path parentPath,
Path.Element childPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session) {
return propertyAdded(parentId, parentPath, childPath,
@@ -472,7 +474,7 @@
Path parentPath,
Path.Element childPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session,
boolean external) {
@@ -498,7 +500,7 @@
Path parentPath,
Path.Element childPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session) {
return propertyRemoved(parentId, parentPath, childPath,
@@ -524,7 +526,7 @@
Path parentPath,
Path.Element childPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session,
boolean external) {
@@ -550,7 +552,7 @@
Path parentPath,
Path.Element childPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session) {
return propertyChanged(parentId, parentPath, childPath,
@@ -576,7 +578,7 @@
Path parentPath,
Path.Element childPath,
Name nodeType,
- Set mixins,
+ Set<Name> mixins,
Session session,
boolean external) {
@@ -645,7 +647,7 @@
*
* @return the mixin names as <code>Name</code>s.
*/
- public Set getMixinNames() {
+ public Set<Name> getMixinNames() {
return mixins;
}
@@ -657,17 +659,17 @@
*
* @return <code>Set</code> of {@link javax.jcr.nodetype.NodeType}s.
*/
- public Set getNodeTypes(NodeTypeManagerImpl ntMgr) {
+ public Set<NodeType> getNodeTypes(NodeTypeManagerImpl ntMgr) {
if (allTypes == null) {
- Set tmp = new HashSet();
+ Set<NodeType> tmp = new HashSet<NodeType>();
try {
tmp.add(ntMgr.getNodeType(nodeType));
} catch (NoSuchNodeTypeException e) {
log.warn("Unknown node type: " + nodeType);
}
- Iterator it = mixins.iterator();
+ Iterator<Name> it = mixins.iterator();
while (it.hasNext()) {
- Name mixinName = (Name) it.next();
+ Name mixinName = it.next();
try {
tmp.add(ntMgr.getNodeType(mixinName));
} catch (NoSuchNodeTypeException e) {
@@ -725,7 +727,7 @@
/**
* @return an unmodifiable info Map.
*/
- public Map getInfo() {
+ public Map<String, InternalValue> getInfo() {
return info;
}
@@ -734,8 +736,8 @@
*
* @param info the new info map.
*/
- public void setInfo(Map info) {
- this.info = Collections.unmodifiableMap(new HashMap(info));
+ public void setInfo(Map<String, InternalValue> info) {
+ this.info = Collections.unmodifiableMap(new HashMap<String, InternalValue>(info));
}
/**
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollection.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollection.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/observation/EventStateCollection.java Tue Sep 8 16:09:28 2009
@@ -562,7 +562,13 @@
if (n.getParentId().equals(parentId)) {
continue;
}
- NodeState parent = (NodeState) changes.get(parentId);
+ NodeState parent = null;
+ try {
+ parent = (NodeState) changes.get(parentId);
+ } catch (NoSuchItemStateException e) {
+ // parent has been removed as well
+ // ignore and retrieve from stateMgr
+ }
if (parent == null) {
// happens when mix:shareable is removed from an existing
// node. Usually the parent node state is in the change log
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java?rev=812570&r1=812569&r2=812570&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/PersistenceCopier.java Tue Sep 8 16:09:28 2009
@@ -16,9 +16,15 @@
*/
package org.apache.jackrabbit.core.persistence;
+import java.io.IOException;
+import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.core.data.DataStore;
import org.apache.jackrabbit.core.id.NodeId;
import org.apache.jackrabbit.core.id.PropertyId;
import org.apache.jackrabbit.core.state.ChangeLog;
@@ -27,6 +33,7 @@
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.value.InternalValue;
import org.apache.jackrabbit.spi.Name;
/**
@@ -48,6 +55,11 @@
private final PersistenceManager target;
/**
+ * Target data store, possibly <code>null</code>.
+ */
+ private final DataStore store;
+
+ /**
* Identifiers of the nodes that have already been copied or that
* should explicitly not be copied. Used to avoid duplicate copies
* of shareable nodes and to avoid trying to copy "missing" nodes
@@ -61,11 +73,14 @@
*
* @param source source persistence manager
* @param target target persistence manager
+ * @param store target data store
*/
public PersistenceCopier(
- PersistenceManager source, PersistenceManager target) {
+ PersistenceManager source, PersistenceManager target,
+ DataStore store) {
this.source = source;
this.target = target;
+ this.store = store;
}
/**
@@ -84,18 +99,22 @@
* are automatically skipped.
*
* @param id identifier of the node to be copied
- * @throws ItemStateException if the copy operation fails
+ * @throws RepositoryException if the copy operation fails
*/
- public void copy(NodeId id) throws ItemStateException {
+ public void copy(NodeId id) throws RepositoryException {
if (!exclude.contains(id)) {
- NodeState node = source.load(id);
+ try {
+ NodeState node = source.load(id);
- for (ChildNodeEntry entry : node.getChildNodeEntries()) {
- copy(entry.getId());
+ for (ChildNodeEntry entry : node.getChildNodeEntries()) {
+ copy(entry.getId());
+ }
+
+ copy(node);
+ exclude.add(id);
+ } catch (ItemStateException e) {
+ throw new RepositoryException("Unable to copy " + id, e);
}
-
- copy(node);
- exclude.add(id);
}
}
@@ -104,54 +123,71 @@
* to the target persistence manager.
*
* @param sourceNode source node state
- * @throws ItemStateException if the copy operation fails
+ * @throws RepositoryException if the copy operation fails
*/
- private void copy(NodeState sourceNode) throws ItemStateException {
- ChangeLog changes = new ChangeLog();
+ private void copy(NodeState sourceNode) throws RepositoryException {
+ try {
+ ChangeLog changes = new ChangeLog();
+
+ // Copy the node state
+ NodeState targetNode = target.createNew(sourceNode.getNodeId());
+ targetNode.setParentId(sourceNode.getParentId());
+ targetNode.setDefinitionId(sourceNode.getDefinitionId());
+ targetNode.setNodeTypeName(sourceNode.getNodeTypeName());
+ targetNode.setMixinTypeNames(sourceNode.getMixinTypeNames());
+ targetNode.setPropertyNames(sourceNode.getPropertyNames());
+ targetNode.setChildNodeEntries(sourceNode.getChildNodeEntries());
+ if (target.exists(targetNode.getNodeId())) {
+ changes.modified(targetNode);
+ } else {
+ changes.added(targetNode);
+ }
- // Copy the node state
- NodeState targetNode = target.createNew(sourceNode.getNodeId());
- targetNode.setParentId(sourceNode.getParentId());
- targetNode.setDefinitionId(sourceNode.getDefinitionId());
- targetNode.setNodeTypeName(sourceNode.getNodeTypeName());
- targetNode.setMixinTypeNames(sourceNode.getMixinTypeNames());
- targetNode.setPropertyNames(sourceNode.getPropertyNames());
- targetNode.setChildNodeEntries(sourceNode.getChildNodeEntries());
- if (target.exists(targetNode.getNodeId())) {
- changes.modified(targetNode);
- } else {
- changes.added(targetNode);
- }
+ // Copy all associated property states
+ for (Name name : sourceNode.getPropertyNames()) {
+ PropertyId id = new PropertyId(sourceNode.getNodeId(), name);
+ PropertyState sourceState = source.load(id);
+ PropertyState targetState = target.createNew(id);
+ targetState.setDefinitionId(sourceState.getDefinitionId());
+ targetState.setType(sourceState.getType());
+ targetState.setMultiValued(sourceState.isMultiValued());
+ InternalValue[] values = sourceState.getValues();
+ if (sourceState.getType() == PropertyType.BINARY) {
+ for (int i = 0; i < values.length; i++) {
+ InputStream stream = values[i].getStream();
+ try {
+ values[i] = InternalValue.create(stream, store);
+ } finally {
+ stream.close();
+ }
+ }
+ }
+ targetState.setValues(values);
+ if (target.exists(targetState.getPropertyId())) {
+ changes.modified(targetState);
+ } else {
+ changes.added(targetState);
+ }
+ }
- // Copy all associated property states
- for (Name name : sourceNode.getPropertyNames()) {
- PropertyId id = new PropertyId(sourceNode.getNodeId(), name);
- PropertyState sourceState = source.load(id);
- PropertyState targetState = target.createNew(id);
- targetState.setDefinitionId(sourceState.getDefinitionId());
- targetState.setType(sourceState.getType());
- targetState.setMultiValued(sourceState.isMultiValued());
- // TODO: Copy binaries?
- targetState.setValues(sourceState.getValues());
- if (target.exists(targetState.getPropertyId())) {
- changes.modified(targetState);
- } else {
- changes.added(targetState);
+ // Copy all node references
+ if (source.existsReferencesTo(sourceNode.getNodeId())) {
+ changes.modified(source.loadReferencesTo(sourceNode.getNodeId()));
+ } else if (target.existsReferencesTo(sourceNode.getNodeId())) {
+ NodeReferences references =
+ target.loadReferencesTo(sourceNode.getNodeId());
+ references.clearAllReferences();
+ changes.modified(references);
}
- }
- // Copy all node references
- if (source.existsReferencesTo(sourceNode.getNodeId())) {
- changes.modified(source.loadReferencesTo(sourceNode.getNodeId()));
- } else if (target.existsReferencesTo(sourceNode.getNodeId())) {
- NodeReferences references =
- target.loadReferencesTo(sourceNode.getNodeId());
- references.clearAllReferences();
- changes.modified(references);
+ // Persist the copied states
+ target.store(changes);
+ } catch (IOException e) {
+ throw new RepositoryException(
+ "Unable to copy binary values of " + sourceNode, e);
+ } catch (ItemStateException e) {
+ throw new RepositoryException("Unable to copy " + sourceNode, e);
}
-
- // Persist the copied states
- target.store(changes);
}
}