[exo-jcr-commits] exo-jcr SVN: r723 - in jcr/branches/1.12.0-JBC/component/core/src: main/java/org/exoplatform/services/jcr/impl and 5 other directories.
do-not-reply at jboss.org
do-not-reply at jboss.org
Tue Nov 17 11:18:15 EST 2009
Author: nzamosenchuk
Date: 2009-11-17 11:18:15 -0500 (Tue, 17 Nov 2009)
New Revision: 723
Added:
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/SessionLockManager.java
Removed:
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockManager.java
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockManagerImpl.java
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockRemover.java
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/LockCacheLoader.java
jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/LockCacheLoaderTest.java
jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/TesterLockManagerImpl.java
Modified:
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/core/lock/ExtendedLock.java
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockData.java
jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockImpl.java
jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockImpl.java
Log:
EXOJCR-243: Initial implementation of new lock manager: Created class: SessionLockManager, updated NodeImpl and SessionImpl to use it, reworked LockData and LockImpl. Removed LockCacheLoaders and it's tests, old LockManager and LockRemover*. Needed to implement: Lock removing on session logout, lock removing by time out. Fill JBossCacheWorkspaceDataManager with functionality.
Modified: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/core/lock/ExtendedLock.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/core/lock/ExtendedLock.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/core/lock/ExtendedLock.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -18,6 +18,8 @@
*/
package org.exoplatform.services.jcr.core.lock;
+import org.exoplatform.services.jcr.impl.core.lock.LockData;
+
import javax.jcr.lock.Lock;
/**
@@ -31,4 +33,9 @@
* @return The time to death in sec
*/
public long getTimeToDeath();
+
+ /**
+ * @return LockData instance
+ */
+ public LockData getLockData();
}
Modified: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/RepositoryContainer.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -40,7 +40,6 @@
import org.exoplatform.services.jcr.impl.core.SessionRegistry;
import org.exoplatform.services.jcr.impl.core.WorkspaceInitializer;
import org.exoplatform.services.jcr.impl.core.access.DefaultAccessManagerImpl;
-import org.exoplatform.services.jcr.impl.core.lock.LockManagerImpl;
import org.exoplatform.services.jcr.impl.core.nodetype.NodeTypeDataManagerImpl;
import org.exoplatform.services.jcr.impl.core.nodetype.NodeTypeManagerImpl;
import org.exoplatform.services.jcr.impl.core.nodetype.registration.JcrNodeTypeDataPersister;
@@ -259,23 +258,6 @@
workspaceContainer.registerComponentImplementation(LocalWorkspaceDataManagerStub.class);
workspaceContainer.registerComponentImplementation(ObservationManagerRegistry.class);
- // Lock manager and Lock persister is a optional parameters
- if (wsConfig.getLockManager() != null && wsConfig.getLockManager().getPersister() != null)
- {
- try
- {
- Class<?> lockPersister = Class.forName(wsConfig.getLockManager().getPersister().getType());
- workspaceContainer.registerComponentImplementation(lockPersister);
- }
- catch (ClassNotFoundException e)
- {
- throw new RepositoryConfigurationException("Class not found for workspace lock persister "
- + wsConfig.getLockManager().getPersister().getType() + ", container " + wsConfig.getUniqueName()
- + " : " + e);
- }
- }
- workspaceContainer.registerComponentImplementation(LockManagerImpl.class);
-
// Query handler
if (wsConfig.getQueryHandler() != null)
{
Modified: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/NodeImpl.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -29,6 +29,7 @@
import org.exoplatform.services.jcr.core.nodetype.NodeTypeDataManager;
import org.exoplatform.services.jcr.core.nodetype.PropertyDefinitionData;
import org.exoplatform.services.jcr.dataflow.ItemState;
+import org.exoplatform.services.jcr.dataflow.LockPlainChangesLogImpl;
import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
import org.exoplatform.services.jcr.dataflow.PlainChangesLogImpl;
import org.exoplatform.services.jcr.datamodel.Identifier;
@@ -895,7 +896,7 @@
checkValid();
- LockImpl lock = session.getLockManager().getLock(this);
+ LockImpl lock = session.getLockManager().getLock((NodeData)this.getData());
if (lock == null)
throw new LockException("Lock not found " + getPath());
return lock;
@@ -1279,7 +1280,6 @@
*/
public boolean isLocked() throws RepositoryException
{
-
checkValid();
return session.getLockManager().isLocked((NodeData)this.getData());
}
@@ -1359,7 +1359,7 @@
public Lock lock(boolean isDeep, boolean isSessionScoped) throws UnsupportedRepositoryOperationException,
LockException, AccessDeniedException, RepositoryException
{
-
+ // checks
checkValid();
if (!isNodeType(Constants.MIX_LOCKABLE))
@@ -1368,25 +1368,14 @@
if (dataManager.hasPendingChanges(getInternalPath()))
throw new InvalidItemStateException("Node has pending unsaved changes " + getPath());
- Lock newLock = session.getLockManager().addPendingLock(this, isDeep, isSessionScoped, -1);
+ if (session.getLockManager().isLocked((NodeData)this.getData()))
+ {
+ throw new LockException("Node is already locked itself or due to deep lock of parent, ");
+ }
+ Lock lock = session.getLockManager().lock((NodeData)data, isDeep, isSessionScoped, -1);
- PlainChangesLog changesLog =
- new PlainChangesLogImpl(new ArrayList<ItemState>(), session.getId(), ExtendedEvent.LOCK);
-
- PropertyData propData =
- TransientPropertyData.createPropertyData(nodeData(), Constants.JCR_LOCKOWNER, PropertyType.STRING, false,
- new TransientValueData(session.getUserID()));
- changesLog.add(ItemState.createAddedState(propData));
-
- propData =
- TransientPropertyData.createPropertyData(nodeData(), Constants.JCR_LOCKISDEEP, PropertyType.BOOLEAN, false,
- new TransientValueData(isDeep));
- changesLog.add(ItemState.createAddedState(propData));
-
- dataManager.getTransactManager().save(changesLog);
-
session.getActionHandler().postLock(this);
- return newLock;
+ return lock;
}
@@ -1396,6 +1385,7 @@
public Lock lock(boolean isDeep, long timeOut) throws UnsupportedRepositoryOperationException, LockException,
AccessDeniedException, RepositoryException
{
+ // checks
checkValid();
if (!isNodeType(Constants.MIX_LOCKABLE))
@@ -1404,25 +1394,15 @@
if (dataManager.hasPendingChanges(getInternalPath()))
throw new InvalidItemStateException("Node has pending unsaved changes " + getPath());
- Lock newLock = session.getLockManager().addPendingLock(this, isDeep, false, timeOut);
+ if (session.getLockManager().isLocked((NodeData)this.getData()))
+ {
+ throw new LockException("Node is already locked itself or due to deep lock of parent, ");
+ }
- PlainChangesLog changesLog =
- new PlainChangesLogImpl(new ArrayList<ItemState>(), session.getId(), ExtendedEvent.LOCK);
+ Lock lock = session.getLockManager().lock((NodeData)data, isDeep, false, timeOut);
- PropertyData propData =
- TransientPropertyData.createPropertyData(nodeData(), Constants.JCR_LOCKOWNER, PropertyType.STRING, false,
- new TransientValueData(session.getUserID()));
- changesLog.add(ItemState.createAddedState(propData));
-
- propData =
- TransientPropertyData.createPropertyData(nodeData(), Constants.JCR_LOCKISDEEP, PropertyType.BOOLEAN, false,
- new TransientValueData(isDeep));
- changesLog.add(ItemState.createAddedState(propData));
-
- dataManager.getTransactManager().save(changesLog);
-
session.getActionHandler().postLock(this);
- return newLock;
+ return lock;
}
@@ -2023,13 +2003,13 @@
if (!session.getLockManager().holdsLock((NodeData)this.getData()))
throw new LockException("The node not locked " + getPath());
- if (!session.getLockManager().isLockHolder(this))
+ if (!session.getLockManager().isLockHolder((NodeData)this.getData()))
throw new LockException("There are no permission to unlock the node " + getPath());
if (dataManager.hasPendingChanges(getInternalPath()))
throw new InvalidItemStateException("Node has pending unsaved changes " + getPath());
- doUnlock();
+ session.getLockManager().unlock((NodeData)data);
session.getActionHandler().postUnlock(this);
}
@@ -2167,8 +2147,8 @@
boolean checkLocking() throws RepositoryException
{
- return (!isLocked() || session.getLockManager().isLockHolder(this) || session.getUserID().equals(
- SystemIdentity.SYSTEM));
+ return (!isLocked() || session.getLockManager().isLockHolder((NodeData)this.getData()) || session.getUserID()
+ .equals(SystemIdentity.SYSTEM));
}
protected void doOrderBefore(QPath srcPath, QPath destPath) throws RepositoryException
@@ -2330,28 +2310,6 @@
dataManager.getChangesLog().addAll(changes);
}
- /**
- * Remove mix:lockable properties.
- *
- * @throws RepositoryException if error occurs
- */
- protected void doUnlock() throws RepositoryException
- {
-
- PlainChangesLog changesLog =
- new PlainChangesLogImpl(new ArrayList<ItemState>(), session.getId(), ExtendedEvent.UNLOCK);
-
- ItemData lockOwner = dataManager.getItemData(nodeData(), new QPathEntry(Constants.JCR_LOCKOWNER, 0));
-
- changesLog.add(ItemState.createDeletedState(lockOwner));
-
- ItemData lockIsDeep = dataManager.getItemData(nodeData(), new QPathEntry(Constants.JCR_LOCKISDEEP, 0));
-
- changesLog.add(ItemState.createDeletedState(lockIsDeep));
-
- dataManager.getTransactManager().save(changesLog);
- }
-
protected NodeData nodeData()
{
return (NodeData)data;
@@ -2372,11 +2330,11 @@
{
// locked, should be unlocked
- if (!session.getLockManager().isLockHolder(this))
+ if (!session.getLockManager().isLockHolder((NodeData)this.getData()))
throw new LockException("There are no permission to unlock the node " + getPath());
// remove mix:lockable properties (as the node is locked)
- doUnlock();
+ session.getLockManager().unlock((NodeData)data);
}
}
Modified: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/SessionImpl.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -31,7 +31,7 @@
import org.exoplatform.services.jcr.datamodel.NodeData;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.impl.Constants;
-import org.exoplatform.services.jcr.impl.core.lock.LockManagerImpl;
+import org.exoplatform.services.jcr.impl.core.lock.SessionLockManager;
import org.exoplatform.services.jcr.impl.core.nodetype.NodeTypeImpl;
import org.exoplatform.services.jcr.impl.core.observation.ObservationManagerImpl;
import org.exoplatform.services.jcr.impl.core.observation.ObservationManagerRegistry;
@@ -118,7 +118,7 @@
private final LocationFactory systemLocationFactory;
- private final LockManagerImpl lockManager;
+ private final SessionLockManager sessionLockManager;
protected final String workspaceName;
@@ -152,7 +152,6 @@
this.systemLocationFactory = (LocationFactory)container.getComponentInstanceOfType(LocationFactory.class);
this.accessManager = (AccessManager)container.getComponentInstanceOfType(AccessManager.class);
- this.lockManager = (LockManagerImpl)container.getComponentInstanceOfType(LockManagerImpl.class);
WorkspaceEntry wsConfig = (WorkspaceEntry)container.getComponentInstanceOfType(WorkspaceEntry.class);
WorkspaceFileCleanerHolder cleanerHolder =
(WorkspaceFileCleanerHolder)container.getComponentInstanceOfType(WorkspaceFileCleanerHolder.class);
@@ -177,9 +176,12 @@
this.workspace = new WorkspaceImpl(workspaceName, container, this, observationManager);
+ // TODO: try to get lock time out from workspace configuration, as it was before
+ this.sessionLockManager = new SessionLockManager(this, SessionLockManager.DEFAULT_LOCK_TIMEOUT);
+
this.lifecycleListeners = new ArrayList<SessionLifecycleListener>();
this.registerLifecycleListener((ObservationManagerImpl)observationManager);
- this.registerLifecycleListener(lockManager);
+ this.registerLifecycleListener(sessionLockManager);
SessionActionCatalog catalog =
(SessionActionCatalog)container.getComponentInstanceOfType(SessionActionCatalog.class);
@@ -197,7 +199,7 @@
*/
public void addLockToken(String lt)
{
- getLockManager().addLockToken(getId(), lt);
+ sessionLockManager.addLockToken(lt);
}
/**
@@ -543,9 +545,9 @@
return locationFactory;
}
- public LockManagerImpl getLockManager()
+ public SessionLockManager getLockManager()
{
- return lockManager;
+ return sessionLockManager;
}
/**
@@ -553,7 +555,7 @@
*/
public String[] getLockTokens()
{
- return getLockManager().getLockTokens(getId());
+ return sessionLockManager.getLockTokens();
}
/**
@@ -901,7 +903,7 @@
*/
public void removeLockToken(String lt)
{
- getLockManager().removeLockToken(getId(), lt);
+ sessionLockManager.removeLockToken(lt);
}
/**
Modified: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockData.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockData.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockData.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -18,11 +18,6 @@
*/
package org.exoplatform.services.jcr.impl.core.lock;
-import org.exoplatform.services.jcr.access.SystemIdentity;
-
-import java.util.HashSet;
-import java.util.Set;
-
/**
* Created by The eXo Platform SAS.
*
@@ -49,15 +44,10 @@
private boolean live;
/**
- * List of session id's which holds a lock tokens.
- */
- private final Set<String> lockHolders = new HashSet<String>();
-
- /**
* A lock token is a string that uniquely identifies a particular lock and acts as a “key”
- * allowing a user to alter a locked node.
+ * allowing a user to alter a locked node. LockData stores only token hash.
*/
- private String lockToken;
+ private String tokenHash;
/**
* Identifier of locked node.
@@ -95,7 +85,7 @@
long timeOut)
{
this.nodeIdentifier = nodeIdentifier;
- this.lockToken = lockToken;
+ this.tokenHash = lockToken;
this.deep = deep;
this.sessionScoped = sessionScoped;
this.owner = owner;
@@ -104,15 +94,6 @@
this.birthday = System.currentTimeMillis() / 1000;
}
- /**
- * @param sessionId
- * @return
- */
- public boolean addLockHolder(String sessionId)
- {
- return lockHolders.add(sessionId);
- }
-
/*
* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
@@ -131,20 +112,11 @@
return false;
}
- public int getLockHolderSize()
+ public String getTokenHash()
{
- return lockHolders.size();
+ return tokenHash;
}
- public String getLockToken(String sessionId)
- {
- if (isLockHolder(sessionId))
- {
- return lockToken;
- }
- return null;
- }
-
/**
* @return the nodeIdentifier
*/
@@ -176,7 +148,7 @@
@Override
public int hashCode()
{
- return super.hashCode() + lockToken.hashCode();
+ return super.hashCode() + tokenHash.hashCode();
}
public boolean isDeep()
@@ -193,17 +165,8 @@
}
/**
- * @param sessionId
* @return
*/
- public boolean isLockHolder(String sessionId)
- {
- return lockHolders.contains(sessionId) || SystemIdentity.SYSTEM.equals(sessionId);
- }
-
- /**
- * @return
- */
public boolean isSessionScoped()
{
return sessionScoped;
@@ -218,15 +181,6 @@
}
/**
- * @param sessionId
- * @return
- */
- public boolean removeLockHolder(String sessionId)
- {
- return lockHolders.remove(sessionId);
- }
-
- /**
* @param the
* live to set
*/
@@ -236,31 +190,6 @@
}
/**
- * @param lockToken
- */
- public void setLockToken(String lockToken)
- {
- this.lockToken = lockToken;
- }
-
- /**
- * @param nodeIdentifier
- * the nodeIdentifier to set
- */
- public void setNodeIdentifier(String nodeIdentifier)
- {
- this.nodeIdentifier = nodeIdentifier;
- }
-
- /**
- * @param owner
- */
- public void setOwner(String owner)
- {
- this.owner = owner;
- }
-
- /**
* @return
*/
protected long getTimeOut()
Modified: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockImpl.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockImpl.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockImpl.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -38,27 +38,47 @@
private SessionImpl session;
- public LockImpl(SessionImpl session, LockData lockData)
+ // Token is not stored in lockData any more
+ private String token;
+
+ /**
+ * @param session
+ * @param lockData
+ */
+ public LockImpl(SessionImpl session, LockData lockData, String token)
{
this.lockData = lockData;
this.session = session;
+ this.token = token;
}
+ /**
+ * @see javax.jcr.lock.Lock#getLockOwner()
+ */
public String getLockOwner()
{
return lockData.getOwner();
}
+ /**
+ * @see javax.jcr.lock.Lock#getLockToken()
+ */
public String getLockToken()
{
- return lockData.getLockToken(session.getId());
+ return token;
}
+ /**
+ * @see javax.jcr.lock.Lock#isLive()
+ */
public boolean isLive()
{
return lockData.isLive();
}
+ /**
+ * @see javax.jcr.lock.Lock#refresh()
+ */
public void refresh() throws LockException, RepositoryException
{
if (!isLive())
@@ -66,6 +86,9 @@
lockData.refresh();
}
+ /**
+ * @see javax.jcr.lock.Lock#getNode()
+ */
public Node getNode()
{
try
@@ -74,29 +97,49 @@
}
catch (RepositoryException e)
{
- e.printStackTrace();
}
return null;
}
+ /**
+ * @see javax.jcr.lock.Lock#isDeep()
+ */
public boolean isDeep()
{
return lockData.isDeep();
}
+ /**
+ * @see javax.jcr.lock.Lock#isSessionScoped()
+ */
public boolean isSessionScoped()
{
return lockData.isSessionScoped();
}
+ /**
+ * @see org.exoplatform.services.jcr.core.lock.ExtendedLock#getTimeToDeath()
+ */
public long getTimeToDeath()
{
return lockData.getTimeToDeath();
}
+ /**
+ * @see org.exoplatform.services.jcr.core.lock.ExtendedLock#getLockData()
+ */
+ public LockData getLockData()
+ {
+ return lockData;
+ }
+
+ /**
+ * @param timeOut
+ */
protected void setTimeOut(long timeOut)
{
lockData.setTimeOut(timeOut);
}
+
}
Deleted: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockManager.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockManager.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockManager.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2009 eXo Platform SAS.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.exoplatform.services.jcr.impl.core.lock;
-
-import org.exoplatform.services.jcr.datamodel.NodeData;
-import org.exoplatform.services.jcr.impl.core.NodeImpl;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.lock.Lock;
-import javax.jcr.lock.LockException;
-
-/**
- * @author <a href="mailto:Sergey.Kabashnyuk at gmail.com">Sergey Kabashnyuk</a>
- * @version $Id$
- */
-public interface LockManager
-{
- /**
- * Invoked by a session to inform that a lock token has been added.
- *
- * @param session
- * session that has a added lock token
- * @param lt
- * added lock token
- */
- public void addLockToken(String sessionId, String lt);
-
- public Lock addPendingLock(NodeImpl node, boolean isDeep, boolean isSessionScoped, long timeOut)
- throws LockException, RepositoryException;
-
- /**
- * Returns the Lock object that applies to a node. This may be either a lock on this node itself
- * or a deep lock on a node above this node.
- *
- * @param node
- * node
- * @return lock object
- * @throws LockException
- * if this node is not locked
- * @see javax.jcr.Node#getLock
- */
- public LockImpl getLock(NodeImpl node) throws LockException, RepositoryException;
-
- /**
- * Return lock tokens enshrined by session
- *
- * @param sessionID
- * - Id of session.
- * @return array of lock tokens.
- */
- public String[] getLockTokens(String sessionID);
-
- /**
- * Returns <code>true</code> if the node given holds a lock; otherwise returns <code>false</code>.
- *
- * @param node
- * node
- * @return <code>true</code> if the node given holds a lock; otherwise returns <code>false</code>
- * @see javax.jcr.Node#holdsLock
- */
- public boolean holdsLock(NodeData node) throws RepositoryException;
-
- /**
- * Returns <code>true</code> 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 <code>false</code>
- *
- * @param node
- * node
- * @return <code>true</code> 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 <code>false</code>
- * @see javax.jcr.Node#isLocked
- */
- public boolean isLocked(NodeData node);
-
- /**
- * Returns <code>true</code> if the specified session holds a lock on the given node; otherwise
- * returns <code>false</code>. <p/> Note that <code>isLockHolder(session, node)==true</code>
- * implies <code>holdsLock(node)==true</code>.
- *
- * @param session
- * session
- * @param node
- * node
- * @return if the specified session holds a lock on the given node; otherwise returns
- * <code>false</code>
- */
- public boolean isLockHolder(NodeImpl node) throws RepositoryException;
-
- /**
- * Invoked by a session to inform that a lock token has been removed.
- *
- * @param session
- * session that has a removed lock token
- * @param lt
- * removed lock token
- */
- public void removeLockToken(String sessionId, String lt);
-
-}
Deleted: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockManagerImpl.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockManagerImpl.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockManagerImpl.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -1,831 +0,0 @@
-/*
- * Copyright (C) 2009 eXo Platform SAS.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.exoplatform.services.jcr.impl.core.lock;
-
-import org.exoplatform.management.annotations.Managed;
-import org.exoplatform.management.annotations.ManagedDescription;
-import org.exoplatform.management.jmx.annotations.NameTemplate;
-import org.exoplatform.management.jmx.annotations.Property;
-import org.exoplatform.services.jcr.access.SystemIdentity;
-import org.exoplatform.services.jcr.config.WorkspaceEntry;
-import org.exoplatform.services.jcr.core.ExtendedSession;
-import org.exoplatform.services.jcr.core.SessionLifecycleListener;
-import org.exoplatform.services.jcr.dataflow.ChangesLogIterator;
-import org.exoplatform.services.jcr.dataflow.CompositeChangesLog;
-import org.exoplatform.services.jcr.dataflow.DataManager;
-import org.exoplatform.services.jcr.dataflow.ItemState;
-import org.exoplatform.services.jcr.dataflow.ItemStateChangesLog;
-import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
-import org.exoplatform.services.jcr.dataflow.PlainChangesLogImpl;
-import org.exoplatform.services.jcr.dataflow.TransactionChangesLog;
-import org.exoplatform.services.jcr.dataflow.persistent.ItemsPersistenceListener;
-import org.exoplatform.services.jcr.datamodel.InternalQName;
-import org.exoplatform.services.jcr.datamodel.ItemData;
-import org.exoplatform.services.jcr.datamodel.NodeData;
-import org.exoplatform.services.jcr.datamodel.PropertyData;
-import org.exoplatform.services.jcr.datamodel.QPathEntry;
-import org.exoplatform.services.jcr.datamodel.ValueData;
-import org.exoplatform.services.jcr.impl.Constants;
-import org.exoplatform.services.jcr.impl.core.NodeImpl;
-import org.exoplatform.services.jcr.impl.core.SessionImpl;
-import org.exoplatform.services.jcr.impl.dataflow.AbstractValueData;
-import org.exoplatform.services.jcr.impl.dataflow.TransientItemData;
-import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
-import org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager;
-import org.exoplatform.services.jcr.observation.ExtendedEvent;
-import org.exoplatform.services.jcr.util.IdGenerator;
-import org.exoplatform.services.log.ExoLogger;
-import org.exoplatform.services.log.Log;
-import org.jboss.cache.factories.annotations.NonVolatile;
-import org.picocontainer.Startable;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.AccessDeniedException;
-import javax.jcr.RepositoryException;
-import javax.jcr.UnsupportedRepositoryOperationException;
-import javax.jcr.lock.Lock;
-import javax.jcr.lock.LockException;
-
-/**
- * Created by The eXo Platform SAS.
- *
- * @author <a href="mailto:gennady.azarenkov at exoplatform.com">Gennady Azarenkov</a>
- * @version $Id$
- */
- at Managed
- at NameTemplate(@Property(key = "service", value = "lockmanager"))
- at NonVolatile
-public class LockManagerImpl implements ItemsPersistenceListener, SessionLifecycleListener, LockManager, Startable
-{
- /**
- * Default lock time out. 30min
- */
- public static final long DEFAULT_LOCK_TIMEOUT = 1000 * 60 * 30;
-
- // Search constants
- /**
- * The exact lock token.
- */
- private static final int SEARCH_EXECMATCH = 1;
-
- /**
- * Lock token of closed parent
- */
- private static final int SEARCH_CLOSEDPARENT = 2;
-
- /**
- * Lock token of closed child
- */
- private static final int SEARCH_CLOSEDCHILD = 4;
-
- /**
- * Logger
- */
- private final Log log = ExoLogger.getLogger("jcr.lock.LockManager");
-
- /**
- * Map NodeIdentifier -- lockData
- *
- * TODO: changed from private to protected
- */
- protected final Map<String, LockData> locks;
-
- /**
- * Data manager.
- */
- private final DataManager dataManager;
-
- /**
- * Map NodeIdentifier -- lockData
- *
- * TODO: changed from private to protected
- */
- protected final Map<String, LockData> pendingLocks;
-
- /**
- * Map lockToken --lockData
- */
- private final Map<String, LockData> tokensMap;
-
- /**
- * Run time lock time out.
- */
- private long lockTimeOut;
-
- /**
- * Lock remover thread.
- */
- private LockRemover lockRemover;
-
- /**
- * Lock persister instance.
- */
- private final LockPersister persister;
-
- /**
- * Constructor for workspace without LockPersister
- *
- * @param dataManager
- * @param config
- */
- public LockManagerImpl(WorkspacePersistentDataManager dataManager, WorkspaceEntry config)
- {
- this(dataManager, config, null);
- }
-
- public LockManagerImpl(WorkspacePersistentDataManager dataManager, WorkspaceEntry config, LockPersister persister)
- {
-
- this.dataManager = dataManager;
- this.persister = persister;
- if (config.getLockManager() != null)
- {
- lockTimeOut =
- config.getLockManager().getTimeout() > 0 ? config.getLockManager().getTimeout() : DEFAULT_LOCK_TIMEOUT;
- }
- else
- lockTimeOut = DEFAULT_LOCK_TIMEOUT;
-
- locks = new HashMap<String, LockData>();
- pendingLocks = new HashMap<String, LockData>();
- tokensMap = new HashMap<String, LockData>();
-
- dataManager.addItemPersistenceListener(this);
- }
-
- /*
- * (non-Javadoc)
- * @see
- * org.exoplatform.services.jcr.impl.core.lock.LockManager#lockTokenAdded(org.exoplatform.services
- * .jcr.impl.core.SessionImpl, java.lang.String)
- */
- public synchronized void addLockToken(String sessionId, String lt)
- {
- LockData currLock = tokensMap.get(lt);
- if (currLock != null)
- {
- currLock.addLockHolder(sessionId);
- }
- }
-
- /*
- * (non-Javadoc)
- * @see
- * org.exoplatform.services.jcr.impl.core.lock.LockManager#addPendingLock(org.exoplatform.services
- * .jcr.impl.core.NodeImpl, boolean, boolean, long)
- */
- public synchronized Lock addPendingLock(NodeImpl node, boolean isDeep, boolean isSessionScoped, long timeOut)
- throws LockException
- {
- LockData lData = getLockData((NodeData)node.getData(), SEARCH_EXECMATCH | SEARCH_CLOSEDPARENT);
- if (lData != null)
- {
- if (lData.getNodeIdentifier().equals(node.getInternalIdentifier()))
- {
- throw new LockException("Node already locked: " + node.getData().getQPath());
- }
- else if (lData.isDeep())
- {
- throw new LockException("Parent node has deep lock.");
- }
- }
-
- if (isDeep && getLockData((NodeData)node.getData(), SEARCH_CLOSEDCHILD) != null)
- {
- throw new LockException("Some child node is locked.");
- }
-
- String lockToken = IdGenerator.generate();
- lData =
- new LockData(node.getInternalIdentifier(), lockToken, isDeep, isSessionScoped, node.getSession().getUserID(),
- timeOut > 0 ? timeOut : lockTimeOut);
-
- lData.addLockHolder(node.getSession().getId());
- pendingLocks.put(node.getInternalIdentifier(), lData);
- tokensMap.put(lockToken, lData);
-
- LockImpl lock = new LockImpl(node.getSession(), lData);
- return lock;
- }
-
- /*
- * (non-Javadoc)
- * @see
- * org.exoplatform.services.jcr.impl.core.lock.LockManager#getLock(org.exoplatform.services.jcr
- * .impl.core.NodeImpl)
- */
- public LockImpl getLock(NodeImpl node) throws LockException, RepositoryException
- {
-
- LockData lData = getLockData((NodeData)node.getData(), SEARCH_EXECMATCH | SEARCH_CLOSEDPARENT);
-
- if (lData == null || (!node.getInternalIdentifier().equals(lData.getNodeIdentifier()) && !lData.isDeep()))
- {
- throw new LockException("Node not locked: " + node.getData().getQPath());
-
- }
- return new LockImpl(node.getSession(), lData);
- }
-
- /*
- * (non-Javadoc)
- * @see org.exoplatform.services.jcr.impl.core.lock.LockManager#getLockTokens(java.lang.String)
- */
- public synchronized String[] getLockTokens(String sessionID)
- {
- List<String> retval = new ArrayList<String>();
-
- for (LockData lockData : locks.values())
- {
- if (lockData.isLockHolder(sessionID))
- retval.add(lockData.getLockToken(sessionID));
-
- }
- return retval.toArray(new String[retval.size()]);
- }
-
- /*
- * (non-Javadoc)
- * @see
- * org.exoplatform.services.jcr.impl.core.lock.LockManager#holdsLock(org.exoplatform.services.
- * jcr.impl.core.NodeImpl)
- */
- public boolean holdsLock(NodeData node) throws RepositoryException
- {
- return getLockData(node, SEARCH_EXECMATCH) != null;
- }
-
- /*
- * (non-Javadoc)
- * @see
- * org.exoplatform.services.jcr.impl.core.lock.LockManager#isLocked(org.exoplatform.services.jcr
- * .datamodel.NodeData)
- */
- public boolean isLocked(NodeData node)
- {
- LockData lData = getLockData(node, SEARCH_EXECMATCH | SEARCH_CLOSEDPARENT);
-
- if (lData == null || (!node.getIdentifier().equals(lData.getNodeIdentifier()) && !lData.isDeep()))
- {
- return false;
- }
- return true;
- }
-
- /*
- * (non-Javadoc)
- * @see
- * org.exoplatform.services.jcr.impl.core.lock.LockManager#isLockHolder(org.exoplatform.services
- * .jcr.impl.core.NodeImpl)
- */
- public boolean isLockHolder(NodeImpl node) throws RepositoryException
- {
- LockData lData = getLockData((NodeData)node.getData(), SEARCH_EXECMATCH | SEARCH_CLOSEDPARENT);
- return lData != null && lData.isLockHolder(node.getSession().getId());
- }
-
- /*
- * (non-Javadoc)
- * @see
- * org.exoplatform.services.jcr.core.SessionLifecycleListener#onCloseSession(org.exoplatform.services
- * .jcr.core.ExtendedSession)
- */
- public synchronized void onCloseSession(ExtendedSession session)
- {
- // List<String> deadLocksList = new ArrayList<String>();
- SessionImpl sessionImpl = (SessionImpl)session;
- for (Iterator<Map.Entry<String, LockData>> entries = locks.entrySet().iterator(); entries.hasNext();)
- {
- Map.Entry<String, LockData> entry = entries.next();
- LockData lockData = entry.getValue();
- if (lockData.isLive())
- {
- if (lockData.isLockHolder(session.getId()))
- {
- if (lockData.isSessionScoped())
- {
- // if no session currently holds lock except this
- try
- {
- // TODO it's possible to have next error
- // java.lang.NullPointerException
- // at
- // org.exoplatform.services.jcr.impl.core.lock.LockManagerImpl.onCloseSession(LockManagerImpl.java:312)
- // at org.exoplatform.services.jcr.impl.core.SessionImpl.logout(SessionImpl.java:794)
- // at
- // org.exoplatform.services.jcr.impl.core.XASessionImpl.logout(XASessionImpl.java:254)
- // at
- // org.exoplatform.services.jcr.impl.core.SessionRegistry$SessionCleaner.callPeriodically(SessionRegistry.java:165)
- // at
- // org.exoplatform.services.jcr.impl.proccess.WorkerThread.run(WorkerThread.java:46)
- ((NodeImpl)sessionImpl.getTransientNodesManager().getItemByIdentifier(
- lockData.getNodeIdentifier(), false)).unlock();
- }
- catch (UnsupportedRepositoryOperationException e)
- {
- log.error(e.getLocalizedMessage());
- }
- catch (LockException e)
- {
- log.error(e.getLocalizedMessage());
- }
- catch (AccessDeniedException e)
- {
- log.error(e.getLocalizedMessage());
- }
- catch (RepositoryException e)
- {
- log.error(e.getLocalizedMessage());
- }
-
- }
- else
- {
- lockData.removeLockHolder(session.getId());
- }
- }
- }
- else
- {
- entries.remove();
- }
- }
- }
-
- /*
- * (non-Javadoc)
- * @seeorg.exoplatform.services.jcr.dataflow.persistent.ItemsPersistenceListener#onSaveItems(org.
- * exoplatform.services.jcr.dataflow.ItemStateChangesLog)
- */
- @Deprecated
- public void onSaveItems(ItemStateChangesLog changesLog)
- {
- List<PlainChangesLog> chengesLogList = new ArrayList<PlainChangesLog>();
- if (changesLog instanceof TransactionChangesLog)
- {
- ChangesLogIterator logIterator = ((TransactionChangesLog)changesLog).getLogIterator();
-
- while (logIterator.hasNextLog())
- {
- chengesLogList.add(logIterator.nextLog());
- }
- }
- else if (changesLog instanceof PlainChangesLog)
- {
- chengesLogList.add((PlainChangesLog)changesLog);
- }
- else if (changesLog instanceof CompositeChangesLog)
- {
- for (ChangesLogIterator iter = ((CompositeChangesLog)changesLog).getLogIterator(); iter.hasNextLog();)
- {
- chengesLogList.add(iter.nextLog());
- }
- }
-
- for (PlainChangesLog currChangesLog : chengesLogList)
- {
- String nodeIdentifier;
- try
- {
- switch (currChangesLog.getEventType())
- {
- case ExtendedEvent.LOCK :
- if (currChangesLog.getSize() < 2)
- {
- log.error("Incorrect changes log of type ExtendedEvent.LOCK size=" + currChangesLog.getSize()
- + "<2 \n" + currChangesLog.dump());
- break;
- }
- nodeIdentifier = currChangesLog.getAllStates().get(0).getData().getParentIdentifier();
-
- if (pendingLocks.containsKey(nodeIdentifier))
- {
- internalLock(nodeIdentifier);
- }
- else
- {
- log.warn("No lock in pendingLocks for identifier " + nodeIdentifier
- + " Probably lock come from replication.");
-
- String lockToken = IdGenerator.generate();
- ItemState ownerState = getItemState(currChangesLog, Constants.JCR_LOCKOWNER);
- ItemState isDeepState = getItemState(currChangesLog, Constants.JCR_LOCKISDEEP);
- if (ownerState != null && isDeepState != null)
- {
-
- String owner =
- new String(((((TransientPropertyData)(ownerState.getData())).getValues()).get(0))
- .getAsByteArray(), Constants.DEFAULT_ENCODING);
-
- boolean isDeep =
- Boolean.valueOf(
- new String(((((TransientPropertyData)(isDeepState.getData())).getValues()).get(0))
- .getAsByteArray(), Constants.DEFAULT_ENCODING)).booleanValue();
-
- createRemoteLock(currChangesLog.getSessionId(), nodeIdentifier, lockToken, isDeep, false, owner);
- }
- }
- break;
- case ExtendedEvent.UNLOCK :
- if (currChangesLog.getSize() < 2)
- {
- log.error("Incorrect changes log of type ExtendedEvent.UNLOCK size=" + currChangesLog.getSize()
- + "<2 \n" + currChangesLog.dump());
- break;
- }
-
- internalUnLock(currChangesLog.getSessionId(), currChangesLog.getAllStates().get(0).getData()
- .getParentIdentifier());
- break;
- default :
- HashSet<String> removedLock = new HashSet<String>();
- for (ItemState itemState : currChangesLog.getAllStates())
- {
- // this is a node and node is locked
- if (itemState.getData().isNode() && locks.containsKey(itemState.getData().getIdentifier()))
- {
- nodeIdentifier = itemState.getData().getIdentifier();
- if (itemState.isDeleted())
- {
- removedLock.add(nodeIdentifier);
- }
- else if (itemState.isAdded() || itemState.isRenamed() || itemState.isUpdated())
- {
- removedLock.remove(nodeIdentifier);
- }
- }
- }
- for (String identifier : removedLock)
- {
- internalUnLock(currChangesLog.getSessionId(), identifier);
- }
- break;
- }
- }
- catch (LockException e)
- {
- log.error(e.getLocalizedMessage(), e);
- }
- catch (UnsupportedEncodingException e)
- {
- log.error(e.getLocalizedMessage(), e);
- }
- catch (IllegalStateException e)
- {
- log.error(e.getLocalizedMessage(), e);
- }
- catch (IOException e)
- {
- log.error(e.getLocalizedMessage(), e);
- }
- }
- }
-
- /*
- * (non-Javadoc)
- * @see
- * org.exoplatform.services.jcr.impl.core.lock.LockManager#lockTokenRemoved(org.exoplatform.services
- * .jcr.impl.core.SessionImpl, java.lang.String)
- */
- public synchronized void removeLockToken(String sessionId, String lt)
- {
- LockData lData = tokensMap.get(lt);
- if (lData != null && lData.isLockHolder(sessionId))
- {
- lData.removeLockHolder(sessionId);
- }
- }
-
- /*
- * (non-Javadoc)
- * @see org.picocontainer.Startable#start()
- */
- public void start()
- {
- lockRemover = new LockRemover(this);
- }
-
- // Quick method. We need to reconstruct
- synchronized List<LockData> getLockList()
- {
- return new ArrayList<LockData>(locks.values());
- }
-
- /**
- * Remove expired locks. Used from LockRemover.
- */
- synchronized void removeExpired()
- {
- final List<String> removeLockList = new ArrayList<String>();
-
- for (LockData lock : locks.values())
- {
- if (!lock.isSessionScoped() && lock.getTimeToDeath() < 0)
- {
- removeLockList.add(lock.getNodeIdentifier());
- }
- }
-
- for (String rLock : removeLockList)
- {
- removeLock(rLock);
- }
- }
-
- /*
- * (non-Javadoc)
- * @see org.picocontainer.Startable#stop()
- */
- public void stop()
- {
- lockRemover.halt();
- lockRemover.interrupt();
- locks.clear();
- pendingLocks.clear();
- tokensMap.clear();
- }
-
- /**
- * Copy <code>PropertyData prop<code> to new TransientItemData
- *
- * @param prop
- * @return
- * @throws RepositoryException
- */
- private TransientItemData copyItemData(PropertyData prop) throws RepositoryException
- {
-
- if (prop == null)
- return null;
-
- // make a copy
- TransientPropertyData newData =
- new TransientPropertyData(prop.getQPath(), prop.getIdentifier(), prop.getPersistedVersion(), prop.getType(),
- prop.getParentIdentifier(), prop.isMultiValued());
-
- List<ValueData> values = null;
- // null is possible for deleting items
- if (prop.getValues() != null)
- {
- values = new ArrayList<ValueData>();
- for (ValueData val : prop.getValues())
- {
- values.add(((AbstractValueData)val).createTransientCopy());
- }
- }
- newData.setValues(values);
- return newData;
- }
-
- /**
- * Search item with name <code>itemName<code> in changesLog
- *
- * @param changesLog
- * @param itemName
- * @return Item
- */
- private ItemState getItemState(PlainChangesLog changesLog, InternalQName itemName)
- {
- List<ItemState> allStates = changesLog.getAllStates();
- for (int i = allStates.size() - 1; i >= 0; i--)
- {
- ItemState state = allStates.get(i);
- if (state.getData().getQPath().getName().equals(itemName))
- return state;
- }
- return null;
- }
-
- /**
- * Search lock in maps.
- *
- * @param data
- * @param searchType
- * @return
- */
- private LockData getLockData(NodeData data, int searchType)
- {
- if (data == null || locks.size() == 0)
- return null;
- LockData retval = null;
- try
- {
- if ((searchType & SEARCH_EXECMATCH) != 0)
- {
- retval = locks.get(data.getIdentifier());
- }
- if (retval == null && (searchType & SEARCH_CLOSEDPARENT) != 0)
- {
-
- NodeData parentData = (NodeData)dataManager.getItemData(data.getParentIdentifier());
- if (parentData != null)
- {
- retval = locks.get(parentData.getIdentifier());
- // parent not found try to fo upper
- if (retval == null)
- {
- retval = getLockData(parentData, SEARCH_CLOSEDPARENT);
- }
- }
- }
- if (retval == null && (searchType & SEARCH_CLOSEDCHILD) != 0)
- {
-
- List<NodeData> childData = dataManager.getChildNodesData(data);
- for (NodeData nodeData : childData)
- {
- retval = locks.get(nodeData.getIdentifier());
- if (retval != null)
- break;
- }
- if (retval == null)
- {
- // child not found try to find diper
- for (NodeData nodeData : childData)
- {
- retval = getLockData(nodeData, SEARCH_CLOSEDCHILD);
- if (retval != null)
- break;
- }
- }
- }
- }
- catch (RepositoryException e)
- {
- return null;
- }
-
- return retval;
- }
-
- /**
- * Internal lock
- *
- * @param nodeIdentifier
- * @throws LockException
- *
- * TODO: Changed from private to public. Need for LockCacheLoader.
- */
- public synchronized void internalLock(String nodeIdentifier) throws LockException
- {
- LockData ldata = pendingLocks.get(nodeIdentifier);
- if (ldata != null)
- {
- locks.put(nodeIdentifier, ldata);
-
- if (persister != null)
- {
- persister.add(ldata);
- }
- pendingLocks.remove(nodeIdentifier);
- }
- else
- {
- throw new LockException("No lock in pending locks");
- }
- }
-
- /**
- * Internal unlock.
- *
- * @param sessionId
- * @param nodeIdentifier
- * @throws LockException
- *
- * TODO: Changed from private to public. Need for LockCacheLoader.
- */
- public synchronized void internalUnLock(String sessionId, String nodeIdentifier) throws LockException
- {
- LockData lData = locks.get(nodeIdentifier);
-
- if (lData != null)
- {
- tokensMap.remove(lData.getLockToken(sessionId));
- locks.remove(nodeIdentifier);
-
- lData.setLive(false);
- if (persister != null)
- {
- persister.remove(lData);
- }
- lData = null;
- }
- }
-
- /**
- * For locks comes from remote JCRs (replication usecase)
- *
- * @param sessionId
- * String
- * @param nodeIdentifier
- * String
- * @param lockToken
- * String
- * @param isDeep
- * boolean
- * @param sessionScoped
- * boolean
- * @param owner
- * String
- * @return LockData
- *
- * TODO: Changed from private to public. Need for LockCacheLoader.
- */
- public synchronized LockData createRemoteLock(String sessionId, String nodeIdentifier, String lockToken,
- boolean isDeep, boolean sessionScoped, String owner)
- {
- LockData lData = new LockData(nodeIdentifier, lockToken, isDeep, sessionScoped, owner, lockTimeOut);
- lData.addLockHolder(sessionId);
- locks.put(nodeIdentifier, lData);
- tokensMap.put(lockToken, lData);
-
- return lData;
- }
-
- /**
- * Remove lock, used by Lock remover.
- *
- * @param nodeIdentifier String
- */
- protected void removeLock(String nodeIdentifier)
- {
- try
- {
- NodeData nData = (NodeData)dataManager.getItemData(nodeIdentifier);
- PlainChangesLog changesLog =
- new PlainChangesLogImpl(new ArrayList<ItemState>(), SystemIdentity.SYSTEM, ExtendedEvent.UNLOCK);
-
- ItemData lockOwner =
- copyItemData((PropertyData)dataManager.getItemData(nData, new QPathEntry(Constants.JCR_LOCKOWNER, 1)));
-
- changesLog.add(ItemState.createDeletedState(lockOwner));
-
- ItemData lockIsDeep =
- copyItemData((PropertyData)dataManager.getItemData(nData, new QPathEntry(Constants.JCR_LOCKISDEEP, 1)));
- changesLog.add(ItemState.createDeletedState(lockIsDeep));
-
- // lock probably removed by other thread
- if (lockOwner == null && lockIsDeep == null)
- return;
- dataManager.save(new TransactionChangesLog(changesLog));
- }
- catch (RepositoryException e)
- {
- log.error("Error occur during removing lock" + e.getLocalizedMessage());
- }
- }
-
- @Managed
- @ManagedDescription("The number of active locks")
- public int getNumLocks()
- {
- return locks.size();
- }
-
- @Managed
- @ManagedDescription("Remove the expired locks")
- public void cleanExpiredLocks()
- {
- removeExpired();
- }
-
- /**
- * TODO: Added. Need for LockCacheLoader..
- */
- public boolean hasPendingLocks(String nodeIdentifier)
- {
- return pendingLocks.containsKey(nodeIdentifier);
- }
-
- /**
- * TODO: Added. Need for LockCacheLoader..
- */
- public boolean hasLockNode(String nodeIdentifier)
- {
- return locks.containsKey(nodeIdentifier);
- }
-}
Deleted: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockRemover.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockRemover.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/LockRemover.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2009 eXo Platform SAS.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.exoplatform.services.jcr.impl.core.lock;
-
-import org.exoplatform.services.jcr.impl.proccess.WorkerThread;
-import org.exoplatform.services.log.ExoLogger;
-import org.exoplatform.services.log.Log;
-
-/**
- * Created by The eXo Platform SAS.
- *
- * @author <a href="mailto:Sergey.Kabashnyuk at gmail.com">Sergey Kabashnyuk</a>
- * @version $Id$
- */
-public class LockRemover extends WorkerThread
-{
-
- private final Log log = ExoLogger.getLogger("jcr.lock.LockRemover");
-
- public static final long DEFAULT_THREAD_TIMEOUT = 30000; // 30
-
- // sec
-
- private final LockManagerImpl lockManagerImpl;
-
- public LockRemover(LockManagerImpl lockManagerImpl)
- {
- this(lockManagerImpl, DEFAULT_THREAD_TIMEOUT);
- }
-
- private LockRemover(LockManagerImpl lockManagerImpl, long timeout)
- {
- super(timeout);
- this.lockManagerImpl = lockManagerImpl;
- setName("LockRemover " + getId());
- setPriority(Thread.MIN_PRIORITY);
- setDaemon(true);
- start();
- if (log.isDebugEnabled())
- log.debug("LockRemover instantiated name= " + getName() + " timeout= " + timeout);
- }
-
- @Override
- protected void callPeriodically() throws Exception
- {
- lockManagerImpl.removeExpired();
- }
-}
Added: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/SessionLockManager.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/SessionLockManager.java (rev 0)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/SessionLockManager.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -0,0 +1,398 @@
+/*
+ * Copyright (C) 2009 eXo Platform SAS.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.exoplatform.services.jcr.impl.core.lock;
+
+import org.exoplatform.services.jcr.access.SystemIdentity;
+import org.exoplatform.services.jcr.core.ExtendedSession;
+import org.exoplatform.services.jcr.core.SessionLifecycleListener;
+import org.exoplatform.services.jcr.dataflow.ItemState;
+import org.exoplatform.services.jcr.dataflow.LockPlainChangesLogImpl;
+import org.exoplatform.services.jcr.dataflow.PlainChangesLog;
+import org.exoplatform.services.jcr.dataflow.PlainChangesLogImpl;
+import org.exoplatform.services.jcr.datamodel.ItemData;
+import org.exoplatform.services.jcr.datamodel.NodeData;
+import org.exoplatform.services.jcr.datamodel.PropertyData;
+import org.exoplatform.services.jcr.datamodel.QPathEntry;
+import org.exoplatform.services.jcr.impl.Constants;
+import org.exoplatform.services.jcr.impl.core.SessionImpl;
+import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
+import org.exoplatform.services.jcr.impl.dataflow.TransientValueData;
+import org.exoplatform.services.jcr.observation.ExtendedEvent;
+import org.exoplatform.services.jcr.util.IdGenerator;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.math.BigInteger;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+
+/**
+ * @author <a href="mailto:nikolazius at gmail.com">Nikolay Zamosenchuk</a>
+ * @version $Id$
+ *
+ */
+public class SessionLockManager implements SessionLifecycleListener
+{
+ /**
+ * Default lock time out. 30min
+ */
+ public static final long DEFAULT_LOCK_TIMEOUT = 1000 * 60 * 30;
+
+ /**
+ * Search lockData for given node
+ */
+ private static final int SEARCH_EXACMATCH = 1;
+
+ /**
+ * Search lockData for parent's of given node
+ */
+ private static final int SEARCH_PARENT = 2;
+
+ /**
+ * Search lockData for children of given node
+ */
+ private static final int SEARCH_CHILD = 4;
+
+ /**
+ * Session through which this lock manager is created
+ */
+ private final SessionImpl session;
+
+ protected final Log log = ExoLogger.getLogger(this.getClass().getName());
+
+ /**
+ * Holds session's tokens and their hashes to avoid calculation every time.
+ * Token <--> Hash
+ */
+ private Map<String, String> tokens;
+
+ /**
+ * Holds session's tokens and their hashes to avoid calculation every time.
+ * Hash <--> Token
+ * Added to speed up operations
+ */
+ private Map<String, String> tokenHash;
+
+ /**
+ * Configured lock timeout
+ */
+ private long lockTimeOut;
+
+ /**
+ * @param session
+ * @param lockTimeOut
+ */
+ public SessionLockManager(SessionImpl session, long lockTimeOut)
+ {
+ this.session = session;
+ this.lockTimeOut = lockTimeOut;
+ // TODO: configured lock timeout should be acquired from WSconfig
+ /* if (config.getLockManager() != null)
+ {
+ lockTimeOut =
+ config.getLockManager().getTimeout() > 0 ? config.getLockManager().getTimeout() : DEFAULT_LOCK_TIMEOUT;
+ }
+ else
+ lockTimeOut = DEFAULT_LOCK_TIMEOUT;*/
+ }
+
+ /**
+ * Adds token to current session
+ * @param token
+ */
+ public void addLockToken(String token)
+ {
+ String hash = getHash(token);
+ tokens.put(token, hash);
+ tokenHash.put(hash, token);
+ }
+
+ /**
+ * Removes token from current session
+ * @param token
+ */
+ public void removeLockToken(String token)
+ {
+ String hash = getHash(token);
+ tokens.remove(token);
+ tokenHash.remove(hash);
+ }
+
+ /**
+ * Tries to get Lock for node. Is node is not a lockholder, then parent with deep lock is looked for.
+ *
+ * @param node
+ * @return
+ * @throws LockException
+ * @throws RepositoryException
+ */
+ public LockImpl getLock(NodeData node) throws LockException, RepositoryException
+ {
+ LockData lockData = getLockData(node, SEARCH_EXACMATCH | SEARCH_PARENT);
+
+ if (lockData == null || (!node.getIdentifier().equals(lockData.getNodeIdentifier()) && !lockData.isDeep()))
+ {
+ throw new LockException("Node not locked: " + node.getQPath());
+ }
+ // if session doesn't have token, null will be returned
+ return new LockImpl(session, lockData, tokenHash.get(lockData.getTokenHash()));
+ }
+
+ /**
+ * Returns the list of token that current session owns.
+ * @return
+ */
+ public String[] getLockTokens()
+ {
+ return tokens.keySet().toArray(new String[tokens.size()]);
+ }
+
+ /**
+ * Checks if node actually has a lock.
+ *
+ * @param node
+ * @return
+ * @throws RepositoryException
+ */
+ public boolean holdsLock(NodeData node) throws RepositoryException
+ {
+ return getLockData(node, SEARCH_EXACMATCH) != null;
+ }
+
+ /**
+ * Checks if current session has a token (access) for this node.
+ *
+ * @param node
+ * @return
+ * @throws RepositoryException
+ */
+ public boolean isLockHolder(NodeData node) throws RepositoryException
+ {
+ LockData lockData = getLockData(node, SEARCH_EXACMATCH | SEARCH_PARENT);
+ return lockData != null && isLockHolder(lockData);
+ }
+
+ /**
+ * Checks if node is locked, or it's any parent has a deep lock.
+ *
+ * @param node
+ * @return
+ */
+ public boolean isLocked(NodeData node)
+ {
+ LockData lockData = getLockData(node, SEARCH_EXACMATCH | SEARCH_PARENT);
+
+ if (lockData == null || (!node.getIdentifier().equals(lockData.getNodeIdentifier()) && !lockData.isDeep()))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Actually locks the node, adding jcr:lockOwner and jcr:lockIsDeep properties to node and adds lock token
+ * to current session.
+ *
+ * @param node
+ * @param isDeep
+ * @param isSessionScoped
+ * @param timeOut
+ * @return
+ * @throws LockException
+ * @throws RepositoryException
+ */
+ public LockImpl lock(NodeData node, boolean isDeep, boolean isSessionScoped, long timeOut) throws LockException,
+ RepositoryException
+ {
+ // check child node is not locked
+ if (isDeep && getLockData(node, SEARCH_CHILD) != null)
+ {
+ throw new LockException("Can't place deep lock: some child node is locked.");
+ }
+
+ String token = IdGenerator.generate();
+ String hash = getHash(token);
+
+ LockData lockData =
+ new LockData(node.getIdentifier(), hash, isDeep, isSessionScoped, session.getUserID(), timeOut > 0 ? timeOut
+ : lockTimeOut);
+
+ tokens.put(token, hash);
+ tokenHash.put(hash, token);
+
+ // Create and pass changes log
+ LockPlainChangesLogImpl changesLog =
+ new LockPlainChangesLogImpl(new ArrayList<ItemState>(), session.getId(), ExtendedEvent.LOCK);
+
+ changesLog.setLockData(lockData);
+
+ PropertyData propData =
+ TransientPropertyData.createPropertyData(node, Constants.JCR_LOCKOWNER, PropertyType.STRING, false,
+ new TransientValueData(session.getUserID()));
+ changesLog.add(ItemState.createAddedState(propData));
+
+ propData =
+ TransientPropertyData.createPropertyData(node, Constants.JCR_LOCKISDEEP, PropertyType.BOOLEAN, false,
+ new TransientValueData(isDeep));
+ changesLog.add(ItemState.createAddedState(propData));
+
+ LockImpl newLock = new LockImpl(session, lockData, token);
+
+ session.getTransientNodesManager().getTransactManager().save(changesLog);
+ return newLock;
+ }
+
+ /**
+ * Actually unlock the node also removing jcr:lockOwner and jcr:lockIsDeep properties
+ *
+ * @param node
+ * @throws RepositoryException
+ */
+ public void unlock(NodeData node) throws RepositoryException
+ {
+ PlainChangesLog changesLog =
+ new PlainChangesLogImpl(new ArrayList<ItemState>(), session.getId(), ExtendedEvent.UNLOCK);
+
+ ItemData lockOwner =
+ session.getTransientNodesManager().getItemData(node, new QPathEntry(Constants.JCR_LOCKOWNER, 0));
+
+ changesLog.add(ItemState.createDeletedState(lockOwner));
+
+ ItemData lockIsDeep =
+ session.getTransientNodesManager().getItemData(node, new QPathEntry(Constants.JCR_LOCKISDEEP, 0));
+
+ changesLog.add(ItemState.createDeletedState(lockIsDeep));
+
+ session.getTransientNodesManager().getTransactManager().save(changesLog);
+ }
+
+ /**
+ * Calculates md5 hash of string.
+ *
+ * @param token
+ * @return
+ */
+ private String getHash(String token)
+ {
+ String hash = "";
+ try
+ {
+ MessageDigest m = MessageDigest.getInstance("MD5");
+ m.update(token.getBytes(), 0, token.length());
+ hash = new BigInteger(1, m.digest()).toString(16);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ log.error("Can't get instanse of MD5 MessageDigest!", e);
+ }
+ return hash;
+ }
+
+ /**
+ * Search lock with given search options:
+ * * for only given node
+ * * for any upper parent of given node
+ * * for any deeper child of given node
+ *
+ * @param data
+ * @param searchType
+ * @return
+ */
+ private LockData getLockData(NodeData data, int searchType)
+ {
+ if (data == null)
+ return null;
+ LockData retval = null;
+ try
+ {
+ if ((searchType & SEARCH_EXACMATCH) != 0)
+ {
+ retval = session.getTransientNodesManager().getLockData(data.getIdentifier());
+ }
+ if (retval == null && (searchType & SEARCH_PARENT) != 0)
+ {
+
+ NodeData parentData = (NodeData)session.getTransientNodesManager().getItemData(data.getParentIdentifier());
+ if (parentData != null)
+ {
+ retval = session.getTransientNodesManager().getLockData(parentData.getIdentifier());
+ // parent not found try to find upper
+ if (retval == null)
+ {
+ retval = getLockData(parentData, SEARCH_PARENT);
+ }
+ }
+ }
+ if (retval == null && (searchType & SEARCH_CHILD) != 0)
+ {
+
+ List<NodeData> childData = session.getTransientNodesManager().getChildNodesData(data);
+ for (NodeData nodeData : childData)
+ {
+ retval = session.getTransientNodesManager().getLockData(nodeData.getIdentifier());
+ if (retval != null)
+ break;
+ }
+ if (retval == null)
+ {
+ // child not found try to find deeper
+ for (NodeData nodeData : childData)
+ {
+ retval = getLockData(nodeData, SEARCH_CHILD);
+ if (retval != null)
+ break;
+ }
+ }
+ }
+ }
+ catch (RepositoryException e)
+ {
+ return null;
+ }
+
+ return retval;
+ }
+
+ /**
+ * Checks if session has token to this lock data or session is System.
+ *
+ * @param lockData
+ * @return
+ */
+ private boolean isLockHolder(LockData lockData)
+ {
+ return (SystemIdentity.SYSTEM.equals(session.getId()) || tokenHash.get(lockData.getTokenHash()) != null);
+ }
+
+ /**
+ * @see org.exoplatform.services.jcr.core.SessionLifecycleListener#onCloseSession(org.exoplatform.services.jcr.core.ExtendedSession)
+ */
+ public void onCloseSession(ExtendedSession session)
+ {
+ // TODO: remove session scoped locks
+ }
+
+}
Property changes on: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/SessionLockManager.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Deleted: jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/LockCacheLoader.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/LockCacheLoader.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/main/java/org/exoplatform/services/jcr/impl/storage/jbosscache/LockCacheLoader.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -1,324 +0,0 @@
-/*
- * Copyright (C) 2003-2009 eXo Platform SAS.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see<http://www.gnu.org/licenses/>.
- */
-package org.exoplatform.services.jcr.impl.storage.jbosscache;
-
-import org.exoplatform.services.jcr.config.RepositoryConfigurationException;
-import org.exoplatform.services.jcr.datamodel.InternalQName;
-import org.exoplatform.services.jcr.datamodel.PropertyData;
-import org.exoplatform.services.jcr.impl.Constants;
-import org.exoplatform.services.jcr.impl.core.lock.LockManagerImpl;
-import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
-import org.exoplatform.services.jcr.util.IdGenerator;
-import org.exoplatform.services.log.ExoLogger;
-import org.exoplatform.services.log.Log;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.Modification;
-import org.jboss.cache.Modification.ModificationType;
-import org.jboss.cache.factories.annotations.Inject;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-
-import javax.jcr.lock.LockException;
-
-/**
- * Created by The eXo Platform SAS.
- *
- * <br/>Date: 2009
- *
- * @author <a href="mailto:anatoliy.bazko at exoplatform.com.ua">Anatoliy Bazko</a>
- * @version $Id$
- */
-public class LockCacheLoader extends AbstractWriteOnlyCacheLoader
-{
-
- /**
- * Lock manager.
- */
- private LockManagerImpl lockManager;
-
- /**
- * Logger.
- */
- private final Log log = ExoLogger.getLogger("jcr.LockCacheLoader");
-
- /**
- * Injection dependencies.
- *
- * @param lockManager LockManagerImpl
- */
- @Inject
- public void injectDependencies(LockManagerImpl lockManager) throws RepositoryConfigurationException
- {
- if (this.lockManager != null)
- {
- throw new RepositoryConfigurationException("Cannot set LockManagerImpl twice");
- }
-
- this.lockManager = lockManager;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void put(List<Modification> modifications) throws Exception
- {
- String sessionId = null;
- HashSet<String> removedLock = new HashSet<String>();
- List<Modification> lockChanges = new ArrayList<Modification>();
-
- for (Modification m : modifications)
- {
- if (m.getFqn().get(0).equals(JBossCacheStorage.SESSION))
- {
- switch (m.getType())
- {
- case PUT_DATA_ERASE :
- break;
- case PUT_DATA :
- break;
- case PUT_KEY_VALUE :
- // begin new changes log
- if (m.getKey().equals(JBossCacheStorage.SESSION_ID))
- {
- sessionId = (String)m.getValue();
- }
- break;
- case REMOVE_DATA :
- // end changes log
- if (lockChanges.size() == 2)
- {
- if (lockChanges.get(0).getType() == ModificationType.PUT_KEY_VALUE
- && lockChanges.get(1).getType() == ModificationType.PUT_KEY_VALUE)
- {
- performLock(lockChanges, sessionId);
- }
- else if (lockChanges.get(0).getType() == ModificationType.REMOVE_KEY_VALUE
- && lockChanges.get(1).getType() == ModificationType.REMOVE_KEY_VALUE)
- {
- performUnLock(lockChanges, (String)lockChanges.get(0).getFqn().get(1), sessionId);
- }
- else
- {
- log.error("Incorrect changes log contains lock and unlock operation simultaneously");
- }
- }
- else if (lockChanges.size() != 0)
- {
- log.error("Incorrect changes log size for lock or unlock operation");
- }
-
- for (String identifier : removedLock)
- {
- lockManager.internalUnLock(identifier, sessionId);
- }
-
- lockChanges = new ArrayList<Modification>();
- removedLock = new HashSet<String>();
- sessionId = null;
- break;
- case REMOVE_KEY_VALUE :
- break;
- case REMOVE_NODE :
- break;
- case MOVE :
- break;
- default :
- throw new CacheException("Unknown modification " + m.getType());
- }
- }
- else if (m.getFqn().get(0).equals(JBossCacheStorage.PROPS))
- {
- switch (m.getType())
- {
- case PUT_DATA_ERASE :
- break;
- case PUT_DATA :
- break;
- case PUT_KEY_VALUE :
- // lock operation
- if (m.getKey().equals(JBossCacheStorage.ITEM_DATA))
- {
- InternalQName propName = ((PropertyData)m.getValue()).getQPath().getName();
- if (propName.equals(Constants.JCR_LOCKISDEEP) || propName.equals(Constants.JCR_LOCKOWNER))
- {
- lockChanges.add(m);
- }
- }
- break;
- case REMOVE_DATA :
- break;
- case REMOVE_KEY_VALUE :
- break;
- case REMOVE_NODE :
- break;
- case MOVE :
- break;
- default :
- throw new CacheException("Unknown modification " + m.getType());
- }
- }
- else if (m.getFqn().get(0).equals(JBossCacheStorage.NODES))
- {
- switch (m.getType())
- {
- case PUT_DATA_ERASE :
- break;
- case PUT_DATA :
- if (m.getFqn().size() == 2)
- {
- String nodeIdentifier = (String)m.getFqn().get(1);
- if (lockManager.hasLockNode(nodeIdentifier))
- {
- removedLock.remove(nodeIdentifier);
- }
- }
- break;
- case PUT_KEY_VALUE :
- break;
- case REMOVE_DATA :
- break;
- case REMOVE_KEY_VALUE :
- // unLock operation
- if (m.getKey().equals(Constants.JCR_LOCKISDEEP.getAsString())
- || m.getKey().equals(Constants.JCR_LOCKOWNER.getAsString()))
- {
- lockChanges.add(m);
- }
- break;
- case REMOVE_NODE :
- if (m.getFqn().size() == 2)
- {
- String nodeIdentifier = (String)m.getFqn().get(1);
- if (lockManager.hasLockNode(nodeIdentifier))
- {
- removedLock.add(nodeIdentifier);
- }
- }
- break;
- case MOVE :
- if (m.getFqn().size() == 2)
- {
- String nodeIdentifier = (String)m.getFqn().get(1);
- if (lockManager.hasLockNode(nodeIdentifier))
- {
- removedLock.remove(nodeIdentifier);
- }
- }
- break;
- default :
- throw new CacheException("Unknown modification " + m.getType());
- }
- }
- }
- }
-
- /**
- * Perform lock operation.
- *
- * @param lockChanges
- * @throws LockException
- */
- private void performLock(List<Modification> lockChanges, String sessionId)
- {
- String nodeIdentifier = ((PropertyData)lockChanges.get(0).getValue()).getParentIdentifier();
-
- try
- {
- if (lockManager.hasPendingLocks(nodeIdentifier))
- {
- log.info("Perform lock operation nodeIdentifier=" + nodeIdentifier);
- lockManager.internalLock(nodeIdentifier);
- }
- else
- {
- log.warn("No lock in pendingLocks for identifier " + nodeIdentifier
- + " Probably lock come from replication.");
-
- String lockToken = IdGenerator.generate();
- Modification ownerModification = getModification(lockChanges, Constants.JCR_LOCKOWNER);
- Modification isDeepModification = getModification(lockChanges, Constants.JCR_LOCKISDEEP);
-
- if (ownerModification != null && isDeepModification != null)
- {
-
- String owner =
- new String(((((TransientPropertyData)(ownerModification.getValue())).getValues()).get(0))
- .getAsByteArray(), Constants.DEFAULT_ENCODING);
-
- boolean isDeep =
- Boolean.valueOf(
- new String(((((TransientPropertyData)(isDeepModification.getValue())).getValues()).get(0))
- .getAsByteArray(), Constants.DEFAULT_ENCODING)).booleanValue();
-
- lockManager.createRemoteLock(sessionId, nodeIdentifier, lockToken, isDeep, false, owner);
- }
- }
- }
- catch (LockException e)
- {
- log.error(e.getLocalizedMessage(), e);
- }
- catch (UnsupportedEncodingException e)
- {
- log.error(e.getLocalizedMessage(), e);
- }
- catch (IllegalStateException e)
- {
- log.error(e.getLocalizedMessage(), e);
- }
- catch (IOException e)
- {
- log.error(e.getLocalizedMessage(), e);
- }
- }
-
- private void performUnLock(List<Modification> lockChanges, String nodeIdentifier, String sessionId)
- {
- try
- {
- log.info("Perform unlock operation nodeIdentifier=" + nodeIdentifier + " sessionId=" + sessionId);
- lockManager.internalUnLock(nodeIdentifier, sessionId);
- }
- catch (LockException e)
- {
- log.error(e.getLocalizedMessage(), e);
- }
- }
-
- /**
- * Search item with name <code>itemName<code> in modification list
- *
- * @param changes
- * @param itemName
- * @return Item
- */
- private Modification getModification(List<Modification> changes, InternalQName itemName)
- {
- for (Modification m : changes)
- {
- if (((PropertyData)changes.get(0).getValue()).getQPath().getName().equals(itemName))
- return m;
- }
- return null;
- }
-
-}
Modified: jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockImpl.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockImpl.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockImpl.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -32,11 +32,10 @@
{
private ExtendedNode lockedNode = null;
- private LockManagerImpl service;
-
private static final long LOCK_TIMEOUT = 5; // sec
- private static final long LOCK_REMOVER_WAIT = LockRemover.DEFAULT_THREAD_TIMEOUT + (LOCK_TIMEOUT + 1) * 1000; // 15
+ //private static final long LOCK_REMOVER_WAIT = LockRemover.DEFAULT_THREAD_TIMEOUT + (LOCK_TIMEOUT + 1) * 1000; // 15
+ private static final long LOCK_REMOVER_WAIT = (LOCK_TIMEOUT + 30) * 1000; //
// sec
@@ -45,8 +44,6 @@
super.setUp();
- service = (LockManagerImpl)container.getComponentInstanceOfType(LockManagerImpl.class);
-
if (lockedNode == null)
try
{
Deleted: jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/LockCacheLoaderTest.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/LockCacheLoaderTest.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/LockCacheLoaderTest.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2003-2009 eXo Platform SAS.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see<http://www.gnu.org/licenses/>.
- */
-package org.exoplatform.services.jcr.impl.storage.jbosscache;
-
-import org.exoplatform.services.idgenerator.impl.IDGeneratorServiceImpl;
-import org.exoplatform.services.jcr.config.ContainerEntry;
-import org.exoplatform.services.jcr.config.RepositoryEntry;
-import org.exoplatform.services.jcr.config.SimpleParameterEntry;
-import org.exoplatform.services.jcr.config.WorkspaceEntry;
-import org.exoplatform.services.jcr.datamodel.InternalQName;
-import org.exoplatform.services.jcr.datamodel.QPath;
-import org.exoplatform.services.jcr.impl.Constants;
-import org.exoplatform.services.jcr.impl.core.lock.LockData;
-import org.exoplatform.services.jcr.impl.core.lock.LockManagerImpl;
-import org.exoplatform.services.jcr.impl.core.value.ValueFactoryImpl;
-import org.exoplatform.services.jcr.impl.dataflow.TransientNodeData;
-import org.exoplatform.services.jcr.impl.dataflow.TransientPropertyData;
-import org.exoplatform.services.jcr.impl.dataflow.TransientValueData;
-import org.exoplatform.services.jcr.impl.storage.jdbc.JDBCWorkspaceDataContainer;
-import org.exoplatform.services.jcr.impl.storage.value.StandaloneStoragePluginProvider;
-import org.exoplatform.services.jcr.storage.WorkspaceDataContainer;
-import org.exoplatform.services.jcr.storage.value.ValueStoragePluginProvider;
-import org.exoplatform.services.jcr.util.IdGenerator;
-
-import org.jboss.cache.Cache;
-import org.jboss.cache.CacheSPI;
-import org.jboss.cache.DefaultCacheFactory;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.Modification;
-import org.jboss.cache.Node;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.jcr.PropertyType;
-import javax.naming.Context;
-
-/**
- * Created by The eXo Platform SAS.
- *
- * <br/>Date: 2009
- *
- * @author <a href="mailto:anatoliy.bazko at exoplatform.com.ua">Anatoliy Bazko</a>
- * @version $Id$
- */
-public class LockCacheLoaderTest extends AbstractCacheLoaderTest
-{
-
- private TesterLockManagerImpl lockManager;
-
- private LockCacheLoader lockCacheLoader;
-
- private final QPath testRoot = QPath.makeChildPath(Constants.ROOT_PATH, new InternalQName("", "testRoot"));
-
- public void setUp() throws Exception
- {
- super.setUp();
-
- lockManager = new TesterLockManagerImpl();
- lockCacheLoader = new LockCacheLoader();
- lockCacheLoader.injectDependencies(lockManager);
- }
-
- /**
- * {@inheritDoc}
- */
- protected void tearDown() throws Exception
- {
-
- super.tearDown();
- }
-
- public void testLock() throws Exception
- {
- List<Modification> modifications = new ArrayList<Modification>();
- String nodeIdentifier = "node1";
- String sessionId = "session1";
-
- TransientPropertyData lockIsDeepData =
- new TransientPropertyData(QPath.makeChildPath(testRoot, Constants.JCR_LOCKISDEEP), "prop1", 1,
- PropertyType.BOOLEAN, nodeIdentifier, false);
- TransientValueData lockIsDeepValue = new TransientValueData(false);
- lockIsDeepData.setValue(lockIsDeepValue);
-
- TransientPropertyData lockOwnerData =
- new TransientPropertyData(QPath.makeChildPath(testRoot, Constants.JCR_LOCKOWNER), "prop2", 1,
- PropertyType.BOOLEAN, nodeIdentifier, false);
- TransientValueData lockOwner = new TransientValueData("__system");
- lockOwnerData.setValue(lockOwner);
-
- lockManager.addPendingLock(nodeIdentifier, new LockData(nodeIdentifier, "token", false, false, "__system", -1));
-
- modifications.addAll(addSessionInfo(sessionId, "userId"));
- modifications.addAll(addProperty(lockIsDeepData));
- modifications.addAll(addProperty(lockOwnerData));
- modifications.addAll(removeSessionInfo());
- lockCacheLoader.put(modifications);
-
- assertEquals(nodeIdentifier, lockManager.getNodeIdentifier());
- }
-
- public void testUnLock() throws Exception
- {
- List<Modification> modifications = new ArrayList<Modification>();
- String nodeIdentifier = "node1";
- String sessionId = "session1";
-
- TransientPropertyData lockIsDeepData =
- new TransientPropertyData(QPath.makeChildPath(testRoot, Constants.JCR_LOCKISDEEP), "prop1", 1,
- PropertyType.BOOLEAN, nodeIdentifier, false);
- TransientValueData lockIsDeepValue = new TransientValueData(false);
- lockIsDeepData.setValue(lockIsDeepValue);
-
- TransientPropertyData lockOwnerData =
- new TransientPropertyData(QPath.makeChildPath(testRoot, Constants.JCR_LOCKOWNER), "prop2", 1,
- PropertyType.BOOLEAN, nodeIdentifier, false);
- TransientValueData lockOwner = new TransientValueData("__system");
- lockOwnerData.setValue(lockOwner);
-
- modifications.addAll(addSessionInfo(sessionId, "userId"));
- modifications.addAll(removeProperty(lockIsDeepData));
- modifications.addAll(removeProperty(lockOwnerData));
- modifications.addAll(removeSessionInfo());
- lockCacheLoader.put(modifications);
-
- assertEquals(nodeIdentifier, lockManager.getNodeIdentifier());
- assertEquals(sessionId, lockManager.getSessionid());
- }
-
- public void testAddNodeLock() throws Exception
- {
- List<Modification> modifications = new ArrayList<Modification>();
- String nodeIdentifier = "node1";
- String sessionId = "session1";
-
- TransientNodeData node =
- new TransientNodeData(testRoot, nodeIdentifier, 0, null, null, 0, Constants.ROOT_UUID, null);
-
- lockManager.addLock(nodeIdentifier, new LockData(nodeIdentifier, "token", false, false, "__system", -1));
-
- modifications.addAll(addSessionInfo(sessionId, "userId"));
- modifications.addAll(addNode(node));
- modifications.addAll(removeSessionInfo());
- lockCacheLoader.put(modifications);
-
- assertNull(lockManager.getNodeIdentifier());
- assertNull(lockManager.getSessionid());
- }
-
- public void testRemoveNodeLock() throws Exception
- {
- List<Modification> modifications = new ArrayList<Modification>();
- String nodeIdentifier = "node1";
- String sessionId = "session1";
-
- TransientNodeData node =
- new TransientNodeData(testRoot, nodeIdentifier, 0, null, null, 0, Constants.ROOT_UUID, null);
-
- lockManager.addLock(nodeIdentifier, new LockData(nodeIdentifier, "token", false, false, "__system", -1));
-
- modifications.addAll(addSessionInfo(sessionId, "userId"));
- modifications.addAll(removeNode(node));
- modifications.addAll(removeSessionInfo());
- lockCacheLoader.put(modifications);
-
- assertEquals(nodeIdentifier, lockManager.getNodeIdentifier());
- assertEquals(sessionId, lockManager.getSessionid());
- }
-}
Deleted: jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/TesterLockManagerImpl.java
===================================================================
--- jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/TesterLockManagerImpl.java 2009-11-17 16:14:29 UTC (rev 722)
+++ jcr/branches/1.12.0-JBC/component/core/src/test/java/org/exoplatform/services/jcr/impl/storage/jbosscache/TesterLockManagerImpl.java 2009-11-17 16:18:15 UTC (rev 723)
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2003-2009 eXo Platform SAS.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Affero General Public License
- * as published by the Free Software Foundation; either version 3
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see<http://www.gnu.org/licenses/>.
- */
-package org.exoplatform.services.jcr.impl.storage.jbosscache;
-
-import org.exoplatform.services.jcr.config.WorkspaceEntry;
-import org.exoplatform.services.jcr.impl.core.lock.LockData;
-import org.exoplatform.services.jcr.impl.core.lock.LockManagerImpl;
-import org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager;
-import org.jboss.cache.factories.annotations.NonVolatile;
-
-import javax.jcr.lock.LockException;
-
-/**
- * Created by The eXo Platform SAS.
- *
- * <br/>Date: 2009
- *
- * @author <a href="mailto:anatoliy.bazko at exoplatform.com.ua">Anatoliy Bazko</a>
- * @version $Id$
- */
- at NonVolatile
-public class TesterLockManagerImpl extends LockManagerImpl
-{
-
- private String nodeIdentifier = null;
-
- private String sessionId = null;
-
- public TesterLockManagerImpl(WorkspacePersistentDataManager dataManager, WorkspaceEntry config)
- {
- super(dataManager, config);
- }
-
- public TesterLockManagerImpl()
- {
- this(new TesterWorkspacePersistedDataManager(null, null), new TesterWorkspaceEntry());
- }
-
- /**
- * Internal lock
- */
- public synchronized void internalLock(String nodeIdentifier) throws LockException
- {
- if (this.nodeIdentifier != null)
- throw new LockException("NodeIdentifier already exist!");
-
- this.nodeIdentifier = nodeIdentifier;
- }
-
- /**
- * Internal lock
- */
- public synchronized void internalUnLock(String nodeIdentifier, String sessionId) throws LockException
- {
- if (this.nodeIdentifier != null)
- throw new LockException("NodeIdentifier already exist!");
-
- if (this.sessionId != null)
- throw new LockException("SessionId already exist!");
-
- this.nodeIdentifier = nodeIdentifier;
- this.sessionId = sessionId;
- }
-
- public String getNodeIdentifier()
- {
- return nodeIdentifier;
- }
-
- public String getSessionid()
- {
- return sessionId;
- }
-
- public void addPendingLock(String nodeIdentifier, LockData lData)
- {
- pendingLocks.put(nodeIdentifier, lData);
- }
-
- public void addLock(String nodeIdentifier, LockData lData)
- {
- locks.put(nodeIdentifier, lData);
- }
-}
More information about the exo-jcr-commits
mailing list