Author: angela Date: Fri Mar 13 13:37:44 2009 New Revision: 753244 URL: http://svn.apache.org/viewvc?rev=753244&view=rev Log: JCR-1590 JSR 283: Locking - getSecondsRemaining is negative if lock is expired or released - getLockToken always returns null if lock is sessionscoped JCR-2004 Update SPI locking to match JCR 2.0 - extend spi/LockInfo.java - add JCR 2.0 variant of RepositoryService#lock that takes timeoutHint and ownerHint - adjust jcr2spi - adjust spi implementation(s) Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/WorkspaceTest.java (with props) Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/AbstractLockInfo.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockImpl.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/TestAll.java jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java jackrabbit/trunk/jackrabbit-jcr2spi/pom.xml jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/DefaultLockManager.java jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManager.java jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManagerImpl.java jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/LockOperation.java jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/lock/AbstractLockTest.java jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/LockInfoImpl.java jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/LockInfo.java jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java jackrabbit/trunk/jackrabbit-spi2jcr/pom.xml jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/LockInfoImpl.java jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/NodeImpl.java Fri Mar 13 13:37:44 2009 @@ -4408,7 +4408,7 @@ RepositoryException { // check state of this instance sanityCheck(); - LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).get283LockManager(); + LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).getLockManager(); return lockMgr.lock(getPath(), isDeep, isSessionScoped, Long.MAX_VALUE, null); } @@ -4420,7 +4420,7 @@ AccessDeniedException, RepositoryException { // check state of this instance sanityCheck(); - LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).get283LockManager(); + LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).getLockManager(); return lockMgr.getLock(getPath()); } @@ -4433,7 +4433,7 @@ RepositoryException { // check state of this instance sanityCheck(); - LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).get283LockManager(); + LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).getLockManager(); lockMgr.unlock(getPath()); } @@ -4443,7 +4443,7 @@ public boolean holdsLock() throws RepositoryException { // check state of this instance sanityCheck(); - LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).get283LockManager(); + LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).getLockManager(); return lockMgr.holdsLock(getPath()); } @@ -4453,7 +4453,7 @@ public boolean isLocked() throws RepositoryException { // check state of this instance sanityCheck(); - LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).get283LockManager(); + LockManager lockMgr = ((WorkspaceImpl) session.getWorkspace()).getLockManager(); return lockMgr.isLocked(getPath()); } 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=753244&r1=753243&r2=753244&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 Fri Mar 13 13:37:44 2009 @@ -1252,7 +1252,7 @@ */ public void addLockToken(String lt) { try { - wsp.get283LockManager().addLockToken(lt); + wsp.getLockManager().addLockToken(lt); } catch (RepositoryException e) { log.debug("Error while adding lock token."); } @@ -1263,7 +1263,7 @@ */ public String[] getLockTokens() { try { - return wsp.get283LockManager().getLockTokens(); + return wsp.getLockManager().getLockTokens(); } catch (RepositoryException e) { log.debug("Error while accessing lock tokens."); return new String[0]; @@ -1275,7 +1275,7 @@ */ public void removeLockToken(String lt) { try { - wsp.get283LockManager().removeLockToken(lt); + wsp.getLockManager().removeLockToken(lt); } catch (RepositoryException e) { log.debug("Error while removing lock token."); } @@ -1286,7 +1286,7 @@ * @return lock manager for this session */ public LockManager getLockManager() throws RepositoryException { - return wsp.getLockManager(); + return wsp.getInternalLockManager(); } /** Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/WorkspaceImpl.java Fri Mar 13 13:37:44 2009 @@ -18,6 +18,7 @@ import org.apache.jackrabbit.api.JackrabbitWorkspace; import org.apache.jackrabbit.api.jsr283.observation.EventJournal; +import org.apache.jackrabbit.api.jsr283.version.VersionManager; import org.apache.jackrabbit.core.config.WorkspaceConfig; import org.apache.jackrabbit.core.lock.LockManager; import org.apache.jackrabbit.core.lock.SessionLockManager; @@ -73,7 +74,8 @@ * A WorkspaceImpl ... */ public class WorkspaceImpl extends AbstractWorkspace - implements JackrabbitWorkspace, EventStateCollectionFactory { + implements JackrabbitWorkspace, org.apache.jackrabbit.api.jsr283.Workspace, + EventStateCollectionFactory { private static Logger log = LoggerFactory.getLogger(WorkspaceImpl.class); @@ -282,18 +284,22 @@ * @see org.apache.jackrabbit.api.jsr283.Workspace#getLockManager() * @see org.apache.jackrabbit.api.jsr283.lock.LockManager */ - // TODO: rename to 'getLockManager'. - // TODO in order not to break compatilibiy with the 1.x releases - // TODO the 283 method has been tmp. renamed since it conflicts with an - // TODO existing public method, exposing the internal lock manager. - public org.apache.jackrabbit.api.jsr283.lock.LockManager get283LockManager() throws UnsupportedRepositoryOperationException, RepositoryException { + public org.apache.jackrabbit.api.jsr283.lock.LockManager getLockManager() throws UnsupportedRepositoryOperationException, RepositoryException { if (jcr283LockManager == null) { jcr283LockManager = new SessionLockManager(session, session.getLockManager()); } return jcr283LockManager; } + /** + * @see org.apache.jackrabbit.api.jsr283.Workspace#getVersionManager() + */ + public VersionManager getVersionManager() throws UnsupportedRepositoryOperationException, RepositoryException { + throw new UnsupportedRepositoryOperationException("not yet implemented"); + } + //-------------------------------< JackrabbitWorkspace/new JSR 283 method > + /** * Creates a new Workspace with the specified * name. The new workspace is empty, meaning it contains only @@ -520,7 +526,7 @@ * @return lock manager for this workspace * @throws RepositoryException if an error occurs */ - public synchronized LockManager getLockManager() throws RepositoryException { + public synchronized org.apache.jackrabbit.core.lock.LockManager getInternalLockManager() throws RepositoryException { // check state of this instance sanityCheck(); @@ -744,7 +750,7 @@ boolean succeeded = false; try { - NodeId id = ops.move(srcPath, destPath); + ops.move(srcPath, destPath); ops.update(); succeeded = true; } finally { Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/XASessionImpl.java Fri Mar 13 13:37:44 2009 @@ -180,7 +180,7 @@ */ public LockManager getLockManager() throws RepositoryException { if (lockMgr == null) { - LockManagerImpl lockMgr = (LockManagerImpl) wsp.getLockManager(); + LockManagerImpl lockMgr = (LockManagerImpl) wsp.getInternalLockManager(); this.lockMgr = new XALockManager(lockMgr); } return lockMgr; Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/AbstractLockInfo.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/AbstractLockInfo.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/AbstractLockInfo.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/AbstractLockInfo.java Fri Mar 13 13:37:44 2009 @@ -27,6 +27,15 @@ public abstract class AbstractLockInfo { /** + * Constant for the undefined or infinite timeout. + */ + static final long TIMEOUT_INFINITE = Long.MAX_VALUE; + /** + * Constant for the expired timeout. + */ + static final long TIMEOUT_EXPIRED = -1; + + /** * Lock token */ protected final LockToken lockToken; @@ -66,7 +75,7 @@ */ public AbstractLockInfo(LockToken lockToken, boolean sessionScoped, boolean deep, String lockOwner) { - this(lockToken, sessionScoped, deep, lockOwner, Long.MAX_VALUE); + this(lockToken, sessionScoped, deep, lockOwner, TIMEOUT_INFINITE); } /** @@ -172,7 +181,7 @@ public long getSecondsRemaining() { // TODO: TOBEFIXED for 2.0 // TODO - add support for timeout specified by the API user -> LockManager#lock - return Long.MAX_VALUE; + return isLive() ? TIMEOUT_INFINITE : TIMEOUT_EXPIRED; } /** Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockImpl.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockImpl.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockImpl.java Fri Mar 13 13:37:44 2009 @@ -78,14 +78,9 @@ * {@inheritDoc} */ public String getLockToken() { - // TODO: TOBEFIXED for 2.0 - // TODO - token must not be exposed for session-scoped locks (-> adjust tests and derived projects first) - // TODO - openScoped tokens *may* be exposed even if session is not lock holder - /* if (info.isSessionScoped()) { return null; } - */ try { return info.getLockToken(node.getSession()); } catch (RepositoryException e) { Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java Fri Mar 13 13:37:44 2009 @@ -47,6 +47,7 @@ import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException; import org.apache.jackrabbit.spi.commons.name.NameConstants; import org.apache.jackrabbit.spi.commons.name.PathMap; +import org.apache.jackrabbit.api.jsr283.Workspace; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -275,8 +276,8 @@ } static SessionLockManager getSessionLockManager(SessionImpl session) throws RepositoryException { - WorkspaceImpl wsp = (WorkspaceImpl) session.getWorkspace(); - return (SessionLockManager) wsp.get283LockManager(); + Workspace wsp = (Workspace) session.getWorkspace(); + return (SessionLockManager) wsp.getLockManager(); } /** @@ -463,7 +464,7 @@ */ public Lock lock(NodeImpl node, boolean isDeep, boolean isSessionScoped) throws LockException, RepositoryException { - return lock(node, isDeep, isSessionScoped, Long.MAX_VALUE, null); + return lock(node, isDeep, isSessionScoped, AbstractLockInfo.TIMEOUT_INFINITE, null); } public Lock lock(NodeImpl node, boolean isDeep, boolean isSessionScoped, long timoutHint, String ownerInfo) @@ -1134,7 +1135,7 @@ */ public LockInfo(LockToken lockToken, boolean sessionScoped, boolean deep, String lockOwner) { - this(lockToken, sessionScoped, deep, lockOwner, Long.MAX_VALUE); + this(lockToken, sessionScoped, deep, lockOwner, TIMEOUT_INFINITE); } /** Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/SessionLockManager.java Fri Mar 13 13:37:44 2009 @@ -41,7 +41,7 @@ * is associated with a single Session and its * Workspace. * - * @see javax.jcr.Workspace#getLockManager() + * @see org.apache.jackrabbit.api.jsr283.Workspace#getLockManager() */ public class SessionLockManager implements org.apache.jackrabbit.api.jsr283.lock.LockManager { @@ -190,7 +190,7 @@ /** * * @param lockToken - * @return + * @return true if the token was successfully added to the set. */ boolean lockTokenAdded(String lockToken) { synchronized (lockTokens) { @@ -201,7 +201,7 @@ /** * * @param lockToken - * @return + * @return true if the token was successfully removed from the set. */ boolean lockTokenRemoved(String lockToken) { synchronized (lockTokens) { Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java Fri Mar 13 13:37:44 2009 @@ -107,7 +107,7 @@ */ public AbstractLockInfo lock(NodeImpl node, boolean isDeep, boolean isSessionScoped) throws LockException, RepositoryException { - return lock(node, isDeep, isSessionScoped, Long.MAX_VALUE, null); + return lock(node, isDeep, isSessionScoped, AbstractLockInfo.TIMEOUT_INFINITE, null); } /** @@ -392,7 +392,7 @@ public LockInfo(NodeImpl node, LockToken lockToken, boolean sessionScoped, boolean deep, String lockOwner) { - this(node, lockToken, sessionScoped, deep, lockOwner, Long.MAX_VALUE); + this(node, lockToken, sessionScoped, deep, lockOwner, TIMEOUT_INFINITE); } /** Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XALockManager.java Fri Mar 13 13:37:44 2009 @@ -65,7 +65,7 @@ */ public Lock lock(NodeImpl node, boolean isDeep, boolean isSessionScoped) throws LockException, RepositoryException { - return lock(node, isDeep, isSessionScoped, Long.MAX_VALUE, null); + return lock(node, isDeep, isSessionScoped, AbstractLockInfo.TIMEOUT_INFINITE, null); } /** Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/TestAll.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/TestAll.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/TestAll.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/TestAll.java Fri Mar 13 13:37:44 2009 @@ -30,6 +30,7 @@ public static Test suite() { TestSuite suite = new TestSuite("org.apache.jackrabbit.api.jsr283 tests"); + suite.addTestSuite(WorkspaceTest.class); suite.addTestSuite(SessionRemoveItemTest.class); return suite; Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/WorkspaceTest.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/WorkspaceTest.java?rev=753244&view=auto ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/WorkspaceTest.java (added) +++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/WorkspaceTest.java Fri Mar 13 13:37:44 2009 @@ -0,0 +1,61 @@ +/* + * 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.api.jsr283; + +import org.apache.jackrabbit.test.AbstractJCRTest; +import org.apache.jackrabbit.test.NotExecutableException; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.UnsupportedRepositoryOperationException; + +/** + * WorkspaceTest... + */ +public class WorkspaceTest extends AbstractJCRTest { + + private Workspace workspace; + + protected void setUp() throws Exception { + super.setUp(); + + javax.jcr.Workspace wsp = superuser.getWorkspace(); + if (wsp instanceof Workspace) { + workspace = (Workspace) wsp; + } else { + throw new NotExecutableException("JCR 2.0 Workspace expected."); + } + } + + /** + * Tests {@link org.apache.jackrabbit.api.jsr283.Workspace#getLockManager()}. + * + * @throws RepositoryException + */ + public void testGetLockManager() throws RepositoryException { + if (isSupported(Repository.OPTION_LOCKING_SUPPORTED)) { + assertNotNull(workspace.getLockManager()); + } else { + try { + workspace.getLockManager(); + fail("UnsupportedRepositoryOperationException expected. Locking is not supported."); + } catch (UnsupportedRepositoryOperationException e) { + // success. + } + } + } +} \ No newline at end of file Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/WorkspaceTest.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/WorkspaceTest.java ------------------------------------------------------------------------------ svn:keywords = author date id revision url Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/AbstractLockTest.java Fri Mar 13 13:37:44 2009 @@ -21,12 +21,16 @@ import org.apache.jackrabbit.test.AbstractJCRTest; import org.apache.jackrabbit.test.RepositoryStub; import org.apache.jackrabbit.test.NotExecutableException; +import org.apache.jackrabbit.test.JUnitTest; +import org.apache.jackrabbit.test.api.observation.EventResult; import org.apache.jackrabbit.core.WorkspaceImpl; import javax.jcr.Node; import javax.jcr.Session; import javax.jcr.RepositoryException; import javax.jcr.Repository; +import javax.jcr.observation.ObservationManager; +import javax.jcr.observation.Event; import javax.jcr.lock.LockException; import javax.jcr.nodetype.ConstraintViolationException; @@ -59,7 +63,7 @@ protected void tearDown() throws Exception { // release the lock created during setup - if (lockMgr != null && lockedNode != null) { + if (lockMgr != null && lockedNode != null && lockMgr.isLocked(lockedNode.getPath())) { try { lockMgr.unlock(lockedNode.getPath()); } catch (RepositoryException e) { @@ -95,7 +99,7 @@ private static LockManager getLockManager(Session session) throws RepositoryException { // TODO: rm cast and adjust call as soon as 283 is released - return ((WorkspaceImpl) session.getWorkspace()).get283LockManager(); + return ((WorkspaceImpl) session.getWorkspace()).getLockManager(); } /** @@ -178,11 +182,61 @@ /** * Test {@link org.apache.jackrabbit.api.jsr283.lock.Lock#getSecondsRemaining()} */ - public void testGetSecondsRemaining() { - assertTrue("Seconds remaining must be a positive long or 0.", lock.getSecondsRemaining() >= 0); + public void testGetSecondsRemaining() throws RepositoryException { + if (lock.isLive()) { + assertTrue("Seconds remaining must be a positive long.", lock.getSecondsRemaining() > 0); + } else { + assertTrue("Seconds remaining must be a negative long.", lock.getSecondsRemaining() < 0); + } + } + + /** + * Test {@link org.apache.jackrabbit.api.jsr283.lock.Lock#getSecondsRemaining()} + */ + public void testGetSecondsRemainingAfterUnlock() throws RepositoryException { + lockMgr.unlock(lockedNode.getPath()); + assertTrue("Lock has been released: seconds remaining must be a negative long.", lock.getSecondsRemaining() < 0); } /** + * Test expiration of the lock + */ + public void testLockExpiration() throws RepositoryException, NotExecutableException { + lockedNode.unlock(); + + ObservationManager obsMgr = superuser.getWorkspace().getObservationManager(); + EventResult listener = new EventResult(((JUnitTest) this).log); + try { + obsMgr.addEventListener(listener, Event.PROPERTY_REMOVED, lockedNode.getPath(), false, new String[0], new String[0], false); + + boolean lockPropRemoved = false; + long hint = 1; + lock = lockMgr.lock(lockedNode.getPath(), isDeep(), isSessionScoped(), hint, null); + // only test if timeout hint was respected. + if (lock.getSecondsRemaining() <= 1) { + Event[] evts = listener.getEvents(2000); + for (int i = 0; i < evts.length; i++) { + if (evts[i].getType() == Event.PROPERTY_REMOVED && + evts[i].getPath().endsWith(jcrLockOwner)) { + lockPropRemoved = true; + // lock property has been removed -> make sure lock has + // been released and lock.getSecondsRemaining behaves properly. + assertTrue("A released lock must return a negative number of seconds", lock.getSecondsRemaining() < 0); + assertFalse("If the timeout hint is respected the lock must be automatically released.", lock.isLive()); + assertFalse("If the timeout hint is respected the lock must be automatically released.", lockedNode.isLocked()); + } + } + if (!lockPropRemoved) { + fail("If the timeout hint is respected the lock must be automatically released."); + } + } else { + throw new NotExecutableException("timeout hint was ignored."); + } + } finally { + obsMgr.removeEventListener(listener); + } + } + /** * Test {@link LockManager#unlock(String)} for a session that is not * lock owner. * Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/LockManagerTest.java Fri Mar 13 13:37:44 2009 @@ -72,7 +72,7 @@ private static LockManager getLockManager(Session session) throws RepositoryException { // TODO: rm cast and adjust call as soon as 283 is released - return ((WorkspaceImpl) session.getWorkspace()).get283LockManager(); + return ((WorkspaceImpl) session.getWorkspace()).getLockManager(); } private static boolean containsLockToken(LockManager lMgr, String token) throws RepositoryException { Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java (original) +++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/api/jsr283/lock/SessionScopedLockTest.java Fri Mar 13 13:37:44 2009 @@ -36,9 +36,7 @@ * {@link org.apache.jackrabbit.api.jsr283.lock.Lock#getLockToken()} must * always return null for session scoped locks. */ - /* public void testGetLockToken() { assertNull("A session scoped lock may never expose the token.", lock.getLockToken()); } - */ } \ No newline at end of file Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java (original) +++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/DefaultItemCollection.java Fri Mar 13 13:37:44 2009 @@ -611,10 +611,10 @@ try { boolean sessionScoped = EXCLUSIVE_SESSION.equals(reqLockInfo.getScope()); Lock jcrLock = ((Node)item).lock(reqLockInfo.isDeep(), sessionScoped); - // add reference to DAVSession for this lock - getSession().addReference(jcrLock.getLockToken()); - return new JcrActiveLock(jcrLock, sessionScoped); - + ActiveLock lock = new JcrActiveLock(jcrLock); + // add reference to DAVSession for this lock + getSession().addReference(lock.getToken()); + return lock; } catch (RepositoryException e) { // UnsupportedRepositoryOperationException should not occur... throw new JcrDavException(e); @@ -653,7 +653,7 @@ try { Lock jcrLock = ((Node) item).getLock(); jcrLock.refresh(); - return new JcrActiveLock(jcrLock, EXCLUSIVE_SESSION.equals(lock.getScope())); + return new JcrActiveLock(jcrLock); } catch (RepositoryException e) { /* NOTE: LockException is only thrown by Lock.refresh() Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java (original) +++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/lock/JcrActiveLock.java Fri Mar 13 13:37:44 2009 @@ -16,7 +16,6 @@ */ package org.apache.jackrabbit.webdav.jcr.lock; -import org.apache.jackrabbit.JcrConstants; import org.apache.jackrabbit.webdav.DavConstants; import org.apache.jackrabbit.webdav.jcr.ItemResourceConstants; import org.apache.jackrabbit.webdav.lock.AbstractActiveLock; @@ -26,7 +25,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.lock.Lock; @@ -38,7 +36,6 @@ private static Logger log = LoggerFactory.getLogger(JcrActiveLock.class); private final Lock lock; - private final boolean sessionScoped; /** * Create a new ActiveLock object with type '{@link Type#WRITE write}' @@ -47,21 +44,10 @@ * @param lock */ public JcrActiveLock(Lock lock) { - this (lock, lock.isSessionScoped()); - } - - /** - * Create a new ActiveLock object with type '{@link Type#WRITE write}' - * and scope '{@link Scope#EXCLUSIVE exclusive}'. - * - * @param lock - */ - public JcrActiveLock(Lock lock, boolean sessionScoped) { if (lock == null) { throw new IllegalArgumentException("Can not create a ActiveLock with a 'null' argument."); } this.lock = lock; - this.sessionScoped = sessionScoped; } /** @@ -98,11 +84,30 @@ * UUID [Extension] ; The UUID production is the string representation of a * UUID, as defined in [ISO-11578]. Note that white space (LWS) is not allowed * between elements of this production."). + *

+ * In case of session-scoped JCR 2.0 locks, the token is never exposed even + * if the current session is lock holder. In order to cope with DAV specific + * requirements and the fulfill the requirement stated above, the node's + * identifier is subsequently exposed as DAV-token. * * @see ActiveLock#getToken() */ public String getToken() { - return lock.getLockToken(); + String token = lock.getLockToken(); + if (token == null && lock.isSessionScoped() + && lock instanceof org.apache.jackrabbit.api.jsr283.lock.Lock + && ((org.apache.jackrabbit.api.jsr283.lock.Lock)lock).isLockOwningSession()) { + // special handling for session scoped locks that are owned by the + // current session but never expose their token with jsr 283. + try { + token = ((org.apache.jackrabbit.api.jsr283.Node)lock.getNode()).getIdentifier(); + } catch (RepositoryException e) { + // should never get here + log.warn("Unexpected error while retrieving node identifier for building a DAV specific lock token.",e.getMessage()); + } + } + // default behaviour: just return the token exposed by the lock. + return token; } /** @@ -143,17 +148,7 @@ * @see ActiveLock#isDeep() */ public boolean isDeep() { - boolean isDeep = true; - Node n = lock.getNode(); - try { - // find out about deepness. if node does not hold the lock its deep anyway - if (n.holdsLock() && n.hasProperty(JcrConstants.JCR_LOCKISDEEP)) { - isDeep = n.getProperty(JcrConstants.JCR_LOCKISDEEP).getBoolean(); - } - } catch (RepositoryException e) { - // ignore and keep default depth settings - } - return isDeep; + return lock.isDeep(); } /** @@ -180,6 +175,6 @@ * @see ActiveLock#getScope() */ public Scope getScope() { - return (sessionScoped) ? ItemResourceConstants.EXCLUSIVE_SESSION : Scope.EXCLUSIVE; + return (lock.isSessionScoped()) ? ItemResourceConstants.EXCLUSIVE_SESSION : Scope.EXCLUSIVE; } } \ No newline at end of file Modified: jackrabbit/trunk/jackrabbit-jcr2spi/pom.xml URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/pom.xml?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr2spi/pom.xml (original) +++ jackrabbit/trunk/jackrabbit-jcr2spi/pom.xml Fri Mar 13 13:37:44 2009 @@ -88,6 +88,13 @@ jackrabbit-jcr-commons 1.6-SNAPSHOT + + + org.apache.jackrabbit + jackrabbit-api + 1.6-SNAPSHOT + + org.slf4j slf4j-api Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java (original) +++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java Fri Mar 13 13:37:44 2009 @@ -1090,10 +1090,14 @@ * @see Node#lock(boolean, boolean) */ public Lock lock(boolean isDeep, boolean isSessionScoped) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException { + return lock(isDeep, isSessionScoped, Long.MAX_VALUE, null); + } + + public Lock lock(boolean isDeep, boolean isSessionScoped, long timeoutHint, String ownerHint) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, InvalidItemStateException, RepositoryException { checkIsLockable(); checkHasPendingChanges(); - return session.getLockManager().lock(getNodeState(), isDeep, isSessionScoped); + return session.getLockManager().lock(getNodeState(), isDeep, isSessionScoped, timeoutHint, ownerHint); } /** Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java (original) +++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceImpl.java Fri Mar 13 13:37:44 2009 @@ -493,7 +493,7 @@ * @return a new LockManager instance. */ protected LockManager createLockManager(WorkspaceManager wspManager, ItemManager itemManager) { - LockManager lMgr = new LockManagerImpl(wspManager, itemManager, session.getCacheBehaviour()); + LockManager lMgr = new LockManagerImpl(wspManager, itemManager, session.getCacheBehaviour(), getPathResolver()); session.addListener((LockManagerImpl) lMgr); return lMgr; } Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java (original) +++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java Fri Mar 13 13:37:44 2009 @@ -946,7 +946,7 @@ * @see OperationVisitor#visit(LockOperation) */ public void visit(LockOperation operation) throws AccessDeniedException, InvalidItemStateException, UnsupportedRepositoryOperationException, LockException, RepositoryException { - LockInfo lInfo = service.lock(sessionInfo, operation.getNodeId(), operation.isDeep(), operation.isSessionScoped()); + LockInfo lInfo = service.lock(sessionInfo, operation.getNodeId(), operation.isDeep(), operation.isSessionScoped(), operation.getTimeoutHint(), operation.getOwnerHint()); operation.setLockInfo(lInfo); } Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/DefaultLockManager.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/DefaultLockManager.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/DefaultLockManager.java (original) +++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/DefaultLockManager.java Fri Mar 13 13:37:44 2009 @@ -36,6 +36,10 @@ throw new UnsupportedRepositoryOperationException("Locking ist not supported by this repository."); } + public Lock lock(NodeState nodeState, boolean isDeep, boolean isSessionScoped, long timeoutHint, String ownerHint) throws LockException, RepositoryException { + throw new UnsupportedRepositoryOperationException("Locking ist not supported by this repository."); + } + public void unlock(NodeState nodeState) throws LockException, RepositoryException { throw new UnsupportedRepositoryOperationException("Locking ist not supported by this repository."); } Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManager.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManager.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManager.java (original) +++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManager.java Fri Mar 13 13:37:44 2009 @@ -44,6 +44,24 @@ throws LockException, RepositoryException; /** + * Lock a node. Checks whether the node is not locked and then + * returns a lock object for this node. + * + * @param nodeState + * @param isDeep whether the lock applies to this node only + * @param isSessionScoped whether the lock is session scoped + * @param timeoutHint optional timeout hint. + * @param ownerHint optional String defining the lock owner info to be + * displayed. + * @return lock object + * @throws LockException if this node already is locked, or some descendant + * node is locked and isDeep is true + * @see javax.jcr.Node#lock + */ + Lock lock(NodeState nodeState, boolean isDeep, boolean isSessionScoped, long timeoutHint, String ownerHint) + throws LockException, RepositoryException; + + /** * Removes the lock on a node. * * @param nodeState @@ -74,6 +92,7 @@ * @return true if this node is locked either as a result * of a lock held by this node or by a deep lock on a node above this * node; otherwise returns false + * @throws RepositoryException If an error occurs. * @see javax.jcr.Node#isLocked */ boolean isLocked(NodeState nodeState) throws RepositoryException; @@ -93,7 +112,8 @@ /** * - * @return + * @return The lock tokens associated with the Session this + * lock manager has been created for. */ public String[] getLockTokens(); Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManagerImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManagerImpl.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManagerImpl.java (original) +++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/lock/LockManagerImpl.java Fri Mar 13 13:37:44 2009 @@ -19,6 +19,7 @@ import org.apache.jackrabbit.jcr2spi.ItemManager; import org.apache.jackrabbit.jcr2spi.SessionListener; import org.apache.jackrabbit.jcr2spi.WorkspaceManager; +import org.apache.jackrabbit.jcr2spi.NodeImpl; import org.apache.jackrabbit.jcr2spi.config.CacheBehaviour; import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry; import org.apache.jackrabbit.jcr2spi.operation.LockOperation; @@ -33,6 +34,7 @@ import org.apache.jackrabbit.spi.LockInfo; import org.apache.jackrabbit.spi.NodeId; import org.apache.jackrabbit.spi.commons.name.NameConstants; +import org.apache.jackrabbit.spi.commons.conversion.PathResolver; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,15 +48,19 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Date; /** * LockManagerImpl... * TODO: TOBEFIXED. Lock objects obtained through this mgr are not informed if another session is or becomes lock-holder and removes the lock again. */ -public class LockManagerImpl implements LockManager, SessionListener { +public class LockManagerImpl implements LockManager, org.apache.jackrabbit.api.jsr283.lock.LockManager, SessionListener { private static Logger log = LoggerFactory.getLogger(LockManagerImpl.class); + private static final long TIMEOUT_EXPIRED = -1; + private static final long TIMEOUT_INFINITE = Long.MAX_VALUE; + /** * WorkspaceManager used to apply and release locks as well as to retrieve * Lock information for a given NodeState. @@ -63,6 +69,7 @@ private final WorkspaceManager wspManager; private final ItemManager itemManager; private final CacheBehaviour cacheBehaviour; + private final PathResolver resolver; /** * Map holding all locks that where created by this Session upon @@ -74,19 +81,69 @@ private final Map lockMap; public LockManagerImpl(WorkspaceManager wspManager, ItemManager itemManager, - CacheBehaviour cacheBehaviour) { + CacheBehaviour cacheBehaviour, PathResolver pathResolver) { this.wspManager = wspManager; this.itemManager = itemManager; this.cacheBehaviour = cacheBehaviour; + this.resolver = pathResolver; // use hard references in order to make sure, that entries refering // to locks created by the current session are not removed. lockMap = new HashMap(); } + //--------------------------------------------------------< LockManager >--- + /** + * @see org.apache.jackrabbit.api.jsr283.lock.LockManager#getLock(String) + */ + public org.apache.jackrabbit.api.jsr283.lock.Lock getLock(String absPath) throws LockException, RepositoryException { + Node n = itemManager.getNode(resolver.getQPath(absPath)); + return (org.apache.jackrabbit.api.jsr283.lock.Lock) n.getLock(); + } + + /** + * @see org.apache.jackrabbit.api.jsr283.lock.LockManager#isLocked(String) + */ + public boolean isLocked(String absPath) throws RepositoryException { + Node n = itemManager.getNode(resolver.getQPath(absPath)); + return n.isLocked(); + } + + /** + * @see org.apache.jackrabbit.api.jsr283.lock.LockManager#holdsLock(String) + */ + public boolean holdsLock(String absPath) throws RepositoryException { + Node n = itemManager.getNode(resolver.getQPath(absPath)); + return n.holdsLock(); + } + + /** + * @see org.apache.jackrabbit.api.jsr283.lock.LockManager#lock(String, boolean, boolean, long, String) + */ + public org.apache.jackrabbit.api.jsr283.lock.Lock lock(String absPath, boolean isDeep, boolean isSessionScoped, long timeoutHint, String ownerInfo) throws RepositoryException { + Node n = itemManager.getNode(resolver.getQPath(absPath)); + return (org.apache.jackrabbit.api.jsr283.lock.Lock) ((NodeImpl) n).lock(isDeep, isSessionScoped, timeoutHint, ownerInfo); + } + + /** + * @see org.apache.jackrabbit.api.jsr283.lock.LockManager#unlock(String) + */ + public void unlock(String absPath) throws LockException, RepositoryException { + Node n = itemManager.getNode(resolver.getQPath(absPath)); + n.unlock(); + } + + //---------------------< org.apache.jackrabbit.jcr2spi.lock.LockManager >--- /** * @see LockManager#lock(NodeState,boolean,boolean) */ public Lock lock(NodeState nodeState, boolean isDeep, boolean isSessionScoped) throws LockException, RepositoryException { + return lock(nodeState, isDeep, isSessionScoped, Long.MAX_VALUE, null); + } + + /** + * @see LockManager#lock(NodeState,boolean,boolean,long,String) + */ + public Lock lock(NodeState nodeState, boolean isDeep, boolean isSessionScoped, long timeoutHint, String ownerHint) throws RepositoryException { // retrieve node first Node lhNode; // NOTE: Node must be retrieved from the given NodeState and not from @@ -99,7 +156,7 @@ } // execute the operation - LockOperation op = LockOperation.create(nodeState, isDeep, isSessionScoped); + LockOperation op = LockOperation.create(nodeState, isDeep, isSessionScoped, timeoutHint, ownerHint); wspManager.execute(op); Lock lock = new LockImpl(new LockState(nodeState, op.getLockInfo()), lhNode); @@ -169,12 +226,13 @@ } LockImpl l = getLockImpl(nodeState, true); - if (l != null && l.getLockToken() == null) { + if (l != null && !l.isLockOwningSession()) { // lock is present and token is null -> session is not lock-holder. throw new LockException("Node with id '" + nodeState + "' is locked."); } // else: state is not locked at all || session is lock-holder } + //--------< LockManager, org.apache.jackrabbit.jcr2spi.lock.LockManager >--- /** * Returns the lock tokens present on the SessionInfo this * manager has been created with. @@ -245,7 +303,7 @@ for (int i = 0; i < lhStates.length; i++) { NodeState nState = lhStates[i]; LockImpl l = (LockImpl) lockMap.get(nState); - if (l.isSessionScoped() && l.getLockToken() != null) { + if (l.isSessionScoped() && l.isLockOwningSession()) { try { unlock(nState); } catch (RepositoryException e) { @@ -325,7 +383,7 @@ } else { NodeEntry lockedEntry = wspManager.getHierarchyManager().getNodeEntry(lockNodeId); try { - lockHoldingState = ((NodeEntry) lockedEntry).getNodeState(); + lockHoldingState = lockedEntry.getNodeState(); } catch (RepositoryException e) { log.warn("Cannot build LockState"); throw new RepositoryException("Cannot build LockState", e); @@ -382,7 +440,7 @@ lState = buildLockState(lockHoldingState); } } else { - // need correct information about lock status -> retrieve lockInfo + // need precise information about lock status -> retrieve lockInfo // from the persistent layer. lState = buildLockState(nState); } @@ -393,7 +451,7 @@ // may fail if the session does not have permission to see this node. LockImpl lock = getLockFromMap(lState.lockHoldingState); if (lock != null) { - lock.lockState.lockInfo = lState.lockInfo; + lock.lockState.setLockInfo(lState.lockInfo); } else { Item lockHoldingNode = itemManager.getItem(lState.lockHoldingState.getHierarchyEntry()); lock = new LockImpl(lState, (Node)lockHoldingNode); @@ -459,10 +517,11 @@ private LockInfo lockInfo; private boolean isLive = true; + private long expiration = TIMEOUT_INFINITE; private LockState(NodeState lockHoldingState, LockInfo lockInfo) { this.lockHoldingState = lockHoldingState; - this.lockInfo = lockInfo; + setLockInfo(lockInfo); } private void refresh() throws RepositoryException { @@ -507,6 +566,52 @@ } } + private void setLockInfo(LockInfo lockInfo) { + this.lockInfo = lockInfo; + long seconds = lockInfo.getSecondsRemaining(); + if (seconds <= TIMEOUT_EXPIRED) { + expiration = TIMEOUT_EXPIRED; + isLive = false; + } else if (seconds < TIMEOUT_INFINITE) { + // calculate timeout + expiration = new Date().getTime()/1000 + lockInfo.getSecondsRemaining(); + } else { + expiration = TIMEOUT_INFINITE; + } + } + + /** + * @return true if the lock is still alive. + */ + private boolean isLive() { + if (isLive) { + isLive = getSecondsRemaining() > 0; + } + return isLive; + } + + /** + * @return the number of seconds until the lock's timeout is reached, + * {@link Long#MAX_VALUE} if timeout is infinite or undefined and + * a negative value if timeout has already been reached or the lock + * has been otherwise released. + */ + private long getSecondsRemaining() { + if (!isLive) { + return TIMEOUT_EXPIRED; + } else if (expiration == TIMEOUT_INFINITE) { + return expiration; + } else { + long seconds = expiration - new Date().getTime()/1000; + if (seconds <= 0) { + isLive = false; + return TIMEOUT_EXPIRED; + } else { + return seconds; + } + } + } + /** * Release this lock by removing from the lock map and unregistering * it from event listening @@ -524,9 +629,9 @@ * unlocking, it is released an its status is reset accordingly. */ private void unlocked() { - if (isLive) { - isLive = false; + if (isLive()) { release(); + isLive = false; } } @@ -573,7 +678,7 @@ * @see ItemStateLifeCycleListener#statusChanged(ItemState, int) */ public void statusChanged(ItemState state, int previousStatus) { - if (!isLive) { + if (!isLive()) { // since we only monitor the removal of the lock (by means // of deletion of the jcr:lockIsDeep property, we are not interested // if the lock is not active any more. @@ -597,7 +702,7 @@ /** * Inner class implementing the {@link Lock} interface. */ - private class LockImpl implements Lock, LockTokenListener { + private class LockImpl implements org.apache.jackrabbit.api.jsr283.lock.Lock, LockTokenListener { private final LockState lockState; private final Node node; @@ -618,7 +723,7 @@ if (cacheBehaviour == CacheBehaviour.OBSERVATION) { lockMap.put(lockState.lockHoldingState, this); lockState.startListening(); - } else if (isHoldBySession()) { + } else if (lockState.lockInfo.isLockOwner()) { lockMap.put(lockState.lockHoldingState, this); lockState.startListening(); // open-scoped locks: the map entry and the lock information @@ -658,6 +763,12 @@ * @see Lock#getLockToken() */ public String getLockToken() { + // shortcut for jsr 283 session scoped locks: they never expose + // the lock token to the API users. + if (isSessionScoped()) { + return null; + } + updateLockInfo(); return getLockInfo().getLockToken(); } @@ -667,7 +778,7 @@ */ public boolean isLive() throws RepositoryException { updateLockInfo(); - return lockState.isLive; + return lockState.isLive(); } /** @@ -685,7 +796,7 @@ throw new LockException("Lock is not alive any more."); } - if (getLockToken() == null) { + if (!isLockOwningSession()) { // shortcut, since lock is always updated if the session became // lock-holder of a foreign lock. throw new LockException("Session does not hold lock."); @@ -694,6 +805,21 @@ } } + /** + * @see org.apache.jackrabbit.api.jsr283.lock.Lock#getSecondsRemaining() + */ + public long getSecondsRemaining() throws RepositoryException { + updateLockInfo(); + return lockState.getSecondsRemaining(); + } + + /** + * @see org.apache.jackrabbit.api.jsr283.lock.Lock#isLockOwningSession() + */ + public boolean isLockOwningSession(){ + return lockState.lockInfo.isLockOwner(); + } + //----------------------------------------------< LockTokenListener >--- /** * A lock token as been added to the current Session. If this Lock @@ -706,8 +832,10 @@ * @see LockTokenListener#lockTokenAdded(String) */ public void lockTokenAdded(String lockToken) throws RepositoryException { - if (getLockToken() == null) { - // could be that this affects this lock and session became + if (!isSessionScoped() && !isLockOwningSession()) { + // unless this lock is session-scoped (token is never transfered) + // and the session isn't the owner yet (token already present), + // it could be that this affects this lock and session became // lock holder -> releoad info to assert. lockState.reloadLockInfo(); } @@ -721,7 +849,8 @@ */ public void lockTokenRemoved(String lockToken) throws RepositoryException { // reload lock info, if session gave away its lock-holder status - // for this lock. + // for this lock. this will never be true for session-scoped locks + // that are not exposed (thus cannot be removed). if (lockToken.equals(getLockToken())) { lockState.reloadLockInfo(); } @@ -749,12 +878,6 @@ } } // else: nothing to do. } - /** - * @return true if this lock is hold by this session. false otherwise. - */ - private boolean isHoldBySession() { - return lockState.lockInfo.getLockToken() != null; - } } //--------------------------------------------------< LockTokenListener >--- Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/LockOperation.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/LockOperation.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/LockOperation.java (original) +++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/LockOperation.java Fri Mar 13 13:37:44 2009 @@ -36,13 +36,18 @@ private final NodeState nodeState; private final boolean isDeep; private final boolean isSessionScoped; + private final long timeoutHint; + private final String ownerHint; private LockInfo lockInfo = null; - private LockOperation(NodeState nodeState, boolean isDeep, boolean isSessionScoped) { + private LockOperation(NodeState nodeState, boolean isDeep, boolean isSessionScoped, + long timeoutHint, String ownerHint) { this.nodeState = nodeState; this.isDeep = isDeep; this.isSessionScoped = isSessionScoped; + this.timeoutHint = timeoutHint; + this.ownerHint = ownerHint; // NOTE: affected-states only needed for transient modifications } @@ -81,6 +86,14 @@ return isSessionScoped; } + public long getTimeoutHint() { + return timeoutHint; + } + + public String getOwnerHint() { + return ownerHint; + } + public void setLockInfo(LockInfo lockInfo) { if (lockInfo == null) { throw new IllegalArgumentException("IdIterator must not be null."); @@ -105,7 +118,11 @@ * @return */ public static LockOperation create(NodeState nodeState, boolean isDeep, boolean isSessionScoped) { - LockOperation lck = new LockOperation(nodeState, isDeep, isSessionScoped); + return create(nodeState, isDeep, isSessionScoped, Long.MAX_VALUE, null); + } + + public static LockOperation create(NodeState nodeState, boolean isDeep, boolean isSessionScoped, long timeoutHint, String ownerHint) { + LockOperation lck = new LockOperation(nodeState, isDeep, isSessionScoped, timeoutHint, ownerHint); return lck; } } \ No newline at end of file Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/lock/AbstractLockTest.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/lock/AbstractLockTest.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/lock/AbstractLockTest.java (original) +++ jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/lock/AbstractLockTest.java Fri Mar 13 13:37:44 2009 @@ -229,6 +229,7 @@ assertTrue("Child node locked after save", childNode.isLocked()); } finally { + session.refresh(false); childNode.unlock(); } } @@ -363,4 +364,4 @@ } } } -} \ No newline at end of file +} Modified: jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/LockInfoImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/LockInfoImpl.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/LockInfoImpl.java (original) +++ jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/LockInfoImpl.java Fri Mar 13 13:37:44 2009 @@ -48,6 +48,16 @@ private final boolean isSessionScoped; /** + * Number of seconds until the lock time outs. + */ + private final long secondsRemaining; + + /** + * Flag indicating if the session is lock owner or not. + */ + private final boolean isLockOwner; + + /** * The NodeId of the locked node. */ private final NodeId nodeId; @@ -63,10 +73,31 @@ */ public LockInfoImpl(String lockToken, String lockOwner, boolean isDeep, boolean isSessionScoped, NodeId nodeId) { + this(lockToken, lockOwner, isDeep, isSessionScoped, Long.MAX_VALUE, lockToken != null, nodeId); + } + + /** + * Creates a new lock info for the given lock info. + * + * @param lockToken the lock token + * @param lockOwner the lock owner + * @param isDeep whether this lock is deep or not + * @param isSessionScoped whether this lock is session scoped or not + * @param secondsRemaining Number of seconds until the lock timeout is reached. + * @param isLockOwner true if the calling session is lock + * owner; false otherwise. + * @param nodeId the node id of the locked node. + * @since JCR 2.0 + */ + public LockInfoImpl(String lockToken, String lockOwner, boolean isDeep, + boolean isSessionScoped, long secondsRemaining, + boolean isLockOwner, NodeId nodeId) { this.lockToken = lockToken; this.lockOwner = lockOwner; this.isDeep = isDeep; this.isSessionScoped = isSessionScoped; + this.secondsRemaining = secondsRemaining; + this.isLockOwner = isLockOwner; this.nodeId = nodeId; } @@ -101,7 +132,21 @@ /** * {@inheritDoc} */ + public long getSecondsRemaining() { + return secondsRemaining; + } + + /** + * {@inheritDoc} + */ + public boolean isLockOwner() { + return isLockOwner; + } + + /** + * {@inheritDoc} + */ public NodeId getNodeId() { return nodeId; } -} +} \ No newline at end of file Modified: jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/LockInfo.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/LockInfo.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/LockInfo.java (original) +++ jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/LockInfo.java Fri Mar 13 13:37:44 2009 @@ -26,8 +26,8 @@ public interface LockInfo { /** - * Returns the lock token for this lock if it is hold by the requesting - * session or null otherwise. + * Returns the lock token for this lock or null if the token + * should not be exposed to the API user. * * @return lock token or null * @see javax.jcr.lock.Lock#getLockToken() @@ -35,7 +35,8 @@ public String getLockToken(); /** - * Returns the user ID of the user who owns this lock. + * Returns the user ID of the user who owns this lock or some user defined + * information about the lock owner. * * @return user ID of the user who owns this lock. * @see javax.jcr.lock.Lock#getLockOwner() @@ -57,6 +58,28 @@ * @see javax.jcr.lock.Lock#isSessionScoped() */ public boolean isSessionScoped(); + + /** + * Returns the seconds remaining until the lock times out or + * ({@link Long#MAX_VALUE} if the timeout is unknown or infinite). + * + * @return number of seconds until the lock times out. + * @see javax.jcr.lock.Lock#getSecondsRemaining() + * @since JCR 2.0 + */ + public long getSecondsRemaining(); + + /** + * Returns true if the SessionInfo used to + * retrieve this LockInfo is the lock holder and thus enabled + * to refresh or release the lock. + * + * @return true if the SessionInfo used to + * retrieve this LockInfo is the lock holder. + * @see javax.jcr.lock.Lock#isLockOwningSession() + * @since JCR 2.0 + */ + public boolean isLockOwner(); /** * Returns the NodeId of the lock-holding Node. Modified: jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java (original) +++ jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java Fri Mar 13 13:37:44 2009 @@ -511,6 +511,30 @@ public LockInfo lock(SessionInfo sessionInfo, NodeId nodeId, boolean deep, boolean sessionScoped) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, RepositoryException; /** + * Create a lock on the Node identified by the given id. + * + * @param sessionInfo + * @param nodeId + * @param deep + * @param sessionScoped + * @param timeoutHint long indicating the desired lock timeout in seconds. + * The implementation is free to ignore the hint. + * @param ownerHint String indicating the desired lockOwner info. The + * implementation is free to ignore the hint. + * @return The LockInfo associated with the new lock + * that has been created. + * @throws javax.jcr.UnsupportedRepositoryOperationException If this SPI + * implementation does not support locking at all. + * @throws javax.jcr.lock.LockException If the Node identified by the given + * id cannot be locked due to an existing lock or due to missing mixin type. + * @throws javax.jcr.AccessDeniedException + * @throws javax.jcr.RepositoryException If another error occurs. + * @see javax.jcr.lock.LockManager#lock(String, boolean, boolean, long, String) + * @since JCR 2.0 + */ + public LockInfo lock(SessionInfo sessionInfo, NodeId nodeId, boolean deep, boolean sessionScoped, long timeoutHint, String ownerHint) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, RepositoryException; + + /** * Explicit refresh of an existing lock. Existing locks should be refreshed * implicitely with all read and write methods listed here. * Modified: jackrabbit/trunk/jackrabbit-spi2jcr/pom.xml URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2jcr/pom.xml?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-spi2jcr/pom.xml (original) +++ jackrabbit/trunk/jackrabbit-spi2jcr/pom.xml Fri Mar 13 13:37:44 2009 @@ -116,6 +116,13 @@ jackrabbit-jcr-commons 1.6-SNAPSHOT + + + org.apache.jackrabbit + jackrabbit-api + 1.6-SNAPSHOT + + org.slf4j slf4j-api Modified: jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/LockInfoImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/LockInfoImpl.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/LockInfoImpl.java (original) +++ jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/LockInfoImpl.java Fri Mar 13 13:37:44 2009 @@ -17,6 +17,7 @@ package org.apache.jackrabbit.spi2jcr; import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver; +import org.apache.jackrabbit.spi.LockInfo; import javax.jcr.RepositoryException; import javax.jcr.lock.Lock; @@ -28,21 +29,49 @@ class LockInfoImpl extends org.apache.jackrabbit.spi.commons.LockInfoImpl { /** - * Creates a new lock info for the given locked node. + * Creates a new lock info for the given JCR lock object. * - * @param lock the lock. - * @param idFactory the id factory. - * @param resolver - * @throws RepositoryException if an error occurs while reading from - * node or if node is - * not locked. + * @param lock the lock. + * @param idFactory the id factory. + * @param resolver the name and path resolver. + * @throws RepositoryException if an error occurs while the node from the + * given lock or while creating the node id. */ - public LockInfoImpl(Lock lock, - IdFactoryImpl idFactory, - NamePathResolver resolver) - throws RepositoryException { + private LockInfoImpl(Lock lock, IdFactoryImpl idFactory, + NamePathResolver resolver) throws RepositoryException { super(lock.getLockToken(), lock.getLockOwner(), lock.isDeep(), lock.isSessionScoped(), idFactory.createNodeId(lock.getNode(), resolver)); } -} + + /** + * Creates a new lock info for the given JCR lock object. + * + * @param lock the JCR lock. + * @param idFactory the id factory. + * @param resolver the name and path resolver. + * @throws RepositoryException If an error occurs while creating the info. + * @since JCR 2.0 + */ + private LockInfoImpl(org.apache.jackrabbit.api.jsr283.lock.Lock lock, + IdFactoryImpl idFactory, NamePathResolver resolver) throws RepositoryException { + super(lock.getLockToken(), lock.getLockOwner(), lock.isDeep(), lock.isSessionScoped(), lock.getSecondsRemaining(), lock.isLockOwningSession(), idFactory.createNodeId(lock.getNode(), resolver)); + } + + /** + * Create a new LockInfo from the given parameters. + * + * @param lock the JCR lock. + * @param idFactory the id factory. + * @param resolver the name and path resolver. + * @return a new LockInfo + * @throws RepositoryException If an error occurs while creating the info. + */ + public static LockInfo createLockInfo(Lock lock, IdFactoryImpl idFactory, NamePathResolver resolver) throws RepositoryException { + if (lock instanceof org.apache.jackrabbit.api.jsr283.lock.Lock) { + return new LockInfoImpl((org.apache.jackrabbit.api.jsr283.lock.Lock) lock, idFactory, resolver); + } else { + return new LockInfoImpl(lock, idFactory, resolver); + } + } +} \ No newline at end of file Modified: jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java?rev=753244&r1=753243&r2=753244&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java (original) +++ jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java Fri Mar 13 13:37:44 2009 @@ -545,7 +545,7 @@ SessionInfoImpl sInfo = getSessionInfoImpl(sessionInfo); try { Lock lock = getNode(nodeId, sInfo).getLock(); - return new LockInfoImpl(lock, idFactory, sInfo.getNamePathResolver()); + return LockInfoImpl.createLockInfo(lock, idFactory, sInfo.getNamePathResolver()); } catch (LockException e) { // no lock present on this node. return null; @@ -565,7 +565,28 @@ public Object run() throws RepositoryException { Node n = getNode(nodeId, sInfo); Lock lock = n.lock(deep, sessionScoped); - return new LockInfoImpl(lock, idFactory, sInfo.getNamePathResolver()); + return LockInfoImpl.createLockInfo(lock, idFactory, sInfo.getNamePathResolver()); + } + }, sInfo); + } + + /** + * {@inheritDoc} + */ + public LockInfo lock(SessionInfo sessionInfo, final NodeId nodeId, final boolean deep, final boolean sessionScoped, final long timeoutHint, final String ownerHint) throws UnsupportedRepositoryOperationException, LockException, AccessDeniedException, RepositoryException { + final SessionInfoImpl sInfo = getSessionInfoImpl(sessionInfo); + return (LockInfo) executeWithLocalEvents(new Callable() { + public Object run() throws RepositoryException { + Node n = getNode(nodeId, sInfo); + Lock lock; + // TODO: remove check once jsr283 is released + if (sInfo.getSession() instanceof org.apache.jackrabbit.api.jsr283.Session) { + org.apache.jackrabbit.api.jsr283.lock.LockManager lMgr = (((org.apache.jackrabbit.api.jsr283.Workspace) sInfo.getSession().getWorkspace()).getLockManager()); + lock = lMgr.lock(n.getPath(), deep, sessionScoped, timeoutHint, ownerHint); + } else { + lock = n.lock(deep, sessionScoped); + } + return LockInfoImpl.createLockInfo(lock, idFactory, sInfo.getNamePathResolver()); } }, sInfo); }