[exo-jcr-commits] exo-jcr SVN: r1672 - in jcr/trunk/exo.jcr.component.core/src/main: resources/conf/storage and 1 other directory.

do-not-reply at jboss.org do-not-reply at jboss.org
Thu Feb 4 04:16:48 EST 2010


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 at 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 at 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 at gmail.com">Karpenko Sergiy</a>
+ * @author <a href="mailto:nikolazius at 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 at 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



More information about the exo-jcr-commits mailing list