You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@wookie.apache.org by sc...@apache.org on 2010/06/16 16:16:40 UTC

svn commit: r955236 [4/10] - in /incubator/wookie/branches/pluggablepersistence: ./ WebContent/WEB-INF/ WebContent/admin/ WebContent/webmenu/ ant/ etc/ddl-schema/ etc/tomcat/ etc/tomcat/conf/ parser/java/src/org/apache/wookie/w3c/util/ scripts/ scripts...

Added: incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/IdCollection.java
URL: http://svn.apache.org/viewvc/incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/IdCollection.java?rev=955236&view=auto
==============================================================================
--- incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/IdCollection.java (added)
+++ incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/IdCollection.java Wed Jun 16 14:16:36 2010
@@ -0,0 +1,122 @@
+/*
+ *  Licensed 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.wookie.beans.jcr;
+
+import java.util.AbstractCollection;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * IdCollection - collection that manages collection element ids.
+ * 
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id$
+ */
+public class IdCollection<I extends IIdElement,M> extends AbstractCollection<M>
+{
+    private Collection<I> managedCollection;
+    
+    /**
+     * Construct managing collection.
+     * 
+     * @param managedCollection managed collection
+     */
+    public IdCollection(Collection<I> managedCollection)
+    {
+        this.managedCollection = managedCollection;
+    }
+    
+    /* (non-Javadoc)
+     * @see java.util.AbstractCollection#add(java.lang.Object)
+     */
+    @SuppressWarnings("unchecked")
+    public boolean add(M member)
+    {
+        long maxElementId = -1;
+        for (I idElement : managedCollection)
+        {
+            if (idElement.getElementId() > maxElementId)
+            {
+                maxElementId = idElement.getElementId();
+            }
+        }
+        I idElement = (I)member;
+        idElement.setElementId(maxElementId+1);
+        return managedCollection.add(idElement);
+    }
+
+    /* (non-Javadoc)
+     * @see java.util.AbstractCollection#iterator()
+     */
+    public Iterator<M> iterator()
+    {
+        return new Iterator<M>()
+        {
+            Iterator<I> idElementIter = managedCollection.iterator();
+            I lastIdElement = null;
+            
+            /* (non-Javadoc)
+             * @see java.util.Iterator#hasNext()
+             */
+            public boolean hasNext()
+            {
+                return idElementIter.hasNext();
+            }
+
+            /* (non-Javadoc)
+             * @see java.util.Iterator#next()
+             */
+            @SuppressWarnings("unchecked")
+            public M next()
+            {
+                lastIdElement = idElementIter.next();
+                M member = (M)lastIdElement;
+                return member;
+            }
+
+            /* (non-Javadoc)
+             * @see java.util.Iterator#remove()
+             */
+            public void remove()
+            {
+                idElementIter.remove();
+                lastIdElement.setElementId(-1);
+            }
+        };
+    }
+
+    /* (non-Javadoc)
+     * @see java.util.AbstractCollection#remove(java.lang.Object)
+     */
+    @SuppressWarnings("unchecked")
+    public boolean remove(Object member)
+    {
+        I idElement = (I)member;
+        if (managedCollection.remove(idElement))
+        {
+            idElement.setElementId(-1);
+            return true;
+        }
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see java.util.AbstractCollection#size()
+     */
+    public int size()
+    {
+        return managedCollection.size();
+    }    
+}

Added: incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/InverseRelationshipCollection.java
URL: http://svn.apache.org/viewvc/incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/InverseRelationshipCollection.java?rev=955236&view=auto
==============================================================================
--- incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/InverseRelationshipCollection.java (added)
+++ incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/InverseRelationshipCollection.java Wed Jun 16 14:16:36 2010
@@ -0,0 +1,118 @@
+/*
+ *  Licensed 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.wookie.beans.jcr;
+
+import java.util.AbstractCollection;
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * InverseRelationshipCollection - collection that manages inverse relationships.
+ * 
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id$
+ */
+public class InverseRelationshipCollection<O extends IUuidBean,I extends IInverseRelationship<O>,M> extends AbstractCollection<M>
+{
+    private O owningObject;
+    private Collection<I> inverseCollection;
+
+    /**
+     * Construct managing collection.
+     * 
+     * @param owningObject owning object
+     * @param inverseCollection managed inverse collection
+     */
+    public InverseRelationshipCollection(O owningObject, Collection<I> inverseCollection)
+    {
+        super();
+        this.owningObject = owningObject;
+        this.inverseCollection = inverseCollection;
+    }
+
+    /* (non-Javadoc)
+     * @see java.util.AbstractCollection#add(java.lang.Object)
+     */
+    @SuppressWarnings("unchecked")
+    public boolean add(M member)
+    {
+        I inverse = (I)member;
+        inverse.updateInverseRelationship(owningObject);
+        return inverseCollection.add(inverse);
+    }
+
+    /* (non-Javadoc)
+     * @see java.util.AbstractCollection#iterator()
+     */
+    public Iterator<M> iterator()
+    {
+        return new Iterator<M>()
+        {
+            Iterator<I> inverseIter = inverseCollection.iterator();
+            I lastInverse = null;
+            
+            /* (non-Javadoc)
+             * @see java.util.Iterator#hasNext()
+             */
+            public boolean hasNext()
+            {
+                return inverseIter.hasNext();
+            }
+
+            /* (non-Javadoc)
+             * @see java.util.Iterator#next()
+             */
+            @SuppressWarnings("unchecked")
+            public M next()
+            {
+                lastInverse = inverseIter.next();
+                M member = (M)lastInverse;
+                return member;
+            }
+
+            /* (non-Javadoc)
+             * @see java.util.Iterator#remove()
+             */
+            public void remove()
+            {
+                inverseIter.remove();
+                lastInverse.updateInverseRelationship(null);
+            }
+        };
+    }
+
+    /* (non-Javadoc)
+     * @see java.util.AbstractCollection#remove(java.lang.Object)
+     */
+    @SuppressWarnings("unchecked")
+    public boolean remove(Object member)
+    {
+        I inverse = (I)member;
+        if (inverseCollection.remove(inverse))
+        {
+            inverse.updateInverseRelationship(null);
+            return true;
+        }
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see java.util.AbstractCollection#size()
+     */
+    public int size()
+    {
+        return inverseCollection.size();
+    }  
+}

Added: incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/JCRPersistenceManager.java
URL: http://svn.apache.org/viewvc/incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/JCRPersistenceManager.java?rev=955236&view=auto
==============================================================================
--- incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/JCRPersistenceManager.java (added)
+++ incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/JCRPersistenceManager.java Wed Jun 16 14:16:36 2010
@@ -0,0 +1,1513 @@
+/*
+ *  Licensed 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.wookie.beans.jcr;
+
+import java.io.InputStream;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.pool.BasePoolableObjectFactory;
+import org.apache.commons.pool.PoolableObjectFactory;
+import org.apache.commons.pool.impl.GenericObjectPool;
+import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
+import org.apache.jackrabbit.ocm.manager.ObjectContentManager;
+import org.apache.jackrabbit.ocm.manager.atomictypeconverter.impl.DefaultAtomicTypeConverterProvider;
+import org.apache.jackrabbit.ocm.manager.cache.ObjectCache;
+import org.apache.jackrabbit.ocm.manager.cache.impl.RequestObjectCacheImpl;
+import org.apache.jackrabbit.ocm.manager.impl.ObjectContentManagerImpl;
+import org.apache.jackrabbit.ocm.manager.objectconverter.impl.ObjectConverterImpl;
+import org.apache.jackrabbit.ocm.manager.objectconverter.impl.ProxyManagerImpl;
+import org.apache.jackrabbit.ocm.mapper.Mapper;
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.AnnotationMapperImpl;
+import org.apache.jackrabbit.ocm.query.Filter;
+import org.apache.jackrabbit.ocm.query.Query;
+import org.apache.jackrabbit.ocm.query.QueryManager;
+import org.apache.wookie.beans.IAccessRequest;
+import org.apache.wookie.beans.IApiKey;
+import org.apache.wookie.beans.IBean;
+import org.apache.wookie.beans.IDescription;
+import org.apache.wookie.beans.IFeature;
+import org.apache.wookie.beans.ILicense;
+import org.apache.wookie.beans.IName;
+import org.apache.wookie.beans.IParam;
+import org.apache.wookie.beans.IParticipant;
+import org.apache.wookie.beans.IPost;
+import org.apache.wookie.beans.IPreference;
+import org.apache.wookie.beans.IPreferenceDefault;
+import org.apache.wookie.beans.IServerFeature;
+import org.apache.wookie.beans.ISharedData;
+import org.apache.wookie.beans.IStartFile;
+import org.apache.wookie.beans.IToken;
+import org.apache.wookie.beans.IWhitelist;
+import org.apache.wookie.beans.IWidget;
+import org.apache.wookie.beans.IWidgetDefault;
+import org.apache.wookie.beans.IWidgetIcon;
+import org.apache.wookie.beans.IWidgetInstance;
+import org.apache.wookie.beans.IWidgetService;
+import org.apache.wookie.beans.IWidgetType;
+import org.apache.wookie.beans.jcr.impl.AccessRequestImpl;
+import org.apache.wookie.beans.jcr.impl.ApiKeyImpl;
+import org.apache.wookie.beans.jcr.impl.DescriptionImpl;
+import org.apache.wookie.beans.jcr.impl.FeatureImpl;
+import org.apache.wookie.beans.jcr.impl.LicenseImpl;
+import org.apache.wookie.beans.jcr.impl.NameImpl;
+import org.apache.wookie.beans.jcr.impl.ParamImpl;
+import org.apache.wookie.beans.jcr.impl.ParticipantImpl;
+import org.apache.wookie.beans.jcr.impl.PostImpl;
+import org.apache.wookie.beans.jcr.impl.PreferenceDefaultImpl;
+import org.apache.wookie.beans.jcr.impl.PreferenceImpl;
+import org.apache.wookie.beans.jcr.impl.ServerFeatureImpl;
+import org.apache.wookie.beans.jcr.impl.SharedDataImpl;
+import org.apache.wookie.beans.jcr.impl.StartFileImpl;
+import org.apache.wookie.beans.jcr.impl.TokenImpl;
+import org.apache.wookie.beans.jcr.impl.WhitelistImpl;
+import org.apache.wookie.beans.jcr.impl.WidgetDefaultImpl;
+import org.apache.wookie.beans.jcr.impl.WidgetIconImpl;
+import org.apache.wookie.beans.jcr.impl.WidgetImpl;
+import org.apache.wookie.beans.jcr.impl.WidgetInstanceImpl;
+import org.apache.wookie.beans.jcr.impl.WidgetServiceImpl;
+import org.apache.wookie.beans.jcr.impl.WidgetTypeImpl;
+import org.apache.wookie.beans.util.IPersistenceManager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * JCRPersistenceManager - JCR IPersistenceManager implementation.
+ * 
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id$
+ */
+public class JCRPersistenceManager implements IPersistenceManager
+{
+    private static final Logger logger = LoggerFactory.getLogger(JCRPersistenceManager.class);
+    
+    public static final String WIDGET_REPOSITORY_JNDI_REPOSITORY_NAME = "jcr/widgetrepo";
+    public static final String WIDGET_REPOSITORY_JNDI_REPOSITORY_FULL_NAME = "java:comp/env/"+WIDGET_REPOSITORY_JNDI_REPOSITORY_NAME;
+
+    public static final String PERSISTENCE_MANAGER_USER_PROPERTY_NAME = "widget.persistence.manager.user";
+    public static final String PERSISTENCE_MANAGER_PASSWORD_PROPERTY_NAME = "widget.persistence.manager.password";
+    public static final String PERSISTENCE_MANAGER_ROOT_PATH_PROPERTY_NAME = "widget.persistence.manager.rootpath";
+    public static final String PERSISTENCE_MANAGER_WORKSPACE_PROPERTY_NAME = "widget.persistence.manager.workspace";
+
+    private static final Map<Class<?>,Class<?>> INTERFACE_TO_CLASS_MAP = new HashMap<Class<?>,Class<?>>();
+    private static final Map<Class<? extends IBean>,Class<? extends IBean>> BEAN_INTERFACE_TO_CLASS_MAP = new HashMap<Class<? extends IBean>,Class<? extends IBean>>();
+    private static final Map<String,String> IMPLEMENTATION_FIELD_MAP = new HashMap<String,String>();
+    static
+    {
+        INTERFACE_TO_CLASS_MAP.put(IAccessRequest.class, AccessRequestImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IApiKey.class, ApiKeyImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IDescription.class, DescriptionImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IFeature.class, FeatureImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(ILicense.class, LicenseImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IName.class, NameImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IParam.class, ParamImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IParticipant.class, ParticipantImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IPost.class, PostImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IPreference.class, PreferenceImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IPreferenceDefault.class, PreferenceDefaultImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IServerFeature.class, ServerFeatureImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(ISharedData.class, SharedDataImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IStartFile.class, StartFileImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IToken.class, TokenImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IWhitelist.class, WhitelistImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IWidget.class, WidgetImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IWidgetDefault.class, WidgetDefaultImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IWidgetIcon.class, WidgetIconImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IWidgetInstance.class, WidgetInstanceImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IWidgetService.class, WidgetServiceImpl.class);
+        INTERFACE_TO_CLASS_MAP.put(IWidgetType.class, WidgetTypeImpl.class);
+
+        BEAN_INTERFACE_TO_CLASS_MAP.put(IAccessRequest.class, AccessRequestImpl.class);
+        BEAN_INTERFACE_TO_CLASS_MAP.put(IApiKey.class, ApiKeyImpl.class);
+        BEAN_INTERFACE_TO_CLASS_MAP.put(IParticipant.class, ParticipantImpl.class);
+        BEAN_INTERFACE_TO_CLASS_MAP.put(IPost.class, PostImpl.class);
+        BEAN_INTERFACE_TO_CLASS_MAP.put(IServerFeature.class, ServerFeatureImpl.class);
+        BEAN_INTERFACE_TO_CLASS_MAP.put(IWhitelist.class, WhitelistImpl.class);
+        BEAN_INTERFACE_TO_CLASS_MAP.put(IWidget.class, WidgetImpl.class);
+        BEAN_INTERFACE_TO_CLASS_MAP.put(IWidgetDefault.class, WidgetDefaultImpl.class);
+        BEAN_INTERFACE_TO_CLASS_MAP.put(IWidgetInstance.class, WidgetInstanceImpl.class);
+        BEAN_INTERFACE_TO_CLASS_MAP.put(IWidgetService.class, WidgetServiceImpl.class);
+        
+        IMPLEMENTATION_FIELD_MAP.put("widget", "widgetImpl");
+    }
+    @SuppressWarnings("unchecked")
+    private static final List<Class> CLASS_LIST = new ArrayList<Class>(INTERFACE_TO_CLASS_MAP.values());
+
+    private static String repositoryUser;
+    private static String repositoryPassword;
+    private static String repositoryWorkspace;
+    private static String rootPath;
+    private static Map<Class<? extends IBean>,String> beanClassNodeRootPaths = new HashMap<Class<? extends IBean>,String>();
+    private static GenericObjectPool ocmPool;
+
+    /**
+     * Initialize implementation with configuration.
+     * 
+     * @param configuration configuration properties
+     * @param initializeStore truncate and initialize persistent store
+     */
+    public static void initialize(Configuration configuration, boolean initializeStore)
+    {
+        try
+        {
+            // configuration
+            repositoryUser = configuration.getString(PERSISTENCE_MANAGER_USER_PROPERTY_NAME);
+            repositoryPassword = configuration.getString(PERSISTENCE_MANAGER_PASSWORD_PROPERTY_NAME);
+            repositoryWorkspace = configuration.getString(PERSISTENCE_MANAGER_WORKSPACE_PROPERTY_NAME);
+            rootPath = configuration.getString(PERSISTENCE_MANAGER_ROOT_PATH_PROPERTY_NAME);
+            for (Map.Entry<Class<? extends IBean>,Class<? extends IBean>> mapping : BEAN_INTERFACE_TO_CLASS_MAP.entrySet())
+            {
+                Class<? extends IBean> beanClass = mapping.getValue();
+                Class<? extends IBean> beanInterface = mapping.getKey();
+                String name = beanInterface.getSimpleName();
+                if (name.startsWith("I"))
+                {
+                    name = name.substring(1);
+                }
+                if (!name.endsWith("s"))
+                {
+                    name = name+"s";
+                }
+                String nodeRootPath = rootPath+"/"+name;
+                beanClassNodeRootPaths.put(beanClass, nodeRootPath);
+            }
+            
+            // create JCR credentials session pool
+            PoolableObjectFactory sessionFactory = new BasePoolableObjectFactory()
+            {
+                /* (non-Javadoc)
+                 * @see org.apache.commons.pool.BasePoolableObjectFactory#passivateObject(java.lang.Object)
+                 */
+                public void passivateObject(Object obj) throws Exception
+                {
+                    // clear OCM object cache
+                    ((ObjectContentManagerImpl)obj).setRequestObjectCache(new RequestObjectCacheImpl());
+                }
+
+                /* (non-Javadoc)
+                 * @see org.apache.commons.pool.BasePoolableObjectFactory#makeObject()
+                 */
+                public Object makeObject() throws Exception
+                {
+                    // lookup JCR repository from context
+                    Context initialContext = new InitialContext();
+                    Repository repository = (Repository)initialContext.lookup(WIDGET_REPOSITORY_JNDI_REPOSITORY_FULL_NAME);
+                    
+                    // create and login JCR session
+                    Credentials credentials = new SimpleCredentials(repositoryUser, repositoryPassword.toCharArray());
+                    Session session = ((repositoryWorkspace != null) ? repository.login(credentials, repositoryWorkspace) : repository.login(credentials));
+                    
+                    // return session object content manager for session
+                    return new SessionObjectContentManagerImpl(session, new AnnotationMapperImpl(CLASS_LIST));
+                }
+
+                /* (non-Javadoc)
+                 * @see org.apache.commons.pool.BasePoolableObjectFactory#destroyObject(java.lang.Object)
+                 */
+                public void destroyObject(Object obj) throws Exception
+                {
+                    // logout and close object content manager and session
+                    ((ObjectContentManagerImpl)obj).logout();
+                }
+            };
+            ocmPool = new GenericObjectPool(sessionFactory, 0, GenericObjectPool.WHEN_EXHAUSTED_GROW, 0, 5);
+            ocmPool.setTimeBetweenEvictionRunsMillis(60000);
+            ocmPool.setMinEvictableIdleTimeMillis(300000);
+            
+            // initialize persistent store
+            if (initializeStore)
+            {
+                // borrow object content manager and initialization session from pool
+                ObjectContentManager ocm = (ObjectContentManager)ocmPool.borrowObject();
+                Session session = ocm.getSession();
+                
+                // initialize root path in repository
+                
+                // Jackrabbit/JCR 2.X
+                //boolean rootPathNodeExists = session.nodeExists(rootPath);
+
+                // Jackrabbit/JCR 1.X
+                boolean rootPathNodeExists = session.itemExists(rootPath);
+                
+                if (rootPathNodeExists)
+                {
+                    // delete nodes of root path node
+
+                    // Jackrabbit/JCR 2.X
+                    //Node rootNode = session.getNode(rootPath);
+
+                    // Jackrabbit/JCR 1.X
+                    Node rootNode = (Node)session.getItem(rootPath);
+                    
+                    NodeIterator nodesIter = rootNode.getNodes();
+                    while (nodesIter.hasNext())
+                    {
+                        nodesIter.nextNode().remove();
+                    }
+                }
+                else
+                {
+                    // create unstructured node hierarchy
+                    int rootPathParentIndex = -1;
+                    int rootPathIndex = rootPath.indexOf('/', 1);
+                    while (rootPathIndex != -1)
+                    {
+                        // Jackrabbit/JCR 2.X
+                        //Node parentNode = session.getNode(rootPath.substring(0, ((rootPathParentIndex != -1) ? rootPathParentIndex : 1)));
+
+                        // Jackrabbit/JCR 1.X
+                        Node parentNode = (Node)session.getItem(rootPath.substring(0, ((rootPathParentIndex != -1) ? rootPathParentIndex : 1)));
+
+                        String nodeName = rootPath.substring(((rootPathParentIndex != -1) ? rootPathParentIndex+1 : 1), rootPathIndex);
+                        parentNode.addNode(nodeName, "nt:unstructured");                        
+                        rootPathParentIndex = rootPathIndex;
+                        rootPathIndex = rootPath.indexOf('/', rootPathIndex+1);
+                    }
+
+                    // Jackrabbit/JCR 2.X
+                    //Node parentNode = session.getNode(rootPath.substring(0, ((rootPathParentIndex != -1) ? rootPathParentIndex : 1)));
+
+                    // Jackrabbit/JCR 1.X
+                    Node parentNode = (Node)session.getItem(rootPath.substring(0, ((rootPathParentIndex != -1) ? rootPathParentIndex : 1)));
+
+                    String nodeName = rootPath.substring(((rootPathParentIndex != -1) ? rootPathParentIndex+1 : 1));
+                    parentNode.addNode(nodeName, "nt:unstructured");
+                }
+                // create bean class node root paths
+
+                // Jackrabbit/JCR 2.X
+                //Node rootNode = session.getNode(rootPath);
+
+                // Jackrabbit/JCR 1.X
+                Node rootNode = (Node)session.getItem(rootPath);
+
+                for (String nodeRootPath : beanClassNodeRootPaths.values())
+                {
+                    String nodeName = nodeRootPath.substring(rootPath.length()+1);
+                    rootNode.addNode(nodeName, "nt:unstructured");
+                }
+                session.save();
+
+                // register/reregister repository node types
+                NodeTypeManager nodeTypeManager = session.getWorkspace().getNodeTypeManager();
+                InputStream nodeTypesCNDStream = JCRPersistenceManager.class.getResourceAsStream("wookie-schema.cnd");
+                if (nodeTypesCNDStream == null)
+                {
+                    throw new IllegalArgumentException("Unable to load node types configuration: wookie-schema.cnd");                    
+                }
+                
+                // Jackrabbit/JCR 2.X
+                //Reader nodeTypesCNDReader = new InputStreamReader(nodeTypesCNDStream);
+                //NamespaceRegistry namespaceRegistry = session.getWorkspace().getNamespaceRegistry();
+                //ValueFactory valueFactory = session.getValueFactory();
+                //CndImporter.registerNodeTypes(nodeTypesCNDReader, "wookie-schema.cnd", nodeTypeManager, namespaceRegistry, valueFactory, true);
+
+                // Jackrabbit/JCR 1.X
+                ((NodeTypeManagerImpl)nodeTypeManager).registerNodeTypes(nodeTypesCNDStream, NodeTypeManagerImpl.TEXT_X_JCR_CND, true);
+
+                // save session used to load node types
+                session.save();
+                logger.info("Persistent store initialized at "+rootPath);
+
+                // return object content manager and initialization session to pool
+                ocmPool.returnObject(ocm);
+            }
+            
+            logger.info("Initialized");
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException("Unable to initialize: "+e, e);
+        }
+    }
+
+    /**
+     * Terminate implementation.
+     */
+    public static void terminate()
+    {
+        try
+        {
+            // close JCR credentials session pool
+            ocmPool.close();
+            
+            logger.info("Terminated");
+        }
+        catch (Exception e)
+        {            
+            throw new RuntimeException("Unable to terminate: "+e, e);
+        }
+    }
+    
+    public SessionObjectContentManagerImpl ocm;
+    public SessionObjectCacheImpl ocmCache;
+    public boolean ocmWrite;
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#begin()
+     */
+    public void begin()
+    {
+        // validate object content manager transaction
+        if (ocm != null)
+        {
+            throw new IllegalStateException("Transaction already initiated");
+        }
+
+        // create object content manager session and start transaction
+        try
+        {
+            // borrow session object content manager from pool
+            ocm = (SessionObjectContentManagerImpl)ocmPool.borrowObject();
+            ocmCache = new SessionObjectCacheImpl();
+            ocm.setRequestObjectCache(ocmCache);
+            ocmWrite = false;
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException("Unexpected exception: "+e, e);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#close()
+     */
+    public void close()
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }        
+
+        // rollback transaction and close object content manager session
+        try
+        {
+            if (!ocmWrite)
+            {
+                // return session object content manager to pool
+                ocmCache.reset();
+                ocmPool.returnObject(ocm);
+            }
+            else
+            {
+                // logout and close object content manager: do not return to pool
+                ocmCache.reset();
+                ocm.logout();
+            }
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException("Unexpected exception: "+e, e);
+        }
+        finally
+        {
+            ocm = null;
+            ocmCache = null;
+            ocmWrite = false;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#commit()
+     */
+    public void commit()
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }        
+
+        // commit object content manager session transaction
+        try
+        {
+            // save object content manager writes to repository
+            ocm.save();
+            ocmWrite = false;
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException("Unexpected exception: "+e, e);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#delete(org.apache.wookie.beans.IBean)
+     */
+    public boolean delete(IBean bean)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // track object content manager write
+        ocmWrite = true;
+        
+        // delete bean
+        try
+        {
+            String nodePath = ((IPathBean)bean).getNodePath();
+            if (nodePath != null)
+            {
+                // notify pre-delete listener
+                if (bean instanceof IPersistenceListener)
+                {
+                    if (!((IPersistenceListener)bean).preDelete(this))
+                    {
+                        throw new RuntimeException("Pre-delete listener invocation failed");
+                    }
+                }
+                
+                // delete node
+                ocm.remove(nodePath);
+                ocmCache.removeObject(nodePath);
+
+                // notify post-delete listener
+                if (bean instanceof IPersistenceListener)
+                {
+                    if (!((IPersistenceListener)bean).postDelete(this))
+                    {
+                        throw new RuntimeException("Post-delete listener invocation failed");
+                    }
+                }                
+                return true;
+            }
+        }
+        catch (Exception e)
+        {
+            logger.error("Unexpected exception: "+e, e);
+        }
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#delete(org.apache.wookie.beans.IBean[])
+     */
+    public boolean delete(IBean[] beans)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // track object content manager write
+        ocmWrite = true;
+        
+        // remove beans
+        try
+        {
+            for (IBean bean : beans)
+            {
+                String nodePath = ((IPathBean)bean).getNodePath();
+                if (nodePath != null)
+                {
+                    // notify pre-delete listener
+                    if (bean instanceof IPersistenceListener)
+                    {
+                        if (!((IPersistenceListener)bean).preDelete(this))
+                        {
+                            throw new RuntimeException("Pre-delete listener invocation failed");
+                        }
+                    }
+                    
+                    // delete node
+                    ocm.remove(nodePath);
+                    ocmCache.removeObject(nodePath);
+
+                    // notify post-delete listener
+                    if (bean instanceof IPersistenceListener)
+                    {
+                        if (!((IPersistenceListener)bean).postDelete(this))
+                        {
+                            throw new RuntimeException("Post-delete listener invocation failed");
+                        }
+                    }                
+                }
+            }
+            return true;
+        }
+        catch (Exception e)
+        {
+            logger.error("Unexpected exception: "+e, e);
+        }
+        return false;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findAll(java.lang.Class)
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends IBean> T[] findAll(Class<T> beansInterface)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // validate bean interface
+        Class<? extends IBean> beanClass = BEAN_INTERFACE_TO_CLASS_MAP.get(beansInterface);
+        if (beanClass == null)
+        {
+            throw new IllegalArgumentException("Invalid bean interface specified");            
+        }
+
+        // get persistent bean extent by root path
+        try
+        {
+            // construct query filter
+            QueryManager queryManager = ocm.getQueryManager();
+            Filter filter = queryManager.createFilter(beanClass);
+            filter.setScope(beanClassNodeRootPaths.get(beanClass)+"//");
+            Query query = queryManager.createQuery(filter);
+            
+            // invoke query
+            Collection<? extends IBean> beansExtentList = ocm.getObjects(query);
+            if ((beansExtentList != null) && !beansExtentList.isEmpty())
+            {
+                return beansExtentList.toArray((T [])Array.newInstance(beansInterface, beansExtentList.size()));
+            }
+        }
+        catch (Exception e)
+        {
+            logger.error("Unexpected exception: "+e, e);
+        }
+        return (T [])Array.newInstance(beansInterface, 0);
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findApplicableAccessRequests(org.apache.wookie.beans.IWidget)
+     */
+    public IAccessRequest [] findApplicableAccessRequests(IWidget widget)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // get applicable access requests for widget using custom query
+        if (widget != null)
+        {
+            try
+            {
+                Map<String, Object> values = new HashMap<String, Object>();
+                values.put("widget", widget);
+                values.put("granted", Boolean.TRUE);
+                return findByValues(IAccessRequest.class, values);
+            }
+            catch (Exception e)
+            {
+                logger.error("Unexpected exception: "+e, e);
+            }
+        }
+        return new IAccessRequest[0];
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findById(java.lang.Class, java.lang.Object)
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends IBean> T findById(Class<T> beanInterface, Object id)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // validate bean interface
+        Class<? extends IBean> beanClass = BEAN_INTERFACE_TO_CLASS_MAP.get(beanInterface);
+        if (beanClass == null)
+        {
+            throw new IllegalArgumentException("Invalid bean interface specified");            
+        }
+
+        // get persistent bean by primary id path
+        try
+        {
+            if (!(id instanceof String) && (id != null))
+            {
+                id = id.toString();
+            }
+            return (T)ocm.getObject((String)id);
+        }
+        catch (Exception e)
+        {
+            logger.error("Unexpected exception: "+e, e);
+            return null;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findByValue(java.lang.Class, java.lang.String, java.lang.Object, java.lang.String, boolean)
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends IBean> T[] findByValue(Class<T> beansInterface, String name, Object value, String orderBy, boolean ascending)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // validate bean interface
+        Class<? extends IBean> beanClass = BEAN_INTERFACE_TO_CLASS_MAP.get(beansInterface);
+        if (beanClass == null)
+        {
+            throw new IllegalArgumentException("Invalid bean interface specified");            
+        }
+
+        // get persistent beans by root path and filter
+        try
+        {
+            // construct query filter
+            QueryManager queryManager = ocm.getQueryManager();
+            Filter filter = queryManager.createFilter(beanClass);
+            filter.setScope(beanClassNodeRootPaths.get(beanClass)+"//");
+            if (name != null)
+            {
+                String mappedName = IMPLEMENTATION_FIELD_MAP.get(name);
+                name = ((mappedName != null) ? mappedName : name);
+                if (value instanceof IUuidBean)
+                {
+                    value = ((IUuidBean)value).getUuid(); 
+                }
+                filter = ((value != null) ? filter.addEqualTo(name, value) : filter.addIsNull(name));
+            }            
+            Query query = queryManager.createQuery(filter);
+            if (orderBy != null)
+            {
+                String mappedOrderBy = IMPLEMENTATION_FIELD_MAP.get(orderBy);
+                orderBy = ((mappedOrderBy != null) ? mappedOrderBy : orderBy);
+                if (ascending)
+                {
+                    query.addOrderByAscending(orderBy);
+                }
+                else
+                {
+                    query.addOrderByDescending(orderBy);
+                }
+            }
+
+            // invoke query
+            Collection<? extends IBean> beansExtentList = ocm.getObjects(query);
+            if ((beansExtentList != null) && !beansExtentList.isEmpty())
+            {
+                return beansExtentList.toArray((T [])Array.newInstance(beansInterface, beansExtentList.size()));
+            }
+        }
+        catch (Exception e)
+        {
+            logger.error("Unexpected exception: "+e, e);
+        }
+        return (T [])Array.newInstance(beansInterface, 0);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findByValue(java.lang.Class, java.lang.String, java.lang.Object)
+     */
+    public <T extends IBean> T[] findByValue(Class<T> beansInterface, String name, Object value)
+    {
+        return findByValue(beansInterface, name, value, null, true);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findByValues(java.lang.Class, java.util.Map, java.lang.String, boolean)
+     */
+    @SuppressWarnings("unchecked")
+    public <T extends IBean> T[] findByValues(Class<T> beansInterface, Map<String, Object> values, String orderBy, boolean ascending)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // validate bean interface
+        Class<? extends IBean> beanClass = BEAN_INTERFACE_TO_CLASS_MAP.get(beansInterface);
+        if (beanClass == null)
+        {
+            throw new IllegalArgumentException("Invalid bean interface specified");            
+        }
+
+        // get persistent beans by root path and filter
+        try
+        {
+            // construct query filter
+            QueryManager queryManager = ocm.getQueryManager();
+            Filter filter = queryManager.createFilter(beanClass);
+            filter.setScope(beanClassNodeRootPaths.get(beanClass)+"//");
+            if ((values != null) && !values.isEmpty())
+            {
+                for (Map.Entry<String,Object> value : values.entrySet())
+                {
+                    String valueName = value.getKey();
+                    String mappedValueName = IMPLEMENTATION_FIELD_MAP.get(valueName);
+                    valueName = ((mappedValueName != null) ? mappedValueName : valueName);
+                    Object valueValue = value.getValue();
+                    if (valueValue instanceof IUuidBean)
+                    {
+                        valueValue = ((IUuidBean)valueValue).getUuid(); 
+                    }
+                    filter = ((valueValue != null) ? filter.addEqualTo(valueName, valueValue) : filter.addIsNull(valueName));
+                }
+            }
+            Query query = queryManager.createQuery(filter);
+            if (orderBy != null)
+            {
+                String mappedOrderBy = IMPLEMENTATION_FIELD_MAP.get(orderBy);
+                orderBy = ((mappedOrderBy != null) ? mappedOrderBy : orderBy);
+                if (ascending)
+                {
+                    query.addOrderByAscending(orderBy);
+                }
+                else
+                {
+                    query.addOrderByDescending(orderBy);
+                }
+            }
+
+            // invoke query
+            Collection<? extends IBean> beansExtentList = ocm.getObjects(query);
+            if ((beansExtentList != null) && !beansExtentList.isEmpty())
+            {
+                return beansExtentList.toArray((T [])Array.newInstance(beansInterface, beansExtentList.size()));
+            }
+        }
+        catch (Exception e)
+        {
+            logger.error("Unexpected exception: "+e, e);
+        }
+        return (T [])Array.newInstance(beansInterface, 0);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findByValues(java.lang.Class, java.util.Map)
+     */
+    public <T extends IBean> T[] findByValues(Class<T> beansInterface, Map<String, Object> values)
+    {
+        return findByValues(beansInterface, values, null, true);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findParticipants(org.apache.wookie.beans.IWidgetInstance)
+     */
+    public IParticipant[] findParticipants(IWidgetInstance widgetInstance)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // get participants for widget instance
+        if (widgetInstance != null)
+        {
+            try
+            {
+                Map<String, Object> values = new HashMap<String, Object>();
+                values.put("sharedDataKey", widgetInstance.getSharedDataKey());
+                values.put("widget", widgetInstance.getWidget());
+                return findByValues(IParticipant.class, values);
+            }
+            catch (Exception e)
+            {
+                logger.error("Unexpected exception: "+e, e);
+            }
+        }
+        return new IParticipant[0];
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findParticipantViewer(org.apache.wookie.beans.IWidgetInstance)
+     */
+    public IParticipant findParticipantViewer(IWidgetInstance widgetInstance)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // get participant viewer for widget instance
+        if (widgetInstance != null)
+        {
+            try
+            {
+                Map<String, Object> values = new HashMap<String, Object>();
+                values.put("sharedDataKey", widgetInstance.getSharedDataKey());
+                values.put("widget", widgetInstance.getWidget());
+                values.put("participantId", widgetInstance.getUserId());
+                IParticipant [] participantViewer = findByValues(IParticipant.class, values);
+                if (participantViewer.length == 1)
+                {
+                    return participantViewer[0];
+                }
+            }
+            catch (Exception e)
+            {
+                logger.error("Unexpected exception: "+e, e);
+            }
+        }
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findServerFeatureByName(java.lang.String)
+     */
+    public IServerFeature findServerFeatureByName(String name)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // get server feature by name
+        if (name != null)
+        {
+            try
+            {
+                IServerFeature [] serverFeature = findByValue(IServerFeature.class, "featureName", name);
+                if (serverFeature.length == 1)
+                {
+                    return serverFeature[0];
+                }
+            }
+            catch (Exception e)
+            {
+                logger.error("Unexpected exception: "+e, e);
+            }
+        }
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findServerFeatureNames()
+     */
+    public String[] findServerFeatureNames()
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // get server feature names
+        try
+        {
+            IServerFeature [] serverFeatures = findAll(IServerFeature.class);
+            if (serverFeatures.length > 0)
+            {
+                String [] names = new String[serverFeatures.length];
+                for (int i = 0; (i < serverFeatures.length); i++)
+                {
+                    names[i] = serverFeatures[i].getFeatureName();
+                }
+                return names;
+            }
+        }
+        catch (Exception e)
+        {
+            logger.error("Unexpected exception: "+e, e);
+        }
+        return new String[0];
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findWidgetByGuid(java.lang.String)
+     */
+    public IWidget findWidgetByGuid(String guid)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // get widget by GUID
+        if (guid != null)
+        {
+            try
+            {
+                IWidget [] widget = findByValue(IWidget.class, "guid", guid);
+                if (widget.length == 1)
+                {
+                    return widget[0];
+                }
+            }
+            catch (Exception e)
+            {
+                logger.error("Unexpected exception: "+e, e);
+            }
+        }
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findWidgetDefaultByType(java.lang.String)
+     */
+    public IWidget findWidgetDefaultByType(String widgetContext)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // get default widget by type
+        if (widgetContext != null)
+        {
+            try
+            {
+                IWidgetDefault [] widgetDefault = findByValue(IWidgetDefault.class, "widgetContext", widgetContext);
+                if (widgetDefault.length == 1)
+                {
+                    return widgetDefault[0].getWidget();
+                }
+            }
+            catch (Exception e)
+            {
+                logger.error("Unexpected exception: "+e, e);
+            }
+        }
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findWidgetInstance(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+     */
+    public IWidgetInstance findWidgetInstance(String apiKey, String userId, String sharedDataKey, String serviceContext)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // get widget instance
+        if ((apiKey != null) && (userId != null) && (sharedDataKey != null) && (serviceContext != null))
+        {
+            try
+            {
+                // get candidate widget instances
+                Map<String, Object> values = new HashMap<String, Object>();
+                values.put("apiKey", apiKey);
+                values.put("userId", userId);
+                values.put("sharedDataKey", sharedDataKey);
+                IWidgetInstance [] widgetInstances = findByValues(IWidgetInstance.class, values);
+
+                // filter widget instances by widget type/context
+                IWidgetInstance foundWidgetInstance = null;
+                for (IWidgetInstance widgetInstance : widgetInstances)
+                {
+                    // check widget type/context
+                    boolean hasServiceContext = false;
+                    for (IWidgetType widgetType : widgetInstance.getWidget().getWidgetTypes())
+                    {
+                        if (widgetType.getWidgetContext().equals(serviceContext))
+                        {
+                            hasServiceContext = true;
+                            break;
+                        }
+                    }
+                    if (hasServiceContext)
+                    {
+                        // validate search matches only one widget
+                        if (foundWidgetInstance != null)
+                        {
+                            foundWidgetInstance = null;
+                            break;
+                        }
+                        foundWidgetInstance = widgetInstance;
+                    }
+                }
+
+                // return single matching widget instance
+                if (foundWidgetInstance != null)
+                {
+                    return foundWidgetInstance;
+                }
+            }
+            catch (Exception e)
+            {
+                logger.error("Unexpected exception: "+e, e);
+            }
+        }
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findWidgetInstanceByGuid(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+     */
+    public IWidgetInstance findWidgetInstanceByGuid(String apiKey, String userId, String sharedDataKey, String widgetGuid)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // get widget instance
+        if ((apiKey != null) && (userId != null) && (sharedDataKey != null) && (widgetGuid != null))
+        {
+            try
+            {
+                // find widget by GUID
+                IWidget widget = findWidgetByGuid(widgetGuid);
+                if (widget != null)
+                {
+                    // get matching widget instance for widget
+                    Map<String, Object> values = new HashMap<String, Object>();
+                    values.put("apiKey", apiKey);
+                    values.put("userId", userId);
+                    values.put("sharedDataKey", sharedDataKey);
+                    values.put("widget", widget);
+                    IWidgetInstance [] widgetInstance = findByValues(IWidgetInstance.class, values);
+                    if (widgetInstance.length == 1)
+                    {
+                        return widgetInstance[0];
+                    }                
+                }
+            }
+            catch (Exception e)
+            {
+                logger.error("Unexpected exception: "+e, e);
+            }
+        }
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#findWidgetInstanceByIdKey(java.lang.String)
+     */
+    public IWidgetInstance findWidgetInstanceByIdKey(String idKey)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // get widget instance
+        if (idKey != null)
+        {
+            try
+            {
+                IWidgetInstance [] widgetInstance = findByValue(IWidgetInstance.class, "idKey", idKey);
+                if (widgetInstance.length == 1)
+                {
+                    return widgetInstance[0];
+                }
+            }
+            catch (Exception e)
+            {
+                logger.error("Unexpected exception: "+e, e);
+            }
+        }
+        return null;
+    }
+
+    public IWidget[] findWidgetsByType(String widgetContext)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+        
+        // get widgets by type
+        if (widgetContext != null)
+        {
+            try
+            {
+                // get candidate widgets
+                IWidget [] widgets = findAll(IWidget.class);
+                
+                // filter widgets by widget type/context
+                Collection<IWidget> foundWidgets = new ArrayList<IWidget>();
+                for (IWidget widget : widgets)
+                {
+                    // check widget type/context
+                    for (IWidgetType widgetType : widget.getWidgetTypes())
+                    {
+                        if (widgetType.getWidgetContext().equals(widgetContext))
+                        {
+                            foundWidgets.add(widget);
+                            break;
+                        }
+                    }
+                }
+                return foundWidgets.toArray(new IWidget[foundWidgets.size()]);
+            }
+            catch (Exception e)
+            {
+                logger.error("Unexpected exception: "+e, e);
+            }
+        }
+        return new IWidget[0];
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#newInstance(java.lang.Class)
+     */
+    @SuppressWarnings("unchecked")
+    public <T> T newInstance(Class<T> instanceInterface)
+    {
+        // validate instance interface
+        Class<?> instanceClass = INTERFACE_TO_CLASS_MAP.get(instanceInterface);
+        if (instanceClass == null)
+        {
+            throw new IllegalArgumentException("Invalid instance interface specified");            
+        }
+
+        // create new instance of persistent class
+        try
+        {
+            return (T)instanceClass.newInstance();
+        }
+        catch (Exception e)
+        {
+            logger.error("Unexpected exception: "+e, e);
+            return null;
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#rollback()
+     */
+    public void rollback()
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }        
+
+        // rollback object content manager session transaction
+        try
+        {
+            if (ocmWrite)
+            {
+                // logout and close object content manager: do not return to pool
+                ocmCache.reset();
+                ocm.logout();
+            }
+            // borrow session object content manager from pool
+            ocm = (SessionObjectContentManagerImpl)ocmPool.borrowObject();
+            ocmCache = new SessionObjectCacheImpl();
+            ocm.setRequestObjectCache(ocmCache);
+            ocmWrite = false;
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException("Unexpected exception: "+e, e);
+        }
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.util.IPersistenceManager#save(org.apache.wookie.beans.IBean)
+     */
+    public boolean save(IBean bean)
+    {
+        // validate object content manager transaction
+        if (ocm == null)
+        {
+            throw new IllegalStateException("Transaction not initiated or already closed");
+        }
+
+        // track object content manager write
+        ocmWrite = true;
+        
+        // persist new or update existing bean
+        boolean newNode = false;
+        IPathBean pathBean = (IPathBean)bean;
+        String nodePath = pathBean.getNodePath();
+        if (nodePath == null)
+        {
+            nodePath = pathBean.setNodePath(beanClassNodeRootPaths.get(pathBean.getClass()));
+            newNode = true;
+        }
+        try
+        {
+            // notify pre-save listener
+            if (bean instanceof IPersistenceListener)
+            {
+                if (!((IPersistenceListener)bean).preSave(this))
+                {
+                    throw new RuntimeException("Pre-save listener invocation failed");
+                }
+            }
+            
+            // save node
+            if (newNode)
+            {
+                // construct parent nodes if necessary
+                constructParentNodes(nodePath);
+                // insert new node
+                ocm.insert(pathBean);
+            }
+            else
+            {
+                // update existing node
+                ocm.update(pathBean);
+            }
+            ocmCache.cache(pathBean.getNodePath(), pathBean);
+
+            // notify post-save listener
+            if (bean instanceof IPersistenceListener)
+            {
+                if (!((IPersistenceListener)bean).postSave(this))
+                {
+                    throw new RuntimeException("Post-save listener invocation failed");                    
+                }
+            }
+            return true;
+        }
+        catch (Exception e)
+        {
+            logger.error("Unexpected exception: "+e, e);
+            return false;
+        }
+    }
+    
+    /**
+     * Create parent node hierarchy if necessary.
+     * 
+     * @param nodePath node path
+     */
+    private Node constructParentNodes(String nodePath) throws RepositoryException
+    {
+        // recursively create parent nodes
+        Session session = ocm.getSession();
+        int parentNodePathEndIndex = nodePath.lastIndexOf('/');
+        if (parentNodePathEndIndex > 0)
+        {
+            String parentNodePath = nodePath.substring(0, parentNodePathEndIndex);
+            if (!parentNodePath.equals(rootPath))
+            {
+                // Jackrabbit/JCR 2.X
+                //boolean parentNodeExists = session.nodeExists(parentNodePath);
+                
+                // Jackrabbit/JCR 1.X
+                boolean parentNodeExists = session.itemExists(parentNodePath);
+
+                if (!parentNodeExists)
+                {
+                    // create parent parent nodes
+                    Node parentNode = constructParentNodes(parentNodePath);
+                    // create parent node
+                    String nodeName = parentNodePath.substring(parentNodePath.lastIndexOf('/')+1);
+                    return parentNode.addNode(nodeName, "nt:unstructured");
+                }
+            }
+
+            // Jackrabbit/JCR 2.X
+            //return session.getNode(parentNodePath);
+
+            // Jackrabbit/JCR 1.X
+            return (Node)session.getItem(parentNodePath);
+        }
+        return session.getRootNode();
+    }
+    
+    /**
+     * Escape invalid JCR characters in name.
+     * 
+     * @param name original name
+     * @return escaped or original name
+     */
+    public static String escapeJCRName(String name)
+    {
+        StringBuilder escapedName = null;
+        if (name != null)
+        {
+            for (int i = 0, limit = name.length(); (i < limit); i++)
+            {
+                char nameChar = name.charAt(i);
+                switch (nameChar)
+                {
+                    case '%' :
+                    case '/' :
+                    case ':' :
+                    case '[' :
+                    case ']' :
+                    case '|' :
+                    case '*' :
+                        if (escapedName == null)
+                        {
+                            escapedName = new StringBuilder(name.substring(0, i));
+                        }
+                        escapedName.append('%');
+                        escapedName.append(Character.toUpperCase(Character.forDigit(nameChar/16, 16)));
+                        escapedName.append(Character.toUpperCase(Character.forDigit(nameChar%16, 16)));
+                        break;
+                    default :
+                        if (escapedName != null)
+                        {
+                            escapedName.append(nameChar);
+                        }
+                        break;
+                }
+            }
+        }
+        return ((escapedName != null) ? escapedName.toString() : name);
+    }
+
+    /**
+     * Unescape invalid JCR characters in name.
+     * 
+     * @param escapedName escaped name
+     * @return original name
+     */
+    public static String unescapeJCRName(String escapedName)
+    {
+        StringBuilder unescapedName = null;
+        if (escapedName != null)
+        {
+            for (int i = 0, limit = escapedName.length(); (i < limit); i++)
+            {
+                char escapedNameChar = escapedName.charAt(i);
+                if (escapedNameChar == '%')
+                {
+                    if (unescapedName == null)
+                    {
+                        unescapedName = new StringBuilder(escapedName.substring(0, i));
+                    }
+                    int high = Character.digit(escapedName.charAt(++i), 16);
+                    int low = Character.digit(escapedName.charAt(++i), 16);
+                    unescapedName.append((char)(high*16+low));
+                }
+                else if (unescapedName != null)
+                {
+                    unescapedName.append(escapedNameChar);
+                }
+            }
+        }
+        return ((unescapedName != null) ? unescapedName.toString() : escapedName);        
+    }
+
+    /**
+     * Extended OCM that supports setting of object cache after construction.
+     */
+    private static class SessionObjectContentManagerImpl extends ObjectContentManagerImpl
+    {
+        /**
+         * Base OCM constructor with session and mapper.
+         * 
+         * @param session session for OCM to manage
+         * @param mapper object mapper component
+         */
+        public SessionObjectContentManagerImpl(Session session, Mapper mapper)
+        {
+            super(session, mapper);
+        }
+        
+        /* (non-Javadoc)
+         * @see org.apache.jackrabbit.ocm.manager.impl.ObjectContentManagerImpl#setRequestObjectCache(org.apache.jackrabbit.ocm.manager.cache.ObjectCache)
+         */
+        public void setRequestObjectCache(ObjectCache requestObjectCache)
+        {
+            super.setObjectConverter(new ObjectConverterImpl(mapper, new DefaultAtomicTypeConverterProvider(), new ProxyManagerImpl(), requestObjectCache));
+            super.setRequestObjectCache(requestObjectCache);
+        }
+    }
+    
+    /**
+     * Customized OCM object cache that is not cleared between requests.
+     */
+    private static class SessionObjectCacheImpl implements ObjectCache
+    {
+        private Map<String,Object> cache = new HashMap<String,Object>();
+        
+        /* (non-Javadoc)
+         * @see org.apache.jackrabbit.ocm.manager.cache.ObjectCache#cache(java.lang.String, java.lang.Object)
+         */
+        public void cache(String path, Object object)
+        {
+            // add to cache
+            cache.put(path, object);
+        }
+
+        /* (non-Javadoc)
+         * @see org.apache.jackrabbit.ocm.manager.cache.ObjectCache#clear()
+         */
+        public void clear()
+        {
+            // do not clear cache on OCM request
+        }
+
+        /* (non-Javadoc)
+         * @see org.apache.jackrabbit.ocm.manager.cache.ObjectCache#getObject(java.lang.String)
+         */
+        public Object getObject(String path)
+        {
+            // retrieve from cache
+            return cache.get(path);
+        }
+
+        /* (non-Javadoc)
+         * @see org.apache.jackrabbit.ocm.manager.cache.ObjectCache#isCached(java.lang.String)
+         */
+        public boolean isCached(String path)
+        {
+            // cache check
+            return cache.containsKey(path);
+        }
+
+        /**
+         * Clear cache on reset.
+         */
+        public void reset()
+        {
+            // clear cache
+            cache.clear();
+        }
+
+        /**
+         * Remove object from cache.
+         * 
+         * @param path object path
+         * @return removed object
+         */
+        public Object removeObject(String path)
+        {
+            // remove from cache
+            return cache.remove(path);
+        }
+    }
+}

Added: incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/PersistenceListenerAdapter.java
URL: http://svn.apache.org/viewvc/incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/PersistenceListenerAdapter.java?rev=955236&view=auto
==============================================================================
--- incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/PersistenceListenerAdapter.java (added)
+++ incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/PersistenceListenerAdapter.java Wed Jun 16 14:16:36 2010
@@ -0,0 +1,62 @@
+/*
+ *  Licensed 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.wookie.beans.jcr;
+
+import org.apache.wookie.beans.util.IPersistenceManager;
+
+/**
+ * PersistenceListenerAdapter - persistence operation notifications listener adapter.
+ * 
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id$
+ */
+public class PersistenceListenerAdapter implements IPersistenceListener
+{
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.jcr.IPersistenceListener#postDelete(org.apache.wookie.beans.util.IPersistenceManager)
+     */
+    public boolean postDelete(IPersistenceManager persistenceManager)
+    {
+        // do nothing by default
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.jcr.IPersistenceListener#postSave(org.apache.wookie.beans.util.IPersistenceManager)
+     */
+    public boolean postSave(IPersistenceManager persistenceManager)
+    {
+        // do nothing by default
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.jcr.IPersistenceListener#preDelete(org.apache.wookie.beans.util.IPersistenceManager)
+     */
+    public boolean preDelete(IPersistenceManager persistenceManager)
+    {
+        // do nothing by default
+        return true;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.jcr.IPersistenceListener#preSave(org.apache.wookie.beans.util.IPersistenceManager)
+     */
+    public boolean preSave(IPersistenceManager persistenceManager)
+    {
+        // do nothing by default
+        return true;
+    }
+}

Added: incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/AccessRequestImpl.java
URL: http://svn.apache.org/viewvc/incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/AccessRequestImpl.java?rev=955236&view=auto
==============================================================================
--- incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/AccessRequestImpl.java (added)
+++ incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/AccessRequestImpl.java Wed Jun 16 14:16:36 2010
@@ -0,0 +1,192 @@
+/*
+ *  Licensed 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.wookie.beans.jcr.impl;
+
+import java.net.URI;
+
+import org.apache.jackrabbit.ocm.manager.beanconverter.impl.ReferenceBeanConverterImpl;
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.Bean;
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.Field;
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.Node;
+
+import org.apache.wookie.beans.IAccessRequest;
+import org.apache.wookie.beans.IWidget;
+import org.apache.wookie.beans.jcr.IPathBean;
+import org.apache.wookie.beans.jcr.JCRPersistenceManager;
+
+/**
+ * AccessRequestImpl - JCR OCM IAccessRequest implementation.
+ * 
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id$
+ */
+@Node(jcrType="wookie:accessRequest", discriminator=false)
+public class AccessRequestImpl implements IAccessRequest, IPathBean
+{
+    @Field(path=true)
+    private String path;
+    
+    @Field(jcrName="wookie:origin")
+    private String origin;
+    
+    @Field(jcrName="wookie:subdomains")
+    private Boolean subdomains;
+    
+    @Field(jcrName="wookie:granted")
+    private Boolean granted;
+
+    @Bean(jcrName="wookie:widget", converter=ReferenceBeanConverterImpl.class)
+    private WidgetImpl widgetImpl;
+    
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IBean#getId()
+     */
+    public Object getId()
+    {
+        return path;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.jcr.IPathBean#getNodePath()
+     */
+    public String getNodePath()
+    {
+        return path;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.jcr.IPathBean#setNodePath(java.lang.String)
+     */
+    public String setNodePath(String nodeRootPath)
+    {
+        if (path == null)
+        {
+            path = nodeRootPath+"/"+JCRPersistenceManager.escapeJCRName(origin)+"/"+JCRPersistenceManager.escapeJCRName(widgetImpl.getGuid());
+        }
+        return path;
+    }
+
+    /**
+     * Get raw persistent JCR absolute node path.
+     * 
+     * @return absolute path
+     */
+    public String getPath()
+    {
+        return path;
+    }
+
+    /**
+     * Set raw persistent JCR absolute node path.
+     * 
+     * @param path absolute path
+     */
+    public void setPath(String path)
+    {
+        this.path = path;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IAccessRequest#getOrigin()
+     */
+    public String getOrigin()
+    {
+        return origin;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IAccessRequest#setOrigin(java.lang.String)
+     */
+    public void setOrigin(String origin)
+    {
+        this.origin = origin;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IAccessRequest#isGranted()
+     */
+    public boolean isGranted()
+    {
+        return ((granted != null) ? granted.booleanValue() : false);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IAccessRequest#setGranted(boolean)
+     */
+    public void setGranted(boolean granted)
+    {
+        this.granted = (granted ? Boolean.TRUE : Boolean.FALSE);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IAccessRequest#isSubdomains()
+     */
+    public boolean isSubdomains()
+    {
+        return ((subdomains != null) ? subdomains.booleanValue() : false);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IAccessRequest#setSubdomains(boolean)
+     */
+    public void setSubdomains(boolean subdomains)
+    {
+        this.subdomains = (subdomains ? Boolean.TRUE : Boolean.FALSE);
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IAccessRequest#getWidget()
+     */
+    public IWidget getWidget()
+    {
+        return widgetImpl;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IAccessRequest#setWidget(org.apache.wookie.beans.IWidget)
+     */
+    public void setWidget(IWidget widget)
+    {
+        this.widgetImpl = (WidgetImpl)widget;
+    }
+    
+    /**
+     * Get widget implementation.
+     * 
+     * @return widget implementation
+     */
+    public WidgetImpl getWidgetImpl()
+    {
+        return widgetImpl;
+    }
+
+    /**
+     * Set widget implementation.
+     * 
+     * @return widgetImpl widget implementation
+     */
+    public void setWidgetImpl(WidgetImpl widgetImpl)
+    {
+        this.widgetImpl = widgetImpl;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IAccessRequest#isAllowed(java.net.URI)
+     */
+    public boolean isAllowed(URI requestedUri)
+    {
+        return Utilities.isAllowed(this, requestedUri);
+    }
+}

Added: incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/ApiKeyImpl.java
URL: http://svn.apache.org/viewvc/incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/ApiKeyImpl.java?rev=955236&view=auto
==============================================================================
--- incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/ApiKeyImpl.java (added)
+++ incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/ApiKeyImpl.java Wed Jun 16 14:16:36 2010
@@ -0,0 +1,121 @@
+/*
+ *  Licensed 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.wookie.beans.jcr.impl;
+
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.Field;
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.Node;
+
+import org.apache.wookie.beans.IApiKey;
+import org.apache.wookie.beans.jcr.IPathBean;
+import org.apache.wookie.beans.jcr.JCRPersistenceManager;
+
+/**
+ * ApiKeyImpl - JCR OCM IApiKey implementation.
+ * 
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id$
+ */
+@Node(jcrType="wookie:apiKey", discriminator=false)
+public class ApiKeyImpl implements IApiKey, IPathBean
+{
+    @Field(path=true)
+    private String path;
+    
+    @Field(jcrName="wookie:value")
+    private String value;
+
+    @Field(jcrName="wookie:email")
+    private String email;
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IApiKey#getEmail()
+     */
+    public String getEmail()
+    {
+        return email;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IApiKey#setEmail(java.lang.String)
+     */
+    public void setEmail(String email)
+    {
+        this.email = email;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IBean#getId()
+     */
+    public Object getId()
+    {
+        return path;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.jcr.IPathBean#getNodePath()
+     */
+    public String getNodePath()
+    {
+        return path;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.jcr.IPathBean#setNodePath(java.lang.String)
+     */
+    public String setNodePath(String nodeRootPath)
+    {
+        if (path == null)
+        {
+            path = nodeRootPath+"/"+JCRPersistenceManager.escapeJCRName(value);
+        }
+        return path;
+    }
+
+    /**
+     * Get raw persistent JCR absolute node path.
+     * 
+     * @return absolute path
+     */
+    public String getPath()
+    {
+        return path;
+    }
+
+    /**
+     * Set raw persistent JCR absolute node path.
+     * 
+     * @param path absolute path
+     */
+    public void setPath(String path)
+    {
+        this.path = path;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IApiKey#getValue()
+     */
+    public String getValue()
+    {
+        return value;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IApiKey#setValue(java.lang.String)
+     */
+    public void setValue(String value)
+    {
+        this.value = value;
+    }
+}

Added: incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/DescriptionImpl.java
URL: http://svn.apache.org/viewvc/incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/DescriptionImpl.java?rev=955236&view=auto
==============================================================================
--- incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/DescriptionImpl.java (added)
+++ incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/DescriptionImpl.java Wed Jun 16 14:16:36 2010
@@ -0,0 +1,69 @@
+/*
+ *  Licensed 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.wookie.beans.jcr.impl;
+
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.Field;
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.Node;
+
+import org.apache.wookie.beans.IDescription;
+import org.apache.wookie.beans.jcr.IIdElement;
+
+/**
+ * DescriptionImpl - JCR OCM IDescription implementation.
+ * 
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id$
+ */
+@Node(jcrType="wookie:description", extend=LocalizedBeanImpl.class, discriminator=false)
+public class DescriptionImpl extends LocalizedBeanImpl implements IDescription, IIdElement
+{
+    @Field(id=true, jcrName="wookie:elementId")
+    private long elementId = -1;
+    
+    @Field(jcrName="wookie:content")
+    private String content;
+    
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IDescription#getContent()
+     */
+    public String getContent()
+    {
+        return content;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IDescription#setContent(java.lang.String)
+     */
+    public void setContent(String text)
+    {
+        this.content = text;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.jcr.IIdElement#getElementId()
+     */
+    public long getElementId()
+    {
+        return elementId;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.jcr.IIdElement#setElementId(long)
+     */
+    public void setElementId(long elementId)
+    {
+        this.elementId = elementId;
+    }
+}

Added: incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/FeatureImpl.java
URL: http://svn.apache.org/viewvc/incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/FeatureImpl.java?rev=955236&view=auto
==============================================================================
--- incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/FeatureImpl.java (added)
+++ incubator/wookie/branches/pluggablepersistence/src/org/apache/wookie/beans/jcr/impl/FeatureImpl.java Wed Jun 16 14:16:36 2010
@@ -0,0 +1,143 @@
+/*
+ *  Licensed 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.wookie.beans.jcr.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.Field;
+import org.apache.jackrabbit.ocm.mapper.impl.annotation.Node;
+
+import org.apache.wookie.beans.IFeature;
+import org.apache.wookie.beans.IParam;
+import org.apache.wookie.beans.jcr.IIdElement;
+import org.apache.wookie.beans.jcr.IdCollection;
+
+/**
+ * FeatureImpl - JCR OCM IFeature implementation.
+ * 
+ * @author <a href="mailto:rwatler@apache.org">Randy Watler</a>
+ * @version $Id$
+ */
+@Node(jcrType="wookie:feature", discriminator=false)
+public class FeatureImpl implements IFeature, IIdElement
+{
+    @Field(id=true, jcrName="wookie:elementId")
+    private long elementId = -1;
+    
+    @Field(jcrName="wookie:featureName")
+    private String featureName;
+    
+    @Field(jcrName="wookie:required")
+    private Boolean required;
+    
+    @org.apache.jackrabbit.ocm.mapper.impl.annotation.Collection(jcrName="wookie:parameters", elementClassName=ParamImpl.class)
+    private Collection<ParamImpl> parameterImpls;
+    
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.jcr.IIdElement#getElementId()
+     */
+    public long getElementId()
+    {
+        return elementId;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.jcr.IIdElement#setElementId(long)
+     */
+    public void setElementId(long elementId)
+    {
+        this.elementId = elementId;
+    }
+    
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IFeature#getFeatureName()
+     */
+    public String getFeatureName()
+    {
+        return featureName;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IFeature#setFeatureName(java.lang.String)
+     */
+    public void setFeatureName(String featureName)
+    {
+        this.featureName = featureName;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IFeature#getParameters()
+     */
+    public Collection<IParam> getParameters()
+    {
+        if (parameterImpls == null)
+        {
+            parameterImpls = new ArrayList<ParamImpl>();
+        }
+        return new IdCollection<ParamImpl,IParam>(parameterImpls);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IFeature#setParameters(java.util.Collection)
+     */
+    public void setParameters(Collection<IParam> parameters)
+    {
+        getParameters().clear();
+        if (parameters != null)
+        {
+            for (IParam parameter : parameters)
+            {
+                getParameters().add((ParamImpl)parameter);
+            }
+        }
+    }
+
+    /**
+     * Get parameter implementations collection.
+     * 
+     * @return parameter implementations collection
+     */
+    public Collection<ParamImpl> getParameterImpls()
+    {
+        return parameterImpls;
+    }
+
+    /**
+     * Set parameter implementations collection.
+     * 
+     * @param parameterImpls parameter implementations collection
+     */
+    public void setParameterImpls(Collection<ParamImpl> parameterImpls)
+    {
+        this.parameterImpls = parameterImpls;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IFeature#isRequired()
+     */
+    public boolean isRequired()
+    {
+        return ((required != null) ? required.booleanValue() : false);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.wookie.beans.IFeature#setRequired(boolean)
+     */
+    public void setRequired(boolean required)
+    {
+        this.required = (required ? Boolean.TRUE : Boolean.FALSE);
+    }
+}