Author: sergiykarpenko
Date: 2010-02-04 04:16:48 -0500 (Thu, 04 Feb 2010)
New Revision: 1672
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockDBInitializer.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
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/OracleLockDBInitializer.java
jcr/trunk/exo.jcr.component.core/src/main/resources/conf/storage/lock-jdbc.default.sql
jcr/trunk/exo.jcr.component.core/src/main/resources/conf/storage/lock-jdbc.ora.sql
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManager.java
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockData.java
Log:
EXOJCR-472: LockPersisterDataManager added
Modified:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManager.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManager.java 2010-02-03
17:43:12 UTC (rev 1671)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/CacheableLockManager.java 2010-02-04
09:16:48 UTC (rev 1672)
@@ -147,7 +147,7 @@
/**
* Context recall is a workaround of JDBCCacheLoader starting.
*/
- private final InitialContextInitializer context;
+ //private final InitialContextInitializer context;
/**
* Run time lock time out.
@@ -241,7 +241,7 @@
pendingLocks = new HashMap<String, LockData>();
sessionLockManagers = new HashMap<String, CacheableSessionLockManager>();
- this.context = context;
+ //this.context = context;
dataManager.addItemPersistenceListener(this);
@@ -255,7 +255,7 @@
new ExoJBossCacheFactory<Serializable, Object>(cfm,
transactionManager);
cache = factory.createCache(config.getLockManager());
-
+
cache.create();
cache.start();
@@ -567,12 +567,9 @@
else
{
Fqn<String> fqn = makeLockFqn(newLockData.getNodeIdentifier());
- if (cache.getRoot().hasChild(fqn))
+ Object oldValue = cache.put(fqn, LOCK_DATA, newLockData);
+ if (oldValue == null)
{
- cache.getRoot().addChild(fqn);
- }
- else
- {
throw new LockException("Can't refresh lock for node " +
newLockData.getNodeIdentifier()
+ " since lock is not exist");
}
@@ -970,7 +967,7 @@
/**
* Will be created structured node in cache, like /$LOCKS
*/
- private void createStructuredNode(Fqn fqn)
+ private void createStructuredNode(Fqn<String> fqn)
{
Node<Serializable, Object> node = cache.getRoot().getChild(fqn);
if (node == null)
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockDBInitializer.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockDBInitializer.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockDBInitializer.java 2010-02-04
09:16:48 UTC (rev 1672)
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2003-2010 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.core.lock.jbosscache;
+
+import org.exoplatform.services.jcr.impl.storage.jdbc.init.DBInitializerException;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: LockDBInitializer.java 111 2008-11-11 11:11:11Z serg $
+ */
+public class LockDBInitializer
+{
+ static public String SQL_DELIMITER = ";";
+
+ static public String SQL_DELIMITER_COMMENT_PREFIX = "/*$DELIMITER:";
+
+ static public String SQL_TABLE_NAME_PATTERN = "${table.name}";
+
+ static public String SQL_CREATETABLE =
"^(CREATE(\\s)+TABLE(\\s)+(IF(\\s)+NOT(\\s)+EXISTS(\\s)+)*){1}";
+
+ static public String SQL_CREATEVIEW =
"^(CREATE(\\s)+VIEW(\\s)+(IF(\\s)+NOT(\\s)+EXISTS(\\s)+)*){1}";
+
+ static public String SQL_OBJECTNAME =
"((JCR_[A-Z_]+){1}(\\s*?|(\\(\\))*?)+)+?";
+
+ static public String SQL_CREATEINDEX =
"^(CREATE(\\s)+(UNIQUE(\\s)+)*INDEX(\\s)+){1}";
+
+ static public String SQL_ONTABLENAME =
"(ON(\\s)+(JCR_[A-Z_]+){1}(\\s*?|(\\(\\))*?)+){1}";
+
+ static public String SQL_CREATESEQUENCE =
"^(CREATE(\\s)+SEQUENCE(\\s)+){1}";
+
+ static public String SQL_CREATETRIGGER =
"^(CREATE(\\s)+(OR(\\s){1}REPLACE(\\s)+)*TRIGGER(\\s)+){1}";
+
+ static public String SQL_TRIGGERNAME =
"(([A-Z_]+JCR_[A-Z_]+){1}(\\s*?|(\\(\\))*?)+)+?";
+
+ protected final Log log = ExoLogger.getLogger("jcr.LockDBInitializer");
+
+ protected final Connection connection;
+
+ protected final String containerName;
+
+ protected final String script;
+
+ //protected final boolean multiDb;
+
+ protected final Pattern creatTablePattern;
+
+ protected final Pattern creatViewPattern;
+
+ protected final Pattern dbObjectNamePattern;
+
+ protected final Pattern creatIndexPattern;
+
+ protected final Pattern onTableNamePattern;
+
+ protected final Pattern creatSequencePattern;
+
+ protected final Pattern creatTriggerPattern;
+
+ protected final Pattern dbTriggerNamePattern;
+
+ private final String tableName;
+
+ public LockDBInitializer(String containerName, Connection connection, String
scriptPath, String tableName)
+ throws IOException
+ {
+ this.tableName = tableName;
+ this.connection = connection;
+ this.script = script(scriptPath);
+ this.containerName = containerName;
+
+ this.creatTablePattern = Pattern.compile(SQL_CREATETABLE,
Pattern.CASE_INSENSITIVE);
+ this.creatViewPattern = Pattern.compile(SQL_CREATEVIEW, Pattern.CASE_INSENSITIVE);
+ this.dbObjectNamePattern = Pattern.compile(SQL_OBJECTNAME,
Pattern.CASE_INSENSITIVE);
+ this.creatIndexPattern = Pattern.compile(SQL_CREATEINDEX,
Pattern.CASE_INSENSITIVE);
+ this.onTableNamePattern = Pattern.compile(SQL_ONTABLENAME,
Pattern.CASE_INSENSITIVE);
+ this.creatSequencePattern = Pattern.compile(SQL_CREATESEQUENCE,
Pattern.CASE_INSENSITIVE);
+ this.creatTriggerPattern = Pattern.compile(SQL_CREATETRIGGER,
Pattern.CASE_INSENSITIVE);
+ this.dbTriggerNamePattern = Pattern.compile(SQL_TRIGGERNAME,
Pattern.CASE_INSENSITIVE);
+ }
+
+ protected String script(String scriptPath) throws IOException
+ {
+ String script = readScriptResource(scriptPath);
+
+ //replace table name pattern
+ // TODO make correct replacement
+ script.replaceAll(SQL_TABLE_NAME_PATTERN, tableName);
+ return script;
+ }
+
+ protected String readScriptResource(String path) throws IOException
+ {
+ InputStream is = this.getClass().getResourceAsStream(path);
+ InputStreamReader isr = new InputStreamReader(is);
+ try
+ {
+ StringBuilder sbuff = new StringBuilder();
+ char[] buff = new char[is.available()];
+ int r = 0;
+ while ((r = isr.read(buff)) > 0)
+ {
+ sbuff.append(buff, 0, r);
+ }
+
+ return sbuff.toString();
+ }
+ finally
+ {
+ try
+ {
+ is.close();
+ }
+ catch (IOException e)
+ {
+ }
+ }
+ }
+
+ public String cleanWhitespaces(String string)
+ {
+ if (string != null)
+ {
+ char[] cc = string.toCharArray();
+ for (int ci = cc.length - 1; ci > 0; ci--)
+ {
+ if (Character.isWhitespace(cc[ci]))
+ {
+ cc[ci] = ' ';
+ }
+ }
+ return new String(cc);
+ }
+ return string;
+ }
+
+ protected boolean isTableExists(Connection conn, String tableName) throws
SQLException
+ {
+ ResultSet trs = conn.getMetaData().getTables(null, null, tableName, null);
+ boolean res = false;
+ while (trs.next())
+ {
+ res = true; // check for columns/table type matching etc.
+ }
+ return res;
+ }
+
+ protected boolean isIndexExists(Connection conn, String tableName, String indexName)
throws SQLException
+ {
+ ResultSet irs = conn.getMetaData().getIndexInfo(null, null, tableName, false,
true);
+ boolean res = false;
+ while (irs.next())
+ {
+ if (irs.getShort("TYPE") != DatabaseMetaData.tableIndexStatistic
+ &&
irs.getString("INDEX_NAME").equalsIgnoreCase(indexName))
+ res = true; // check for index params matching etc.
+ }
+ return res;
+ }
+
+ protected boolean isSequenceExists(Connection conn, String sequenceName) throws
SQLException
+ {
+ return false;
+ }
+
+ protected boolean isTriggerExists(Connection conn, String triggerName) throws
SQLException
+ {
+ return false;
+ }
+
+ public boolean isObjectExists(Connection conn, String sql) throws SQLException
+ {
+ Matcher tMatcher = creatTablePattern.matcher(sql);
+ if (tMatcher.find())
+ {
+ // CREATE TABLE
+ tMatcher = dbObjectNamePattern.matcher(sql);
+ if (tMatcher.find())
+ {
+ // got table name
+ String tableName = sql.substring(tMatcher.start(), tMatcher.end());
+ if (isTableExists(conn, tableName))
+ {
+ if (log.isDebugEnabled())
+ log.debug("Table is already exists " + tableName);
+ return true;
+ }
+ }
+ }
+ else if ((tMatcher = creatViewPattern.matcher(sql)).find())
+ {
+ // CREATE VIEW
+ tMatcher = dbObjectNamePattern.matcher(sql);
+ if (tMatcher.find())
+ {
+ // got view name
+ String tableName = sql.substring(tMatcher.start(), tMatcher.end());
+ if (isTableExists(conn, tableName))
+ {
+ if (log.isDebugEnabled())
+ log.debug("View is already exists " + tableName);
+ return true;
+ }
+ }
+ }
+ else if ((tMatcher = creatIndexPattern.matcher(sql)).find())
+ {
+ // CREATE INDEX
+ tMatcher = dbObjectNamePattern.matcher(sql);
+ if (tMatcher.find())
+ {
+ // got index name
+ String indexName = sql.substring(tMatcher.start(), tMatcher.end());
+ if ((tMatcher = onTableNamePattern.matcher(sql)).find())
+ {
+ String onTableName = sql.substring(tMatcher.start(), tMatcher.end());
+ if ((tMatcher = dbObjectNamePattern.matcher(onTableName)).find())
+ {
+ String tableName = onTableName.substring(tMatcher.start(),
tMatcher.end());
+ if (isIndexExists(conn, tableName, indexName))
+ {
+ if (log.isDebugEnabled())
+ log.debug("Index is already exists " + indexName);
+ return true;
+ }
+ }
+ else
+ {
+ log.warn("Index found but $TABLE_NAME is not detected '"
+ sql + "'");
+ }
+ }
+ else
+ {
+ log.warn("Index found but ON $TABLE_NAME clause is not detected
'" + sql + "'");
+ }
+ }
+ else
+ {
+ log.warn("Create index clause found but $INDEX_NAME is not detected
'" + sql + "'");
+ }
+ }
+ else if ((tMatcher = creatSequencePattern.matcher(sql)).find())
+ {
+ tMatcher = dbObjectNamePattern.matcher(sql);
+ if (tMatcher.find())
+ {
+ // got sequence name
+ String sequenceName = sql.substring(tMatcher.start(), tMatcher.end());
+ if (isSequenceExists(conn, sequenceName))
+ {
+ if (log.isDebugEnabled())
+ log.debug("Sequence is already exists " + sequenceName);
+ return true;
+ }
+ }
+ }
+ else if ((tMatcher = creatTriggerPattern.matcher(sql)).find())
+ {
+ tMatcher = dbTriggerNamePattern.matcher(sql);
+ if (tMatcher.find())
+ {
+ // got trigger name
+ String triggerName = sql.substring(tMatcher.start(), tMatcher.end());
+ if (isTriggerExists(conn, triggerName))
+ {
+ if (log.isDebugEnabled())
+ log.debug("Trigger is already exists " + triggerName);
+ return true;
+ }
+ }
+ }
+ else
+ {
+ if (log.isDebugEnabled())
+ log.debug("Command is not detected for check '" + sql +
"'");
+ }
+
+ return false;
+ }
+
+ public void init() throws DBInitializerException
+ {
+ String[] scripts = null;
+ if (script.startsWith(SQL_DELIMITER_COMMENT_PREFIX))
+ {
+ // read custom prefix
+ try
+ {
+ String s = script.substring(SQL_DELIMITER_COMMENT_PREFIX.length());
+ int endOfDelimIndex = s.indexOf("*/");
+ String delim = s.substring(0, endOfDelimIndex).trim();
+ s = s.substring(endOfDelimIndex + 2).trim();
+ scripts = s.split(delim);
+ }
+ catch (IndexOutOfBoundsException e)
+ {
+ log.warn("Error of parse SQL-script file. Invalid DELIMITER
configuration. Valid format is '"
+ + SQL_DELIMITER_COMMENT_PREFIX + "XXX*/' at begin of the
SQL-script file, where XXX - DELIMITER string."
+ + " Spaces will be trimed. ", e);
+ log.info("Using DELIMITER:[" + SQL_DELIMITER + "]");
+ scripts = script.split(SQL_DELIMITER);
+ }
+ }
+ else
+ {
+ scripts = script.split(SQL_DELIMITER);
+ }
+
+ String sql = null;
+ try
+ {
+ connection.setAutoCommit(false);
+
+ for (String scr : scripts)
+ {
+ String s = cleanWhitespaces(scr.trim());
+ if (s.length() > 0)
+ {
+ if (isObjectExists(connection, sql = s))
+ continue;
+
+ if (log.isDebugEnabled())
+ log.debug("Execute script: \n[" + sql + "]");
+
+ connection.createStatement().executeUpdate(sql);
+ }
+ }
+
+ //rootInit(connection);
+
+ connection.commit();
+ log.info("DB schema of DataSource: '" + containerName +
"' initialized succesfully");
+ }
+ catch (SQLException e)
+ {
+ try
+ {
+ connection.rollback();
+ }
+ catch (SQLException re)
+ {
+ log.error("Rollback error " + e, e);
+ }
+
+ SQLException next = e.getNextException();
+ String errorTrace = "";
+ while (next != null)
+ {
+ errorTrace += next.getMessage() + "; ";
+ next = e.getNextException();
+ }
+ Throwable cause = e.getCause();
+ String msg =
+ "Could not create db schema of DataSource: '" + containerName +
"'. Reason: " + e.getMessage() + "; "
+ + errorTrace + (cause != null ? " (Cause: " + cause.getMessage()
+ ")" : "") + ". Last command: " + sql;
+
+ throw new DBInitializerException(msg, e);
+ }
+ finally
+ {
+ try
+ {
+ connection.close();
+ }
+ catch (SQLException e)
+ {
+ log.error("Error of a connection closing. " + e, e);
+ }
+ }
+ }
+}
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-03
17:43:12 UTC (rev 1671)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockData.java 2010-02-04
09:16:48 UTC (rev 1672)
@@ -235,6 +235,11 @@
return timeOut;
}
+ protected long getBirthDay()
+ {
+ return birthday;
+ }
+
public void setTimeOut(long timeOut)
{
this.timeOut = timeOut;
Added:
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
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockJDBCConnection.java 2010-02-04
09:16:48 UTC (rev 1672)
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2003-2010 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.core.lock.jbosscache;
+
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+import javax.jcr.RepositoryException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: LockJDBCConnection.java 111 2008-11-11 11:11:11Z serg $
+ */
+public class LockJDBCConnection
+{
+
+ private final Log LOG = ExoLogger.getLogger(LockPersistentDataManager.class);
+
+ protected String ADD_LOCK_DATA;
+
+ protected String REMOVE_LOCK_DATA;
+
+ private PreparedStatement insertLockData;
+
+ private PreparedStatement removeLockData;
+
+ private Connection dbConnection;
+
+ public LockJDBCConnection(Connection dbConnection, String tableName) throws
SQLException
+ {
+
+ this.dbConnection = dbConnection;
+
+ if (dbConnection.getAutoCommit())
+ {
+ dbConnection.setAutoCommit(false);
+ }
+
+ prepareQueries(tableName);
+ }
+
+ protected void prepareQueries(String tableName) throws SQLException
+ {
+ // Table structure
+ // CREATE TABLE ${table.name}(
+ // 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 " + tableName
+ + "(NODE_ID, TOKEN_HASH, OWNER, IS_SESSIONSCOPED, IS_DEEP, BIRTHDAY,
TIMEOUT) VALUES(?,?,?,?,?,?,?)";
+
+ REMOVE_LOCK_DATA = "delete from " + tableName + " where
NODE_ID=?";
+
+ }
+
+ public int addLockData(LockData data) throws RepositoryException
+ {
+
+ if (!isOpened())
+ {
+ throw new IllegalStateException("Connection is closed");
+ }
+ try
+ {
+ if (insertLockData == null)
+ insertLockData = dbConnection.prepareStatement(ADD_LOCK_DATA);
+ else
+ insertLockData.clearParameters();
+
+ 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)
+ {
+ throw new RepositoryException(e);
+ }
+ }
+
+ public int removeLockData(String nodeID) throws RepositoryException
+ {
+ if (!isOpened())
+ {
+ throw new IllegalStateException("Connection is closed");
+ }
+ try
+ {
+ if (removeLockData == null)
+ removeLockData = dbConnection.prepareStatement(ADD_LOCK_DATA);
+ else
+ removeLockData.clearParameters();
+
+ removeLockData.setString(1, nodeID);
+
+ return removeLockData.executeUpdate();
+ }
+ catch (SQLException e)
+ {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isOpened()
+ {
+ try
+ {
+ return !dbConnection.isClosed();
+ }
+ catch (SQLException e)
+ {
+ LOG.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void close() throws IllegalStateException, RepositoryException
+ {
+ if (!isOpened())
+ {
+ throw new IllegalStateException("Connection is closed");
+ }
+
+ try
+ {
+ dbConnection.close();
+ }
+ catch (SQLException e)
+ {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void commit() throws IllegalStateException, RepositoryException
+ {
+ if (!isOpened())
+ {
+ throw new IllegalStateException("Connection is closed");
+ }
+
+ try
+ {
+ if (!dbConnection.isReadOnly())
+ {
+ dbConnection.commit();
+ }
+
+ dbConnection.close();
+ }
+ catch (SQLException e)
+ {
+ throw new RepositoryException(e);
+ }
+ }
+
+}
Added:
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
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/LockPersistentDataManager.java 2010-02-04
09:16:48 UTC (rev 1672)
@@ -0,0 +1,180 @@
+/*
+ * 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.jbosscache;
+
+import org.exoplatform.services.jcr.impl.storage.jdbc.DBConstants;
+import org.exoplatform.services.jcr.impl.storage.jdbc.DialectDetecter;
+import org.exoplatform.services.jcr.impl.storage.jdbc.init.DBInitializerException;
+import org.exoplatform.services.log.ExoLogger;
+import org.exoplatform.services.log.Log;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import javax.jcr.RepositoryException;
+import javax.naming.InitialContext;
+import javax.sql.DataSource;
+
+/**
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @author <a href="mailto:nikolazius@gmail.com">Nikolay
Zamosenchuk</a>
+ * @version $Id: LockPersistentDataManager.java 34360 2009-07-22 23:58:59Z nzamosenchuk
$
+ *
+ */
+public class LockPersistentDataManager
+{
+ private final Log log = ExoLogger.getLogger(LockPersistentDataManager.class);
+
+ private DataSource dataSource;
+
+ private String tableName;
+
+ /**
+ * @param dataSourceName DataSource name
+ * @param tableName Name of DB table
+ * @throws RepositoryException
+ */
+ public LockPersistentDataManager(String dataSourceName, String tableName) throws
RepositoryException, IOException
+ {
+ this.tableName = tableName;
+
+ // try to resolve DataSource
+ try
+ {
+ dataSource = (DataSource)new InitialContext().lookup(dataSourceName);
+ if (dataSource != null)
+ {
+ // initialize DB table if needed
+ Connection jdbcConn = null;
+ try
+ {
+ log.info("Creating LockManager DB tables.");
+ jdbcConn = dataSource.getConnection();
+ String dialect = DialectDetecter.detect(jdbcConn.getMetaData());
+ // if table not exists, create it
+ initDatabase(dataSourceName, jdbcConn, dialect, tableName);
+ }
+ catch (SQLException e)
+ {
+ throw new RepositoryException(e);
+ }
+ finally
+ {
+ // close connection even if exception
+ if (jdbcConn != null)
+ {
+ try
+ {
+ jdbcConn.close();
+ }
+ catch (SQLException e)
+ {
+ throw new RepositoryException(e);
+ }
+ }
+ }
+ }
+ else
+ {
+ throw new RepositoryException("Datasource '" + dataSourceName +
"' is not bound in this context.");
+ }
+ }
+ catch (Exception e)
+ {
+ throw new RepositoryException(e);
+ }
+
+ }
+
+ public LockJDBCConnection openConnection(boolean readOnly) throws RepositoryException
+ {
+ try
+ {
+ return new LockJDBCConnection(getJDBCConnection(readOnly), tableName);
+ }
+ catch (SQLException e)
+ {
+ throw new RepositoryException(e);
+ }
+ }
+
+ /**
+ * Returns connection to database
+ * @return
+ *
+ * @return connection to database
+ * @throws RepositoryException
+ * @throws RepositoryException
+ */
+ private Connection getJDBCConnection(boolean readOnly) throws RepositoryException
+ {
+ try
+ {
+ //TODO make connection as in GenericConnectionFactory
+ final Connection conn = dataSource.getConnection();
+
+ if (readOnly)
+ {
+ // set this feature only if it asked
+ conn.setReadOnly(readOnly);
+ }
+
+ return conn;
+ }
+ catch (SQLException e)
+ {
+ String err =
+ "Error of JDBC connection open. SQLException: " + e.getMessage() +
", SQLState: " + e.getSQLState()
+ + ", VendorError: " + e.getErrorCode();
+ throw new RepositoryException(err, e);
+ }
+ }
+
+ /**
+ * Creates table in DB if not present
+ *
+ * @param dialect
+ * @throws IOException
+ * @throws DBInitializerException
+ */
+ protected void initDatabase(String dataSource, Connection jdbcConn, String dialect,
String tableName)
+ throws IOException, DBInitializerException
+ {
+ LockDBInitializer dbInitializer = null;
+
+ // prepare DB
+ if (DBConstants.DB_DIALECT_ORACLE.equals(dialect))
+ {
+ // oracle preparation script
+ String sqlPath = "/conf/storage/lock-jdbc.ora.sql";
+ dbInitializer = new OracleLockDBInitializer(dataSource, jdbcConn, sqlPath,
tableName);
+ }
+ else
+ {
+ // generic preparation script
+ String sqlPath = "/conf/storage/lock-jdbc.default.sql";
+ dbInitializer = new LockDBInitializer(dataSource, jdbcConn, sqlPath,
tableName);
+ }
+
+ // init DB
+ dbInitializer.init();
+ }
+
+}
\ No newline at end of file
Added:
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/OracleLockDBInitializer.java
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/OracleLockDBInitializer.java
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/java/org/exoplatform/services/jcr/impl/core/lock/jbosscache/OracleLockDBInitializer.java 2010-02-04
09:16:48 UTC (rev 1672)
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2003-2010 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.core.lock.jbosscache;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+/**
+ * Created by The eXo Platform SAS.
+ *
+ * <br/>Date:
+ *
+ * @author <a href="karpenko.sergiy(a)gmail.com">Karpenko Sergiy</a>
+ * @version $Id: OracleLockDBInitializer.java 111 2008-11-11 11:11:11Z serg $
+ */
+public class OracleLockDBInitializer extends LockDBInitializer
+{
+
+ public OracleLockDBInitializer(String containerName, Connection connection, String
script, String tableName)
+ throws IOException
+ {
+ super(containerName, connection, script, tableName);
+ }
+
+ @Override
+ protected boolean isSequenceExists(Connection conn, String sequenceName) throws
SQLException
+ {
+ try
+ {
+ ResultSet srs = conn.createStatement().executeQuery("SELECT " +
sequenceName + ".nextval FROM DUAL");
+ if (srs.next())
+ {
+ return true;
+ }
+ srs.close();
+ return false;
+ }
+ catch (SQLException e)
+ {
+ // check: ORA-02289: sequence does not exist
+ if (e.getMessage().indexOf("ORA-02289") >= 0)
+ return false;
+ throw e;
+ }
+ }
+
+ @Override
+ protected boolean isTriggerExists(Connection conn, String triggerName) throws
SQLException
+ {
+ String sql = "SELECT COUNT(trigger_name) FROM all_triggers WHERE trigger_name
= '" + triggerName + "'";
+ ResultSet r = conn.createStatement().executeQuery(sql);
+ if (r.next())
+ return r.getInt(1) > 0;
+ else
+ return false;
+ }
+
+ @Override
+ protected boolean isTableExists(Connection conn, String tableName) throws
SQLException
+ {
+ try
+ {
+ conn.createStatement().executeUpdate("SELECT 1 FROM " + tableName);
+ return true;
+ }
+ catch (SQLException e)
+ {
+ // check: ORA-00942: table or view does not exist
+ if (e.getMessage().indexOf("ORA-00942") >= 0)
+ return false;
+ throw e;
+ }
+ }
+
+ @Override
+ protected boolean isIndexExists(Connection conn, String tableName, String indexName)
throws SQLException
+ {
+ // use of oracle system view
+ String sql = "SELECT COUNT(index_name) FROM all_indexes WHERE
index_name='" + indexName + "'";
+ ResultSet r = conn.createStatement().executeQuery(sql);
+ if (r.next())
+ return r.getInt(1) > 0;
+ else
+ return false;
+ }
+}
Added:
jcr/trunk/exo.jcr.component.core/src/main/resources/conf/storage/lock-jdbc.default.sql
===================================================================
---
jcr/trunk/exo.jcr.component.core/src/main/resources/conf/storage/lock-jdbc.default.sql
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/resources/conf/storage/lock-jdbc.default.sql 2010-02-04
09:16:48 UTC (rev 1672)
@@ -0,0 +1,9 @@
+CREATE TABLE ${table.name}(
+ 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 BIGINT NOT NULL,
+ TIMEOUT BIGINT NOT NULL
+);
\ No newline at end of file
Added: jcr/trunk/exo.jcr.component.core/src/main/resources/conf/storage/lock-jdbc.ora.sql
===================================================================
--- jcr/trunk/exo.jcr.component.core/src/main/resources/conf/storage/lock-jdbc.ora.sql
(rev 0)
+++
jcr/trunk/exo.jcr.component.core/src/main/resources/conf/storage/lock-jdbc.ora.sql 2010-02-04
09:16:48 UTC (rev 1672)
@@ -0,0 +1,11 @@
+/*$DELIMITER:/ */
+CREATE TABLE ${table.name}(
+ 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
+)
+/
\ No newline at end of file