jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r827966 [3/15] - in /jackrabbit/sandbox/JCR-1456: ./ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/management/ jackrabbit-api/src/main/java/org/apache/jackrabbit/api/security/...
Date Wed, 21 Oct 2009 11:38:44 GMT
Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SearchManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SearchManager.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SearchManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SearchManager.java Wed Oct 21 11:38:31 2009
@@ -24,6 +24,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Executor;
 
 import javax.jcr.NamespaceException;
 import javax.jcr.Node;
@@ -36,7 +37,6 @@
 
 import org.apache.jackrabbit.core.config.SearchConfig;
 import org.apache.jackrabbit.core.fs.FileSystem;
-import org.apache.jackrabbit.core.fs.FileSystemException;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
 import org.apache.jackrabbit.core.observation.EventImpl;
@@ -45,6 +45,7 @@
 import org.apache.jackrabbit.core.query.AbstractQueryImpl;
 import org.apache.jackrabbit.core.query.QueryHandler;
 import org.apache.jackrabbit.core.query.QueryHandlerContext;
+import org.apache.jackrabbit.core.query.QueryHandlerFactory;
 import org.apache.jackrabbit.core.query.QueryObjectModelImpl;
 import org.apache.jackrabbit.core.state.ItemStateException;
 import org.apache.jackrabbit.core.state.NodeState;
@@ -84,36 +85,11 @@
     public static final String NS_XS_URI = "http://www.w3.org/2001/XMLSchema";
 
     /**
-     * The search configuration.
-     */
-    private final SearchConfig config;
-
-    /**
-     * The node type registry.
-     */
-    private final NodeTypeRegistry ntReg;
-
-    /**
      * The shared item state manager instance for the workspace.
      */
     private final SharedItemStateManager itemMgr;
 
     /**
-     * The underlying persistence manager.
-     */
-    private final PersistenceManager pm;
-
-    /**
-     * Storage for search index
-     */
-    private final FileSystem fs;
-
-    /**
-     * The root node for this search manager.
-     */
-    private final NodeId rootNodeId;
-
-    /**
      * QueryHandler where query execution is delegated to
      */
     private QueryHandler handler;
@@ -130,12 +106,6 @@
     private final NamespaceRegistryImpl nsReg;
 
     /**
-     * ID of the node that should be excluded from indexing or <code>null</code>
-     * if no node should be excluded.
-     */
-    private final NodeId excludedNodeId;
-
-    /**
      * Path that will be excluded from indexing.
      */
     private Path excludePath;
@@ -156,23 +126,18 @@
      *                       excluded from indexing.
      * @throws RepositoryException if the search manager cannot be initialized
      */
-    public SearchManager(SearchConfig config,
+    public SearchManager(QueryHandlerFactory qhf,
                          final NamespaceRegistryImpl nsReg,
                          NodeTypeRegistry ntReg,
                          SharedItemStateManager itemMgr,
                          PersistenceManager pm,
                          NodeId rootNodeId,
                          SearchManager parentMgr,
-                         NodeId excludedNodeId) throws RepositoryException {
-        this.fs = config.getFileSystem();
-        this.config = config;
-        this.ntReg = ntReg;
+                         NodeId excludedNodeId,
+                         Executor executor) throws RepositoryException {
         this.nsReg = nsReg;
         this.itemMgr = itemMgr;
-        this.pm = pm;
-        this.rootNodeId = rootNodeId;
         this.parentHandler = (parentMgr != null) ? parentMgr.handler : null;
-        this.excludedNodeId = excludedNodeId;
 
         // register namespaces
         safeRegisterNamespace(NS_XS_PREFIX, NS_XS_URI);
@@ -205,7 +170,9 @@
         }
 
         // initialize query handler
-        initializeQueryHandler();
+        this.handler = qhf.getQueryHandler(new QueryHandlerContext(
+                itemMgr, pm, rootNodeId, ntReg, nsReg,
+                parentHandler, excludedNodeId, executor));
     }
 
     /**
@@ -252,14 +219,8 @@
     public void close() {
         try {
             shutdownQueryHandler();
-
-            if (fs != null) {
-                fs.close();
-            }
         } catch (IOException e) {
             log.error("Exception closing QueryHandler.", e);
-        } catch (FileSystemException e) {
-            log.error("Exception closing FileSystem.", e);
         }
     }
 
@@ -497,24 +458,6 @@
     //------------------------< internal >--------------------------------------
 
     /**
-     * Initializes the query handler.
-     *
-     * @throws RepositoryException if the query handler cannot be initialized.
-     */
-    private void initializeQueryHandler() throws RepositoryException {
-        // initialize query handler
-        try {
-            handler = (QueryHandler) config.newInstance();
-            QueryHandlerContext context
-                    = new QueryHandlerContext(fs, itemMgr, pm, rootNodeId,
-                            ntReg, nsReg, parentHandler, excludedNodeId);
-            handler.init(context);
-        } catch (Exception e) {
-            throw new RepositoryException(e.getMessage(), e);
-        }
-    }
-
-    /**
      * Shuts down the query handler. If the query handler is already shut down
      * this method does nothing.
      *

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/SessionImpl.java Wed Oct 21 11:38:31 2009
@@ -29,7 +29,6 @@
 import org.apache.jackrabbit.core.data.GarbageCollector;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.lock.LockManager;
-import org.apache.jackrabbit.core.nodetype.NodeDefinitionImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
 import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
 import org.apache.jackrabbit.core.persistence.IterablePersistenceManager;
@@ -61,6 +60,7 @@
 import org.apache.jackrabbit.spi.commons.conversion.MalformedPathException;
 import org.apache.jackrabbit.spi.commons.conversion.NameException;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -688,7 +688,7 @@
             }
             ipmList[i] = (IterablePersistenceManager) pm;
         }
-        GarbageCollector gc = new GarbageCollector(this, ipmList, sessions);
+        GarbageCollector gc = new GarbageCollector(rep, this, ipmList, sessions);
         return gc;
     }
 
@@ -852,20 +852,12 @@
     public Node getNodeByUUID(String uuid) throws ItemNotFoundException, RepositoryException {
         try {
             NodeImpl node = getNodeById(new NodeId(uuid));
-            // since the uuid of a node is only exposed through jcr:uuid declared
-            // by mix:referenceable it's rather unlikely that a client can possibly
-            // know the internal uuid of a non-referenceable node; omitting the
-            // check for mix:referenceable seems therefore to be a reasonable
-            // compromise in order to improve performance.
-            /*
-            if (node.isNodeType(Name.MIX_REFERENCEABLE)) {
+            if (node.isNodeType(NameConstants.MIX_REFERENCEABLE)) {
                 return node;
             } else {
                 // there is a node with that uuid but the node does not expose it
-                throw new ItemNotFoundException(uuid.toString());
+                throw new ItemNotFoundException(uuid);
             }
-             */
-            return node;
         } catch (IllegalArgumentException e) {
             // Assuming the exception is from UUID.fromString()
             throw new RepositoryException("Invalid UUID: " + uuid, e);
@@ -1081,7 +1073,7 @@
         // check constraints
         // get applicable definition of target node at new location
         NodeTypeImpl nt = (NodeTypeImpl) targetNode.getPrimaryNodeType();
-        NodeDefinitionImpl newTargetDef;
+        org.apache.jackrabbit.spi.commons.nodetype.NodeDefinitionImpl newTargetDef;
         try {
             newTargetDef = destParentNode.getApplicableChildNodeDefinition(destName.getName(), nt.getQName());
         } catch (RepositoryException re) {
@@ -1140,7 +1132,7 @@
         }
 
         // change definition of target
-        targetNode.onRedefine(newTargetDef.unwrap().getId());
+        targetNode.onRedefine(newTargetDef.unwrap());
     }
 
     /**
@@ -1174,6 +1166,7 @@
                 ItemValidator.CHECK_CONSTRAINTS | ItemValidator.CHECK_HOLD | ItemValidator.CHECK_RETENTION;
         getValidator().checkModify(parent, options, Permission.NONE);
 
+        // TODO: make configurable
         ProtectedNodeImporter pi = new AccessControlImporter(this, this, false, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
         SessionImporter importer = new SessionImporter(parent, this, uuidBehavior, pi, null);
         return new ImportHandler(importer, this);
@@ -1549,7 +1542,7 @@
     }
 
     /**
-     * @see javax.jcr.Session#hasCapability(String, Object, Object[]) 
+     * @see javax.jcr.Session#hasCapability(String, Object, Object[])
      * @since JCR 2.0
      */
     public boolean hasCapability(String methodName, Object target, Object[] arguments)

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransientRepository.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransientRepository.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransientRepository.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/TransientRepository.java Wed Oct 21 11:38:31 2009
@@ -418,4 +418,13 @@
     public void loggingOut(SessionImpl session) {
     }
 
+    /**
+     * Get the current repository.
+     *
+     * @return the repository
+     */
+    RepositoryImpl getRepository() {
+        return repository;
+    }
+
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/ZombieHierarchyManager.java Wed Oct 21 11:38:31 2009
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.core;
 
+import java.util.Iterator;
+
 import org.apache.jackrabbit.core.id.ItemId;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.state.ChildNodeEntry;
@@ -99,16 +101,19 @@
     protected ChildNodeEntry getChildNodeEntry(NodeState parent,
                                                          Name name,
                                                          int index) {
-        // check removed child node entries first
-        for (ChildNodeEntry entry : parent.getRemovedChildNodeEntries()) {
-            if (entry.getName().equals(name)
-                    && entry.getIndex() == index) {
-                return entry;
+        // first look for the entry in the current child node entry list
+        ChildNodeEntry entry = super.getChildNodeEntry(parent, name, index);
+        if (entry == null) {
+            // if not found, we need to look for a removed child node entry
+            for (ChildNodeEntry candidate : parent.getRemovedChildNodeEntries()) {
+                if (candidate.getName().equals(name)
+                        && candidate.getIndex() == index) {
+                    entry = candidate;
+                    break;
+                }
             }
         }
-        // no matching removed child node entry found in parent,
-        // delegate to base class
-        return super.getChildNodeEntry(parent, name, index);
+        return entry;
     }
 
     /**
@@ -118,14 +123,17 @@
      */
     protected ChildNodeEntry getChildNodeEntry(NodeState parent,
                                                          NodeId id) {
-        // check removed child node entries first
-        for (ChildNodeEntry entry : parent.getRemovedChildNodeEntries()) {
-            if (entry.getId().equals(id)) {
-                return entry;
+        // first look for the entry in the current child node entry list
+        ChildNodeEntry entry = super.getChildNodeEntry(parent, id);
+        if (entry == null) {
+            // if not found, we need to look for a removed child node entry
+            for (ChildNodeEntry candidate : parent.getRemovedChildNodeEntries()) {
+                if (candidate.getId().equals(id)) {
+                    entry = candidate;
+                    break;
+                }
             }
         }
-        // no matching removed child node entry found in parent,
-        // delegate to base class
-        return super.getChildNodeEntry(parent, id);
+        return entry;
     }
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/ClusterNode.java Wed Oct 21 11:38:31 2009
@@ -16,23 +16,16 @@
  */
 package org.apache.jackrabbit.core.cluster;
 
-import java.io.File;
-import java.io.IOException;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.UUID;
 
 import javax.jcr.RepositoryException;
 
-import org.apache.commons.io.FileUtils;
-import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.cluster.WorkspaceRecord.CreateWorkspaceAction;
 import org.apache.jackrabbit.core.config.ClusterConfig;
-import org.apache.jackrabbit.core.config.ConfigurationException;
-import org.apache.jackrabbit.core.config.JournalConfig;
-import org.apache.jackrabbit.core.journal.AbstractJournal;
+import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.journal.InstanceRevision;
 import org.apache.jackrabbit.core.journal.Journal;
 import org.apache.jackrabbit.core.journal.JournalException;
@@ -40,10 +33,10 @@
 import org.apache.jackrabbit.core.journal.RecordConsumer;
 import org.apache.jackrabbit.core.journal.RecordProducer;
 import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
-import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
 import org.apache.jackrabbit.core.observation.EventState;
 import org.apache.jackrabbit.core.state.ChangeLog;
 import org.apache.jackrabbit.core.xml.ClonedInputSource;
+import org.apache.jackrabbit.spi.QNodeTypeDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -63,11 +56,6 @@
     public static final String SYSTEM_PROPERTY_NODE_ID = "org.apache.jackrabbit.core.cluster.node_id";
 
     /**
-     * Cluster node id file.
-     */
-    private static final String CLUSTER_NODE_ID_FILE = "cluster_node.id";
-
-    /**
      * Producer identifier.
      */
     private static final String PRODUCER_ID = "JR";
@@ -209,35 +197,20 @@
      */
     protected void init() throws ClusterException {
         ClusterConfig cc = clusterContext.getClusterConfig();
-        clusterNodeId = getClusterNodeId(cc.getId());
+        clusterNodeId = cc.getId();
         syncDelay = cc.getSyncDelay();
 
         try {
-            JournalConfig jc = cc.getJournalConfig();
-            journal = (Journal) jc.newInstance();
-            setRepositoryHome(journal, clusterContext.getRepositoryHome());
-            journal.init(clusterNodeId, clusterContext.getNamespaceResolver());
+            journal = cc.getJournal(clusterContext.getNamespaceResolver());
             instanceRevision = journal.getInstanceRevision();
             journal.register(this);
             producer = journal.getProducer(PRODUCER_ID);
-        } catch (ConfigurationException e) {
-            throw new ClusterException(e.getMessage(), e.getCause());
+        } catch (RepositoryException e) {
+            throw new ClusterException(
+                    "Cluster initialization failed: " + this, e);
         } catch (JournalException e) {
-            throw new ClusterException(e.getMessage(), e.getCause());
-        }
-    }
-
-    /**
-     * Set a journal's repository home, if possible, i.e. if it is an
-     * <code>AbstractJournal</code>
-     *
-     * @param journal journal instance
-     * @param repHome repository home
-     */
-    private void setRepositoryHome(Journal journal, File repHome) {
-        if (journal instanceof AbstractJournal) {
-            AbstractJournal aj = (AbstractJournal) journal;
-            aj.setRepositoryHome(repHome);
+            throw new ClusterException(
+                    "Journal initialization failed: " + this, e);
         }
     }
 
@@ -394,44 +367,6 @@
         return journal;
     }
 
-    /**
-     * Return the instance id to be used for this node in the cluster.
-     * @param id configured id, <code>null</code> to generate a unique id
-     */
-    private String getClusterNodeId(String id) throws ClusterException {
-        if (id == null) {
-            id = System.getProperty(SYSTEM_PROPERTY_NODE_ID);
-            if (id == null) {
-                try {
-                    id = getClusterNodeIdFromFile();
-                } catch (IOException e) {
-                    throw new ClusterException(e.getMessage(), e.getCause());
-                }
-            }
-        }
-        return id;
-    }
-
-    /**
-     * Return a cluster node from a file, creating it if necessary.
-     *
-     * @return stored or generated cluster id
-     * @throws IOException if an I/O error occurs
-     */
-    protected String getClusterNodeIdFromFile() throws IOException {
-        String filename = clusterContext.getRepositoryHome() + File.separator + CLUSTER_NODE_ID_FILE;
-        File f = new File(filename);
-
-        if (f.exists() && f.canRead()) {
-            return FileUtils.readFileToString(f);
-        }
-
-        String id = UUID.randomUUID().toString();
-        FileUtils.writeStringToFile(f, id);
-        return id;
-
-    }
-
     //-----------------------------------------------< NamespaceEventListener >
 
     /**
@@ -503,7 +438,7 @@
     /**
      * {@inheritDoc}
      */
-    public void reregistered(NodeTypeDef ntDef) {
+    public void reregistered(QNodeTypeDefinition ntDef) {
         if (status != STARTED) {
             log.info("not started: nodetype operation ignored.");
             return;
@@ -953,7 +888,7 @@
                 nodeTypeListener.externalUnregistered(coll);
                 break;
             case NodeTypeRecord.REREGISTER:
-                NodeTypeDef ntd = (NodeTypeDef) coll.iterator().next();
+                QNodeTypeDefinition ntd = (QNodeTypeDefinition) coll.iterator().next();
                 nodeTypeListener.externalReregistered(ntd);
                 break;
             }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventChannel.java Wed Oct 21 11:38:31 2009
@@ -16,8 +16,8 @@
  */
 package org.apache.jackrabbit.core.cluster;
 
-import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.QNodeTypeDefinition;
 
 import java.util.Collection;
 
@@ -31,14 +31,14 @@
      *
      * @param ntDefs collection of node type definitions
      */
-    void registered(Collection<NodeTypeDef> ntDefs);
+    void registered(Collection<QNodeTypeDefinition> ntDefs);
 
     /**
      * Called when a node types has been re-registered.
      *
      * @param ntDef node type definition
      */
-    void reregistered(NodeTypeDef ntDef);
+    void reregistered(QNodeTypeDefinition ntDef);
 
     /**
      * Called when one or more node types have been unregistered.

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeEventListener.java Wed Oct 21 11:38:31 2009
@@ -17,8 +17,8 @@
 package org.apache.jackrabbit.core.cluster;
 
 import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
-import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.QNodeTypeDefinition;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.nodetype.NoSuchNodeTypeException;
@@ -36,7 +36,7 @@
      * @throws RepositoryException if an error occurs
      * @throws InvalidNodeTypeDefException if the node type definition is invalid
      */
-    void externalRegistered(Collection<NodeTypeDef> ntDefs)
+    void externalRegistered(Collection<QNodeTypeDefinition> ntDefs)
         throws RepositoryException, InvalidNodeTypeDefException;
 
     /**
@@ -47,7 +47,7 @@
      * @throws NoSuchNodeTypeException if the node type had not yet been registered
      * @throws InvalidNodeTypeDefException if the node type definition is invalid
      */
-    void externalReregistered(NodeTypeDef ntDef)
+    void externalReregistered(QNodeTypeDefinition ntDef)
         throws NoSuchNodeTypeException, InvalidNodeTypeDefException, RepositoryException;
 
     /**

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeRecord.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeRecord.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/cluster/NodeTypeRecord.java Wed Oct 21 11:38:31 2009
@@ -24,8 +24,8 @@
 
 import org.apache.jackrabbit.core.journal.JournalException;
 import org.apache.jackrabbit.core.journal.Record;
-import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.QNodeTypeDefinition;
 
 /**
  * Cluster record representing a node type registration, re-registration or
@@ -106,7 +106,7 @@
      * @param ntDef node type definition
      * @param record journal record
      */
-    public NodeTypeRecord(NodeTypeDef ntDef, Record record) {
+    public NodeTypeRecord(QNodeTypeDefinition ntDef, Record record) {
         super(record);
 
         this.collection = new ArrayList();
@@ -173,7 +173,7 @@
             if (operation == UNREGISTER) {
                 record.writeQName((Name) iter.next());
             } else {
-                record.writeNodeTypeDef((NodeTypeDef) iter.next());
+                record.writeNodeTypeDef((QNodeTypeDefinition) iter.next());
             }
         }
     }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/BeanConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/BeanConfig.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/BeanConfig.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/BeanConfig.java Wed Oct 21 11:38:31 2009
@@ -22,7 +22,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Iterator;
 import java.util.Properties;
 import java.util.Map;
 import java.util.HashMap;
@@ -35,7 +34,7 @@
  * and property information required to instantiate a class that conforms
  * with the JavaBean conventions.
  */
-public class BeanConfig {
+public class BeanConfig<T> {
 
     private static Logger log = LoggerFactory.getLogger(BeanConfig.class);
 
@@ -171,18 +170,16 @@
     public Object newInstance() throws ConfigurationException {
         try {
             // Instantiate the object using the default constructor
-            Class objectClass =
+            Class<?> objectClass =
                 Class.forName(getClassName(), true, getClassLoader());
             Object object = objectClass.newInstance();
 
             // Set all configured bean properties
             BeanMap map = new BeanMap(object);
-            Iterator iterator = map.keyIterator();
-            while (iterator.hasNext()) {
-                String name = (String) iterator.next();
-                String value = properties.getProperty(name);
+            for (Object key : map.keySet()) {
+                String value = properties.getProperty(key.toString());
                 if (value != null) {
-                    map.put(name, properties.getProperty(name));
+                    map.put(key, value);
                 }
             }
 
@@ -192,10 +189,9 @@
 
             if (validate) {
                 // Check that no invalid property names were configured
-                Iterator it = properties.keySet().iterator();
-                while (it.hasNext()) {
-                    String key = (String) it.next();
-                    if (!map.containsKey(key) && properties.getProperty(key) != null) {
+                for (Object key : properties.keySet()) {
+                    if (!map.containsKey(key)
+                            && properties.getProperty(key.toString()) != null) {
                         String msg =
                             "Configured class " + object.getClass().getName()
                             + " does not contain the property " + key
@@ -206,7 +202,7 @@
                 }
             }
 
-            return object;
+            return (T) object;
         } catch (ClassNotFoundException e) {
             throw new ConfigurationException(
                     "Configured bean implementation class " + getClassName()

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/ClusterConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/ClusterConfig.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/ClusterConfig.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/ClusterConfig.java Wed Oct 21 11:38:31 2009
@@ -16,11 +16,16 @@
  */
 package org.apache.jackrabbit.core.config;
 
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.core.journal.Journal;
+import org.apache.jackrabbit.core.journal.JournalFactory;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
+
 /**
- * Cluster configuration. This includes the journal configuration
- * {@link JournalConfig}.
+ * Cluster configuration.
  */
-public class ClusterConfig {
+public class ClusterConfig implements JournalFactory {
 
     /**
      * Identifier.
@@ -33,9 +38,9 @@
     private final long syncDelay;
 
     /**
-     * Journal configuration.
+     * Journal factory.
      */
-    private final JournalConfig jc;
+    private final JournalFactory jf;
 
     /**
      * Creates a new cluster configuration.
@@ -44,10 +49,10 @@
      * @param syncDelay syncDelay, in milliseconds
      * @param jc journal configuration
      */
-    public ClusterConfig(String id, long syncDelay, JournalConfig jc) {
+    public ClusterConfig(String id, long syncDelay, JournalFactory jf) {
         this.id = id;
         this.syncDelay = syncDelay;
-        this.jc = jc;
+        this.jf = jf;
     }
 
     /**
@@ -69,11 +74,16 @@
     }
 
     /**
-     * Returns the journal configuration.
+     * Returns an initialized journal instance.
      *
-     * @return journal configuration
-     */
-    public JournalConfig getJournalConfig() {
-        return jc;
+     * @param resolver namespace resolver
+     * @return initialized journal
+     * @throws RepositoryException 
+     * @throws RepositoryException if the journal can not be created
+     */
+    public Journal getJournal(NamespaceResolver resolver)
+            throws RepositoryException {
+        return jf.getJournal(resolver);
     }
+
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java Wed Oct 21 11:38:31 2009
@@ -24,6 +24,9 @@
 import org.apache.jackrabbit.core.fs.FileSystemException;
 import org.apache.jackrabbit.core.fs.FileSystemFactory;
 import org.apache.jackrabbit.core.fs.FileSystemPathUtil;
+import org.apache.jackrabbit.core.query.QueryHandler;
+import org.apache.jackrabbit.core.query.QueryHandlerContext;
+import org.apache.jackrabbit.core.query.QueryHandlerFactory;
 import org.apache.jackrabbit.core.util.RepositoryLockMechanism;
 import org.apache.jackrabbit.core.util.RepositoryLockMechanismFactory;
 import org.apache.jackrabbit.core.util.db.ConnectionFactory;
@@ -70,7 +73,8 @@
  * addition the workspace configuration object keeps track of all configured
  * workspaces.
  */
-public class RepositoryConfig implements FileSystemFactory, DataStoreFactory {
+public class RepositoryConfig
+        implements FileSystemFactory, DataStoreFactory, QueryHandlerFactory {
 
     /** the default logger */
     private static Logger log = LoggerFactory.getLogger(RepositoryConfig.class);
@@ -326,9 +330,9 @@
     private final VersioningConfig vc;
 
     /**
-     * Optional search configuration for system search manager.
+     * Query handler factory, or <code>null</code> if not configured.
      */
-    private final SearchConfig sc;
+    private final QueryHandlerFactory qhf;
 
     /**
      * Optional cluster configuration.
@@ -367,7 +371,7 @@
      * @param workspaceMaxIdleTime maximum workspace idle time in seconds
      * @param template workspace configuration template
      * @param vc versioning configuration
-     * @param sc search configuration for system search manager.
+     * @param qhf query handler factory for the system search manager
      * @param cc optional cluster configuration
      * @param dsf data store factory
      * @param rlf the RepositoryLockMechanismFactory
@@ -379,7 +383,7 @@
             String home, SecurityConfig sec, FileSystemFactory fsf,
             String workspaceDirectory, String workspaceConfigDirectory,
             String defaultWorkspace, int workspaceMaxIdleTime,
-            Element template, VersioningConfig vc, SearchConfig sc,
+            Element template, VersioningConfig vc, QueryHandlerFactory qhf,
             ClusterConfig cc, DataStoreFactory dsf,
             RepositoryLockMechanismFactory rlf,
             DataSourceConfig dsc,
@@ -395,7 +399,7 @@
         this.defaultWorkspace = defaultWorkspace;
         this.template = template;
         this.vc = vc;
-        this.sc = sc;
+        this.qhf = qhf;
         this.cc = cc;
         this.dsf = dsf;
         this.rlf = rlf;
@@ -905,13 +909,28 @@
     }
 
     /**
-     * Returns the system search index configuration. Returns
-     * <code>null</code> if no search index has been configured.
+     * Checks whether search configuration is present.
      *
-     * @return search index configuration, or <code>null</code>
+     * @return <code>true</code> if search is configured,
+     *         <code>false</code> otherwise
      */
-    public SearchConfig getSearchConfig() {
-        return sc;
+    public boolean isSearchEnabled() {
+        return qhf != null;
+    }
+
+    /**
+     * Returns the initialized query handler, or <code>null</code> if one
+     * has not been configured.
+     *
+     * @return initialized query handler, or <code>null</code>
+     */
+    public QueryHandler getQueryHandler(QueryHandlerContext context)
+            throws RepositoryException {
+        if (qhf != null) {
+            return qhf.getQueryHandler(context);
+        } else {
+            return null;
+        }
     }
 
     /**

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/RepositoryConfigurationParser.java Wed Oct 21 11:38:31 2009
@@ -16,11 +16,20 @@
  */
 package org.apache.jackrabbit.core.config;
 
+import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.core.cluster.ClusterNode;
 import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.data.DataStoreFactory;
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
 import org.apache.jackrabbit.core.fs.FileSystemFactory;
+import org.apache.jackrabbit.core.journal.AbstractJournal;
+import org.apache.jackrabbit.core.journal.Journal;
+import org.apache.jackrabbit.core.journal.JournalException;
+import org.apache.jackrabbit.core.journal.JournalFactory;
+import org.apache.jackrabbit.core.query.QueryHandler;
+import org.apache.jackrabbit.core.query.QueryHandlerContext;
+import org.apache.jackrabbit.core.query.QueryHandlerFactory;
 import org.apache.jackrabbit.core.state.DefaultISMLocking;
 import org.apache.jackrabbit.core.state.ISMLocking;
 import org.apache.jackrabbit.core.state.ISMLockingFactory;
@@ -28,13 +37,16 @@
 import org.apache.jackrabbit.core.util.RepositoryLockMechanism;
 import org.apache.jackrabbit.core.util.RepositoryLockMechanismFactory;
 import org.apache.jackrabbit.core.util.db.ConnectionFactory;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 import org.xml.sax.InputSource;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.Properties;
+import java.util.UUID;
 
 import javax.jcr.RepositoryException;
 
@@ -181,6 +193,11 @@
     private final ConnectionFactory connectionFactory;
 
     /**
+     * Name of the cluster node id file.
+     */
+    private static final String CLUSTER_NODE_ID_FILE = "cluster_node.id";
+
+    /**
      * Creates a new configuration parser with the given parser variables.
      *
      * @param variables parser variables
@@ -274,11 +291,11 @@
         // Versioning configuration
         VersioningConfig vc = parseVersioningConfig(root);
 
-        // Optional search configuration
-        SearchConfig sc = parseSearchConfig(root);
+        // Query handler implementation
+        QueryHandlerFactory qhf = getQueryHandlerFactory(root);
 
         // Optional journal configuration
-        ClusterConfig cc = parseClusterConfig(root);
+        ClusterConfig cc = parseClusterConfig(root, new File(home));
 
         // Optional data store factory
         DataStoreFactory dsf = getDataStoreFactory(root, home);
@@ -290,7 +307,7 @@
 
         return new RepositoryConfig(home, securityConfig, fsf,
                 workspaceDirectory, workspaceConfigDirectory, defaultWorkspace,
-                maxIdleTime, template, vc, sc, cc, dsf, rlf, dsc, connectionFactory, this);
+                maxIdleTime, template, vc, qhf, cc, dsf, rlf, dsc, connectionFactory, this);
     }
 
     
@@ -506,8 +523,8 @@
         // Persistence manager implementation
         PersistenceManagerConfig pmc = tmpParser.parsePersistenceManagerConfig(root);
 
-        // Search implementation (optional)
-        SearchConfig sc = tmpParser.parseSearchConfig(root);
+        // Query handler implementation
+        QueryHandlerFactory qhf = tmpParser.getQueryHandlerFactory(root);
 
         // Item state manager locking configuration (optional)
         ISMLockingFactory ismLockingFactory =
@@ -517,7 +534,7 @@
         WorkspaceSecurityConfig workspaceSecurityConfig = tmpParser.parseWorkspaceSecurityConfig(root);
 
         return new WorkspaceConfig(
-                home, name, clustered, fsf, pmc, sc,
+                home, name, clustered, fsf, pmc, qhf,
                 ismLockingFactory, workspaceSecurityConfig);
     }
 
@@ -545,32 +562,43 @@
      * However some implementations may require a FileSystem.
      *
      * @param parent parent of the <code>SearchIndex</code> element
-     * @return search configuration, or <code>null</code>
-     * @throws ConfigurationException if the configuration is broken
+     * @return query handler factory
      */
-    protected SearchConfig parseSearchConfig(Element parent)
-            throws ConfigurationException {
+    protected QueryHandlerFactory getQueryHandlerFactory(final Element parent) {
         NodeList children = parent.getChildNodes();
         for (int i = 0; i < children.getLength(); i++) {
-            Node child = children.item(i);
+            final Node child = children.item(i);
             if (child.getNodeType() == Node.ELEMENT_NODE
                     && SEARCH_INDEX_ELEMENT.equals(child.getNodeName())) {
-                Element element = (Element) child;
-
-                // Search implementation class
-                String className = getAttribute(
-                        element, CLASS_ATTRIBUTE, DEFAULT_QUERY_HANDLER);
-
-                // Search parameters
-                Properties parameters = parseParameters(element);
-
-                // Optional file system implementation
-                FileSystemFactory fsf = null;
-                if (getElement(element, FILE_SYSTEM_ELEMENT, false) != null) {
-                    fsf = getFileSystemFactory(element, FILE_SYSTEM_ELEMENT);
-                }
-
-                return new SearchConfig(className, parameters, fsf);
+                return new QueryHandlerFactory() {
+                    public QueryHandler getQueryHandler(QueryHandlerContext context)
+                            throws RepositoryException {
+                        Element element = (Element) child;
+
+                        // Optional file system implementation
+                        FileSystem fs = null;
+                        if (getElement(element, FILE_SYSTEM_ELEMENT, false) != null) {
+                            fs = getFileSystemFactory(
+                                    element, FILE_SYSTEM_ELEMENT).getFileSystem();
+                        }
+
+                        // Search implementation class
+                        String className = getAttribute(
+                                element, CLASS_ATTRIBUTE, DEFAULT_QUERY_HANDLER);
+                        BeanConfig config = new BeanConfig(
+                                className, parseParameters(element));
+
+                        QueryHandler handler =
+                            (QueryHandler) config.newInstance();
+                        try {
+                            handler.init(fs, context);
+                            return handler;
+                        } catch (IOException e) {
+                            throw new RepositoryException(
+                                    "Unable to initialize query handler: " + handler, e);
+                        }
+                    }
+                };
             }
         }
         return null;
@@ -703,10 +731,11 @@
      * method returns <code>null</code>.
      *
      * @param parent parent of the <code>Journal</code> element
+     * @param home repository home directory
      * @return cluster configuration, or <code>null</code>
      * @throws ConfigurationException if the configuration is broken
      */
-    protected ClusterConfig parseClusterConfig(Element parent)
+    protected ClusterConfig parseClusterConfig(Element parent, File home)
             throws ConfigurationException {
 
         NodeList children = parent.getChildNodes();
@@ -716,17 +745,32 @@
                     && CLUSTER_ELEMENT.equals(child.getNodeName())) {
                 Element element = (Element) child;
 
-                String id = null;
-
+                // Find the cluster node id
+                String id =
+                    System.getProperty(ClusterNode.SYSTEM_PROPERTY_NODE_ID);
                 String value = getAttribute(element, ID_ATTRIBUTE, null);
                 if (value != null) {
                     id = replaceVariables(value);
+                } else if (id == null) {
+                    File file = new File(home, CLUSTER_NODE_ID_FILE);
+                    try {
+                        if (file.exists() && file.canRead()) {
+                            id = FileUtils.readFileToString(file);
+                        } else {
+                            id = UUID.randomUUID().toString();
+                            FileUtils.writeStringToFile(file, id);
+                        }
+                    } catch (IOException e) {
+                        throw new ConfigurationException(
+                                "Failed to access cluster node id: " + file, e);
+                    }
                 }
-                value = getAttribute(element, SYNC_DELAY_ATTRIBUTE, DEFAULT_SYNC_DELAY);
-                long syncDelay = Long.parseLong(replaceVariables(value));
 
-                JournalConfig jc = parseJournalConfig(element);
-                return new ClusterConfig(id, syncDelay, jc);
+                long syncDelay = Long.parseLong(replaceVariables(getAttribute(
+                        element, SYNC_DELAY_ATTRIBUTE, DEFAULT_SYNC_DELAY)));
+
+                JournalFactory jf = getJournalFactory(element, home, id);
+                return new ClusterConfig(id, syncDelay, jf);
             }
         }
         return null;
@@ -745,14 +789,39 @@
      * element.
      *
      * @param cluster parent cluster element
-     * @return journal configuration, or <code>null</code>
-     * @throws ConfigurationException if the configuration is broken
-     */
-    protected JournalConfig parseJournalConfig(Element cluster)
-            throws ConfigurationException {
-
-        return new JournalConfig(
-                parseBeanConfig(cluster, JOURNAL_ELEMENT));
+     * @param home repository home directory
+     * @param id cluster node id
+     * @return journal factory
+     * @throws ConfigurationException if the configuration is broken
+     */
+    protected JournalFactory getJournalFactory(
+            final Element cluster, final File home, final String id)
+            throws ConfigurationException {
+        return new JournalFactory() {
+            public Journal getJournal(NamespaceResolver resolver)
+                    throws RepositoryException {
+                BeanConfig config = parseBeanConfig(cluster, JOURNAL_ELEMENT);
+                Object object = config.newInstance();
+                if (object instanceof Journal) {
+                    Journal journal = (Journal) object;
+                    if (journal instanceof AbstractJournal) {
+                        ((AbstractJournal) journal).setRepositoryHome(home);
+                    }
+                    try {
+                        journal.init(id, resolver);
+                    } catch (JournalException e) {
+                        // TODO: Should JournalException extend RepositoryException?
+                        throw new RepositoryException(
+                                "Journal initialization failed: " + journal, e);
+                    }
+                    return journal;
+                } else {
+                    throw new RepositoryException(
+                            "Invalid Journal implementation class: "
+                            + config.getClassName());
+                }
+            }
+        };
     }
 
     /**

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceConfig.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceConfig.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceConfig.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/config/WorkspaceConfig.java Wed Oct 21 11:38:31 2009
@@ -20,6 +20,9 @@
 
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemFactory;
+import org.apache.jackrabbit.core.query.QueryHandler;
+import org.apache.jackrabbit.core.query.QueryHandlerContext;
+import org.apache.jackrabbit.core.query.QueryHandlerFactory;
 import org.apache.jackrabbit.core.state.ISMLocking;
 import org.apache.jackrabbit.core.state.ISMLockingFactory;
 
@@ -32,7 +35,8 @@
  * the item state manager locking configuration. The search index and the item
  * state manager locking and the security config are optional parts.
  */
-public class WorkspaceConfig implements FileSystemFactory, ISMLockingFactory {
+public class WorkspaceConfig
+        implements FileSystemFactory, ISMLockingFactory, QueryHandlerFactory {
 
     /**
      * Workspace home directory.
@@ -60,9 +64,9 @@
     private PersistenceManagerConfig pmc;
 
     /**
-     * Workspace search index configuration. Can be <code>null</code>.
+     * Query handler factory, or <code>null</code> if search is not configured.
      */
-    private SearchConfig sc;
+    private QueryHandlerFactory qhf;
 
     /**
      * The item state manager locking factory.
@@ -82,20 +86,21 @@
      * @param clustered
      * @param fsf file system factory
      * @param pmc persistence manager configuration
-     * @param sc search index configuration
+     * @param qhf query handler factory, or <code>null</code> if not configured
      * @param ismLockingFactory the item state manager locking factory
      * @param workspaceSecurityConfig the workspace specific security configuration.
      */
     public WorkspaceConfig(String home, String name, boolean clustered,
                            FileSystemFactory fsf, PersistenceManagerConfig pmc,
-                           SearchConfig sc, ISMLockingFactory ismLockingFactory,
+                           QueryHandlerFactory qhf,
+                           ISMLockingFactory ismLockingFactory,
                            WorkspaceSecurityConfig workspaceSecurityConfig) {
         this.home = home;
         this.name = name;
         this.clustered = clustered;
         this.fsf = fsf;
         this.pmc = pmc;
-        this.sc = sc;
+        this.qhf = qhf;
         this.ismLockingFactory = ismLockingFactory;
         this.workspaceSecurityConfig = workspaceSecurityConfig;
     }
@@ -158,13 +163,28 @@
     }
 
     /**
-     * Returns the workspace search index configuration. Returns
-     * <code>null</code> if a search index has not been configured.
+     * Checks whether search configuration is present.
      *
-     * @return search index configuration, or <code>null</code>
+     * @return <code>true</code> if search is configured,
+     *         <code>false</code> otherwise
+     */
+    public boolean isSearchEnabled() {
+        return qhf != null;
+    }
+
+    /**
+     * Returns an initialized query handler, or <code>null</code> if one
+     * was not configured.
+     *
+     * @return initialized query handler, or <code>null</code>
      */
-    public SearchConfig getSearchConfig() {
-        return sc;
+    public QueryHandler getQueryHandler(QueryHandlerContext context)
+            throws RepositoryException {
+        if (qhf != null) {
+            return qhf.getQueryHandler(context);
+        } else {
+            return null;
+        }
     }
     /**
      * @return workspace-specific security settings.

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/GarbageCollector.java Wed Oct 21 11:38:31 2009
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.core.data;
 
+import org.apache.jackrabbit.api.management.DataStoreGarbageCollector;
+import org.apache.jackrabbit.api.management.MarkEventListener;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.id.PropertyId;
 import org.apache.jackrabbit.core.RepositoryImpl;
@@ -32,7 +34,6 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -64,20 +65,25 @@
  * <p>
  * Example code to run the data store garbage collection:
  * <pre>
- * GarbageCollector gc = ((SessionImpl)session).createDataStoreGarbageCollector();
- * gc.scan();
- * gc.stopScan();
- * gc.deleteUnused();
+ * JackrabbitRepositoryFactory jf = (JackrabbitRepositoryFactory) factory;
+ * RepositoryManager m = factory.getRepositoryManager((JackrabbitRepository) rep);
+ * GarbageCollector gc = m.createDataStoreGarbageCollector();
+ * try {
+ *     gc.mark();
+ *     gc.sweep();
+ * } finally {
+ *     gc.close();
+ * }
  * </pre>
  */
-public class GarbageCollector {
+public class GarbageCollector implements DataStoreGarbageCollector {
 
     /** logger instance */
     private static final Logger LOG = LoggerFactory.getLogger(GarbageCollector.class);
 
-    private ScanEventListener callback;
+    private MarkEventListener callback;
 
-    private int sleepBetweenNodes;
+    private long sleepBetweenNodes;
 
     private int testDelay;
 
@@ -90,52 +96,49 @@
     private final IterablePersistenceManager[] pmList;
 
     private final Session[] sessionList;
-    private final SessionListener sessionListener;
+    private SessionListener sessionListener;
 
     private final AtomicBoolean closed = new AtomicBoolean();
 
     private boolean persistenceManagerScan;
 
-    // TODO It should be possible to stop and restart a garbage collection scan.
-
     /**
      * Create a new garbage collector.
      * This method is usually not called by the application, it is called
      * by SessionImpl.createDataStoreGarbageCollector().
      *
-     * @param session the session that created this object
+     * @param rep the repository
+     * @param session the session that created this object (optional)
      * @param list the persistence managers
      * @param sessionList the sessions to access the workspaces
      */
-    public GarbageCollector(SessionImpl session, IterablePersistenceManager[] list, Session[] sessionList) {
-        RepositoryImpl rep = (RepositoryImpl) session.getRepository();
+    public GarbageCollector(RepositoryImpl rep, SessionImpl session, IterablePersistenceManager[] list, Session[] sessionList) {
         store = rep.getDataStore();
         this.pmList = list;
         this.persistenceManagerScan = list != null;
         this.sessionList = sessionList;
 
-        // Auto-close if the main session logs out
-        this.sessionListener = new SessionListener() {
-            public void loggedOut(SessionImpl session) {
-            }
-            public void loggingOut(SessionImpl session) {
-                close();
-            }
-        };
-        session.addListener(sessionListener);
+        if (session != null) {
+            // Auto-close if the main session logs out
+            this.sessionListener = new SessionListener() {
+                public void loggedOut(SessionImpl session) {
+                }
+                public void loggingOut(SessionImpl session) {
+                    close();
+                }
+            };
+            session.addListener(sessionListener);
+        }
     }
 
-    /**
-     * Set the delay between scanning items.
-     * The main scan loop sleeps this many milliseconds after
-     * scanning a node. The default is 0, meaning the scan should run at full speed.
-     *
-     * @param millis the number of milliseconds to sleep
-     */
-    public void setSleepBetweenNodes(int millis) {
+    public void setSleepBetweenNodes(long millis) {
         this.sleepBetweenNodes = millis;
     }
 
+    public long getSleepBetweenNodes() {
+        return sleepBetweenNodes;
+    }
+
     /**
      * When testing the garbage collection, a delay is used instead of simulating concurrent access.
      *
@@ -146,29 +149,24 @@
     }
 
     /**
-     * Set the event listener. If set, the event listener will be called
-     * for each item that is scanned. This mechanism can be used
-     * to display the progress.
-     *
-     * @param callback if set, this is called while scanning
+     * @deprecated use setMarkEventListener().
      */
     public void setScanEventListener(ScanEventListener callback) {
+        setMarkEventListener(callback);
+    }
+
+    public void setMarkEventListener(MarkEventListener callback) {
         this.callback = callback;
     }
 
     /**
-     * Scan the repository. The garbage collector will iterate over all nodes in the repository
-     * and update the last modified date. If all persistence managers implement the
-     * IterablePersistenceManager interface, this mechanism will be used; if not, the garbage
-     * collector will scan the repository using the JCR API starting from the root node.
-     *
-     * @throws RepositoryException
-     * @throws IllegalStateException
-     * @throws IOException
-     * @throws ItemStateException
+     * @deprecated use mark().
      */
-    public void scan() throws RepositoryException,
-            IllegalStateException, IOException, ItemStateException {
+    public void scan() throws RepositoryException {
+        mark();
+    }
+
+    public void mark() throws RepositoryException {
         if (store == null) {
             throw new RepositoryException("No DataStore configured.");
         }
@@ -183,12 +181,15 @@
                 scanNodes(s);
             }
         } else {
-            scanPersistenceManagers();
+            try {
+                scanPersistenceManagers();
+            } catch (ItemStateException e) {
+                throw new RepositoryException(e);
+            }
         }
     }
 
-    private void scanNodes(Session session)
-        throws RepositoryException, IllegalStateException, IOException {
+    private void scanNodes(Session session) throws RepositoryException {
 
         // add a listener to get 'new' nodes
         // actually, new nodes are not the problem, but moved nodes
@@ -199,28 +200,22 @@
         recurse(session.getRootNode(), sleepBetweenNodes);
     }
 
-    /**
-     * Enable or disable using the IterablePersistenceManager interface
-     * to scan the items. This is important for clients that need
-     * the complete Node implementation in the ScanEventListener
-     * callback.
-     *
-     * @param allow true if using the IterablePersistenceManager interface is allowed
-     */
     public void setPersistenceManagerScan(boolean allow) {
         persistenceManagerScan = allow;
     }
 
+    public boolean isPersistenceManagerScan() {
+        return persistenceManagerScan;
+    }
+
     /**
-     * Check if using the IterablePersistenceManager interface is allowed.
-     *
-     * @return true if using IterablePersistenceManager is possible.
+     * @deprecated use isPersistenceManagerScan().
      */
     public boolean getPersistenceManagerScan() {
-        return persistenceManagerScan;
+        return isPersistenceManagerScan();
     }
 
-    private void scanPersistenceManagers() throws ItemStateException, RepositoryException {
+    private void scanPersistenceManagers() throws RepositoryException, ItemStateException {
         for (IterablePersistenceManager pm : pmList) {
             for (NodeId id : pm.getAllNodeIds(null, 0)) {
                 if (callback != null) {
@@ -244,50 +239,39 @@
                     // the node may have been deleted or moved in the meantime
                     // ignore it
                 }
-                if (callback != null) {
-                    callback.afterScanning(null);
-                }
             }
         }
     }
 
     /**
-     * The repository was scanned. This method will stop the observation
-     * listener.
+     * Stop the observation listener if any are installed.
      */
     public void stopScan() throws RepositoryException {
-        checkScanStarted();
-        for (Listener listener : listeners) {
-            try {
-                listener.stop();
-            } catch (Exception e) {
-                throw new RepositoryException(e);
+        if (listeners.size() > 0) {
+            for (Listener listener : listeners) {
+                try {
+                    listener.stop();
+                } catch (Exception e) {
+                    throw new RepositoryException(e);
+                }
             }
+            listeners.clear();
         }
-        listeners.clear();
     }
 
     /**
-     * Delete all unused items in the data store.
-     *
-     * @return the number of deleted items
+     * @deprecated use sweep().
      */
     public int deleteUnused() throws RepositoryException {
-        checkScanStarted();
-        checkScanStopped();
-        return store.deleteAllOlderThan(startScanTimestamp);
+        return sweep();
     }
 
-    private void checkScanStarted() throws RepositoryException {
+    public int sweep() throws RepositoryException {
         if (startScanTimestamp == 0) {
             throw new RepositoryException("scan must be called first");
         }
-    }
-
-    private void checkScanStopped() throws RepositoryException {
-        if (listeners.size() > 0) {
-            throw new RepositoryException("stopScan must be called first");
-        }
+        stopScan();
+        return store.deleteAllOlderThan(startScanTimestamp);
     }
 
     /**
@@ -299,8 +283,7 @@
         return store;
     }
 
-    private void recurse(final Node n, int sleep) throws RepositoryException,
-            IllegalStateException, IOException {
+    private void recurse(final Node n, long sleep) throws RepositoryException {
         if (sleep > 0) {
             try {
                 Thread.sleep(sleep);
@@ -334,9 +317,6 @@
         } catch (InvalidItemStateException e) {
             LOG.debug("Node removed concurrently - ignoring", e);
         }
-        if (callback != null) {
-            callback.afterScanning(n);
-        }
         try {
             for (NodeIterator it = n.getNodes(); it.hasNext();) {
                 recurse(it.nextNode(), sleep);
@@ -382,11 +362,13 @@
          */
     }
 
-    /**
-     * Cleanup resources used internally by this instance.
-     */
     public void close() {
         if (!closed.getAndSet(true)) {
+            try {
+                stopScan();
+            } catch (RepositoryException e) {
+                LOG.warn("An error occured when stopping the event listener", e);
+            }
             for (Session s : sessionList) {
                 s.logout();
             }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/ScanEventListener.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/ScanEventListener.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/ScanEventListener.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/ScanEventListener.java Wed Oct 21 11:38:31 2009
@@ -16,28 +16,11 @@
  */
 package org.apache.jackrabbit.core.data;
 
-import java.util.EventListener;
-
-import javax.jcr.Node;
-import javax.jcr.RepositoryException;
+import org.apache.jackrabbit.api.management.MarkEventListener;
 
 /**
  * The listener interface for receiving garbage collection scan events.
  */
-public interface ScanEventListener extends EventListener {
-
-    /**
-     * This method is called before a node is scanned.
-     */
-    void beforeScanning(Node n) throws RepositoryException;
-
-    /**
-     * This method is called after a node is scanned.
-     */
-    void afterScanning(Node n) throws RepositoryException;
+public interface ScanEventListener extends MarkEventListener {
 
-    /**
-     * This method is called when the garbage collection scan is finished.
-     */
-    void done();
 }

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/data/db/DbDataStore.java Wed Oct 21 11:38:31 2009
@@ -656,7 +656,7 @@
         } catch (IOException e) {
             String msg = "Configuration error: Could not read properties '" + databaseType + ".properties'";
             log.debug(msg);
-            throw new DataStoreException(msg);
+            throw new DataStoreException(msg, e);
         }
         if (driver == null) {
             driver = getProperty(prop, "driver", driver);

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/AbstractRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/AbstractRecord.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/AbstractRecord.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/AbstractRecord.java Wed Oct 21 11:38:31 2009
@@ -25,9 +25,10 @@
 
 import org.apache.commons.collections.BidiMap;
 import org.apache.commons.collections.bidimap.DualHashBidiMap;
+import org.apache.jackrabbit.commons.cnd.CompactNodeTypeDefReader;
+import org.apache.jackrabbit.commons.cnd.ParseException;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.id.PropertyId;
-import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
 import org.apache.jackrabbit.spi.QNodeTypeDefinition;
@@ -37,9 +38,8 @@
 import org.apache.jackrabbit.spi.commons.name.PathFactoryImpl;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceMapping;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.CompactNodeTypeDefReader;
+import org.apache.jackrabbit.spi.commons.nodetype.QDefinitionBuilderFactory;
 import org.apache.jackrabbit.spi.commons.nodetype.compact.CompactNodeTypeDefWriter;
-import org.apache.jackrabbit.spi.commons.nodetype.compact.ParseException;
 
 /**
  * Base implementation for a record.
@@ -143,11 +143,11 @@
     /**
      * {@inheritDoc}
      */
-    public void writeNodeTypeDef(NodeTypeDef ntd) throws JournalException {
+    public void writeNodeTypeDef(QNodeTypeDefinition ntd) throws JournalException {
         try {
             StringWriter sw = new StringWriter();
             CompactNodeTypeDefWriter writer = new CompactNodeTypeDefWriter(sw, nsResolver, resolver);
-            writer.write(ntd.getQNodeTypeDefinition());
+            writer.write(ntd);
             writer.close();
 
             writeString(sw.toString());
@@ -245,16 +245,20 @@
     /**
      * {@inheritDoc}
      */
-    public NodeTypeDef readNodeTypeDef() throws JournalException {
+    public QNodeTypeDefinition readNodeTypeDef() throws JournalException {
         try {
             StringReader sr = new StringReader(readString());
-            CompactNodeTypeDefReader reader = new CompactNodeTypeDefReader(
-                    sr, "(internal)", new NamespaceMapping(nsResolver));
+
+            CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping> reader =
+                new CompactNodeTypeDefReader<QNodeTypeDefinition, NamespaceMapping>(
+                    sr, "(internal)", new NamespaceMapping(nsResolver),
+                    new QDefinitionBuilderFactory());
+
             Collection<QNodeTypeDefinition> ntds = reader.getNodeTypeDefinitions();
             if (ntds.size() != 1) {
                 throw new JournalException("Expected one node type definition: got " + ntds.size());
             }
-            return new NodeTypeDef(ntds.iterator().next());
+            return ntds.iterator().next();
         } catch (ParseException e) {
             String msg = "Parse error while reading node type definition.";
             throw new JournalException(msg, e);

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/Record.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/Record.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/Record.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/journal/Record.java Wed Oct 21 11:38:31 2009
@@ -18,9 +18,9 @@
 
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.id.PropertyId;
-import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.QNodeTypeDefinition;
 
 /**
  * Record interface.
@@ -150,7 +150,7 @@
      * @return node type definition
      * @throws JournalException if an error occurs
      */
-    NodeTypeDef readNodeTypeDef() throws JournalException;
+    QNodeTypeDefinition readNodeTypeDef() throws JournalException;
 
     /**
      * Write a byte to the underlying stream.
@@ -254,7 +254,7 @@
      * @param ntd node type definition
      * @throws JournalException if an error occurs
      */
-    void writeNodeTypeDef(NodeTypeDef ntd) throws JournalException;
+    void writeNodeTypeDef(QNodeTypeDefinition ntd) throws JournalException;
 
     /**
      * Update the changes made to an appended record. This will also update

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/LockManagerImpl.java Wed Oct 21 11:38:31 2009
@@ -20,7 +20,6 @@
 import org.apache.commons.collections.map.LinkedMap;
 import org.apache.commons.io.IOUtils;
 import org.apache.jackrabbit.core.id.ItemId;
-import org.apache.jackrabbit.core.ItemValidator;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.id.PropertyId;
@@ -34,7 +33,6 @@
 import org.apache.jackrabbit.core.fs.FileSystem;
 import org.apache.jackrabbit.core.fs.FileSystemException;
 import org.apache.jackrabbit.core.fs.FileSystemResource;
-import org.apache.jackrabbit.core.nodetype.PropDef;
 import org.apache.jackrabbit.core.observation.EventImpl;
 import org.apache.jackrabbit.core.observation.SynchronousEventListener;
 import org.apache.jackrabbit.core.state.ItemStateException;
@@ -874,7 +872,6 @@
         SessionImpl editingSession = (SessionImpl) node.getSession();
         WorkspaceImpl wsp = (WorkspaceImpl) editingSession.getWorkspace();
         UpdatableItemStateManager stateMgr = wsp.getItemStateManager();
-        ItemValidator helper = new ItemValidator(editingSession.getNodeTypeManager().getNodeTypeRegistry(), wsp.getHierarchyManager(), editingSession);
 
         synchronized (stateMgr) {
             if (stateMgr.inEditMode()) {
@@ -888,9 +885,7 @@
 
                 PropertyState propState;
                 if (!nodeState.hasPropertyName(NameConstants.JCR_LOCKOWNER)) {
-                    PropDef def = helper.findApplicablePropertyDefinition(NameConstants.JCR_LOCKOWNER, PropertyType.STRING, false, nodeState);
                     propState = stateMgr.createNew(NameConstants.JCR_LOCKOWNER, nodeId);
-                    propState.setDefinitionId(def.getId());
                     propState.setType(PropertyType.STRING);
                     propState.setMultiValued(false);
                 } else {
@@ -901,9 +896,7 @@
                 stateMgr.store(nodeState);
 
                 if (!nodeState.hasPropertyName(NameConstants.JCR_LOCKISDEEP)) {
-                    PropDef def = helper.findApplicablePropertyDefinition(NameConstants.JCR_LOCKISDEEP, PropertyType.BOOLEAN, false, nodeState);
                     propState = stateMgr.createNew(NameConstants.JCR_LOCKISDEEP, nodeId);
-                    propState.setDefinitionId(def.getId());
                     propState.setType(PropertyType.BOOLEAN);
                     propState.setMultiValued(false);
                 } else {

Modified: jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java?rev=827966&r1=827965&r2=827966&view=diff
==============================================================================
--- jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java (original)
+++ jackrabbit/sandbox/JCR-1456/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/lock/XAEnvironment.java Wed Oct 21 11:38:31 2009
@@ -19,6 +19,7 @@
 import org.apache.jackrabbit.core.TransactionException;
 import org.apache.jackrabbit.core.NodeImpl;
 import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.XAWorkspace;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -472,7 +473,11 @@
          */
         public void update() throws LockException, RepositoryException {
             if (isUnlock) {
-                lockMgr.internalUnlock(node);
+                // Only if we have a valid ItemState try to unlock
+                // JCR-2332
+                if (((XAWorkspace)((SessionImpl)node.getSession()).getWorkspace()).getItemStateManager().hasItemState(node.getId())) {
+                    lockMgr.internalUnlock(node);
+                }
             } else {
                 LockInfo internalLock = lockMgr.internalLock(
                         node, isDeep(), isSessionScoped(),
@@ -480,6 +485,8 @@
                 LockInfo xaEnvLock = getLockInfo(node);
                 // Check if the lockToken has been removed in the transaction ...
                 if (xaEnvLock != null && xaEnvLock.getLockHolder() == null) {
+                    //Remove lockToken from SessionLockManager
+                    getSessionLockManager(internalLock.getLockHolder()).lockTokenRemoved(internalLock.getLockToken());
                     internalLock.setLockHolder(null);
                 }
             }



Mime
View raw message