Author: nzamosenchuk
Date: 2010-02-04 10:58:26 -0500 (Thu, 04 Feb 2010)
New Revision: 1683
Added:
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockPerstistentDataManager.java
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockData.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockJDBCConnection.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockPersistentDataManager.java
Log:
EXOJCR-472: LockJDBCConnection extended with needed functionality and test for it added.
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockData.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockData.java 2010-02-04
15:49:29 UTC (rev 1682)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockData.java 2010-02-04
15:58:26 UTC (rev 1683)
@@ -94,13 +94,29 @@
public LockData(String nodeIdentifier, String lockTokenHash, boolean deep, boolean
sessionScoped, String owner,
long timeOut)
{
+ this(nodeIdentifier, lockTokenHash, deep, sessionScoped, owner, timeOut,
System.currentTimeMillis());
+ }
+
+ /**
+ * @param nodeIdentifier
+ * @param lockToken
+ * @param deep
+ * @param sessionScoped
+ * @param owner
+ * @param timeOut
+ * is seconds!
+ * @param birthday
+ */
+ protected LockData(String nodeIdentifier, String lockTokenHash, boolean deep, boolean
sessionScoped, String owner,
+ long timeOut, long birthday)
+ {
this.nodeIdentifier = nodeIdentifier;
this.tokenHash = lockTokenHash;
this.deep = deep;
this.sessionScoped = sessionScoped;
this.owner = owner;
this.timeOut = timeOut;
- this.birthday = System.currentTimeMillis();
+ this.birthday = birthday;
}
/*
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockJDBCConnection.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockJDBCConnection.java 2010-02-04
15:49:29 UTC (rev 1682)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockJDBCConnection.java 2010-02-04
15:58:26 UTC (rev 1683)
@@ -21,7 +21,9 @@
import java.sql.Connection;
import java.sql.PreparedStatement;
+import java.sql.ResultSet;
import java.sql.SQLException;
+import java.util.HashSet;
import java.util.Set;
import javax.jcr.RepositoryException;
@@ -40,6 +42,7 @@
private final Log LOG = ExoLogger.getLogger(LockPersistentDataManager.class);
+ // queries
protected String ADD_LOCK_DATA;
protected String REMOVE_LOCK_DATA;
@@ -48,6 +51,26 @@
protected String GET_LOCKED_NODES;
+ protected String GET_LOCK_DATA;
+
+ // column names
+ protected static String COLUMN_WS_NAME = "WS_NAME";
+
+ protected static String COLUMN_NODE_ID = "NODE_ID";
+
+ protected static String COLUMN_TOKEN_HASH = "TOKEN_HASH";
+
+ protected static String COLUMN_OWNER = "OWNER";
+
+ protected static String COLUMN_IS_SESSIONSCOPED = "IS_SESSIONSCOPED";
+
+ protected static String COLUMN_IS_DEEP = "IS_DEEP";
+
+ protected static String COLUMN_BIRTHDAY = "BIRTHDAY";
+
+ protected static String COLUMN_TIMEOUT = "TIMEOUT";
+
+ // prepared statements
private PreparedStatement insertLockData;
private PreparedStatement removeLockData;
@@ -56,53 +79,51 @@
private PreparedStatement getLockedNodes;
+ private PreparedStatement getLockData;
+
private Connection dbConnection;
+ private String wsName;
+
+ /**
+ * Creates LockJDBCConnection instance based on given connection to
+ * database with specified workspace name.
+ *
+ * @param dbConnection Connection to database.
+ * @param wsName Current workspace's name.
+ * @throws SQLException if database exception occurs.
+ */
public LockJDBCConnection(Connection dbConnection, String wsName) throws SQLException
{
-
this.dbConnection = dbConnection;
if (dbConnection.getAutoCommit())
{
dbConnection.setAutoCommit(false);
}
+ this.wsName = wsName;
- prepareQueries(wsName);
- }
-
- protected void prepareQueries(String wsName) throws SQLException
- {
- // Table structure
- // CREATE TABLE JCR_LOCKS(
- // WS_NAME VARCHAR(96) NOT NULL,
- // NODE_ID VARCHAR(96) NOT NULL,
- // TOKEN_HASH VARCHAR(32) NOT NULL,
- // OWNER VARCHAR(96) NOT NULL,
- // IS_SESSIONSCOPED CHAR NOT NULL,
- // IS_DEEP CHAR NOT NULL,
- // BIRTHDAY LONG NOT NULL,
- // TIMEOUT LONG NOT NULL
- // )
-
ADD_LOCK_DATA =
- "insert into JCR_LOCKS"
- + "(WS_NAME, NODE_ID, TOKEN_HASH, OWNER, IS_SESSIONSCOPED, IS_DEEP,
BIRTHDAY, TIMEOUT) VALUES( " + wsName
- + " ,?,?,?,?,?,?,?)";
+ "insert into JCR_LOCKS(WS_NAME, NODE_ID, TOKEN_HASH, OWNER,
IS_SESSIONSCOPED, IS_DEEP, BIRTHDAY, TIMEOUT) VALUES(?,?,?,?,?,?,?,?)";
- REMOVE_LOCK_DATA = "delete from JCR_LOCKS where WS_NAME=" + wsName +
" and NODE_ID=?";
+ REMOVE_LOCK_DATA = "delete from JCR_LOCKS where NODE_ID=? and
WS_NAME=?";
- REFRESH_LOCK_DATA =
- // TODO check list of updated columns
- "update JCR_LOCKS set OWNER=?, IS_SESSIONSCOPED=?, IS_DEEP=?, BIRTHDAY=?,
TIMEOUT=? where NODE_ID=?";
+ REFRESH_LOCK_DATA = "update JCR_LOCKS set BIRTHDAY=? where NODE_ID=? and
WS_NAME=?";
- GET_LOCKED_NODES = "select NODE_ID from JCR_LOCKS where WS_NAME=" +
wsName;
+ GET_LOCKED_NODES = "select NODE_ID from JCR_LOCKS where WS_NAME=?";
+ GET_LOCK_DATA = "select * from JCR_LOCKS where NODE_ID=? and WS_NAME=?";
}
+ /**
+ * Inserts new lock data into DB
+ *
+ * @param data
+ * @return
+ * @throws LockException
+ */
public int addLockData(LockData data) throws LockException
{
-
if (!isOpened())
{
throw new IllegalStateException("Connection is closed");
@@ -110,18 +131,22 @@
try
{
if (insertLockData == null)
+ {
insertLockData = dbConnection.prepareStatement(ADD_LOCK_DATA);
+ }
else
+ {
insertLockData.clearParameters();
+ }
+ insertLockData.setString(1, wsName);
+ insertLockData.setString(2, data.getNodeIdentifier());
+ insertLockData.setString(3, data.getTokenHash());
+ insertLockData.setString(4, data.getOwner());
+ insertLockData.setBoolean(5, data.isSessionScoped());
+ insertLockData.setBoolean(6, data.isDeep());
+ insertLockData.setLong(7, data.getBirthDay());
+ insertLockData.setLong(8, data.getTimeOut());
- insertLockData.setString(1, data.getNodeIdentifier());
- insertLockData.setString(2, data.getTokenHash());
- insertLockData.setString(3, data.getOwner());
- insertLockData.setBoolean(4, data.isSessionScoped());
- insertLockData.setBoolean(5, data.isDeep());
- insertLockData.setLong(6, data.getBirthDay());
- insertLockData.setLong(7, data.getTimeOut());
-
return insertLockData.executeUpdate();
}
catch (SQLException e)
@@ -130,6 +155,13 @@
}
}
+ /**
+ * Removes LockData for given node identifier from database
+ *
+ * @param nodeID
+ * @return
+ * @throws LockException
+ */
public int removeLockData(String nodeID) throws LockException
{
if (!isOpened())
@@ -139,11 +171,16 @@
try
{
if (removeLockData == null)
- removeLockData = dbConnection.prepareStatement(ADD_LOCK_DATA);
+ {
+ removeLockData = dbConnection.prepareStatement(REMOVE_LOCK_DATA);
+ }
else
+ {
removeLockData.clearParameters();
-
+ }
+ // REMOVE_LOCK_DATA = "delete from JCR_LOCKS where NODE_ID=? and
WS_NAME=?";
removeLockData.setString(1, nodeID);
+ removeLockData.setString(2, wsName);
return removeLockData.executeUpdate();
}
@@ -154,7 +191,11 @@
}
/**
- * Refreshes given lockData
+ * Refreshes given LockData (updates birthday column)
+ *
+ * @param data
+ * @return
+ * @throws LockException
*/
public int refreshLockData(LockData data) throws LockException
{
@@ -165,20 +206,20 @@
try
{
if (refreshLockData == null)
+ {
refreshLockData = dbConnection.prepareStatement(REFRESH_LOCK_DATA);
+ }
else
+ {
refreshLockData.clearParameters();
+ }
- //update JCR_LOCKS set OWNER=?, IS_SESSIONSCOPED=?, IS_DEEP=?, BIRTHDAY=?,
TIMEOUT=? where NODE_ID=?;
+ // REFRESH_LOCK_DATA = "update JCR_LOCKS set BIRTHDAY=? where NODE_ID=? and
WS_NAME=?";
+ refreshLockData.setLong(1, data.getBirthDay());
+ refreshLockData.setString(2, data.getNodeIdentifier());
+ refreshLockData.setString(3, wsName);
- refreshLockData.setString(1, data.getOwner());
- refreshLockData.setBoolean(2, data.isSessionScoped());
- refreshLockData.setBoolean(3, data.isDeep());
- refreshLockData.setLong(4, data.getBirthDay());
- refreshLockData.setLong(5, data.getTimeOut());
- refreshLockData.setString(6, data.getNodeIdentifier());
-
- return removeLockData.executeUpdate();
+ return refreshLockData.executeUpdate();
}
catch (SQLException e)
{
@@ -187,16 +228,92 @@
}
/**
- * Returns set of locked nodes identifiers
+ * Returns the set of locked nodes identifiers
+ *
+ * @return
+ * @throws LockException
*/
public Set<String> getLockedNodes() throws LockException
{
- return null;
+ if (!isOpened())
+ {
+ throw new IllegalStateException("Connection is closed");
+ }
+ try
+ {
+ if (getLockedNodes == null)
+ {
+ getLockedNodes = dbConnection.prepareStatement(GET_LOCKED_NODES);
+ }
+ else
+ {
+ getLockedNodes.clearParameters();
+ }
+ // GET_LOCKED_NODES = "select NODE_ID from JCR_LOCKS where
WS_NAME=?";
+ getLockedNodes.setString(1, wsName);
+ // get result set
+ ResultSet result = getLockedNodes.executeQuery();
+ Set<String> identifiers = new HashSet<String>();
+ // traverse result set
+ while (result.next())
+ {
+ identifiers.add(new String(result.getString(COLUMN_NODE_ID)));
+ }
+ return identifiers;
+ }
+ catch (SQLException e)
+ {
+ throw new LockException(e);
+ }
}
/**
- * {@inheritDoc}
- */
+ * Returns LockData for given node identifier from database
+ * or null if not exists
+ *
+ * @param identifier
+ * @return
+ * @throws LockException
+ */
+ public LockData getLockData(String identifier) throws LockException
+ {
+ if (!isOpened())
+ {
+ throw new IllegalStateException("Connection is closed");
+ }
+ try
+ {
+ if (getLockData == null)
+ {
+ getLockData = dbConnection.prepareStatement(GET_LOCK_DATA);
+ }
+ else
+ {
+ getLockData.clearParameters();
+ }
+ // GET_LOCK_DATA = "select * from JCR_LOCKS where NODE_ID=? and
WS_NAME=?";
+ getLockData.setString(1, identifier);
+ getLockData.setString(2, wsName);
+ // get result set
+ ResultSet result = getLockData.executeQuery();
+ if (result.next())
+ {
+ return new LockData(result.getString(COLUMN_NODE_ID),
result.getString(COLUMN_TOKEN_HASH), result
+ .getBoolean(COLUMN_IS_DEEP), result.getBoolean(COLUMN_IS_SESSIONSCOPED),
result.getString(COLUMN_OWNER),
+ result.getLong(COLUMN_TIMEOUT), result.getLong(COLUMN_BIRTHDAY));
+ }
+ return null;
+ }
+ catch (SQLException e)
+ {
+ throw new LockException(e);
+ }
+ }
+
+ /**
+ * Check if connection is alive and opened
+ * @return
+ */
public boolean isOpened()
{
try
@@ -211,7 +328,10 @@
}
/**
- * {@inheritDoc}
+ * Closes database connectio
+ *
+ * @throws IllegalStateException
+ * @throws RepositoryException
*/
public final void close() throws IllegalStateException, RepositoryException
{
@@ -231,7 +351,10 @@
}
/**
- * {@inheritDoc}
+ * Commits and closes database connection
+ *
+ * @throws IllegalStateException
+ * @throws RepositoryException
*/
public final void commit() throws IllegalStateException, RepositoryException
{
@@ -239,7 +362,6 @@
{
throw new IllegalStateException("Connection is closed");
}
-
try
{
if (!dbConnection.isReadOnly())
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockPersistentDataManager.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockPersistentDataManager.java 2010-02-04
15:49:29 UTC (rev 1682)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockPersistentDataManager.java 2010-02-04
15:58:26 UTC (rev 1683)
@@ -63,13 +63,13 @@
if (dataSource != null)
{
// initialize DB table if needed
- Connection jdbcConn = null;
try
{
log.info("Creating LockManager DB tables.");
- jdbcConn = dataSource.getConnection();
+ Connection jdbcConn = dataSource.getConnection();
String dialect = DialectDetecter.detect(jdbcConn.getMetaData());
// if table not exists, create it
+ // connection is closed by DB initializer
initDatabase(dataSourceName, jdbcConn, dialect);
}
catch (SQLException e)
@@ -80,21 +80,6 @@
{
throw new RepositoryException(e);
}
- finally
- {
- // close connection even if exception
- if (jdbcConn != null)
- {
- try
- {
- jdbcConn.close();
- }
- catch (SQLException e)
- {
- throw new RepositoryException(e);
- }
- }
- }
}
else
{
Added:
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockPerstistentDataManager.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockPerstistentDataManager.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockPerstistentDataManager.java 2010-02-04
15:58:26 UTC (rev 1683)
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2010 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.JcrImplBaseTest;
+import org.exoplatform.services.jcr.impl.core.lock.jbosscache.LockData;
+import org.exoplatform.services.jcr.impl.core.lock.jbosscache.LockJDBCConnection;
+import org.exoplatform.services.jcr.impl.core.lock.jbosscache.LockPersistentDataManager;
+
+import java.util.Set;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.lock.LockException;
+
+/**
+ * @author <a href="mailto:nikolazius@gmail.com">Nikolay
Zamosenchuk</a>
+ * @version $Id: TestLockPerstistentDataManager.java 34360 2009-07-22 23:58:59Z
nzamosenchuk $
+ *
+ */
+public class TestLockPerstistentDataManager extends JcrImplBaseTest
+{
+ public void testAddLockData() throws RepositoryException
+ {
+ LockPersistentDataManager dataManager = new
LockPersistentDataManager("jdbcjcr", "ws");
+ LockJDBCConnection connection = null;
+ try
+ {
+ // get connection to lock storage
+ connection = dataManager.openConnection(false);
+ // put lock data
+ connection.addLockData(new LockData("identifier", "hash",
false, false, "owner", 100));
+ // commit also closes connection
+ connection.commit();
+ // acquire new connection
+ connection = dataManager.openConnection(false);
+ // get lock data
+ LockData lockData = connection.getLockData("identifier");
+ // asserts
+ assertTrue("Lock data should not be null", lockData != null);
+ assertEquals("identifier", lockData.getNodeIdentifier());
+ assertEquals("hash", lockData.getTokenHash());
+ }
+ finally
+ {
+ if (connection != null)
+ {
+ connection.close();
+ }
+ }
+ }
+
+ public void testRemoveLockData() throws RepositoryException
+ {
+ LockPersistentDataManager dataManager = new
LockPersistentDataManager("jdbcjcr", "ws");
+ LockJDBCConnection connection = null;
+ try
+ {
+ // get connection to lock storage
+ connection = dataManager.openConnection(false);
+ // put lock data
+ connection.addLockData(new LockData("identifier2", "hash",
false, false, "owner", 100));
+ // commit also closes connection
+ connection.commit();
+ // acquire new connection
+ connection = dataManager.openConnection(false);
+ // get lock data
+ LockData lockData = connection.getLockData("identifier2");
+ // asserts
+ assertTrue("Lock data should not be null", lockData != null);
+ // remove lock data
+ connection.removeLockData("identifier2");
+ // commit also closes connection
+ connection.commit();
+ // acquire new connection
+ connection = dataManager.openConnection(false);
+ lockData = connection.getLockData("identifier2");
+ // asserts
+ assertTrue("Lock data should be null", lockData == null);
+ }
+ finally
+ {
+ if (connection != null)
+ {
+ connection.close();
+ }
+ }
+ }
+
+ public void testRefreshLockData() throws RepositoryException
+ {
+ LockPersistentDataManager dataManager = new
LockPersistentDataManager("jdbcjcr", "ws");
+ LockJDBCConnection connection = null;
+ try
+ {
+ // get connection to lock storage
+ connection = dataManager.openConnection(false);
+ // put lock data
+ connection.addLockData(new LockData("identifier3", "hash",
false, false, "owner", 100));
+ // commit also closes connection
+ connection.commit();
+ // sleep
+ try
+ {
+ Thread.sleep(1000);
+ }
+ catch (InterruptedException e)
+ {
+ }
+ // acquire new connection
+ connection = dataManager.openConnection(false);
+ // get lock Data
+ LockData lockData = connection.getLockData("identifier3");
+ Long timeToDeathOriginal = lockData.getTimeToDeath();
+ // refresh lock data
+ connection.refreshLockData(new LockData("identifier3",
"hash", false, false, "owner", 100));
+ // commit also closes connection
+ connection.commit();
+ // acquire new connection
+ connection = dataManager.openConnection(false);
+ lockData = connection.getLockData("identifier3");
+ Long timeToDeathNew = lockData.getTimeToDeath();
+ // asserts
+ assertTrue("Birthday should be refreshed", timeToDeathNew >
timeToDeathOriginal);
+ }
+ finally
+ {
+ if (connection != null)
+ {
+ connection.close();
+ }
+ }
+ }
+
+ public void testgetLockedNodes() throws RepositoryException
+ {
+ LockPersistentDataManager dataManager = new
LockPersistentDataManager("jdbcjcr", "test_workspace");
+ LockPersistentDataManager dataManagerAnotherWS = new
LockPersistentDataManager("jdbcjcr", "another_workspace");
+ LockJDBCConnection connection = null;
+ try
+ {
+ // get connection to lock storage
+ connection = dataManager.openConnection(false);
+ // put lock data
+ connection.addLockData(new LockData("identifier1-listTest",
"hash1", false, false, "owner", 100));
+ connection.addLockData(new LockData("identifier2-listTest",
"hash2", false, false, "owner", 100));
+ connection.addLockData(new LockData("identifier3-listTest",
"hash3", false, false, "owner", 100));
+ connection.addLockData(new LockData("identifier4-listTest",
"hash4", false, false, "owner", 100));
+ // commit also closes connection
+ connection.commit();
+
+ // Adding lock data to another workspace
+ connection = dataManagerAnotherWS.openConnection(false);
+ // this lock data is from another workspace and shouldn't be in result set
+ connection.addLockData(new LockData("identifier1-listTest",
"hash1", false, false, "owner", 100));
+ connection.commit();
+ // acquire new connection
+ connection = dataManager.openConnection(false);
+ // get set
+ Set<String> identifiers = connection.getLockedNodes();
+ assertEquals("Wrong size of result.", 4, identifiers.size());
+ }
+ finally
+ {
+ if (connection != null)
+ {
+ connection.close();
+ }
+ }
+ }
+
+ public void testAddLockDataTwice() throws RepositoryException
+ {
+ LockPersistentDataManager dataManager = new
LockPersistentDataManager("jdbcjcr", "ws");
+ LockJDBCConnection connection = null;
+ try
+ {
+ // get connection to lock storage
+ connection = dataManager.openConnection(false);
+ // put lock data
+ connection.addLockData(new LockData("identifier", "hash",
false, false, "owner", 100));
+ // commit also closes connection
+ connection.commit();
+ // acquire new connection
+ connection = dataManager.openConnection(false);
+ // put lock data with same identifier
+ connection.addLockData(new LockData("identifier", "hash",
false, false, "owner", 100));
+ fail("exception expected!");
+ }
+ catch (LockException e) {
+ // it's ok
+ }
+ finally
+ {
+ if (connection != null)
+ {
+ connection.close();
+ }
+ }
+ }
+
+}
Property changes on:
jcr/trunk/exo.jcr.component.core/src/test/java/org/exoplatform/services/jcr/impl/core/lock/TestLockPerstistentDataManager.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain