[jboss-svn-commits] JBoss Portal SVN: r5217 - in trunk: . cms cms/jackrabbit-customization cms/jackrabbit-customization/lib cms/jackrabbit-customization/src cms/jackrabbit-customization/src/org cms/jackrabbit-customization/src/org/apache cms/jackrabbit-customization/src/org/apache/jackrabbit cms/jackrabbit-customization/src/org/apache/jackrabbit/core cms/jackrabbit-customization/src/org/apache/jackrabbit/core/state cms/src/main/org/jboss/portal/cms/hibernate/state cms/src/main/org/jboss/portal/cms/impl/jcr/command cms/src/main/org/jboss/portal/cms/impl/jcr/jackrabbit core core/src/resources/portal-cms-sar/META-INF core/src/resources/portal-cms-sar/conf/hibernate/cms

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Sep 18 00:24:04 EDT 2006


Author: sohil.shah at jboss.com
Date: 2006-09-18 00:21:11 -0400 (Mon, 18 Sep 2006)
New Revision: 5217

Added:
   trunk/cms/jackrabbit-customization/
   trunk/cms/jackrabbit-customization/lib/
   trunk/cms/jackrabbit-customization/lib/jackrabbit-core-1.0.1.jar
   trunk/cms/jackrabbit-customization/lib/jboss-cache.jar
   trunk/cms/jackrabbit-customization/lib/jgroups.jar
   trunk/cms/jackrabbit-customization/src/
   trunk/cms/jackrabbit-customization/src/org/
   trunk/cms/jackrabbit-customization/src/org/apache/
   trunk/cms/jackrabbit-customization/src/org/apache/jackrabbit/
   trunk/cms/jackrabbit-customization/src/org/apache/jackrabbit/core/
   trunk/cms/jackrabbit-customization/src/org/apache/jackrabbit/core/state/
   trunk/cms/jackrabbit-customization/src/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java
   trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/Base.java
   trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/JBossCachePersistenceManager.java
   trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/PortalCMSCacheLoader.java
   trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/Tools.java
   trunk/cms/src/main/org/jboss/portal/cms/impl/jcr/jackrabbit/ClusteredCacheListener.java
Modified:
   trunk/
   trunk/cms/
   trunk/cms/build.xml
   trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/HibernatePersistenceManager.java
   trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/VersionNode.java
   trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/VersionProp.java
   trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/VersionRefs.java
   trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/WSPNode.java
   trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/WSPProp.java
   trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/WSPRefs.java
   trunk/cms/src/main/org/jboss/portal/cms/impl/jcr/command/ContentGetVersionsCommand.java
   trunk/core/build.xml
   trunk/core/src/resources/portal-cms-sar/META-INF/
   trunk/core/src/resources/portal-cms-sar/META-INF/jboss-service.xml
   trunk/core/src/resources/portal-cms-sar/conf/hibernate/cms/domain.hbm.xml
   trunk/core/src/resources/portal-cms-sar/conf/hibernate/cms/hibernate.cfg.xml
Log:
first iteration of CMS performance enhancements - Includes a JBossCache based PersistenceManager and clustered caching of JackRabbit's internal caching mechanism


Property changes on: trunk
___________________________________________________________________
Name: svn:ignore
   + .project
.classpath
thirdparty
eclipseBin



Property changes on: trunk/cms
___________________________________________________________________
Name: svn:ignore
   - output
bin
bin

   + output
bin
bin
*.log


Modified: trunk/cms/build.xml
===================================================================
--- trunk/cms/build.xml	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/build.xml	2006-09-18 04:21:11 UTC (rev 5217)
@@ -84,6 +84,8 @@
          <path refid="sun.jaf.classpath"/>
          <path refid="xdoclet.xdoclet.classpath"/>
          <path refid="jcr.jcr.classpath"/>
+	     <!-- cms optimization integration -->
+	     <path refid="jgroups.jgroups.classpath"/>
       </path>
       
       
@@ -161,7 +163,22 @@
          <fileset dir="${jcr.jcr.root}/lib" includes="jcr-1.0.jar"/>
          <fileset dir="${apache.collections.root}/lib" includes="commons-collections.jar"/>
          <fileset dir="${apache.lucene.root}/lib" includes="lucene.jar"/>
-         <fileset dir="${jackrabbit.jackrabbit.lib}" includes="jackrabbit-core-1.0.jar"/>
+	
+	  	<!-- cms optimization integration - this contains a clustered cache enabled version
+	  	of jackrabbit customization of jackrabbit-core-1.0.1 codebase 
+	    For details regarding this customization see: cms/jackrabbit-customization
+	    also needed are jboss-cache.jar and jgroups.jar to support this customization
+	    1.4.0SP1
+	    
+	    TODO: This is fine for this iteration. Eventually we need to integrate these libraries
+	    for bundling in the thirdparty mechanism. This will follow in the next iteration
+	    -->
+	    <!--fileset dir="${jackrabbit.jackrabbit.lib}" includes="jackrabbit-core-1.0.jar"/-->
+	    <fileset dir="../cms/jackrabbit-customization/lib" includes="jackrabbit-core-1.0.1.jar"/>
+	  	<fileset dir="../cms/jackrabbit-customization/lib" includes="jboss-cache.jar"/>
+	  	<fileset dir="../cms/jackrabbit-customization/lib" includes="jgroups.jar"/>		 
+	     
+	
          <fileset dir="${slf4j.slf4j.lib}" includes="slf4j-log4j12.jar"/>   
       </jar>
 

Added: trunk/cms/jackrabbit-customization/lib/jackrabbit-core-1.0.1.jar
===================================================================
(Binary files differ)


Property changes on: trunk/cms/jackrabbit-customization/lib/jackrabbit-core-1.0.1.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/cms/jackrabbit-customization/lib/jboss-cache.jar
===================================================================
(Binary files differ)


Property changes on: trunk/cms/jackrabbit-customization/lib/jboss-cache.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/cms/jackrabbit-customization/lib/jgroups.jar
===================================================================
(Binary files differ)


Property changes on: trunk/cms/jackrabbit-customization/lib/jgroups.jar
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: trunk/cms/jackrabbit-customization/src/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java
===================================================================
--- trunk/cms/jackrabbit-customization/src/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/jackrabbit-customization/src/org/apache/jackrabbit/core/state/ItemStateReferenceCache.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -0,0 +1,308 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.state;
+
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.core.util.Dumpable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Set;
+import java.util.Collections;
+import java.util.Collection;
+import java.io.PrintStream;
+
+//clustered caching code
+import java.io.InputStream;
+import javax.management.MBeanServer;
+import org.jboss.cache.*;
+import org.jboss.mx.util.MBeanProxyExt;
+import org.jboss.mx.util.MBeanServerLocator;
+import org.jboss.portal.cms.impl.jcr.jackrabbit.ClusteredCacheListener;
+
+/**
+ * <code>ItemStateReferenceCache</code> internally consists of 2 components:
+ * <ul>
+ * <li>an <code>ItemStateReferenceMap<code> serving as the primary (or main)
+ * cache; it holds weak references to <code>ItemState</code> instances. This
+ * <code>ItemStateCache</code> implementation directly represents the
+ * contents of the primary cache, i.e. {@link #isCached(ItemId)},
+ * {@link #retrieve(ItemId)}}, {@link #size()} etc. only refer to the contents
+ * of the primary cache.</li>
+ * <li>an <code>ItemStateCache</code> implementing a custom eviction policy and
+ * serving as the secondary (or auxiliary) cache; entries that are automatically
+ * flusehd from this secondary cache through its eviction policy (LRU, etc.)
+ * will be indirectly flushed from the primary (reference) cache by the garbage
+ * collector if they are thus rendered weakly reachable.
+ * </li>
+ * </ul>
+ */
+public class ItemStateReferenceCache implements ItemStateCache, Dumpable {
+
+    /** Logger instance */
+    private static Logger log = LoggerFactory.getLogger(LRUItemStateCache.class);
+
+    /**
+     * primary cache storing weak references to <code>ItemState</code>
+     * instances.
+     */
+    private final ItemStateReferenceMap refs;
+    /**
+     * secondary cache that automatically flushes entries based on some
+     * eviction policy; entries flushed from the secondary cache will be
+     * indirectly flushed from the primary (reference) cache by the garbage
+     * collector if they thus are rendered weakly reachable.
+     */
+    private final ItemStateCache cache;
+    
+    /**
+     * clustered caching code - integrating a clustered invalidating jbosscache
+     *
+     */
+    private static TreeCache treeCache = null;
+    private static boolean standalone = false;
+    
+
+    /**
+     * Creates a new <code>ItemStateReferenceCache</code> that uses a
+     * <code>LRUItemStateCache</code> instance as internal secondary
+     * cache.
+     */
+    public ItemStateReferenceCache() {
+        this(new LRUItemStateCache());                
+    }
+
+    /**
+     * Creates a new <code>ItemStateReferenceCache</code> that uses the
+     * specified <code>ItemStateCache</code> instance as internal secondary
+     * cache.
+     *
+     * @param cache secondary cache implementing a custom eviction policy
+     */
+    public ItemStateReferenceCache(ItemStateCache cache) {
+        this.cache = cache;
+        refs = new ItemStateReferenceMap();
+        
+        //clustered caching code - initialize the treecache and start it
+        if(treeCache == null)
+        {
+            setUpClustedCache();
+        }
+    }
+
+    //-------------------------------------------------------< ItemStateCache >
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isCached(ItemId id) {  
+                        
+        // check primary cache
+        return refs.contains(id);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ItemState retrieve(ItemId id) {
+                                
+        // fake call to update stats of secondary cache
+        cache.retrieve(id);
+
+        // retrieve from primary cache        
+        return (ItemState) refs.get(id);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void cache(ItemState state) {
+                
+        ItemId id = state.getId();
+        if (refs.contains(id)) {
+            log.warn("overwriting cached entry " + id);
+        }
+        // fake call to update stats of secondary cache
+        cache.cache(state);
+        // store weak reference in primary cache
+        refs.put(state); 
+        
+        //clustered-caching code
+        //hook into the clustered cache for sending invalidation notifications in a clustered environment
+        handleClusteredCaching(state);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void evict(ItemId id) {        
+        // fake call to update stats of secondary cache
+        cache.evict(id);
+        // remove from primary cache
+        refs.remove(id);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void evictAll() {
+        // fake call to update stats of secondary cache
+        cache.evictAll();
+        // remove all weak references from primary cache
+        refs.clear();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isEmpty() {
+        
+        // check primary cache
+        return refs.isEmpty();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public int size() {
+        // size of primary cache
+        return refs.size();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Set keySet() {
+        // keys of primary cache
+        return Collections.unmodifiableSet(refs.keySet());
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Collection values() {
+        // values of primary cache
+        return Collections.unmodifiableCollection(refs.values());
+    }
+
+    //-------------------------------------------------------------< Dumpable >
+    /**
+     * {@inheritDoc}
+     */
+    public void dump(PrintStream ps) {
+        ps.println("ItemStateReferenceCache (" + this + ")");
+        ps.println();
+        ps.print("[refs] ");
+        refs.dump(ps);
+    }
+    
+    //-----clustered caching code integrated for jboss portal cms clustering-------------------------------------------------------------------------
+    /**
+     * clustered-caching code
+     * hook into the clustered cache for sending invalidation notifications in a clustered environment
+     */
+    private void handleClusteredCaching(ItemState state)
+    {
+        if(treeCache != null && !standalone)
+        {
+	        try
+	        {	            	            
+	            //cache the itemid of the itemstate being saved in cache
+	            String node = "/"+ClusteredCacheListener.parseNodeName(state.getId().toString());	            
+	            
+	            treeCache.put(node,
+	            state.getId().toString(),
+	            "sendCacheInvalidation");
+	            log.debug("Placing "+node+" into the clustered cache..");
+	            
+	            ClusteredCacheListener.storeCacheItem(node,state.getId(),this);
+	        }
+	        catch(Exception e)
+	        {
+	            throw new RuntimeException(e);
+	        }
+        }
+    }
+    
+    /**
+     * clustered caching code - initialize the treecache and start it
+     * 
+     * it looks for an MBEAN in case of a managed environment like JBoss or instantiates from a configuration
+     * file in standalone mode
+     * 
+     * This is synchronized so that only one thread is allowed to setup the static TreeCache
+     *
+     */
+    private static synchronized void setUpClustedCache()
+    {
+        log.info("Starting the JackRabbit In-Memory Invalidation Cache. This is helpful in a clustered environment.");
+        InputStream is = null;
+        try
+        {
+            try
+            {
+	            MBeanServer server=MBeanServerLocator.locateJBoss();
+			    TreeCacheMBean treeCacheMBean = (TreeCacheMBean)MBeanProxyExt.create(TreeCacheMBean.class,"jackrabbit.inmemory.cache:service=TreeCache",server);
+			    treeCache = treeCacheMBean.getInstance();
+			    treeCache.addTreeCacheListener(new ClusteredCacheListener());
+			    return;
+            }
+            catch(Exception e)
+            {
+                treeCache = null;
+            }
+            
+            //if nothing found in the environment...chances are running in a non-managed environment
+            if(treeCache == null)
+            {
+		        treeCache = new TreeCache();
+			    
+			    //configure the cache
+			    PropertyConfigurator configurator = new PropertyConfigurator();
+			    is = ItemStateReferenceCache.class.getClassLoader().getResourceAsStream("cluster-cache.xml");
+			    configurator.configure(treeCache,is);
+			    			    
+			    treeCache.addTreeCacheListener(new ClusteredCacheListener());
+			    treeCache.createService();
+			    treeCache.startService();
+            }
+        }
+        catch(Exception e)
+        {
+            treeCache = null;
+            if(!standalone)
+            {
+	            log.info("----------------------------------------------------------------------------------------");
+	            log.info("JackRabbit In-Memory cache running in standalone mode. No cluster configuration detected");
+	            log.info("----------------------------------------------------------------------------------------");
+	            standalone = true;
+            }
+        }
+        finally
+        {
+            if(is != null)
+            {
+                try{is.close();}catch(Exception e){}
+            }
+            
+            if(treeCache != null)
+            {
+                log.info("-------------------------------------------------------------------------------------------------");
+                log.info("The JackRabbit In-Memory Clustered Cache successfully started....("+treeCache.getClusterName()+")");
+                log.info("-------------------------------------------------------------------------------------------------");
+            }
+        }
+    }
+}

Added: trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/Base.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/Base.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/Base.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -0,0 +1,85 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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.jboss.portal.cms.hibernate.state;
+
+import java.io.Serializable;
+
+/*
+ * Created on Aug 31, 2006
+ *
+ * @author <a href="mailto:sohil.shah at jboss.com">Sohil Shah</a>
+ */
+public abstract class Base implements Serializable 
+{
+    /**
+     * 
+     */
+    private boolean persistCacheItem = true; //true by default...all items when placed in cache must be persisted to database by cacheloader by default
+    private Integer key = null;
+    
+    /**
+     * 
+     *
+     */
+    public Base()
+    {
+        
+    }
+    
+    //------cacheItem Persistence related methods------------------------------------------------------------------------------------------------------
+    /**
+     * 
+     *
+     */
+    public void disableCacheItemPersistence()
+    {
+        this.persistCacheItem = false;
+    }
+    
+    /**
+     * 
+     *
+     */
+    public boolean isPersistCacheItem()
+    {
+        return this.persistCacheItem;
+    }
+    
+    /**
+     * 
+     *
+     */
+    public void resetCacheItemPersistence()
+    {
+        this.persistCacheItem = true;
+    }
+    //-----------data access related methods-------------------------------------------------------------------------------------------------------------
+    public Integer getKey()
+    {
+       return key;
+    }
+
+    public void setKey(Integer key)
+    {
+       this.key = key;
+    }
+}

Modified: trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/HibernatePersistenceManager.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/HibernatePersistenceManager.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/HibernatePersistenceManager.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -58,7 +58,7 @@
 import org.hibernate.SessionFactory;
 import org.hibernate.Transaction;
 import org.jboss.portal.cms.hibernate.HibernateStoreConstants;
-import org.jboss.portal.cms.util.HibernateUtil;
+//import org.jboss.portal.cms.util.HibernateUtil;
 import org.jboss.portal.common.util.Tools;
 import org.jboss.portal.jems.hibernate.CacheableBlobUserType;
 import org.jboss.portal.jems.hibernate.ByteArrayBlob;
@@ -155,7 +155,9 @@
          throw new IllegalStateException("already initialized");
       }
 
-      hibernateSessionFactory = HibernateUtil.getSessionFactory(jndiName);
+      //hibernateSessionFactory = HibernateUtil.getSessionFactory(jndiName);
+      org.jboss.portal.cms.hibernate.state.Tools.init(jndiName);
+      hibernateSessionFactory = org.jboss.portal.cms.hibernate.state.Tools.getSessionFactory();
 
       nodeBinValSelect = "from " + schemaObjectPrefix + "BinVal where BINVAL_ID = ?";
 
@@ -388,8 +390,12 @@
          List rs = session.createQuery(nodeStateSelectData).setString(0, id.toString()).list();
 
          Iterator iter = rs.iterator();
-         java.sql.Blob blob = (java.sql.Blob) iter.next();
-         in = blob.getBinaryStream();
+         
+         //java.sql.Blob blob = (java.sql.Blob) iter.next();
+         //in = blob.getBinaryStream();
+         byte[] data = (byte[])iter.next();
+         in = new java.io.ByteArrayInputStream(data);
+         
          NodeState state = createNew(id);
          Serializer.deserialize(state, in);
          Tools.safeClose(in);
@@ -428,8 +434,13 @@
       {
          List rs = session.createQuery(propertyStateSelectData).setCacheable(true).setString(0, id.toString()).list();
          Iterator iter = rs.iterator();
-         java.sql.Blob blob = (java.sql.Blob) iter.next();
-         in = blob.getBinaryStream();
+         
+         //java.sql.Blob blob = (java.sql.Blob) iter.next();
+         //in = blob.getBinaryStream();
+         byte[] data = (byte[])iter.next();
+         in = new java.io.ByteArrayInputStream(data);
+         
+         
          PropertyState state = createNew(id);
          Serializer.deserialize(state, in, blobStore);
          Tools.safeClose(in);
@@ -474,8 +485,9 @@
          {
             throw new NoSuchItemStateException(targetId.toString());
          }
-         java.sql.Blob blob = (java.sql.Blob) iter.next();
-         in = blob.getBinaryStream();
+         byte[] data = (byte[]) iter.next();         
+         in = new java.io.ByteArrayInputStream(data);
+         
          NodeReferences refs = new NodeReferences(targetId);
          Serializer.deserialize(refs, in);
          Tools.safeClose(in);
@@ -515,13 +527,13 @@
          Serializer.serialize(state, out);
          if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
          {
-            VersionNode versionNode = new VersionNode(state.getId().toString(), createBlob(out.toByteArray()));
+            VersionNode versionNode = new VersionNode(state.getId().toString(),out.toByteArray());
             session.save(versionNode);
          }
          else if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
          {
 
-            WSPNode wspNode = new WSPNode(state.getId().toString(), createBlob(out.toByteArray()));
+            WSPNode wspNode = new WSPNode(state.getId().toString(),out.toByteArray());
             session.save(wspNode);
          }
       }
@@ -568,14 +580,14 @@
          if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
          {
 
-            VersionRefs versionRefs = new VersionRefs(refs.getTargetId().toString(), createBlob(out
-                  .toByteArray()));
+            VersionRefs versionRefs = new VersionRefs(refs.getTargetId().toString(),out
+                  .toByteArray());
             session.save(versionRefs);
          }
          else if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
          {
 
-            WSPRefs wspRefs = new WSPRefs(refs.getTargetId().toString(), createBlob(out.toByteArray()));
+            WSPRefs wspRefs = new WSPRefs(refs.getTargetId().toString(),out.toByteArray());
             session.save(wspRefs);
          }
       }
@@ -625,12 +637,12 @@
 
          if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
          {
-            VersionProp versionProp = new VersionProp(state.getId().toString(), createBlob(out.toByteArray()));
+            VersionProp versionProp = new VersionProp(state.getId().toString(),out.toByteArray());
             session.save(versionProp);
          }
          else if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
          {
-            WSPProp wspProp = new WSPProp(state.getId().toString(), createBlob(out.toByteArray()));
+            WSPProp wspProp = new WSPProp(state.getId().toString(),out.toByteArray());
             session.save(wspProp);
          }
       }
@@ -678,7 +690,7 @@
             {
                throw new Exception("No such Node: " + state.getId());
             }
-            versionNode.setData(createBlob(out.toByteArray()));
+            versionNode.setData(out.toByteArray());
          }
          else if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
          {
@@ -688,7 +700,7 @@
             {
                throw new Exception("No such Node: " + state.getId());
             }
-            wspNode.setData(createBlob(out.toByteArray()));
+            wspNode.setData(out.toByteArray());
          }
       }
       catch (Exception e)
@@ -735,7 +747,7 @@
             {
                throw new Exception("No such Property: " + state.getId());
             }
-            versionProp.setData(createBlob(out.toByteArray()));
+            versionProp.setData(out.toByteArray());
          }
          else if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
          {
@@ -745,7 +757,7 @@
             {
                throw new Exception("No such Property: " + state.getId());
             }
-            wspProp.setData(createBlob(out.toByteArray()));
+            wspProp.setData(out.toByteArray());
          }
       }
       catch (Exception e)

Added: trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/JBossCachePersistenceManager.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/JBossCachePersistenceManager.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/JBossCachePersistenceManager.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -0,0 +1,1484 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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.jboss.portal.cms.hibernate.state;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.io.ByteArrayInputStream;
+import java.sql.Blob;
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.PropertyType;
+import javax.management.MBeanServer;
+
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.fs.local.LocalFileSystem;
+import org.apache.jackrabbit.core.state.ChangeLog;
+import org.apache.jackrabbit.core.state.ItemState;
+import org.apache.jackrabbit.core.state.ItemStateException;
+import org.apache.jackrabbit.core.state.NoSuchItemStateException;
+import org.apache.jackrabbit.core.state.NodeReferences;
+import org.apache.jackrabbit.core.state.NodeReferencesId;
+import org.apache.jackrabbit.core.state.NodeState;
+import org.apache.jackrabbit.core.state.PMContext;
+import org.apache.jackrabbit.core.state.PersistenceManager;
+import org.apache.jackrabbit.core.state.PropertyState;
+import org.apache.jackrabbit.core.state.util.BLOBStore;
+import org.apache.jackrabbit.core.state.util.FileSystemBLOBStore;
+import org.apache.jackrabbit.core.state.util.Serializer;
+import org.apache.jackrabbit.core.value.BLOBFileValue;
+import org.apache.jackrabbit.core.value.InternalValue;
+import org.apache.log4j.Logger;
+
+import org.jboss.portal.cms.hibernate.HibernateStoreConstants;
+
+import org.jboss.cache.TreeCacheMBean;
+import org.jboss.cache.CacheException;
+import org.jboss.mx.util.MBeanProxyExt;
+import org.jboss.mx.util.MBeanServerLocator;
+
+import org.hibernate.Hibernate;
+import org.hibernate.HibernateException;
+import org.hibernate.Query;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Transaction;
+
+/*
+ * Created on Aug 28, 2006
+ *
+ * @author <a href="mailto:sohil.shah at jboss.com">Sohil Shah</a>
+ */
+public class JBossCachePersistenceManager implements PersistenceManager 
+{
+    /**
+     * Logger instance
+     */
+    private static Logger log = Logger.getLogger(JBossCachePersistenceManager.class);
+
+    protected static final String SCHEMA_OBJECT_PREFIX_VARIABLE = "${schemaObjectPrefix}";
+
+    protected boolean initialized;
+
+    protected String jndiName;
+
+    protected String schemaObjectPrefix;
+
+    protected boolean externalBLOBs;
+
+    // initial size of buffer used to serialize objects
+    protected static final int INITIAL_BUFFER_SIZE = 1024;
+
+    // shared statements for NodeState management
+    protected String nodeStateSelect;
+
+    protected String nodeStateSelectData;
+
+    protected String nodeStateSelectExist;
+
+    // shared statements for PropertyState management
+    protected String propertyStateSelect;
+
+    protected String propertyStateSelectData;
+
+    protected String propertyStateSelectExist;
+
+    // shared statements for NodeReference management
+    protected String nodeReferenceSelect;
+
+    protected String nodeReferenceSelectData;
+
+    protected String nodeReferenceSelectExist;
+
+    // shared statements for BLOB management
+    // (if <code>externalBLOBs==false</code>)
+    protected String blobSelect;
+
+    protected String blobSelectData;
+
+    protected String blobSelectExist;
+
+    protected String nodeBinValSelect;
+
+    /**
+     * file system where BLOB data is stored
+     * (if <code>externalBLOBs==true</code>)
+     */
+    protected FileSystem blobFS;
+
+    /**
+     * BLOBStore that manages BLOB data in the file system
+     * (if <code>externalBLOBs==true</code>)
+     */
+    protected BLOBStore blobStore;
+
+    /**
+     * 
+     */
+    private static TreeCacheMBean pmCache = null;
+    private static boolean preloaded = false;
+    
+    /**
+     * Creates a new <code>SimpleDbPersistenceManager</code> instance.
+     */
+    public JBossCachePersistenceManager()
+    {
+       schemaObjectPrefix = "";
+       externalBLOBs = true;
+       initialized = false;
+    }
+    
+    
+    /* 
+     * 
+     */
+    public void init(PMContext context) throws Exception 
+    {
+        if (initialized)
+        {
+           throw new IllegalStateException("already initialized");
+        }     
+
+        nodeBinValSelect = "from " + schemaObjectPrefix + "BinVal where BINVAL_ID = ?";
+
+        nodeStateSelect = "from " + schemaObjectPrefix + "Node where NODE_ID = ?";
+        nodeStateSelectData = "select data from " + schemaObjectPrefix + "Node where NODE_ID = ?";
+        nodeStateSelectExist = "select 1 from " + schemaObjectPrefix + "Node where NODE_ID = ?";
+
+        propertyStateSelect = "from " + schemaObjectPrefix + "Prop where PROP_ID = ?";
+        propertyStateSelectData = "select data from " + schemaObjectPrefix + "Prop where PROP_ID = ?";
+        propertyStateSelectExist = "select 1 from " + schemaObjectPrefix + "Prop where PROP_ID = ?";
+
+        nodeReferenceSelect = "from " + schemaObjectPrefix + "Refs where NODE_ID = ?";
+        nodeReferenceSelectData = "select data from " + schemaObjectPrefix + "Refs where NODE_ID = ?";
+        nodeReferenceSelectExist = "select 1 from " + schemaObjectPrefix + "Refs where NODE_ID = ?";
+
+
+        if (externalBLOBs)
+        {
+           /**
+            * store BLOBs in local file system in a sub directory
+            * of the workspace home directory
+            */
+           LocalFileSystem blobFS = new LocalFileSystem();
+           blobFS.setRoot(new File(context.getHomeDir(), "blobs"));
+           blobFS.init();
+           this.blobFS = blobFS;
+           blobStore = new FileSystemBLOBStore(blobFS);
+        }
+        else
+        {
+           /**
+            * store BLOBs in db
+            */
+           blobStore = new DbBLOBStore();
+
+           blobSelect = "from " + schemaObjectPrefix + "BinVal where BINVAL_ID = ?";
+           blobSelectData = "select data from " + schemaObjectPrefix + "BinVal where BINVAL_ID = ?";
+           blobSelectExist = "select 1 from " + schemaObjectPrefix + "BinVal where BINVAL_ID = ?";
+        }
+
+        initialized = true;
+        
+        try
+        { 
+           Tools.init(this.jndiName);
+	       if(JBossCachePersistenceManager.pmCache == null)
+	       {
+	           MBeanServer server=MBeanServerLocator.locateJBoss();
+		       JBossCachePersistenceManager.pmCache = (TreeCacheMBean)MBeanProxyExt.create(TreeCacheMBean.class,"cms.pm.cache:service=TreeCache",server);
+	       }
+	       
+	       //pre-load the cache with property nodes
+	       if(!JBossCachePersistenceManager.preloaded)
+	       {
+	           JBossCachePersistenceManager.loadProperties();	           
+	           log.info("-------------------------------------------------");
+	           log.info("JBossCachePersistenceManager is fully loaded.....");
+	           log.info("-------------------------------------------------");
+	       }
+        }
+        catch(Exception e)
+        {
+            throw new RuntimeException(e);
+        }
+    }  
+        
+    /**
+     * 
+     *
+     */
+    private static synchronized void loadProperties() throws Exception
+    {
+        if(JBossCachePersistenceManager.preloaded)
+        {
+            return;
+        }
+        
+        log.info("Pre-loading the PersistenceManager Cache in the background (started).......");        
+        
+        CacheLoader wspProp = new CacheLoader(CacheLoader.wspProp,PortalCMSCacheLoader.WSP_PROP_NODE);
+        Thread wspPropLoader = new Thread(wspProp);
+        CacheLoader versionProp = new CacheLoader(CacheLoader.versionProp,PortalCMSCacheLoader.VERSION_PROP_NODE);
+        Thread versionPropLoader = new Thread(versionProp);
+        CacheLoader wspNode = new CacheLoader(CacheLoader.wspNode,PortalCMSCacheLoader.WSP_NODE_NODE);
+        Thread wspNodeLoader = new Thread(wspNode);
+        CacheLoader versionNode = new CacheLoader(CacheLoader.versionNode,PortalCMSCacheLoader.VERSION_NODE_NODE);
+        Thread versionNodeLoader = new Thread(versionNode);
+        CacheLoader wspRef = new CacheLoader(CacheLoader.wspRef,PortalCMSCacheLoader.WSP_REF_NODE);
+        Thread wspRefLoader = new Thread(wspRef);
+        CacheLoader versionRef = new CacheLoader(CacheLoader.versionRef,PortalCMSCacheLoader.VERSION_REF_NODE);
+        Thread versionRefLoader = new Thread(versionRef);
+        
+        wspPropLoader.start();
+        versionPropLoader.start();
+        wspNodeLoader.start();
+        versionNodeLoader.start();
+        wspRefLoader.start();
+        versionRefLoader.start();
+        
+        //hang out here till the cache loader threads have pre-loaded the busy nodes
+        //of the CMS...don't allow the usage of CMS till this operation is completed.
+        while(
+                !wspProp.done	||
+                !versionProp.done ||
+                !wspNode.done ||
+                !versionNode.done ||
+                !wspRef.done ||
+                !versionRef.done
+        )
+        {
+            Thread.currentThread().sleep((long)2000);
+        }
+        
+        JBossCachePersistenceManager.preloaded = true;                
+    }
+    
+    private static class CacheLoader implements Runnable
+    {
+        /**
+         * 
+         */
+        private static final String wspProp = "from org.jboss.portal.cms.hibernate.state.WSPProp";
+        private static final String versionProp = "from org.jboss.portal.cms.hibernate.state.VersionProp";
+        private static final String wspNode = "from org.jboss.portal.cms.hibernate.state.WSPNode";
+        private static final String versionNode = "from org.jboss.portal.cms.hibernate.state.VersionNode";
+        private static final String wspRef = "from org.jboss.portal.cms.hibernate.state.WSPRefs";
+        private static final String versionRef = "from org.jboss.portal.cms.hibernate.state.VersionRefs";
+        
+        
+        /**
+         * 
+         */
+        private String nodeQuery = null;
+        private String nodePrefix = null;
+        private boolean done = false;
+        
+        private CacheLoader(String nodeQuery,String nodePrefix)
+        {
+           this.nodeQuery = nodeQuery;
+           this.nodePrefix = nodePrefix;
+        }
+                        
+        public void run()
+        {                                    
+            Session session = null;
+            try
+            {
+                session = Tools.getOpenSession();  
+                List rs = session.createQuery(this.nodeQuery).list();                                
+                if(rs != null)
+                {
+    	            for(Iterator itr=rs.iterator();itr.hasNext();)
+    	            {
+    	                Base cour = (Base)itr.next();
+    	                cour.disableCacheItemPersistence();
+    	                
+    	                if(cour instanceof WSPProp)
+    	                {    	                    
+    	                    String node = this.nodePrefix + "/" + PortalCMSCacheLoader.parseNodeName(((WSPProp)cour).getPropId());    	                    
+    	                    pmCache.put(node,((WSPProp)cour).getPropId(),cour);
+    	                }
+    	                else if(cour instanceof VersionProp)
+    	                {    	                    
+    	                    String node = this.nodePrefix + "/" + PortalCMSCacheLoader.parseNodeName(((VersionProp)cour).getPropId());
+    	                    pmCache.put(node,((VersionProp)cour).getPropId(),cour);
+    	                }
+    	                else if(cour instanceof WSPNode)
+    	                {    	                    
+    	                    String node = this.nodePrefix + "/" + PortalCMSCacheLoader.parseNodeName(((WSPNode)cour).getNodeId());
+    	                    pmCache.put(node,((WSPNode)cour).getNodeId(),cour);
+    	                }
+    	                else if(cour instanceof VersionNode)
+    	                {    	                    
+    	                    String node = this.nodePrefix + "/" + PortalCMSCacheLoader.parseNodeName(((VersionNode)cour).getNodeId());
+    	                    pmCache.put(node,((VersionNode)cour).getNodeId(),cour);
+    	                }
+    	                else if(cour instanceof WSPRefs)
+    	                {    	                    
+    	                    String node = this.nodePrefix + "/" + PortalCMSCacheLoader.parseNodeName(((WSPRefs)cour).getRefId());
+    	                    pmCache.put(node,((WSPRefs)cour).getRefId(),cour);
+    	                }
+    	                else if(cour instanceof VersionRefs)
+    	                {    	                    
+    	                    String node = this.nodePrefix + "/" + PortalCMSCacheLoader.parseNodeName(((VersionRefs)cour).getRefId());
+    	                    pmCache.put(node,((VersionRefs)cour).getRefId(),cour);
+    	                }
+    	            }
+                }                                
+                log.info("Pre-loading the PersistenceManager Cache for"+this.nodePrefix+" (finished).......");
+            }
+            catch(CacheException ce)
+            {
+                throw new RuntimeException(ce);
+            }
+            finally
+            {
+                Tools.closeSession(session);
+                this.done = true;
+            }
+        }
+    }
+    
+    //----------actions for node entities-------------------------------------------------------------------------------------------------------------
+    /* 
+     * 
+     */
+    public boolean exists(NodeId node) throws ItemStateException 
+    {
+        try
+        {
+	        boolean exists = false;
+	        String nodeId = node.toString();
+	        if(this.schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+	        {
+	            Object o = this.pmCache.get(PortalCMSCacheLoader.WSP_NODE_NODE+"/"+PortalCMSCacheLoader.parseNodeName(nodeId),nodeId);
+	            if(o != null)
+	            {
+	                if(o instanceof WSPNode)
+	                {
+	                    exists = true;
+	                }
+	            }
+	            else
+	            {
+	                this.pmCache.put(PortalCMSCacheLoader.WSP_NODE_NODE+"/"+PortalCMSCacheLoader.parseNodeName(nodeId),nodeId,new Boolean(false));
+	            }
+	        }
+	        else if(this.schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+	        {
+	            Object o = this.pmCache.get(PortalCMSCacheLoader.VERSION_NODE_NODE+"/"+PortalCMSCacheLoader.parseNodeName(nodeId),nodeId);
+	            if(o != null)
+	            {
+	                if(o instanceof VersionNode)
+	                {
+	                    exists = true;
+	                }
+	            }
+	            else
+	            {
+	                this.pmCache.put(PortalCMSCacheLoader.VERSION_NODE_NODE+"/"+PortalCMSCacheLoader.parseNodeName(nodeId),nodeId,new Boolean(false));
+	            }
+	        }
+	        return exists;
+        }
+        catch(CacheException ce)
+        {
+            throw new RuntimeException(ce);
+        }
+    }
+    
+    /* 
+     * 
+     */
+    public NodeState load(NodeId node) throws NoSuchItemStateException,ItemStateException 
+    {
+        try
+        {
+	        NodeState nodeState = null;
+	        String nodeId = node.toString();
+	        
+	        //get the nodeData
+	        byte[] nodeData = null;
+	        if(this.schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+	        {
+	            Object o = this.pmCache.get(PortalCMSCacheLoader.WSP_NODE_NODE+"/"+PortalCMSCacheLoader.parseNodeName(nodeId),nodeId);
+	            nodeData = ((WSPNode)o).getData();
+	        }
+	        else if(this.schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+	        {
+	            Object o = this.pmCache.get(PortalCMSCacheLoader.VERSION_NODE_NODE+"/"+PortalCMSCacheLoader.parseNodeName(nodeId),nodeId);
+	            nodeData = ((VersionNode)o).getData();
+	        }
+	        
+	        //parse propertyData into propertyState
+	        if(nodeData!=null)
+	        {
+	            Session session = null;
+	            Transaction tx = null;
+	            boolean success = false;
+	            try
+	            {
+	                session = Tools.getOpenSession();
+	                tx = session.beginTransaction();
+	                              
+	                InputStream in = new ByteArrayInputStream(nodeData);
+	                
+	                //setup the propertyState
+	                nodeState = createNew(node);
+	                Serializer.deserialize(nodeState,in);
+	                org.jboss.portal.common.util.Tools.safeClose(in);
+	                
+	                tx.commit();
+	                success = true;
+	            }
+	            catch(Exception e)
+	            {
+	                if (e instanceof NoSuchItemStateException)
+	                {
+	                   throw (NoSuchItemStateException) e;
+	                }
+	                String msg = "failed to read node state from cache: " + node.toString();
+	                log.error(msg, e);
+	                throw new ItemStateException(msg, e);
+	            }
+	            finally
+	            {
+	                if(!success)
+	                {
+	                    tx.rollback();
+	                }
+	                Tools.closeSession(session);
+	            }
+	        }	        
+	        
+	        return nodeState;
+        }
+        catch(CacheException ce)
+        {
+            throw new RuntimeException(ce);
+        }
+    }
+    
+    /**
+     * 
+     *
+     */
+    private void store(NodeState state) throws ItemStateException
+    {
+       if (!initialized)
+       {
+          throw new IllegalStateException("not initialized");
+       }
+
+       ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
+       try
+       {
+          Serializer.serialize(state, out);
+          if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+          {
+             VersionNode versionNode = new VersionNode(state.getId().toString(), out.toByteArray());
+             
+             //place this in the cache
+             versionNode.resetCacheItemPersistence();
+             String cacheNode = PortalCMSCacheLoader.VERSION_NODE_NODE + "/" + PortalCMSCacheLoader.parseNodeName(versionNode.getNodeId());
+             pmCache.put(cacheNode,versionNode.getNodeId(),versionNode);
+          }
+          else if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+          {
+
+             WSPNode wspNode = new WSPNode(state.getId().toString(), out.toByteArray());
+             
+             //place this in the cache
+             wspNode.resetCacheItemPersistence();
+             String cacheNode = PortalCMSCacheLoader.WSP_NODE_NODE + "/" + PortalCMSCacheLoader.parseNodeName(wspNode.getNodeId());
+             pmCache.put(cacheNode,wspNode.getNodeId(),wspNode);
+          }
+       }
+       catch (Exception e)
+       {
+          String msg = "failed to write node state: " + state.getId();
+          log.error(msg, e);
+          throw new ItemStateException(msg, e);
+       }
+       finally
+       {
+          try
+          {
+             out.close();
+          }
+          catch (Exception e)
+          {
+             e.printStackTrace();
+          }
+       }
+    }
+    
+    /**
+     * 
+     *
+     */
+    private void update(NodeState state) throws ItemStateException
+    {
+       if (!initialized)
+       {
+          throw new IllegalStateException("not initialized");
+       }
+
+       ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
+       try
+       {
+          Serializer.serialize(state, out);
+          String id = state.getId().toString();
+          String cacheNodeName = PortalCMSCacheLoader.parseNodeName(id);
+          if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+          {
+             VersionNode versionNode = (VersionNode)pmCache.get(PortalCMSCacheLoader.VERSION_NODE_NODE+"/"+cacheNodeName,id);
+             if (versionNode == null)
+             {
+                throw new Exception("No such Node: " + state.getId());
+             }
+             versionNode.setData(out.toByteArray());
+             versionNode.resetCacheItemPersistence();
+             pmCache.put(PortalCMSCacheLoader.VERSION_NODE_NODE+"/"+cacheNodeName,id,versionNode);
+          }
+          else if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+          {
+             WSPNode wspNode = (WSPNode)pmCache.get(PortalCMSCacheLoader.WSP_NODE_NODE+"/"+cacheNodeName,id);
+             if (wspNode == null)
+             {
+                throw new Exception("No such Node: " + state.getId());
+             }
+             wspNode.setData(out.toByteArray());
+             wspNode.resetCacheItemPersistence();
+             pmCache.put(PortalCMSCacheLoader.WSP_NODE_NODE+"/"+cacheNodeName,id,wspNode);
+          }
+       }
+       catch (Exception e)
+       {
+          String msg = "failed to write node state: " + state.getId();
+          log.error(msg, e);
+          throw new ItemStateException(msg, e);
+       }
+       finally
+       {
+          try
+          {
+             out.close();
+          }
+          catch (Exception e)
+          {
+             e.printStackTrace();
+          }
+       }
+    }
+    
+    /**
+     * This is called by store(Changelog) this should not be called anywhere else
+     */
+    private void destroy(NodeState state) throws ItemStateException
+    {
+       if (!initialized)
+       {
+          throw new IllegalStateException("not initialized");
+       }
+
+       String id = state.getId().toString();
+       String cacheNodeName = PortalCMSCacheLoader.parseNodeName(id);
+       try
+       {
+           if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+           {
+               pmCache.remove(PortalCMSCacheLoader.VERSION_NODE_NODE+"/"+cacheNodeName,id);
+           }
+           else if(schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+           {
+               pmCache.remove(PortalCMSCacheLoader.WSP_NODE_NODE+"/"+cacheNodeName,id);
+           }
+       }
+       catch (Exception e)
+       {
+          String msg = "failed to delete node state: " + state.getId();
+          log.error(msg, e);
+          throw new ItemStateException(msg, e);
+       }
+    }
+    
+    //----------actions for property entities-------------------------------------------------------------------------------------------------------------    
+    /* 
+     * 
+     */
+    public boolean exists(PropertyId property) throws ItemStateException 
+    {
+        try
+        {
+	        boolean exists = false;
+	        String propId = property.toString();
+	        if(this.schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+	        {
+	            Object o = this.pmCache.get(PortalCMSCacheLoader.WSP_PROP_NODE+"/"+PortalCMSCacheLoader.parseNodeName(propId),propId);
+	            if(o != null)
+	            {
+	                if(o instanceof WSPProp)
+	                {
+	                    exists = true;
+	                }
+	            }
+	            else
+	            {
+	                this.pmCache.put(PortalCMSCacheLoader.WSP_PROP_NODE+"/"+PortalCMSCacheLoader.parseNodeName(propId),propId,new Boolean(false));
+	            }
+	        }
+	        else if(this.schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+	        {
+	            Object o = this.pmCache.get(PortalCMSCacheLoader.VERSION_PROP_NODE+"/"+PortalCMSCacheLoader.parseNodeName(propId),propId);
+	            if(o != null)
+	            {
+	                if(o instanceof VersionProp)
+	                {
+	                    exists = true;
+	                }
+	            }
+	            else
+	            {
+	                this.pmCache.put(PortalCMSCacheLoader.VERSION_PROP_NODE+"/"+PortalCMSCacheLoader.parseNodeName(propId),propId,new Boolean(false));
+	            }
+	        }
+	        return exists;
+        }
+        catch(CacheException ce)
+        {
+            throw new RuntimeException(ce);
+        }
+    }
+
+    /* 
+     * 
+     */
+    public PropertyState load(PropertyId property) throws NoSuchItemStateException,ItemStateException 
+    {
+        try
+        {
+	        PropertyState propertyState = null;
+	        String propId = property.toString();
+	        
+	        //get the propertyData
+	        byte[] propertyData = null;
+	        if(this.schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+	        {
+	            Object o = this.pmCache.get(PortalCMSCacheLoader.WSP_PROP_NODE+"/"+PortalCMSCacheLoader.parseNodeName(propId),propId);	
+	            propertyData = ((WSPProp)o).getData();
+	        }
+	        else if(this.schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+	        {
+	            Object o = this.pmCache.get(PortalCMSCacheLoader.VERSION_PROP_NODE+"/"+PortalCMSCacheLoader.parseNodeName(propId),propId);
+	            propertyData = ((VersionProp)o).getData();
+	        }
+	        
+	        //parse propertyData into propertyState
+	        if(propertyData!=null)
+	        {
+	            Session session = null;
+	            Transaction tx = null;
+	            boolean success = false;
+	            try
+	            {
+	                session = Tools.getOpenSession();
+	                tx = session.beginTransaction();
+	                              
+	                InputStream in = new ByteArrayInputStream(propertyData);
+	                
+	                //setup the propertyState
+	                propertyState = createNew(property);
+	                Serializer.deserialize(propertyState,in,blobStore);
+	                org.jboss.portal.common.util.Tools.safeClose(in);
+	                
+	                tx.commit();
+	                success = true;
+	            }
+	            catch(Exception e)
+	            {
+	                if (e instanceof NoSuchItemStateException)
+	                {
+	                   throw (NoSuchItemStateException) e;
+	                }
+	                String msg = "failed to read property state from cache: " + property.toString();
+	                log.error(msg, e);
+	                throw new ItemStateException(msg, e);
+	            }
+	            finally
+	            {
+	                if(!success)
+	                {
+	                    tx.rollback();
+	                }
+	                Tools.closeSession(session);
+	            }
+	        }	        
+	        
+	        return propertyState;
+        }
+        catch(CacheException ce)
+        {
+            throw new RuntimeException(ce);
+        }
+    }
+            
+    /**
+     * 
+     */
+    private void store(PropertyState state) throws ItemStateException
+    {
+       if (!initialized)
+       {
+          throw new IllegalStateException("not initialized");
+       }
+
+       ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
+       try
+       {
+          Serializer.serialize(state,out,blobStore);
+          if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+          {
+             VersionProp versionProp = new VersionProp(state.getId().toString(), out.toByteArray());
+             
+             //place this in the cache
+             versionProp.resetCacheItemPersistence();
+             String cacheNode = PortalCMSCacheLoader.VERSION_PROP_NODE + "/" + PortalCMSCacheLoader.parseNodeName(versionProp.getPropId());
+             pmCache.put(cacheNode,versionProp.getPropId(),versionProp);
+          }
+          else if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+          {
+
+             WSPProp wspProp = new WSPProp(state.getId().toString(), out.toByteArray());
+             
+             //place this in the cache
+             wspProp.resetCacheItemPersistence();
+             String cacheNode = PortalCMSCacheLoader.WSP_PROP_NODE + "/" + PortalCMSCacheLoader.parseNodeName(wspProp.getPropId());
+             pmCache.put(cacheNode,wspProp.getPropId(),wspProp);
+          }
+       }
+       catch (Exception e)
+       {
+          String msg = "failed to write property state: " + state.getId();
+          log.error(msg, e);
+          throw new ItemStateException(msg, e);
+       }
+       finally
+       {
+          try
+          {
+             out.close();
+          }
+          catch (Exception e)
+          {
+             e.printStackTrace();
+          }
+       }
+    }
+    
+    /**
+     * 
+     *
+     */
+    private void update(PropertyState state) throws ItemStateException
+    {
+        if (!initialized)
+        {
+           throw new IllegalStateException("not initialized");
+        }
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
+        try
+        {
+           Serializer.serialize(state, out, blobStore);
+           String id = state.getId().toString();
+           String cacheNodeName = PortalCMSCacheLoader.parseNodeName(id);
+           if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+           {
+              VersionProp versionProp = (VersionProp)pmCache.get(PortalCMSCacheLoader.VERSION_PROP_NODE+"/"+cacheNodeName,id);
+              if (versionProp == null)
+              {
+                 throw new Exception("No such Property: " + state.getId());
+              }
+              versionProp.setData(out.toByteArray());
+              versionProp.resetCacheItemPersistence();
+              pmCache.put(PortalCMSCacheLoader.VERSION_PROP_NODE+"/"+cacheNodeName,id,versionProp);
+           }
+           else if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+           {
+              WSPProp wspProp = (WSPProp)pmCache.get(PortalCMSCacheLoader.WSP_PROP_NODE+"/"+cacheNodeName,id);
+              if (wspProp == null)
+              {
+                 throw new Exception("No such Property: " + state.getId());
+              }
+              wspProp.setData(out.toByteArray());
+              wspProp.resetCacheItemPersistence();
+              pmCache.put(PortalCMSCacheLoader.WSP_PROP_NODE+"/"+cacheNodeName,id,wspProp);
+           }
+        }
+        catch (Exception e)
+        {
+           String msg = "failed to write property state: " + state.getId();
+           log.error(msg, e);
+           throw new ItemStateException(msg, e);
+        }
+        finally
+        {
+           try
+           {
+              out.close();
+           }
+           catch (Exception e)
+           {
+              e.printStackTrace();
+           }
+        }
+    }
+
+    /**
+     * This is called by store(Changelog) this should not be called anywhere else
+     */
+    private void destroy(PropertyState state) throws ItemStateException
+    {
+       if (!initialized)
+       {
+          throw new IllegalStateException("not initialized");
+       }
+
+       // make sure binary values (BLOBs) are properly removed
+       InternalValue[] values = state.getValues();
+       if (values != null)
+       {
+          for (int i = 0; i < values.length; i++)
+          {
+             InternalValue val = values[i];
+             if (val != null)
+             {
+                if (val.getType() == PropertyType.BINARY)
+                {
+                   BLOBFileValue blobVal = (BLOBFileValue) val.internalValue();
+                   // delete internal resource representation of BLOB value
+                   blobVal.delete(true);
+                   // also remove from BLOBStore
+                   String blobId = blobStore.createId((PropertyId) state.getId(), i);
+                   try
+                   {
+                      blobStore.remove(blobId);
+                   }
+                   catch (Exception e)
+                   {
+                      log.warn("failed to remove from BLOBStore: " + blobId, e);
+                   }
+                }
+             }
+          }
+       }
+
+       //remove the property node
+       String id = state.getId().toString();
+       String cacheNodeName = PortalCMSCacheLoader.parseNodeName(id);
+       try
+       {
+           if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+           {
+               pmCache.remove(PortalCMSCacheLoader.VERSION_PROP_NODE+"/"+cacheNodeName,id);
+           }
+           else if(schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+           {
+               pmCache.remove(PortalCMSCacheLoader.WSP_PROP_NODE+"/"+cacheNodeName,id);
+           }
+       }
+       catch (Exception e)
+       {
+          String msg = "failed to delete property state: " + state.getId();
+          log.error(msg, e);
+          throw new ItemStateException(msg, e);
+       }
+    }
+    //----------actions for nodereferences entities-------------------------------------------------------------------------------------------------------------
+    /**
+    *
+    */
+   public boolean exists(NodeReferencesId targetId) throws ItemStateException
+   {
+       try
+       {
+	        boolean exists = false;
+	        String nodeId = targetId.toString();
+	        if(this.schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+	        {
+	            Object o = this.pmCache.get(PortalCMSCacheLoader.WSP_REF_NODE+"/"+PortalCMSCacheLoader.parseNodeName(nodeId),nodeId);
+	            if(o != null)
+	            {
+	                if(o instanceof WSPRefs)
+	                {
+	                    exists = true;
+	                }
+	            }
+	            else
+	            {
+	                this.pmCache.put(PortalCMSCacheLoader.WSP_REF_NODE+"/"+PortalCMSCacheLoader.parseNodeName(nodeId),nodeId,new Boolean(false));
+	            }
+	        }
+	        else if(this.schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+	        {
+	            Object o = this.pmCache.get(PortalCMSCacheLoader.VERSION_REF_NODE+"/"+PortalCMSCacheLoader.parseNodeName(nodeId),nodeId);
+	            if(o != null)
+	            {
+	                if(o instanceof VersionRefs)
+	                {
+	                    exists = true;
+	                }
+	            }
+	            else
+	            {
+	                this.pmCache.put(PortalCMSCacheLoader.VERSION_REF_NODE+"/"+PortalCMSCacheLoader.parseNodeName(nodeId),nodeId,new Boolean(false));
+	            }
+	        }
+	        return exists;
+       }
+       catch(CacheException ce)
+       {
+           throw new RuntimeException(ce);
+       }
+   }
+    
+    /**
+    *
+    */
+   public NodeReferences load(NodeReferencesId targetId) throws NoSuchItemStateException, ItemStateException
+   {
+       try
+       {
+	        NodeReferences refs = null;
+	        String nodeId = targetId.toString();
+	        
+	        //get the nodeData
+	        byte[] nodeData = null;
+	        if(this.schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+	        {
+	            Object o = this.pmCache.get(PortalCMSCacheLoader.WSP_REF_NODE+"/"+PortalCMSCacheLoader.parseNodeName(nodeId),nodeId);
+	            nodeData = ((WSPRefs)o).getData();
+	        }
+	        else if(this.schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+	        {
+	            Object o = this.pmCache.get(PortalCMSCacheLoader.VERSION_REF_NODE+"/"+PortalCMSCacheLoader.parseNodeName(nodeId),nodeId);
+	            nodeData = ((VersionRefs)o).getData();
+	        }
+	        
+	        //parse propertyData into propertyState
+	        if(nodeData!=null)
+	        {
+	            Session session = null;
+	            Transaction tx = null;
+	            boolean success = false;
+	            try
+	            {
+	                session = Tools.getOpenSession();
+	                tx = session.beginTransaction();
+	                              
+	                InputStream in = new ByteArrayInputStream(nodeData);
+	                
+	                //setup the propertyState
+	                refs = new NodeReferences(targetId);
+	                Serializer.deserialize(refs,in);
+	                org.jboss.portal.common.util.Tools.safeClose(in);
+	                
+	                tx.commit();
+	                success = true;
+	            }
+	            catch(Exception e)
+	            {
+	                if (e instanceof NoSuchItemStateException)
+	                {
+	                   throw (NoSuchItemStateException) e;
+	                }
+	                String msg = "failed to read reference from cache: " + targetId.toString();
+	                log.error(msg, e);
+	                throw new ItemStateException(msg, e);
+	            }
+	            finally
+	            {
+	                if(!success)
+	                {
+	                    tx.rollback();
+	                }
+	                Tools.closeSession(session);
+	            }
+	        }	        
+	        
+	        return refs;
+       }
+       catch(CacheException ce)
+       {
+           throw new RuntimeException(ce);
+       }
+   }
+   
+   /**
+    * 
+    *
+    */
+   private void store(NodeReferences refs) throws ItemStateException
+   {
+       if (!initialized)
+       {
+          throw new IllegalStateException("not initialized");
+       }
+
+       ByteArrayOutputStream out = new ByteArrayOutputStream(INITIAL_BUFFER_SIZE);
+       try
+       {
+          Serializer.serialize(refs,out);
+          if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+          {
+             VersionRefs versionRefs = new VersionRefs(refs.getId().toString(), out.toByteArray());
+             
+             //place this in the cache
+             versionRefs.resetCacheItemPersistence();
+             String cacheNode = PortalCMSCacheLoader.VERSION_REF_NODE + "/" + PortalCMSCacheLoader.parseNodeName(versionRefs.getRefId());
+             pmCache.put(cacheNode,versionRefs.getRefId(),versionRefs);
+          }
+          else if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+          {
+
+             WSPRefs wspRefs = new WSPRefs(refs.getId().toString(), out.toByteArray());
+             
+             //place this in the cache
+             wspRefs.resetCacheItemPersistence();
+             String cacheNode = PortalCMSCacheLoader.WSP_REF_NODE + "/" + PortalCMSCacheLoader.parseNodeName(wspRefs.getRefId());
+             pmCache.put(cacheNode,wspRefs.getRefId(),wspRefs);
+          }
+       }
+       catch (Exception e)
+       {
+          String msg = "failed to write reference state: " + refs.getId();
+          log.error(msg, e);
+          throw new ItemStateException(msg, e);
+       }
+       finally
+       {
+          try
+          {
+             out.close();
+          }
+          catch (Exception e)
+          {
+             e.printStackTrace();
+          }
+       }
+   }
+   
+   /**
+    *
+    */
+   private void destroy(NodeReferences refs) throws ItemStateException
+   {
+       if (!initialized)
+       {
+          throw new IllegalStateException("not initialized");
+       }
+
+       String id = refs.getId().toString();
+       String cacheNodeName = PortalCMSCacheLoader.parseNodeName(id);
+       try
+       {
+           if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+           {
+               pmCache.remove(PortalCMSCacheLoader.VERSION_REF_NODE+"/"+cacheNodeName,id);
+           }
+           else if(schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+           {
+               pmCache.remove(PortalCMSCacheLoader.WSP_REF_NODE+"/"+cacheNodeName,id);
+           }
+       }
+       catch (Exception e)
+       {
+          String msg = "failed to delete reference state: " + refs.getId();
+          log.error(msg, e);
+          throw new ItemStateException(msg, e);
+       }
+   }          
+    //---------------------------------------------------< PersistenceManager >
+    public String getJNDIName()
+    {
+       return jndiName;
+    }
+
+    public void setJNDIName(String JNDIName)
+    {
+       this.jndiName = JNDIName;
+    }
+
+    public String getSchemaObjectPrefix()
+    {
+       return schemaObjectPrefix;
+    }
+
+    public void setSchemaObjectPrefix(String schemaObjectPrefix)
+    {
+       this.schemaObjectPrefix = schemaObjectPrefix;//.toUpperCase();
+    }
+
+    public boolean isExternalBLOBs()
+    {
+       return externalBLOBs;
+    }
+
+    public void setExternalBLOBs(boolean externalBLOBs)
+    {
+       this.externalBLOBs = externalBLOBs;
+    }
+
+    public void setExternalBLOBs(String externalBLOBs)
+    {
+       this.externalBLOBs = Boolean.valueOf(externalBLOBs).booleanValue();
+    }
+    //---------------------------------------------------< PersistenceManager >
+    /**
+    *
+    */
+   public void close() throws Exception
+   {
+      if (!initialized)
+      {
+         throw new IllegalStateException("not initialized");
+      }
+
+      try
+      {
+         if (externalBLOBs)
+         {
+            //close BLOB file system
+            blobFS.close();
+            blobFS = null;
+         }
+         blobStore = null;
+      }
+      finally
+      {
+         initialized = false;
+      }
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public NodeState createNew(NodeId id)
+   {
+      return new NodeState(id, null, null, NodeState.STATUS_NEW, false);
+   }
+
+   /**
+    * {@inheritDoc}
+    */
+   public PropertyState createNew(PropertyId id)
+   {
+      return new PropertyState(id, PropertyState.STATUS_NEW, false);
+   }
+   
+    /**
+     * 
+     */
+    public void store(ChangeLog changeLog) throws ItemStateException
+    {
+       Session session = null;
+       Transaction tx = null;
+       try
+       {
+          session = Tools.getOpenSession();
+          tx = session.beginTransaction();
+          storeHB(changeLog);
+          tx.commit();
+       }
+       catch (ItemStateException e)
+       {
+          tx.rollback();
+          throw e;
+       }
+       finally
+       {
+          Tools.closeSession(session);            
+       }
+    }
+    
+    private Blob createBlob(byte[] bytes)
+    {
+       return Hibernate.createBlob(bytes);
+       //return new ByteArrayBlob(bytes);
+    }
+
+    public void storeHB(ChangeLog changeLog) throws ItemStateException
+    {
+       Iterator iter = changeLog.deletedStates();
+       while (iter.hasNext())
+       {
+          ItemState state = (ItemState) iter.next();
+          if (state.isNode())
+          {
+             destroy((NodeState) state);
+          }
+          else
+          {
+             destroy((PropertyState) state);
+          }
+       }
+       iter = changeLog.addedStates();
+       while (iter.hasNext())
+       {
+          ItemState state = (ItemState) iter.next();
+          if (state.isNode())
+          {
+             store((NodeState) state);
+          }
+          else
+          {
+             store((PropertyState) state);
+          }
+       }
+       iter = changeLog.modifiedStates();
+       while (iter.hasNext())
+       {
+          ItemState state = (ItemState) iter.next();
+          if (state.isNode())
+          {
+             update((NodeState) state);
+          }
+          else
+          {
+             update((PropertyState) state);
+          }
+       }
+       iter = changeLog.modifiedRefs();
+       while (iter.hasNext())
+       {
+          NodeReferences refs = (NodeReferences) iter.next();
+          if (refs.hasReferences())
+          {
+             store(refs);
+          }
+          else
+          {
+             if (exists(refs.getId()))
+             {
+                destroy(refs);
+             }
+          }
+       }
+    }
+
+    /**
+     *
+     */
+    protected boolean exists(String blobid) throws ItemStateException
+    {
+       return exists(blobSelectExist, blobid);
+    }
+    
+    /**
+     * 
+     *
+     */
+    private boolean exists(String query, String id) throws ItemStateException
+    {
+       if (!initialized)
+       {
+          throw new IllegalStateException("not initialized");
+       }
+
+       Session session = Tools.getOpenSession();
+       try
+       {
+          List rs = session.createQuery(query).setCacheable(true).setString(0, id).list();
+          Iterator iter = rs.iterator();
+          return iter.hasNext();
+       }
+       catch (Exception e)
+       {
+          String msg = "failed to check existence of node state: " + id;
+          log.error(msg, e);
+          throw new ItemStateException(msg, e);
+       }
+       finally
+       {
+          Tools.closeSession(session);
+       }
+
+    }
+    //-------------------------------------------------< misc. helper methods >
+    protected void logException(String message, SQLException se)
+    {
+       if (message != null)
+       {
+          log.error(message);
+       }
+       log.error("    reason: " + se.getMessage());
+       log.error("state/code: " + se.getSQLState() + "/" + se.getErrorCode());
+       log.debug("      dump:", se);
+    }
+    //--------------------------------------------------------< inner classes >
+    class DbBLOBStore implements BLOBStore
+    {
+
+       /**
+        *
+        */
+       public String createId(PropertyId id, int index)
+       {
+          // the blobId is a simple string concatenation of id plus index
+          StringBuffer sb = new StringBuffer();
+          sb.append(id.toString());
+          sb.append('[');
+          sb.append(index);
+          sb.append(']');
+          return sb.toString();
+       }
+
+       /**
+        *
+        */
+       public InputStream get(String blobId) throws Exception
+       {
+          Session session = Tools.getCurrentSession();
+          try
+          {
+             List rs = session.createQuery(blobSelectData).setCacheable(true).setString(0, blobId).list();
+             Iterator iter = rs.iterator();
+             java.sql.Blob blob = (java.sql.Blob) iter.next();
+             InputStream is = blob.getBinaryStream();
+             return is;
+          }
+          catch (Exception e)
+          {
+             if (e instanceof NoSuchItemStateException)
+             {
+                throw (NoSuchItemStateException) e;
+             }
+             String msg = "failed to read binary data: " + blobId;
+             log.error(msg, e);
+             throw new ItemStateException(msg, e);
+          }
+       }
+
+       /**
+        *
+        */
+       public void put(String blobId, InputStream in, long size) throws Exception
+       {
+          boolean update = exists(blobId);
+
+          Session session = Tools.getCurrentSession();
+
+          if (update)
+          {
+             try
+             {
+
+                Query query = session.createQuery(blobSelect).setCacheable(true);
+                if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+                {
+                   query.setString(0, blobId);
+                   VersionBinVal versionNode = (VersionBinVal) query.uniqueResult();
+                   if (versionNode == null)
+                   {
+                      throw new Exception("No such Node: " + blobId);
+                   }
+                   versionNode.setId(blobId);
+                   versionNode.setData(Hibernate.createBlob(in));
+                }
+                else if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+                {
+                   query.setString(0, blobId);
+                   WSPBinVal wspNode = (WSPBinVal) query.uniqueResult();
+                   if (wspNode == null)
+                   {
+                      throw new Exception("No such Node: " + blobId);
+                   }
+                   wspNode.setId(blobId);
+                   wspNode.setData(Hibernate.createBlob(in));
+                }
+             }
+             catch (Exception e)
+             {
+                String msg = "failed to write node state: " + blobId;
+                log.error(msg, e);
+                throw new ItemStateException(msg, e);
+             }
+          }
+          else
+          // insert
+          {
+             try
+             {
+
+                if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.versionPrefix))
+                {
+                   VersionBinVal versionNode = new VersionBinVal(blobId, Hibernate.createBlob(in));
+                   session.save(versionNode);
+                }
+                else if (schemaObjectPrefix.equalsIgnoreCase(HibernateStoreConstants.wspPrefix))
+                {
+                   WSPBinVal wspNode = new WSPBinVal(blobId, Hibernate.createBlob(in));
+                   session.save(wspNode);
+                }
+             }
+             catch (Exception e)
+             {
+                String msg = "failed to write node state: " + blobId;
+                log.error(msg, e);
+                throw new ItemStateException(msg, e);
+             }
+          }
+       }
+
+       /**
+        *
+        */
+       //      public synchronized boolean remove(String blobId) throws Exception
+       public boolean remove(String blobId) throws Exception
+       {
+          Session session = Tools.getCurrentSession();
+          try
+          {
+             Query query = session.createQuery(nodeBinValSelect).setCacheable(true).setString(0, blobId);
+             Object result = query.uniqueResult();
+             if (result != null)
+             {
+                session.delete(result);
+             }
+             return true;
+          }
+          catch (Exception e)
+          {
+             String msg = "failed to delete binval: " + blobId;
+             log.error(msg, e);
+             throw new ItemStateException(msg, e);
+          }
+       }
+    }        
+}

Added: trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/PortalCMSCacheLoader.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/PortalCMSCacheLoader.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/PortalCMSCacheLoader.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -0,0 +1,845 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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.jboss.portal.cms.hibernate.state;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Collections;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.TreeCache;
+import org.jboss.cache.loader.CacheLoader;
+import org.jboss.cache.Modification;
+
+import org.jboss.portal.cms.hibernate.state.Base;
+import org.jboss.portal.cms.hibernate.state.WSPProp;
+import org.jboss.portal.cms.hibernate.state.VersionProp;
+import org.jboss.portal.cms.hibernate.state.WSPNode;
+import org.jboss.portal.cms.hibernate.state.VersionNode;
+
+import org.apache.log4j.Logger;
+import org.hibernate.Session;
+
+
+/*
+ * Created on Aug 29, 2006
+ *
+ * @author <a href="mailto:sohil.shah at jboss.com">Sohil Shah</a>
+ */
+public class PortalCMSCacheLoader implements CacheLoader 
+{
+    /**
+     * Logger instance
+     */
+    private static Logger log = Logger.getLogger(PortalCMSCacheLoader.class);
+    
+    /**
+     * 
+     */
+    private static final String loadWSPProps = "from org.jboss.portal.cms.hibernate.state.WSPProp";
+    private static final String loadWSPPropChildren = "select property.propId from org.jboss.portal.cms.hibernate.state.WSPProp property";
+    private static final String loadWSPProp = "from org.jboss.portal.cms.hibernate.state.WSPProp property where property.propId=?";
+    private static final String loadVersionProps = "from org.jboss.portal.cms.hibernate.state.VersionProp";  
+    private static final String loadVersionPropChildren = "select property.propId from org.jboss.portal.cms.hibernate.state.VersionProp property";
+    private static final String loadVersionProp = "from org.jboss.portal.cms.hibernate.state.VersionProp property where property.propId=?";
+    
+    /**
+     * 
+     */
+    private static final String loadWSPNodes = "from org.jboss.portal.cms.hibernate.state.WSPNode";
+    private static final String loadWSPNodeChildren = "select node.nodeId from org.jboss.portal.cms.hibernate.state.WSPNode node";
+    private static final String loadWSPNode = "from org.jboss.portal.cms.hibernate.state.WSPNode node where node.nodeId=?";
+    private static final String loadVersionNodes = "from org.jboss.portal.cms.hibernate.state.VersionNode";
+    private static final String loadVersionNodeChildren = "select node.nodeId from org.jboss.portal.cms.hibernate.state.VersionNode node";
+    private static final String loadVersionNode = "from org.jboss.portal.cms.hibernate.state.VersionNode node where node.nodeId=?";
+    
+    /**
+     * 
+     */
+    private static final String loadWSPRefs = "from org.jboss.portal.cms.hibernate.state.WSPRefs";
+    private static final String loadWSPRefsChildren = "select ref.refId from org.jboss.portal.cms.hibernate.state.WSPRefs ref";
+    private static final String loadWSPRef = "from org.jboss.portal.cms.hibernate.state.WSPRefs ref where ref.refId=?";
+    private static final String loadVersionRefs = "from org.jboss.portal.cms.hibernate.state.VersionRefs";
+    private static final String loadVersionRefsChildren = "select ref.refId from org.jboss.portal.cms.hibernate.state.VersionRefs ref";
+    private static final String loadVersionRef = "from org.jboss.portal.cms.hibernate.state.VersionRefs ref where ref.refId=?";
+    
+    
+    /**
+     * 
+     */
+    public static final String WSP_PROP_NODE = "/wsp_prop";
+    public static final String VERSION_PROP_NODE = "/version_prop";
+    public static final String WSP_NODE_NODE = "/wsp_node";
+    public static final String VERSION_NODE_NODE = "/version_node";
+    public static final String WSP_REF_NODE = "/wsp_ref";
+    public static final String VERSION_REF_NODE = "/version_ref";
+    
+    /**
+     * map of propertyId-nodeName map
+     */
+    private static Map nodeNames = Collections.synchronizedMap(new HashMap());
+    
+    /**
+     * 
+     */
+    private TreeCache cache = null;
+    
+    
+    /**
+     * 
+     */
+    public void setConfig(Properties properties) 
+    {
+    }
+
+    /**
+     * 
+     */
+    public void setCache(TreeCache cache) 
+    {
+        this.cache = cache;                
+    }
+
+    /**
+     * 
+     */
+    public Set getChildrenNames(Fqn fqn) throws Exception 
+    {
+        Set children = null;
+        
+        if(fqn.toString().equals("/"))
+        {
+            children = new HashSet();
+            children.add(WSP_PROP_NODE.substring(1));
+            children.add(VERSION_PROP_NODE.substring(1));
+            children.add(WSP_NODE_NODE.substring(1));
+            children.add(VERSION_NODE_NODE.substring(1));
+        }
+        else if(fqn.toString().equals(WSP_PROP_NODE))
+        {
+            children = this.getChildrenNames(loadWSPPropChildren);
+        }
+        else if(fqn.toString().equals(VERSION_PROP_NODE))
+        {
+            children = this.getChildrenNames(loadVersionPropChildren);
+        }
+        else if(fqn.toString().equals(WSP_NODE_NODE))
+        {
+            children = this.getChildrenNames(loadWSPNodeChildren);
+        }
+        else if(fqn.toString().equals(VERSION_NODE_NODE))
+        {
+            children = this.getChildrenNames(loadVersionNodeChildren);
+        }
+        else if(fqn.toString().equals(WSP_REF_NODE))
+        {
+            children = this.getChildrenNames(loadWSPRefsChildren);
+        }
+        else if(fqn.toString().equals(VERSION_REF_NODE))
+        {
+            children = this.getChildrenNames(loadVersionRefsChildren);
+        }
+        
+        if(children!=null)
+        {
+            children = Collections.unmodifiableSet(children);
+        }
+        
+        return children;
+    }
+    
+    /**
+     * 
+     */
+    public boolean exists(Fqn fqn) throws Exception 
+    {
+        boolean exists = false;
+        
+        //node calculation
+        String node = fqn.toString();
+        String nodeName = "";
+        int lastIndex = node.lastIndexOf('/');
+        if(lastIndex>0)
+        {
+            nodeName = node.substring(lastIndex+1);
+        }
+        String query = null;
+        
+        if(
+                node.equals("/") 
+        )
+        {
+            exists = true;
+            return exists;
+        }
+        else if(node.startsWith(WSP_PROP_NODE))
+        {
+            query = loadWSPProp;
+        }
+        else if(node.startsWith(VERSION_PROP_NODE))
+        {
+            query = loadVersionProp;
+        }
+        else if(node.startsWith(WSP_NODE_NODE))
+        {
+            query = loadWSPNode;
+        }
+        else if(node.startsWith(VERSION_NODE_NODE))
+        {
+            query = loadVersionNode;
+        }
+        else if(node.startsWith(WSP_REF_NODE))
+        {
+            query = loadWSPRef;
+        }
+        else if(node.startsWith(VERSION_REF_NODE))
+        {
+            query = loadVersionRef;
+        }
+        
+        if(query!=null && query.trim().length()>0)
+        {
+	        String id = PortalCMSCacheLoader.lookupNodeId(nodeName); 
+	        if(id!=null && id.trim().length()>0)
+	        {
+	            Object nodeValue = this.loadNode(query,id);
+	            if(nodeValue!=null)
+	            {
+	                exists = true;
+	            }	            
+	        }
+        }
+        
+        return exists;
+    }
+
+    /**
+     * 
+     */
+    public Map get(Fqn fqn) throws Exception 
+    {
+        Map map = null;
+        
+        //node calculation
+        String node = fqn.toString();
+        String nodeName = "";
+        int lastIndex = node.lastIndexOf('/');
+        if(lastIndex>0)
+        {
+            nodeName = node.substring(lastIndex+1);
+        }
+        String query = null;
+                
+        if(node.startsWith(WSP_PROP_NODE))
+        {
+            query = loadWSPProp;
+        }
+        else if(node.startsWith(VERSION_PROP_NODE))
+        {   
+            query = loadVersionProp;
+        }
+        else if(node.startsWith(WSP_NODE_NODE))
+        {          
+            query = loadWSPNode;
+        }
+        else if(node.startsWith(VERSION_NODE_NODE))
+        {          
+            query = loadVersionNode;
+        }
+        else if(node.startsWith(WSP_REF_NODE))
+        {          
+            query = loadWSPRef;
+        }
+        else if(node.startsWith(VERSION_REF_NODE))
+        {          
+            query = loadVersionRef;
+        }
+        
+        if(query != null && query.trim().length()>0)
+        {
+            String id = PortalCMSCacheLoader.lookupNodeId(nodeName);
+            if(id !=null && id.trim().length()>0)
+            {
+	            Object nodeValue = this.loadNode(query,id);
+	            if(nodeValue!=null)
+	            {
+	                map = new HashMap();
+	                map.put(id,nodeValue);
+	            }	            
+            }
+        }
+        
+        return map;
+    }
+
+    /**
+     * semantically, if the fqn node does not exist, the entire node needs to be created..
+     * In this cacheLoader's case, the node not existing in the database is not an option.
+     * that scenario never happens
+     * 
+     * returns the oldValue if its found or a new value is created
+     */
+    public Object put(Fqn fqn,Object key,Object value) throws Exception 
+    {
+        Object oldValue = null;
+        String node = fqn.toString();
+        
+        if(node.startsWith(WSP_PROP_NODE) && value instanceof WSPProp)
+        {
+            if(((Base)value).isPersistCacheItem())
+            {
+                oldValue = this.saveWSPPropNodeEntry((WSPProp)value);
+            }
+            ((Base)value).resetCacheItemPersistence();
+        }
+        else if(node.startsWith(VERSION_PROP_NODE) && value instanceof VersionProp)
+        {
+            if(((Base)value).isPersistCacheItem())
+            {
+                oldValue = this.saveVersionPropNodeEntry((VersionProp)value);
+            }
+            ((Base)value).resetCacheItemPersistence();
+        }
+        else if(node.startsWith(WSP_NODE_NODE) && value instanceof WSPNode)
+        {
+            if(((Base)value).isPersistCacheItem())
+            {
+                oldValue = this.saveWSPNodeNodeEntry((WSPNode)value);
+            }
+            ((Base)value).resetCacheItemPersistence();
+        }
+        else if(node.startsWith(VERSION_NODE_NODE) && value instanceof VersionNode)
+        {
+            if(((Base)value).isPersistCacheItem())
+            {
+                oldValue = this.saveVersionNodeNodeEntry((VersionNode)value);
+            }
+            ((Base)value).resetCacheItemPersistence();
+        }
+        else if(node.startsWith(WSP_REF_NODE) && value instanceof WSPRefs)
+        {
+            if(((Base)value).isPersistCacheItem())
+            {
+                oldValue = this.saveWSPRefNodeEntry((WSPRefs)value);
+            }
+            ((Base)value).resetCacheItemPersistence();
+        }
+        else if(node.startsWith(VERSION_REF_NODE) && value instanceof VersionRefs)
+        {
+            if(((Base)value).isPersistCacheItem())
+            {
+                oldValue = this.saveVersionRefNodeEntry((VersionRefs)value);
+            }
+            ((Base)value).resetCacheItemPersistence();
+        }
+        
+        return oldValue;
+    }
+
+    /**
+     * 
+     */
+    public void put(Fqn fqn,Map attributes) throws Exception 
+    {
+        if(attributes!=null)
+        {
+            Set keys = attributes.keySet();
+            for(Iterator itr=keys.iterator();itr.hasNext();)
+            {
+                Object key = itr.next();
+                Object value = attributes.get(key);
+                this.put(fqn,key,value);
+            }
+        }
+    }
+
+    /**
+     * 
+     */
+    public void put(List modifications) throws Exception 
+    {
+        if(modifications!=null)
+        {
+            for(int i = 0; i < modifications.size(); ++i)
+            {
+               Modification m = (Modification) modifications.get(i);
+               switch(m.getType())
+               {
+                  case Modification.PUT_DATA:
+                     put(m.getFqn(),m.getData());
+                     break;
+                  case Modification.PUT_DATA_ERASE:
+                     put(m.getFqn(), m.getData());
+                     break;
+                  case Modification.PUT_KEY_VALUE:
+                     put(m.getFqn(),m.getKey(),m.getValue());
+                     break;
+                  case Modification.REMOVE_DATA:
+                     removeData(m.getFqn());
+                     break;
+                  case Modification.REMOVE_KEY_VALUE:
+                     remove(m.getFqn(),m.getKey());
+                     break;
+                  case Modification.REMOVE_NODE:
+                     remove(m.getFqn());
+                     break;
+                  default:
+                     throw new IllegalStateException("Unexpected modification code: " + m.getType());
+               }
+            }
+        }
+    }
+
+    /**
+     * 
+     */
+    public Object remove(Fqn fqn, Object key) throws Exception 
+    {
+        Object removedValue = null;
+        String node = fqn.toString();
+        String id = (String)key;
+        String query = null;
+        
+        
+        if(node.startsWith(WSP_PROP_NODE))
+        {
+            query = loadWSPProp;
+        }
+        else if(node.startsWith(VERSION_PROP_NODE))
+        {   
+            query = loadVersionProp;
+        }
+        else if(node.startsWith(WSP_NODE_NODE))
+        {          
+            query = loadWSPNode;
+        }
+        else if(node.startsWith(VERSION_NODE_NODE))
+        {          
+            query = loadVersionNode;
+        }
+        else if(node.startsWith(WSP_REF_NODE))
+        {          
+            query = loadWSPRef;
+        }
+        else if(node.startsWith(VERSION_REF_NODE))
+        {          
+            query = loadVersionRef;
+        }
+        
+        if(query != null && query.trim().length()>0)
+        {
+            removedValue = this.delete(query,id);
+        }
+        
+        return removedValue;
+    }
+
+    /**
+     * 
+     */
+    public void remove(Fqn fqn) throws Exception 
+    {
+        //just for safety this is not implemented.
+        //the cache should not be used for this kind of stuff
+        
+        //the admin tool is suited for that
+    }
+
+    /**
+     * 
+     */
+    public void removeData(Fqn fqn) throws Exception 
+    {
+        //just for safety this is not implemented.
+        //the cache should not be used for this kind of stuff
+        
+        //the admin tool is suited for that
+    }
+    //------------cache unit of work transaction-management--------------------------------------------------------------------------------------------------------------------    
+    /**
+     * 
+     */
+    public void prepare(Object tx,List modifications,boolean one_phase) throws Exception 
+    {                
+        this.put(modifications);
+    }
+
+    /**
+     * 
+     */
+    public void commit(Object tx) throws Exception 
+    {                                             
+    }
+
+    /**
+     * 
+     */
+    public void rollback(Object tx) 
+    {                               
+    }
+    //--------------------------------------------------------------------------------------------------------------------------------------------------------
+    /**
+     * 
+     */
+    public byte[] loadEntireState() throws Exception 
+    {
+        //loading the entire cms into a byteBuffer and sending it over the network to a remote cache
+        //is not feasible for this loader
+        //plus, all distributed caches/cache loaders will be loading/saving data to the same database
+        //so the content is in sync across all the caches in the cluster
+        return null;
+    }
+
+    /**
+     * 
+     */
+    public void storeEntireState(byte[] arg0) throws Exception 
+    {
+        //no need for this since all the distributed caches/cacheloaders will be loading/saving data to the same
+        //database
+    }
+    //------Service lifecycle implementation---------------------------------------------------------------------------------------------------------------------
+    /**
+     * 
+     */
+    public void create() throws Exception 
+    {
+    }
+
+    /**
+     * 
+     */
+    public void start() throws Exception 
+    { 
+        log.info("------------------------------------------------------");
+        log.info("PersistenceManager Cache successfully started.....(ClusterName="+this.cache.getClusterName()+")");
+        log.info("------------------------------------------------------");
+    }
+
+    /**
+     * 
+     */
+    public void stop() 
+    {
+        this.cache = null;
+    }
+
+    /**
+     * 
+     */
+    public void destroy() 
+    {
+    }
+    //------internal implementation-----------------------------------------------------------------------------------------------------------------------                    
+    /**
+     * 
+     *
+     */
+    private Object saveWSPPropNodeEntry(WSPProp wspProp) throws Exception
+    {
+        Object oldValue = null;
+        
+        oldValue = this.loadManagedNode(loadWSPProp,wspProp.getPropId());
+        if(oldValue!=null)
+        {
+            Integer id = ((WSPProp)oldValue).getKey();
+            wspProp.setKey(id);
+        }
+        else
+        {
+            wspProp.setKey(null);
+        }
+        this.save(wspProp);
+        
+        return oldValue;
+    }
+        
+    /**
+     * 
+     *
+     */
+    private Object saveVersionPropNodeEntry(VersionProp versionProp) throws Exception
+    {
+        Object oldValue = null;
+        
+        oldValue = this.loadManagedNode(loadVersionProp,versionProp.getPropId());
+        if(oldValue!=null)
+        {
+            Integer id = ((VersionProp)oldValue).getKey();
+            versionProp.setKey(id);
+        }
+        else
+        {
+            versionProp.setKey(null);
+        }
+        this.save(versionProp);
+        
+        return oldValue;
+    }
+    
+    /**
+     * 
+     *
+     */
+    private Object saveWSPNodeNodeEntry(WSPNode wspNode) throws Exception
+    {
+        Object oldValue = null;
+        
+        oldValue = this.loadManagedNode(loadWSPNode,wspNode.getNodeId());
+        if(oldValue!=null)
+        {
+            Integer id = ((WSPNode)oldValue).getKey();
+            wspNode.setKey(id);
+        }
+        else
+        {
+            wspNode.setKey(null);
+        }
+        this.save(wspNode);
+        
+        return oldValue;
+    }
+    
+    /**
+     * 
+     *
+     */
+    private Object saveVersionNodeNodeEntry(VersionNode versionNode) throws Exception
+    {
+        Object oldValue = null;
+        
+        oldValue = this.loadManagedNode(loadVersionNode,versionNode.getNodeId());
+        if(oldValue!=null)
+        {
+            Integer id = ((VersionNode)oldValue).getKey();
+            versionNode.setKey(id);
+        }
+        else
+        {
+            versionNode.setKey(null);
+        }
+        this.save(versionNode);
+        
+        return oldValue;
+    }
+    
+    /**
+     * 
+     *
+     */
+    private Object saveWSPRefNodeEntry(WSPRefs wspRef) throws Exception
+    {
+        Object oldValue = null;
+        
+        oldValue = this.loadManagedNode(loadWSPRef,wspRef.getRefId());
+        if(oldValue!=null)
+        {
+            Integer id = ((WSPRefs)oldValue).getKey();
+            wspRef.setKey(id);
+        }
+        else
+        {
+            wspRef.setKey(null);
+        }
+        this.save(wspRef);
+        
+        return oldValue;
+    }
+    
+    /**
+     * 
+     *
+     */
+    private Object saveVersionRefNodeEntry(VersionRefs versionRef) throws Exception
+    {
+        Object oldValue = null;
+        
+        oldValue = this.loadManagedNode(loadVersionRef,versionRef.getRefId());
+        if(oldValue!=null)
+        {
+            Integer id = ((VersionRefs)oldValue).getKey();
+            versionRef.setKey(id);
+        }
+        else
+        {
+            versionRef.setKey(null);
+        }
+        this.save(versionRef);
+        
+        return oldValue;
+    }
+    //-----------------------------------------------------------------------------------------------------------------------------------------------------
+    /**
+     * 
+     *
+     */
+    private Set getChildrenNames(String query) throws Exception
+    {
+        Set children = null;
+        Session session = null;
+        try
+        {
+            session = Tools.getOpenSession();
+            
+            List rs = session.createQuery(query).list();
+            for(Iterator itr=rs.iterator();itr.hasNext();)
+            {
+                String id = (String)itr.next();   
+                if(children==null)
+                {
+                    children = new HashSet();
+                }
+                children.add(PortalCMSCacheLoader.parseNodeName(id));
+            }
+        }
+        finally
+        {
+            Tools.closeSession(session);
+        }
+        return children;
+    }
+    
+    /**
+     * 
+     *
+     */
+    private Object loadNode(String query,String id) throws Exception
+    {
+        Object node = null;
+        Session session = null;
+        try
+        {
+            session = Tools.getOpenSession();
+            
+            //node = session.createQuery(query).setString(0,id).uniqueResult();
+            List rs = session.createQuery(query).setString(0,id).list();
+            if(rs !=null && !rs.isEmpty())
+            {
+                node = rs.iterator().next();
+            }
+        }
+        finally
+        {
+            Tools.closeSession(session);
+        }
+        return node;
+    }
+    
+    /**
+     * 
+     *
+     */
+    private Object loadManagedNode(String query,String id) throws Exception
+    {
+        Object node = null;
+        
+        Session session = Tools.getCurrentSession();        
+        //node = session.createQuery(query).setString(0,id).uniqueResult();
+        List rs = session.createQuery(query).setString(0,id).list();
+        if(rs !=null && !rs.isEmpty())
+        {
+            node = rs.iterator().next();
+        }
+                
+        return node;
+    }
+    
+    /**
+     * 
+     */
+    private void save(Object object) throws Exception
+    {
+        Session session = Tools.getCurrentSession();
+        if(((Base)object).getKey() != null)
+        {
+            session.merge(object);
+        }
+        else
+        {
+            session.save(object);
+        }
+    }
+    
+    /**
+     * 
+     *
+     */
+    private Object delete(String loadQuery,String id) throws Exception
+    {
+        Object removedValue = null;
+        removedValue = this.loadManagedNode(loadQuery,id);
+        if(removedValue!=null)
+        {
+            Session session = Tools.getCurrentSession();            
+            session.delete(removedValue);            
+        }
+        return removedValue;
+    }
+    //---------------nodeName related methods-------------------------------------------------------------------------------------------------------------
+    /**
+     * 
+     *
+     */
+    public static String parseNodeName(String id)
+    {
+        String node = (String)PortalCMSCacheLoader.nodeNames.get(id);
+        
+        if(node == null)
+        {
+            node = id.replace('/','_');
+            node = node.replace(':','_');
+            node = node.replace('{','_');
+            node = node.replace('}','_');
+            PortalCMSCacheLoader.nodeNames.put(id,node);
+        }
+        
+        return node;
+    }
+    
+    /**
+     * 
+     *
+     */
+    private static String lookupNodeId(String nodeName)
+    {
+       String id = null;
+       
+       Object[] keys = PortalCMSCacheLoader.nodeNames.keySet().toArray();
+       for(int i=0;i<keys.length;i++)
+       {
+           String key = (String)keys[i];
+           String value = (String)PortalCMSCacheLoader.nodeNames.get(key);
+           if(value.equals(nodeName))
+           {
+               id = key;
+               break;
+           }
+       }
+       
+       return id;
+    }
+}

Added: trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/Tools.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/Tools.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/Tools.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -0,0 +1,199 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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.jboss.portal.cms.hibernate.state;
+
+import javax.naming.InitialContext;
+
+import org.apache.log4j.Logger;
+
+import org.hibernate.cfg.Configuration;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.Query;
+import org.hibernate.HibernateException;
+import org.hibernate.metadata.ClassMetadata;
+import org.hibernate.tool.hbm2ddl.SchemaExport;
+import org.hibernate.Transaction;
+
+/*
+ * Created on Aug 29, 2006
+ * 
+ * A Tool for performing some Hibernate related utilities. This is designed to work in both managed as well as non-managed environments
+ *
+ * @author <a href="mailto:sohil.shah at jboss.com">Sohil Shah</a>
+ */
+public class Tools 
+{
+	private static final Logger log = Logger.getLogger(Tools.class);
+	
+	//hibernate configuration relation information
+	private static SessionFactory sessionFactory = null;
+	private static Configuration cfg = null;
+	private static boolean autoClose = false;
+		
+    /**
+     * 
+     *
+     */
+	public static void init(String jndiName)
+	{
+	    if(Tools.sessionFactory == null)
+	    {	        
+			try
+			{
+			    log.info("Loading the PersistenceManager Hibernate System (Started)...........................");
+			    
+			    boolean loadSuccess = true;
+			    try
+			    {
+			        //just to initialize the session factory
+			        Tools.sessionFactory = (SessionFactory)new InitialContext().lookup(jndiName);
+			    }
+			    catch(Exception e)
+			    {
+			        //some reason this is not found in JNDI environment....try and load from hibernate.cfg.xml from 
+			        //classpath
+			        loadSuccess = false;
+			    }
+			    
+			    if(!loadSuccess)
+			    {
+				    //configure session factory from configuration
+				    Tools.cfg = new Configuration();
+					Tools.cfg.configure();
+					Tools.sessionFactory = Tools.cfg.buildSessionFactory();
+					Tools.generateSiteSchema(Tools.cfg);
+			    }
+				
+				
+				log.info("Loading the PersistenceManager Hibernate System (Done)...........................");
+			}
+			catch(Exception e)
+			{
+				log.error("org.jboss.portal.cms.hibernate.state.Tools",e);
+			}			
+	    }
+	}
+    
+    //---------------------------------------------------------------------------------------------------------------------------------------------------
+	/**
+	 * 
+	 */
+	public static SessionFactory getSessionFactory()
+	{
+	    return Tools.sessionFactory;
+	}
+	
+    /**
+     * 
+     * @return
+     */
+	public static Session getCurrentSession()
+	{        
+		Session session = Tools.sessionFactory.getCurrentSession();
+		return session;
+	}
+	
+    /**
+     * 
+     * @return
+     */
+	public static Session getOpenSession()
+	{        
+		Session session = Tools.sessionFactory.openSession();
+		return session;
+	}
+	
+	/**
+     * 
+     * @param session
+	 */	
+	public static void closeSession(Session session)
+	{
+		if(session!=null && session.isOpen() && !Tools.autoClose)
+		{
+		    session.close();
+		}
+	}
+	//-----------------------schema generation capabilities-------------------------------------------------------------------------------------------
+	/**
+     * 
+     * @param cfg
+	 */	
+	private static void generateSiteSchema(Configuration cfg)	
+	{				
+		if(!doesSiteSchemaExist())
+		{
+			SchemaExport export = new SchemaExport(cfg);
+			export.create(true, //print to the console
+					true //run inside the database
+			);
+		}
+		else
+		{
+			log.info("Site Schema successfully found....No need to recreate it.");
+		}
+	}
+	
+    /**
+     * 
+     * @return
+     */
+	private static boolean doesSiteSchemaExist()
+	{		
+		Session session = null;
+		Transaction tx = null;
+        try
+        {
+	         session = Tools.sessionFactory.openSession();
+	         tx = session.beginTransaction();
+	         ClassMetadata cmd = (ClassMetadata)Tools.sessionFactory.getAllClassMetadata().values().iterator().next();
+	         if(cmd!=null)
+	         {
+	             Query query = session.createQuery("from " + cmd.getEntityName());
+	             query.setFirstResult(0);
+	             query.setMaxResults(0);
+		         try
+		         {
+		               query.list();
+		         }
+	             catch (HibernateException e)
+	             {
+	               // We consider that exception means that the schema deos not exist
+	               return false;               
+	             }
+	         }             
+             //if I get here the schemaExists, dont recreate it
+             return true;
+        }
+        finally
+        {
+        	if(tx!=null)
+        	{
+        		tx.rollback(); //does not matter since this is only a read operation
+        		//this is only so that this operation executes within the context
+        		//of a transaction that performs any necessary cleanup automatically
+        	}
+        	Tools.closeSession(session);        	
+        }		
+	}
+}

Modified: trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/VersionNode.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/VersionNode.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/VersionNode.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -27,52 +27,41 @@
 /**
  * @author <a href="mailto:roy at jboss.org">Roy Russo</a>
  */
-public class VersionNode implements Serializable
+public class VersionNode extends Base implements Serializable
 {
    /** The serialVersionUID */
    private static final long serialVersionUID = -2699419131858972327L;
    
-   private Integer key;
-   private String id;
-   private java.sql.Blob data;
+   private String nodeId;
+   private byte[] data;
 
    public VersionNode()
    {
    }
 
-   public VersionNode(String id, Blob data)
+   public VersionNode(String id, byte[] data)
    {
-      this.key = null;
-      this.id = id;
+      this.nodeId = id;
       this.data = data;
    }
 
-   public Integer getKey()
+   
+   public String getNodeId()
    {
-      return key;
+      return nodeId;
    }
 
-   public void setKey(Integer key)
+   public void setNodeId(String id)
    {
-      this.key = key;
+      this.nodeId = id;
    }
 
-   public String getId()
+   public byte[] getData()
    {
-      return id;
-   }
-
-   public void setId(String id)
-   {
-      this.id = id;
-   }
-
-   public Blob getData()
-   {
       return data;
    }
 
-   public void setData(Blob data)
+   public void setData(byte[] data)
    {
       this.data = data;
    }

Modified: trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/VersionProp.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/VersionProp.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/VersionProp.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -27,52 +27,41 @@
 /**
  * @author <a href="mailto:roy at jboss.org">Roy Russo</a>
  */
-public class VersionProp implements Serializable
+public class VersionProp extends Base implements Serializable
 {
    /** The serialVersionUID */
    private static final long serialVersionUID = -699585138297339148L;
    
-   private Integer key;
-   private String id;
-   private java.sql.Blob data;
+   private String propId;
+   private byte[] data;
 
    public VersionProp()
    {
    }
 
-   public VersionProp(String id, Blob data)
+   public VersionProp(String id, byte[] data)
    {
-      this.key = null;
-      this.id = id;
+      this.propId = id;
       this.data = data;
    }
 
-   public Integer getKey()
+   
+   public String getPropId()
    {
-      return key;
+      return propId;
    }
 
-   public void setKey(Integer key)
+   public void setPropId(String id)
    {
-      this.key = key;
+      this.propId = id;
    }
 
-   public String getId()
+   public byte[] getData()
    {
-      return id;
-   }
-
-   public void setId(String id)
-   {
-      this.id = id;
-   }
-
-   public Blob getData()
-   {
       return data;
    }
 
-   public void setData(Blob data)
+   public void setData(byte[] data)
    {
       this.data = data;
    }

Modified: trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/VersionRefs.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/VersionRefs.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/VersionRefs.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -22,59 +22,45 @@
 package org.jboss.portal.cms.hibernate.state;
 
 import java.io.Serializable;
-import java.sql.Blob;
 
 /**
  * @author <a href="mailto:roy at jboss.org">Roy Russo</a>
  */
-public class VersionRefs implements Serializable
+public class VersionRefs extends Base implements Serializable
 {
    /** The serialVersionUID */
    private static final long serialVersionUID = -4096847492469682729L;
    
-   private Integer key;
-   private String id;
-   private java.sql.Blob data;
+   private String refId;
+   private byte[] data;
 
    public VersionRefs()
    {
    }
 
-   public VersionRefs(String id, Blob data)
+   public VersionRefs(String refId, byte[] data)
    {
-      this.key = null;
-      this.id = id;
+      this.refId = refId;
       this.data = data;
    }
 
-   public Integer getKey()
+   public String getRefId()
    {
-      return key;
+      return this.refId;
    }
 
-   public void setKey(Integer key)
+   public void setRefId(String refId)
    {
-      this.key = key;
+      this.refId = refId;
    }
 
-   public String getId()
+   public byte[] getData()
    {
-      return id;
-   }
-
-   public void setId(String id)
-   {
-      this.id = id;
-   }
-
-   public Blob getData()
-   {
       return data;
    }
 
-   public void setData(Blob data)
+   public void setData(byte[] data)
    {
       this.data = data;
    }
-
 }

Modified: trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/WSPNode.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/WSPNode.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/WSPNode.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -27,51 +27,39 @@
 /**
  * @author <a href="mailto:roy at jboss.org">Roy Russo</a>
  */
-public class WSPNode implements Serializable
+public class WSPNode extends Base implements Serializable
 {
    /** The serialVersionUID */
    private static final long serialVersionUID = 624216529218745492L;
-   private Integer key;
-   private String id;
-   private java.sql.Blob data;
+   private String nodeId;
+   private byte[] data;
 
    public WSPNode()
    {
    }
 
-   public WSPNode(String id, Blob data)
+   public WSPNode(String id, byte[] data)
    {
-      this.key = null;
-      this.id = id;
+      this.nodeId = id;
       this.data = data;
    }
 
-   public Integer getKey()
+   public String getNodeId()
    {
-      return key;
+      return nodeId;
    }
 
-   public void setKey(Integer key)
+   public void setNodeId(String id)
    {
-      this.key = key;
+      this.nodeId = id;
    }
 
-   public String getId()
+   public byte[] getData()
    {
-      return id;
-   }
-
-   public void setId(String id)
-   {
-      this.id = id;
-   }
-
-   public Blob getData()
-   {
       return data;
    }
 
-   public void setData(Blob data)
+   public void setData(byte[] data)
    {
       this.data = data;
    }

Modified: trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/WSPProp.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/WSPProp.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/WSPProp.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -27,51 +27,39 @@
 /**
  * @author <a href="mailto:roy at jboss.org">Roy Russo</a>
  */
-public class WSPProp implements Serializable
+public class WSPProp extends Base implements Serializable
 {
    /** The serialVersionUID */
    private static final long serialVersionUID = 6490887142311625721L;
-   private Integer key;
-   private String id;
-   private java.sql.Blob data;
+   private String propId;
+   private byte[] data;
 
    public WSPProp()
    {
    }
 
-   public WSPProp(String id, Blob data)
+   public WSPProp(String id, byte[] data)
    {
-      this.key = null;
-      this.id = id;
+      this.propId = id;
       this.data = data;
    }
 
-   public Integer getKey()
+   public String getPropId()
    {
-      return key;
+      return propId;
    }
 
-   public void setKey(Integer key)
+   public void setPropId(String id)
    {
-      this.key = key;
+      this.propId = id;
    }
 
-   public String getId()
+   public byte[] getData()
    {
-      return id;
-   }
-
-   public void setId(String id)
-   {
-      this.id = id;
-   }
-
-   public Blob getData()
-   {
       return data;
    }
 
-   public void setData(Blob data)
+   public void setData(byte[] data)
    {
       this.data = data;
    }

Modified: trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/WSPRefs.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/WSPRefs.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/hibernate/state/WSPRefs.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -22,58 +22,45 @@
 package org.jboss.portal.cms.hibernate.state;
 
 import java.io.Serializable;
-import java.sql.Blob;
 
 /**
  * @author <a href="mailto:roy at jboss.org">Roy Russo</a>
  */
-public class WSPRefs implements Serializable
+public class WSPRefs extends Base implements Serializable
 {
    /** The serialVersionUID */
    private static final long serialVersionUID = 5259852110944824462L;
-   private Integer key;
-   private String id;
-   private java.sql.Blob data;
+   private String refId;
+   private byte[] data;
 
    public WSPRefs()
    {
    }
 
-   public WSPRefs(String id, Blob data)
+   public WSPRefs(String refId,byte[] data)
    {
-      this.key = null;
-      this.id = id;
+      this.refId = refId;
       this.data = data;
    }
 
-   public Integer getKey()
+  
+   public String getRefId()
    {
-      return key;
+      return this.refId;
    }
 
-   public void setKey(Integer key)
+   public void setRefId(String refId)
    {
-      this.key = key;
+      this.refId = refId;
    }
 
-   public String getId()
+   public byte[] getData()
    {
-      return id;
-   }
-
-   public void setId(String id)
-   {
-      this.id = id;
-   }
-
-   public Blob getData()
-   {
       return data;
    }
 
-   public void setData(Blob data)
+   public void setData(byte[] data)
    {
       this.data = data;
    }
-
 }

Modified: trunk/cms/src/main/org/jboss/portal/cms/impl/jcr/command/ContentGetVersionsCommand.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/impl/jcr/command/ContentGetVersionsCommand.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/impl/jcr/command/ContentGetVersionsCommand.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -36,10 +36,12 @@
 import org.jboss.portal.cms.model.Content;
 import org.jboss.portal.cms.util.FileUtil;
 
+
 /**
  * Returns all versions for a given path, except the rootVersion.
  *
  * @author <a href="mailto:roy at jboss.org">Roy Russo</a>
+ * @author <a href="mailto:sohil.shah at jboss.com">Sohil Shah</a>
  */
 public class ContentGetVersionsCommand extends JCRCommand
 {
@@ -60,30 +62,50 @@
       {
          Session session = context.getSession();
          Node fileNode = (Node) session.getItem(this.msFilePath);
+         
          VersionHistory vh = fileNode.getVersionHistory();
-         VersionIterator vi = vh.getAllVersions();
          Version liveVersion = vh.getVersionByLabel("LIVE");
+         Version rootVersion = vh.getRootVersion();
+         
+         
+         VersionIterator vi = vh.getAllVersions();         
          while(vi.hasNext()) // loop versions
          {
             Content content = new ContentImpl();
+                        
             Version version = vi.nextVersion();
-            if(!version.getName().equalsIgnoreCase("jcr:rootVersion"))  // ignore the root version
-            {
+            if(!(version.equals(rootVersion)))  // ignore the root version
+            {                
                NodeIterator ni = version.getNodes();
                while(ni.hasNext())
                {
                   Node node = ni.nextNode();
-
+                  
                   content.setTitle(node.getProperty("portalcms:title").getString());
                   content.setDescription(node.getProperty("portalcms:description").getString());
                   content.setLocale(new Locale(node.getProperty("portalcms:language").getString()));
 
+                  content.setVersionPath(node.getPath());
                   content.setBaseUUID(node.getProperty("jcr:frozenUuid").getString());
-                  content.setBasePath(session.getNodeByUUID(content.getBaseUUID()).getPath());
-                  content.setVersionPath(node.getPath());
+                  content.setBasePath(session.getNodeByUUID(content.getBaseUUID()).getPath());                  
                   content.setVersionUUID(node.getUUID());
-
-                  content.setBytes(FileUtil.getBytes(node.getProperty("jcr:data").getStream()));
+                  
+                  /**
+                   * TODO: integate content size as a node property instead of a derived value
+                   *       see explanation in comments
+                   */
+                  //this is the hacked code for now, until the size property is integrated end-to-end.
+                  //getting the size this way leads to unnecessary extraction of actual content
+                  //which slows the system down dramatically
+                  content.setBytes("".getBytes());
+                  
+                  //this should be the new code
+                  /*int size = 0;
+                  if(node.hasProperty("portalcms:size"))
+                  {
+                      size = Integer.parseInt(node.getProperty("portalcms:size").getString());
+                  }*/
+                  
                   content.setMimeType(node.getProperty("jcr:mimeType").getString());
                   content.setLastModified(node.getProperty("jcr:lastModified").getDate().getTime());
                   content.setName(node.getName());
@@ -94,11 +116,14 @@
                   {
                      content.setLive(true);
                   }
+                  
+                  
                   content.setEncoding(node.getProperty("jcr:encoding").getString());
+                                    
                   contents.addElement(content);
                }
             }
-         }
+         }          
       }
       catch(Exception e)
       {

Added: trunk/cms/src/main/org/jboss/portal/cms/impl/jcr/jackrabbit/ClusteredCacheListener.java
===================================================================
--- trunk/cms/src/main/org/jboss/portal/cms/impl/jcr/jackrabbit/ClusteredCacheListener.java	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/cms/src/main/org/jboss/portal/cms/impl/jcr/jackrabbit/ClusteredCacheListener.java	2006-09-18 04:21:11 UTC (rev 5217)
@@ -0,0 +1,213 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* 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.jboss.portal.cms.impl.jcr.jackrabbit;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.TreeCache;
+import org.jboss.cache.TreeCacheListener;
+import org.jgroups.View;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.jackrabbit.core.state.ItemStateCache;
+import org.apache.jackrabbit.core.state.ItemState;
+import org.apache.jackrabbit.core.ItemId;
+
+import org.apache.commons.collections.map.ReferenceMap;
+
+
+/*
+ * Created on Sep 6, 2006
+ *
+ * @author <a href="mailto:sohil.shah at jboss.com">Sohil Shah</a>
+ */
+public class ClusteredCacheListener implements TreeCacheListener 
+{
+    /**
+     * 
+     */
+    private static Logger log = LoggerFactory.getLogger(ClusteredCacheListener.class);
+        
+    /**
+     * map of node to corresponding cacheItem to be used for doing itemStateCache invalidation in a cluster
+     */ 
+    private static Map internalCaches = Collections.synchronizedMap(new ReferenceMap(ReferenceMap.HARD,ReferenceMap.WEAK));
+    private static Map nodeToItem = Collections.synchronizedMap(new ReferenceMap(ReferenceMap.HARD,ReferenceMap.WEAK));
+    private static int cacheKeyCounter = 0;
+            
+    /**
+     * 
+     */
+    private TreeCache treeCache = null;
+    
+    /**
+     * 
+     *
+     */
+    public ClusteredCacheListener()
+    {
+    }
+    
+    /**
+     * 
+     *
+     */
+    public static void storeInternalCache(String node,ItemId item,ItemStateCache cache)
+    {
+        if(!ClusteredCacheListener.internalCaches.containsValue(cache))
+        {
+            ClusteredCacheListener.internalCaches.put(getCacheKey(),cache);
+        }
+        ClusteredCacheListener.nodeToItem.put(node,item);
+    }
+    
+    /**
+     * 
+     *
+     */
+    private static synchronized String getCacheKey()
+    {
+        return String.valueOf(cacheKeyCounter++);
+    }
+    
+            
+    /**
+     * 
+     */
+    public void nodeEvicted(Fqn fqn) 
+    { 
+        try
+        {
+            String nodeName = fqn.toString();
+            ItemId item = (ItemId)ClusteredCacheListener.nodeToItem.get(nodeName);
+            if(item != null)
+            {
+                synchronized(item)
+                {
+                    if(!ClusteredCacheListener.nodeToItem.containsKey(nodeName))
+                    {
+                        return;
+                    }
+                    ClusteredCacheListener.nodeToItem.remove(nodeName);                    
+		            Object[] values = ClusteredCacheListener.internalCaches.values().toArray();
+		            for(int i=0;i<values.length;i++)
+		            {		                
+		                ItemStateCache internalCache = (ItemStateCache)values[i];
+		                synchronized(internalCache)
+		                {
+			                if(internalCache.isCached(item))
+			                {
+			                    ItemState state = internalCache.retrieve(item);
+			                    
+			                    log.debug("Evicting..."+item.toString()+" (Transient:"+state.isTransient()+")");
+			                
+			                    state.discard();
+			                }
+		                }
+		            }
+                }	            
+            }
+        }
+        catch(Exception e)
+        {
+            throw new RuntimeException(e);
+        }        
+    }
+        
+    /**
+     * 
+     */
+    public void nodeModified(Fqn fqn) 
+    {        
+    }
+    
+    /**
+     * 
+     */
+    public void nodeCreated(Fqn fqn) 
+    {        
+    }
+    
+    /**
+     * 
+     */
+    public void nodeRemoved(Fqn fqn) 
+    {
+    }
+
+    /**
+     * 
+     */
+    public void nodeLoaded(Fqn fqn) 
+    {
+    }
+    
+    /**
+     * 
+     */
+    public void nodeVisited(Fqn fqn) 
+    {
+    }
+    //----------------------------------------------------------------------------------------------------------------------------------------------------
+    /**
+     * 
+     */
+    public void cacheStarted(TreeCache treeCache) 
+    {
+        this.treeCache = treeCache;
+    }
+
+    /**
+     * 
+     */
+    public void cacheStopped(TreeCache treeCache) 
+    {
+    }
+
+    /**
+     * 
+     */
+    public void viewChange(View view) 
+    {
+    }
+    
+    //---------------nodeName related methods-------------------------------------------------------------------------------------------------------------
+    /**
+     * 
+     *
+     */
+    public static String parseNodeName(String id)
+    {
+        String node = null;
+        
+        node = id.replace('/','_');
+        node = node.replace(':','_');
+        node = node.replace('{','_');
+        node = node.replace('}','_');
+        
+        return node;
+    }
+    //-------------------------------------------------------------------------------------------------------------------------------------------------- 
+}

Modified: trunk/core/build.xml
===================================================================
--- trunk/core/build.xml	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/core/build.xml	2006-09-18 04:21:11 UTC (rev 5217)
@@ -292,7 +292,21 @@
          <fileset dir="${jcr.jcr.lib}" includes="jcr-1.0.jar"/>
          <fileset dir="${apache.collections.lib}" includes="commons-collections.jar"/>
          <fileset dir="${apache.lucene.lib}" includes="lucene.jar"/>
-         <fileset dir="${jackrabbit.jackrabbit.lib}" includes="jackrabbit-core-1.0.jar"/>
+	      	
+	  	<!-- cms optimization integration - this contains a clustered cache enabled version
+	  	of jackrabbit customization of jackrabbit-core-1.0.1 codebase 
+	    For details regarding this customization see: cms/jackrabbit-customization
+	    also needed are jboss-cache.jar and jgroups.jar to support this customization
+	    1.4.0SP1
+	    
+	    TODO: This is fine for this iteration. Eventually we need to integrate these libraries
+	    for bundling in the thirdparty mechanism. This will follow in the next iteration
+	    -->
+	    <!--fileset dir="${jackrabbit.jackrabbit.lib}" includes="jackrabbit-core-1.0.jar"/-->
+	    <fileset dir="../cms/jackrabbit-customization/lib" includes="jackrabbit-core-1.0.1.jar"/>
+	  	<fileset dir="../cms/jackrabbit-customization/lib" includes="jboss-cache.jar"/>
+	  	<fileset dir="../cms/jackrabbit-customization/lib" includes="jgroups.jar"/>		 		 
+      	
          <fileset dir="${slf4j.slf4j.lib}" includes="slf4j-log4j12.jar"/>
       </copy>
       <!-- portal-cms.war -->


Property changes on: trunk/core/src/resources/portal-cms-sar/META-INF
___________________________________________________________________
Name: svn:ignore
   + jboss-service.xml.bak


Modified: trunk/core/src/resources/portal-cms-sar/META-INF/jboss-service.xml
===================================================================
--- trunk/core/src/resources/portal-cms-sar/META-INF/jboss-service.xml	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/core/src/resources/portal-cms-sar/META-INF/jboss-service.xml	2006-09-18 04:21:11 UTC (rev 5217)
@@ -120,7 +120,7 @@
                -->
 
                <!-- HibernatePersistentManager: uses RDBMS + Hibernate for storage -->
-               <PersistenceManager class="org.jboss.portal.cms.hibernate.state.HibernatePersistenceManager">
+               <PersistenceManager class="org.jboss.portal.cms.hibernate.state.JBossCachePersistenceManager">
                   <param name="schemaObjectPrefix" value="WSP"/>
                   <param name="JNDIName" value="java:portal/cms/CMSSessionFactory"/>
                   <param name="externalBLOBs" value="false"/>
@@ -167,7 +167,7 @@
                -->
 
                <!-- HibernatePersistentManager: uses RDBMS + Hibernate for storage -->
-               <PersistenceManager class="org.jboss.portal.cms.hibernate.state.HibernatePersistenceManager">
+               <PersistenceManager class="org.jboss.portal.cms.hibernate.state.JBossCachePersistenceManager">
                   <param name="schemaObjectPrefix" value="Version"/>
                   <param name="JNDIName" value="java:portal/cms/CMSSessionFactory"/>
                   <param name="externalBLOBs" value="false"/>
@@ -270,4 +270,285 @@
       <attribute name="Prefix">content</attribute>
       <depends optional-attribute-name="Factory" proxy-type="attribute">portal:urlFactory=Delegating</depends>
    </mbean>
+   
+   <!-- TreeCache configuration used to cache CMS data -->
+   <mbean code="org.jboss.cache.TreeCache"
+           name="cms.pm.cache:service=TreeCache">
+   
+           <depends>jboss:service=Naming</depends>
+           <depends>jboss:service=TransactionManager</depends>
+           <depends>portal:service=Hibernate,type=CMS</depends>
+   
+           <!--
+           Configure the TransactionManager
+           -->
+           <attribute name="TransactionManagerLookupClass">org.jboss.cache.GenericTransactionManagerLookup</attribute>
+           
+           <!--
+		Node locking scheme:
+		OPTIMISTIC
+		PESSIMISTIC (default)
+		using the OPTIMISTIC scheme, the ISOLATION_LEVEL value is ignored
+	   -->
+	   <!--attribute name="NodeLockingScheme">OPTIMISTIC</attribute-->
+   
+           <!--
+               Isolation level : SERIALIZABLE
+                                 REPEATABLE_READ (default)
+                                 READ_COMMITTED
+                                 READ_UNCOMMITTED
+                                 NONE
+           -->
+           <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
+           
+           	   
+   
+           <!--
+                Valid modes are LOCAL
+                                REPL_ASYNC
+                                REPL_SYNC
+                                INVALIDATION_ASYNC
+                                INVALIDATION_SYNC
+           -->
+           <attribute name="CacheMode">INVALIDATION_ASYNC</attribute>
+   
+           <!--
+           Just used for async repl: use a replication queue
+           -->
+           <attribute name="UseReplQueue">false</attribute>
+   
+           <!--
+               Replication interval for replication queue (in ms)
+           -->
+           <attribute name="ReplQueueInterval">0</attribute>
+   
+           <!--
+               Max number of elements which trigger replication
+           -->
+           <attribute name="ReplQueueMaxElements">0</attribute>
+   
+           <!-- Name of cluster. Needs to be the same for all clusters, in order
+                to find each other
+           -->
+           <attribute name="ClusterName">JCRPMCache</attribute>
+   
+           <!-- JGroups protocol stack properties. Can also be a URL,
+                e.g. file:/home/bela/default.xml
+              <attribute name="ClusterProperties"></attribute>
+           -->
+   
+           <attribute name="ClusterConfig">
+               <config>
+                   <!-- UDP: if you have a multihomed machine,
+                   set the bind_addr attribute to the appropriate NIC IP address -->
+                   <!-- UDP: On Windows machines, because of the media sense feature
+                    being broken with multicast (even after disabling media sense)
+                    set the loopback attribute to true -->
+                   <UDP mcast_addr="228.1.2.3" mcast_port="48866"
+                       ip_ttl="64" ip_mcast="true" 
+                       receive_on_all_interfaces="true"
+                       mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
+                       ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
+                       loopback="false"/>
+                   <PING timeout="2000" num_initial_members="3"
+                       up_thread="false" down_thread="false"/>
+                   <MERGE2 min_interval="10000" max_interval="20000"/>
+                   <!--        <FD shun="true" up_thread="true" down_thread="true" />-->
+                   <FD_SOCK/>
+                   <VERIFY_SUSPECT timeout="1500"
+                       up_thread="false" down_thread="false"/>
+                   <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"
+                       max_xmit_size="8192" up_thread="false" down_thread="false"/>
+                   <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10"
+                       down_thread="false"/>
+                   <pbcast.STABLE desired_avg_gossip="20000"
+                       up_thread="false" down_thread="false"/>
+                   <FRAG frag_size="8192"
+                       down_thread="false" up_thread="false"/>
+                   <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+                       shun="true" print_local_addr="true"/>
+                   <pbcast.STATE_TRANSFER up_thread="true" down_thread="true"/>
+               </config>
+           </attribute>
+   
+           <!--
+            Whether or not to fetch state on joining a cluster
+            NOTE this used to be called FetchStateOnStartup and has been renamed to be more descriptive.
+           -->
+           <attribute name="FetchInMemoryState">false</attribute>
+   
+           <!--
+               The max amount of time (in milliseconds) we wait until the
+               initial state (ie. the contents of the cache) are retrieved from
+               existing members in a clustered environment
+           -->
+           <attribute name="InitialStateRetrievalTimeout">20000</attribute>
+   
+           <!--
+               Number of milliseconds to wait until all responses for a
+               synchronous call have been received.
+           -->
+           <attribute name="SyncReplTimeout">20000</attribute>
+   
+           <!-- Max number of milliseconds to wait for a lock acquisition -->
+           <attribute name="LockAcquisitionTimeout">15000</attribute>
+   
+   
+           <!-- Name of the eviction policy class. -->
+           <attribute name="EvictionPolicyClass"></attribute>
+          
+          <!--
+             Indicate whether to use region based marshalling or not. Set this to true if you are running under a scoped
+             class loader, e.g., inside an application server. Default is "false".
+          -->
+           <attribute name="UseRegionBasedMarshalling">false</attribute>
+           
+           <!--
+           	Configuring the JDBCCacheLoader
+           -->           
+           <attribute name="CacheLoaderConfiguration">
+               <config>                
+                   <passivation>false</passivation>
+                   <preload></preload>
+                   <shared>false</shared>
+                   <cacheloader>
+                       <class>org.jboss.portal.cms.hibernate.state.PortalCMSCacheLoader</class>
+                       <properties></properties>
+                       <async>false</async>
+                       <fetchPersistentState>true</fetchPersistentState>
+                       <ignoreModifications>false</ignoreModifications>
+                   </cacheloader>
+               </config>
+           </attribute>
+    </mbean>
+   
+   <!-- TreeCache configuration for the clustered JackRabbit in-memory cache -->   
+   <mbean code="org.jboss.cache.TreeCache"
+               name="jackrabbit.inmemory.cache:service=TreeCache">
+       
+               <depends>jboss:service=Naming</depends>
+	       <depends>jboss:service=TransactionManager</depends>
+	       
+	               <!--
+	               Configure the TransactionManager
+	               -->
+	               <attribute name="TransactionManagerLookupClass">org.jboss.cache.GenericTransactionManagerLookup</attribute>
+	               
+	               <!--
+		       		Node locking scheme:
+		       		OPTIMISTIC
+		       		PESSIMISTIC (default)
+		       		using the OPTIMISTIC scheme, the ISOLATION_LEVEL value is ignored
+		       	-->
+	   		<!--attribute name="NodeLockingScheme">OPTIMISTIC</attribute-->
+	       
+	               <!--
+	                   Isolation level : SERIALIZABLE
+	                                     REPEATABLE_READ (default)
+	                                     READ_COMMITTED
+	                                     READ_UNCOMMITTED
+	                                     NONE
+	               -->
+	               <attribute name="IsolationLevel">NONE</attribute>
+	       
+	               <!--
+	                    Valid modes are LOCAL
+	                                    REPL_ASYNC
+	                                    REPL_SYNC
+	                                    INVALIDATION_ASYNC
+	                                    INVALIDATION_SYNC
+	               -->
+	               <attribute name="CacheMode">INVALIDATION_ASYNC</attribute>
+	       
+	               <!--
+	               Just used for async repl: use a replication queue
+	               -->
+	               <attribute name="UseReplQueue">false</attribute>
+	       
+	               <!--
+	                   Replication interval for replication queue (in ms)
+	               -->
+	               <attribute name="ReplQueueInterval">0</attribute>
+	       
+	               <!--
+	                   Max number of elements which trigger replication
+	               -->
+	               <attribute name="ReplQueueMaxElements">0</attribute>
+	       
+	               <!-- Name of cluster. Needs to be the same for all clusters, in order
+	                    to find each other
+	               -->
+	               <attribute name="ClusterName">JackRabbitInternalCache</attribute>
+	       
+	               <!-- JGroups protocol stack properties. Can also be a URL,
+	                    e.g. file:/home/bela/default.xml
+	                  <attribute name="ClusterProperties"></attribute>
+	               -->
+	       
+	               <attribute name="ClusterConfig">
+	                   <config>
+	                       <!-- UDP: if you have a multihomed machine,
+	                       set the bind_addr attribute to the appropriate NIC IP address -->
+	                       <!-- UDP: On Windows machines, because of the media sense feature
+	                        being broken with multicast (even after disabling media sense)
+	                        set the loopback attribute to true -->
+	                       <UDP mcast_addr="228.1.2.3" mcast_port="48866"
+	                           ip_ttl="64" ip_mcast="true" 
+	                           receive_on_all_interfaces="true"
+	                           mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
+	                           ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
+	                           loopback="false"/>                
+	                       <PING timeout="2000" num_initial_members="3"
+	                           up_thread="false" down_thread="false"/>
+	                       <MERGE2 min_interval="10000" max_interval="20000"/>
+	                       <!--        <FD shun="true" up_thread="true" down_thread="true" />-->
+	                       <FD_SOCK/>
+	                       <VERIFY_SUSPECT timeout="1500"
+	                           up_thread="false" down_thread="false"/>
+	                       <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800"
+	                           max_xmit_size="8192" up_thread="false" down_thread="false"/>
+	                       <UNICAST timeout="600,1200,2400" window_size="100" min_threshold="10"
+	                           down_thread="false"/>
+	                       <pbcast.STABLE desired_avg_gossip="20000"
+	                           up_thread="false" down_thread="false"/>
+	                       <FRAG frag_size="8192"
+	                           down_thread="false" up_thread="false"/>
+	                       <pbcast.GMS join_timeout="5000" join_retry_timeout="2000"
+	                           shun="true" print_local_addr="true"/>
+	                       <pbcast.STATE_TRANSFER up_thread="true" down_thread="true"/>
+	                   </config>
+	               </attribute>
+	       
+	               <!--
+	                Whether or not to fetch state on joining a cluster
+	                NOTE this used to be called FetchStateOnStartup and has been renamed to be more descriptive.
+	               -->
+	               <attribute name="FetchInMemoryState">false</attribute>
+	       
+	               <!--
+	                   The max amount of time (in milliseconds) we wait until the
+	                   initial state (ie. the contents of the cache) are retrieved from
+	                   existing members in a clustered environment
+	               -->
+	               <attribute name="InitialStateRetrievalTimeout">20000</attribute>
+	       
+	               <!--
+	                   Number of milliseconds to wait until all responses for a
+	                   synchronous call have been received.
+	               -->
+	               <attribute name="SyncReplTimeout">20000</attribute>
+	       
+	               <!-- Max number of milliseconds to wait for a lock acquisition -->
+	               <attribute name="LockAcquisitionTimeout">15000</attribute>
+	       
+	       
+	               <!-- Name of the eviction policy class. -->
+	               <attribute name="EvictionPolicyClass"></attribute>
+	              
+	              <!--
+	                 Indicate whether to use region based marshalling or not. Set this to true if you are running under a scoped
+	                 class loader, e.g., inside an application server. Default is "false".
+	              -->
+        		  <attribute name="UseRegionBasedMarshalling">false</attribute>                        
+    </mbean>   
 </server>

Modified: trunk/core/src/resources/portal-cms-sar/conf/hibernate/cms/domain.hbm.xml
===================================================================
--- trunk/core/src/resources/portal-cms-sar/conf/hibernate/cms/domain.hbm.xml	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/core/src/resources/portal-cms-sar/conf/hibernate/cms/domain.hbm.xml	2006-09-18 04:21:11 UTC (rev 5217)
@@ -30,14 +30,14 @@
          <generator class="native"/>
       </id>
       <property
-            name="id"
+            name="nodeId"
             column="NODE_ID"
             type="string"
             length="36"/>
       <property
             name="data"
             column="NODE_DATA"
-            type="blob"
+            type="binary"
             length="100000000"
             not-null="true"/>
    </class>
@@ -49,14 +49,14 @@
          <generator class="native"/>
       </id>
       <property
-            name="id"
+            name="propId"
             column="PROP_ID"
             type="string"
             length="255"/>
       <property
             name="data"
             column="PROP_DATA"
-            type="blob"
+            type="binary"
             length="100000000"
             not-null="true"/>
    </class>
@@ -68,14 +68,14 @@
          <generator class="native"/>
       </id>
       <property
-            name="id"
+            name="refId"
             column="NODE_ID"
             type="string"
             length="36"/>
       <property
             name="data"
             column="REFS_DATA"
-            type="blob"
+            type="binary"
             length="100000000"
             not-null="true"/>
    </class>
@@ -106,14 +106,14 @@
          <generator class="native"/>
       </id>
       <property
-            name="id"
+            name="nodeId"
             column="NODE_ID"
             type="string"
             length="36"/>
       <property
             name="data"
             column="NODE_DATA"
-            type="blob"
+            type="binary"
             length="100000000"
             not-null="true"/>
    </class>
@@ -125,14 +125,14 @@
          <generator class="native"/>
       </id>
       <property
-            name="id"
+            name="propId"
             column="PROP_ID"
             type="string"
             length="255"/>
       <property
             name="data"
             column="PROP_DATA"
-            type="blob"
+            type="binary"
             length="100000000"
             not-null="true"/>
    </class>
@@ -144,14 +144,14 @@
          <generator class="native"/>
       </id>
       <property
-            name="id"
+            name="refId"
             column="NODE_ID"
             type="string"
             length="36"/>
       <property
             name="data"
             column="REFS_DATA"
-            type="blob"
+            type="binary"
             length="100000000"
             not-null="true"/>
    </class>
@@ -252,3 +252,4 @@
                 not-null="true"/>
    </class>
 </hibernate-mapping>
+

Modified: trunk/core/src/resources/portal-cms-sar/conf/hibernate/cms/hibernate.cfg.xml
===================================================================
--- trunk/core/src/resources/portal-cms-sar/conf/hibernate/cms/hibernate.cfg.xml	2006-09-17 15:27:03 UTC (rev 5216)
+++ trunk/core/src/resources/portal-cms-sar/conf/hibernate/cms/hibernate.cfg.xml	2006-09-18 04:21:11 UTC (rev 5217)
@@ -8,6 +8,10 @@
       <property name="show_sql">@portal.sql.show@</property>
       <property name="cache.use_second_level_cache">false</property>
       <property name="cache.use_query_cache">false</property>
+      
+      <!-- managed environment transaction configuration -->      
+      <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup</property>
+      <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
 
       <!-- Force the dialect instead of using autodetection -->
       <!--




More information about the jboss-svn-commits mailing list