You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by rd...@apache.org on 2008/11/06 23:39:59 UTC

svn commit: r711996 [1/3] - in /james/server/trunk: ./ build-tools/ jcr-backend-function/ jcr-backend-function/src/main/java/org/apache/james/jcr/ jcr-backend-function/src/test/java/org/ jcr-backend-function/src/test/java/org/apache/ jcr-backend-functi...

Author: rdonkin
Date: Thu Nov  6 14:39:45 2008
New Revision: 711996

URL: http://svn.apache.org/viewvc?rev=711996&view=rev
Log:
Basic implementation of User Repository using Jackrabbit. Decided that my JCR-foo is not sufficient to code without integration testing so I've added a working Repository for testing together with H2 for in-memory testing.

Added:
    james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/AbstractJCRRepository.java
    james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRUser.java
    james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRUsersRepository.java
    james/server/trunk/jcr-backend-function/src/test/java/org/
    james/server/trunk/jcr-backend-function/src/test/java/org/apache/
    james/server/trunk/jcr-backend-function/src/test/java/org/apache/james/
    james/server/trunk/jcr-backend-function/src/test/java/org/apache/james/jcr/
    james/server/trunk/jcr-backend-function/src/test/java/org/apache/james/jcr/JcrUserRepositoryTest.java
    james/server/trunk/stage/com.h2database/
    james/server/trunk/stage/com.h2database/jars/
    james/server/trunk/stage/com.h2database/jars/h2.jar   (with props)
    james/server/trunk/stage/com.h2database/jars/license.html
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-api-1.4.LICENSE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-api-1.4.NOTICE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-api-1.4.jar   (with props)
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-core-1.4.6.LICENSE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-core-1.4.6.NOTICE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-core-1.4.6.jar   (with props)
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-jcr-commons-1.4.2.LICENSE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-jcr-commons-1.4.2.NOTICE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-jcr-commons-1.4.2.jar   (with props)
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-jcr-rmi-1.4.1.LICENSE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-jcr-rmi-1.4.1.NOTICE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-jcr-rmi-1.4.1.jar   (with props)
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-spi-1.4.LICENSE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-spi-1.4.NOTICE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-spi-1.4.jar   (with props)
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-spi-commons-1.4.LICENSE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-spi-commons-1.4.NOTICE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-spi-commons-1.4.jar   (with props)
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-text-extractors-1.4.LICENSE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-text-extractors-1.4.NOTICE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-text-extractors-1.4.jar   (with props)
    james/server/trunk/stage/org.apache.lucene/
    james/server/trunk/stage/org.apache.lucene/jars/
    james/server/trunk/stage/org.apache.lucene/jars/lucene-core-2.2.0.LICENSE
    james/server/trunk/stage/org.apache.lucene/jars/lucene-core-2.2.0.NOTICE
    james/server/trunk/stage/org.apache.lucene/jars/lucene-core-2.2.0.jar   (with props)
    james/server/trunk/stage/org.slf4j/
    james/server/trunk/stage/org.slf4j/jars/
    james/server/trunk/stage/org.slf4j/jars/slf4j-api-1.3.0.LICENSE
    james/server/trunk/stage/org.slf4j/jars/slf4j-api-1.3.0.jar   (with props)
    james/server/trunk/stage/org.slf4j/jars/slf4j-log4j12-1.3.0.LICENSE   (with props)
    james/server/trunk/stage/org.slf4j/jars/slf4j-log4j12-1.3.0.jar   (with props)
Removed:
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-api-1.3.LICENSE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-api-1.3.NOTICE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-api-1.3.jar
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-jcr-commons-1.3.LICENSE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-jcr-commons-1.3.NOTICE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-jcr-commons-1.3.jar
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-jcr-rmi-1.3.LICENSE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-jcr-rmi-1.3.NOTICE
    james/server/trunk/stage/org.apache.jackrabbit/jars/jackrabbit-jcr-rmi-1.3.jar
Modified:
    james/server/trunk/LICENSE.txt
    james/server/trunk/build-tools/common-build.xml
    james/server/trunk/include.properties
    james/server/trunk/jcr-backend-function/pom.xml
    james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRMailRepository.java

Modified: james/server/trunk/LICENSE.txt
URL: http://svn.apache.org/viewvc/james/server/trunk/LICENSE.txt?rev=711996&r1=711995&r2=711996&view=diff
==============================================================================
--- james/server/trunk/LICENSE.txt (original)
+++ james/server/trunk/LICENSE.txt Thu Nov  6 14:39:45 2008
@@ -229,4 +229,7 @@
      
    XStream, BSD License
      (see stage/com.thoughtworks.xstream/jars/xstream.LICENSE)
-     
\ No newline at end of file
+
+   H2, Dual H2 License (modified MPL1.1) or EPL1.0
+     (see stage/com/h2database/jars/h2.LICENSE.html) 
+     

Modified: james/server/trunk/build-tools/common-build.xml
URL: http://svn.apache.org/viewvc/james/server/trunk/build-tools/common-build.xml?rev=711996&r1=711995&r2=711996&view=diff
==============================================================================
--- james/server/trunk/build-tools/common-build.xml (original)
+++ james/server/trunk/build-tools/common-build.xml Thu Nov  6 14:39:45 2008
@@ -236,6 +236,19 @@
                     <include name='${path.lib.james}/apache-james-imap*.jar'/>
                 </fileset>   
             </path>   
+            <path id='classpath.jackrabbit.repo'>  
+                <fileset dir="${lib.dir}">   
+                    <include name="${h2.jar}"/>
+                    <include name="${jackrabbit-text-extractors.jar}"/>   
+                    <include name="${jackrabbit-jcr-commons.jar}"/>
+                    <include name="${jackrabbit-spi.jar}"/>
+                    <include name="${jackrabbit-core.jar}"/>
+                    <include name="${jackrabbit-spi-commons.jar}"/>   
+                    <include name="${lucene.jar}"/>
+                    <include name="${slf4j-api.jar}"/>
+                    <include name="${slf4j-log4j.jar}"/>   
+                </fileset>   
+            </path>   
             <path id='classpath.base.test'>  
                 <path refid='classpath.base'/>
                 <pathelement location="${dir.build.bin}"/>
@@ -250,7 +263,8 @@
                     <include name="${cornerstone-sockets-impl.jar}"/>
                     <include name="${excalibur-thread-impl.jar}"/>
                     <include name="${derby.jar}"/>    
-                </fileset>   
+                </fileset>  
+                <path refid='classpath.jackrabbit.repo'/>   
             </path>   
     
             <path 

Modified: james/server/trunk/include.properties
URL: http://svn.apache.org/viewvc/james/server/trunk/include.properties?rev=711996&r1=711995&r2=711996&view=diff
==============================================================================
--- james/server/trunk/include.properties (original)
+++ james/server/trunk/include.properties Thu Nov  6 14:39:45 2008
@@ -100,6 +100,9 @@
 path.lib.spring=org.springframework/jars
 path.lib.avalon-phoenix=avalon-phoenix/jars
 path.lib.log4j=log4j/jars
+path.lib.h2=com.h2database/jars
+path.lib.lucene=org.apache.lucene/jars
+path.lib.slf4j=org.slf4j/jars
 
 # ----- Spring -----
 jarname.spring.jar=spring-2.0.jar
@@ -301,15 +304,27 @@
 # --------------------------------------------------
 #                Apache Jackrabbit (JCR)
 # --------------------------------------------------
-jarname.jackrabbit-api=jackrabbit-api-1.3.jar
+jarname.jackrabbit-api=jackrabbit-api-1.4.jar
 jackrabbit-api.jar=${path.lib.jackrabbit}/${jarname.jackrabbit-api}
-jarname.jackrabbit-commons=jackrabbit-jcr-commons-1.3.jar
+jarname.jackrabbit-commons=jackrabbit-jcr-commons-1.4.2.jar
 jackrabbit-commons.jar=${path.lib.jackrabbit}/${jarname.jackrabbit-commons}
-jarname.jackrabbit-rmi=jackrabbit-jcr-rmi-1.3.jar
+jarname.jackrabbit-rmi=jackrabbit-jcr-rmi-1.4.1.jar
 jackrabbit-rmi.jar=${path.lib.jackrabbit}/${jarname.jackrabbit-rmi}
 jarname.jcr=jcr-1.0.jar
 jcr.jar=${path.lib.jcr}/${jarname.jcr}
 
+# ----- Jackrabbit Embedded Repository ----
+jackrabbit-text-extractors.jar=${path.lib.jackrabbit}/jackrabbit-text-extractors-1.4.jar
+jackrabbit-jcr-commons.jar=${path.lib.jackrabbit}/jackrabbit-jcr-commons-1.4.2.jar
+jackrabbit-spi.jar=${path.lib.jackrabbit}/jackrabbit-spi-1.4.jar
+jackrabbit-core.jar=${path.lib.jackrabbit}/jackrabbit-core-1.4.6.jar
+jackrabbit-spi-commons.jar=${path.lib.jackrabbit}/jackrabbit-spi-commons-1.4.jar
+# Memory only database
+h2.jar=${path.lib.h2}/h2.jar
+lucene.jar=${path.lib.lucene}/lucene-core-2.2.0.jar
+slf4j-api.jar=${path.lib.slf4j}/slf4j-api-1.3.0.jar
+slf4j-log4j.jar=${path.lib.slf4j}/slf4j-log4j12-1.3.0.jar
+
 # --------------------------------------------------
 #                TEST LIBRARIES
 # --------------------------------------------------

Modified: james/server/trunk/jcr-backend-function/pom.xml
URL: http://svn.apache.org/viewvc/james/server/trunk/jcr-backend-function/pom.xml?rev=711996&r1=711995&r2=711996&view=diff
==============================================================================
--- james/server/trunk/jcr-backend-function/pom.xml (original)
+++ james/server/trunk/jcr-backend-function/pom.xml Thu Nov  6 14:39:45 2008
@@ -56,7 +56,7 @@
     <dependency>
       <groupId>org.apache.jackrabbit</groupId>
       <artifactId>jackrabbit-jcr-rmi</artifactId>
-      <version>1.3</version>
+      <version>1.4.1</version>
       <exclusions>
       	<exclusion>
       		<groupId>xerces</groupId>
@@ -67,8 +67,20 @@
     <dependency>
       <groupId>org.apache.jackrabbit</groupId>
       <artifactId>jackrabbit-jcr-commons</artifactId>
-      <version>1.3</version>
+      <version>1.4.2</version>
     </dependency>
+	<dependency>
+      <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>jackrabbit-core</artifactId>
+      <version>1.4.6</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+	    <groupId>com.h2database</groupId>
+    	<artifactId>h2</artifactId>
+   	 	<version>1.1.102</version>
+   	 	<scope>test</scope>
+	</dependency>
   </dependencies>
 
 </project>

Added: james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/AbstractJCRRepository.java
URL: http://svn.apache.org/viewvc/james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/AbstractJCRRepository.java?rev=711996&view=auto
==============================================================================
--- james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/AbstractJCRRepository.java (added)
+++ james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/AbstractJCRRepository.java Thu Nov  6 14:39:45 2008
@@ -0,0 +1,224 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jcr;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.NodeIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.query.InvalidQueryException;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.jackrabbit.util.ISO9075;
+import org.apache.jackrabbit.util.Text;
+
+/**
+ * Framework for JCR repositories used by James.
+ */
+class AbstractJCRRepository {
+    
+    protected Log logger;
+
+    /**
+     * JCR content repository used as the mail repository.
+     * Must be set before the any mail operations are performed.
+     */
+    protected Repository repository;
+    
+    /**
+     * Login credentials for accessing the repository.
+     * Set to <code>null</code> (the default) to use default credentials.
+     */
+    protected Credentials credentials;
+    
+    /**
+     * Name of the workspace used as the mail repository.
+     * Set to <code>null</code> (the default) to use the default workspace.
+     */
+    protected String workspace;
+    
+    /**
+     * Path (relative to root) of the mail repository within the workspace.
+     */
+    protected String path = "james";
+
+    /**
+     * For setter injection.
+     */
+    public AbstractJCRRepository(Log logger) {
+        super();
+        this.logger = logger;
+    }
+    
+    /**
+     * Minimal constructor for injection.
+     * @param repository not null
+     */
+    public AbstractJCRRepository(Repository repository, Log logger) {
+        super();
+        this.repository = repository;
+        credentials = new SimpleCredentials("userid", "".toCharArray());
+        this.logger = logger;
+    }
+
+    /**
+     * Maximal constructor for injection.
+     * @param repository not null
+     * @param credentials login credentials for accessing the repository
+     * or null to use default credentials
+     * @param workspace name of the workspace used as the mail repository.
+     * or null to use default workspace
+     * @param path path (relative to root) of the user node within the workspace,
+     * or null to use default.
+     */
+    public AbstractJCRRepository(Repository repository, Credentials credentials, String workspace, String path, 
+            Log logger) {
+        super();
+        this.repository = repository;
+        this.credentials = credentials;
+        this.workspace = workspace;
+        this.path = path;
+        this.logger = logger;
+    }
+
+    
+    /**
+     * Gets the current logger.
+     * @return the logger, not null
+     */
+    public final Log getLogger() {
+        return logger;
+    }
+
+    /**
+     * Sets the current logger.
+     * @param logger the logger to set, not null
+     */
+    public final void setLogger(Log logger) {
+        this.logger = logger;
+    }
+
+    /**
+     * Retuns the JCR content repository used as the mail repository.
+     *
+     * @return JCR content repository
+     */
+    public Repository getRepository() {
+        return repository;
+    }
+
+    /**
+     * Sets the JCR content repository to be used as the mail repository.
+     *
+     * @param repository JCR content repository
+     */
+    public void setRepository(Repository repository) {
+        this.repository = repository;
+    }
+
+    /**
+     * Returns the login credentials for accessing the repository.
+     *
+     * @return login credentials,
+     *         or <code>null</code> if using the default credentials
+     */
+    public Credentials getCredentials() {
+        return credentials;
+    }
+
+    /**
+     * Sets the login credentials for accessing the repository.
+     *
+     * @param credentials login credentials,
+     *                    or <code>null</code> to use the default credentials
+     */
+    public void setCredentials(Credentials credentials) {
+        this.credentials = credentials;
+    }
+
+    /**
+     * Returns the name of the workspace used as the mail repository.
+     *
+     * @return workspace name,
+     *         or <code>null</code> if using the default workspace
+     */
+    public String getWorkspace() {
+        return workspace;
+    }
+
+    /**
+     * Sets the name of the workspace used as the mail repository.
+     *
+     * @param workspace workspace name,
+     *                  or <code>null</code> to use the default workspace
+     */
+    public void setWorkspace(String workspace) {
+        this.workspace = workspace;
+    }
+
+    /**
+     * Returns the path of the mail repository within the workspace.
+     *
+     * @return repository path
+     */
+    public String getPath() {
+        return path;
+    }
+
+    /**
+     * Sets the path of the mail repository within the workspace.
+     *
+     * @param path repository path
+     */
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    /**
+     * Logs into a new session.
+     * @return new session, not null
+     * @throws LoginException when login fails
+     * @throws NoSuchWorkspaceException when workspace does not exist
+     * @throws RepositoryException when access fails
+     */
+    protected Session login() throws LoginException, NoSuchWorkspaceException, RepositoryException {
+        Session session = repository.login(credentials, workspace);
+        return session;
+    }
+
+    protected String toSafeName(String key) {
+        String name = ISO9075.encode(Text.escapeIllegalJcrChars(key));
+        return name;
+    }
+
+    protected NodeIterator query(Session session, final String xpath) throws RepositoryException, InvalidQueryException {
+        QueryManager manager = session.getWorkspace().getQueryManager();
+        Query query = manager.createQuery(xpath, Query.XPATH);
+        NodeIterator iterator = query.execute().getNodes();
+        return iterator;
+    }
+
+}
\ No newline at end of file

Modified: james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRMailRepository.java
URL: http://svn.apache.org/viewvc/james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRMailRepository.java?rev=711996&r1=711995&r2=711996&view=diff
==============================================================================
--- james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRMailRepository.java (original)
+++ james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRMailRepository.java Thu Nov  6 14:39:45 2008
@@ -32,7 +32,6 @@
 import java.util.Date;
 import java.util.Iterator;
 import java.util.Properties;
-import java.util.logging.Logger;
 
 import javax.jcr.Credentials;
 import javax.jcr.Node;
@@ -50,6 +49,8 @@
 import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.jackrabbit.util.ISO9075;
 import org.apache.jackrabbit.util.Text;
 import org.apache.james.core.MailImpl;
@@ -60,119 +61,48 @@
 /**
  * Mail repository that is backed by a JCR content repository.
  */
-public class JCRMailRepository implements MailRepository {
+public class JCRMailRepository extends AbstractJCRRepository implements MailRepository {
 
     /**
      * Logger instance.
      */
-    private static final Logger logger =
-        Logger.getLogger(JCRMailRepository.class.getName());
+    private static final Log LOGGER = LogFactory.getLog(JCRMailRepository.class.getName());
 
     /**
-     * JCR content repository used as the mail repository.
-     * Must be set before the any mail operations are performed.
+     * For setter injection.
      */
-    private Repository repository;
-
-    /**
-     * Login credentials for accessing the repository.
-     * Set to <code>null</code> (the default) to use default credentials.
-     */
-    private Credentials credentials;
-
-    /**
-     * Name of the workspace used as the mail repository.
-     * Set to <code>null</code> (the default) to use the default workspace.
-     */
-    private String workspace;
-
-    /**
-     * Path (relative to root) of the mail repository within the workspace.
-     */
-    private String path = "james:repository";
-
-    /**
-     * Retuns the JCR content repository used as the mail repository.
-     *
-     * @return JCR content repository
-     */
-    public Repository getRepository() {
-        return repository;
+    public JCRMailRepository() {
+        super(LOGGER);
+        this.path = "james/mail";
     }
-
-    /**
-     * Sets the JCR content repository to be used as the mail repository.
-     *
-     * @param repository JCR content repository
-     */
-    public void setRepository(Repository repository) {
-        this.repository = repository;
-    }
-
-    /**
-     * Returns the login credentials for accessing the repository.
-     *
-     * @return login credentials,
-     *         or <code>null</code> if using the default credentials
-     */
-    public Credentials getCredentials() {
-        return credentials;
-    }
-
-    /**
-     * Sets the login credentials for accessing the repository.
-     *
-     * @param credentials login credentials,
-     *                    or <code>null</code> to use the default credentials
-     */
-    public void setCredentials(Credentials credentials) {
-        this.credentials = credentials;
-    }
-
-    /**
-     * Returns the name of the workspace used as the mail repository.
-     *
-     * @return workspace name,
-     *         or <code>null</code> if using the default workspace
-     */
-    public String getWorkspace() {
-        return workspace;
-    }
-
+    
     /**
-     * Sets the name of the workspace used as the mail repository.
-     *
-     * @param workspace workspace name,
-     *                  or <code>null</code> to use the default workspace
+     * Maximal constructor for injection.
+     * @param repository not null
+     * @param credentials login credentials for accessing the repository
+     * or null to use default credentials
+     * @param workspace name of the workspace used as the mail repository.
+     * or null to use default workspace
+     * @param path path (relative to root) of the user node within the workspace,
+     * or null to use default.
      */
-    public void setWorkspace(String workspace) {
-        this.workspace = workspace;
+    public JCRMailRepository(Repository repository, Credentials credentials, String workspace, String path, Log logger) {
+        super(repository, credentials, workspace, path, logger);
     }
 
     /**
-     * Returns the path of the mail repository within the workspace.
-     *
-     * @return repository path
+     * Minimal constructor for injection.
+     * @param repository not null
      */
-    public String getPath() {
-        return path;
+    public JCRMailRepository(Repository repository, Log logger) {
+        super(repository, logger);
     }
 
-    /**
-     * Sets the path of the mail repository within the workspace.
-     *
-     * @param path repository path
-     */
-    public void setPath(String path) {
-        this.path = path;
-    }
 
-    //------------------------------------------------------< MailRepository >
 
     public Iterator list() throws MessagingException {
-        logger.entering(getClass().getName(), "list()");
         try {
-            Session session = repository.login(credentials, workspace);
+            Session session = login();
             try {
                 Collection keys = new ArrayList();
                 QueryManager manager = session.getWorkspace().getQueryManager();
@@ -190,17 +120,14 @@
             }
         } catch (RepositoryException e) {
             throw new MessagingException("Unable to list messages", e);
-        } finally {
-            logger.exiting(getClass().getName(), "list()");
         }
     }
 
     public Mail retrieve(String key) throws MessagingException {
-        logger.entering(getClass().getName(), "retrieve(" + key + ")");
         try {
-            Session session = repository.login(credentials, workspace);
+            Session session = login();
             try {
-                String name = ISO9075.encode(Text.escapeIllegalJcrChars(key));
+                String name = toSafeName(key);
                 QueryManager manager = session.getWorkspace().getQueryManager();
                 Query query = manager.createQuery(
                         "/jcr:root/" + path + "//element(" + name + ",james:mail)",
@@ -220,22 +147,16 @@
         } catch (RepositoryException e) {
             throw new MessagingException(
                     "Unable to retrieve message: " + key, e);
-        } finally {
-            logger.exiting(getClass().getName(), "retrieve(" + key + ")");
-        }
+        } 
     }
 
     public void store(Mail mail) throws MessagingException {
-        logger.entering(getClass().getName(), "store(" + mail.getName() + ")");
         try {
-            Session session = repository.login(credentials, workspace);
+            Session session = login();
             try {
                 String name = Text.escapeIllegalJcrChars(mail.getName());
-                QueryManager manager = session.getWorkspace().getQueryManager();
-                Query query = manager.createQuery(
-                        "/jcr:root/" + path + "//element(" + name + ",james:mail)",
-                        Query.XPATH);
-                NodeIterator iterator = query.execute().getNodes();
+                final String xpath = "/jcr:root/" + path + "//element(" + name + ",james:mail)";
+                NodeIterator iterator = query(session, xpath);
                 if (iterator.hasNext()) {
                     while (iterator.hasNext()) {
                         setMail(iterator.nextNode(), mail);
@@ -258,15 +179,12 @@
         } catch (RepositoryException e) {
             throw new MessagingException(
                     "Unable to store message: " + mail.getName(), e);
-        } finally {
-            logger.exiting(getClass().getName(), "store(" + mail.getName() + ")");
         }
     }
 
     public void remove(String key) throws MessagingException {
-        logger.entering(getClass().getName(), "remove(" + key + ")");
         try {
-            Session session = repository.login(credentials, workspace);
+            Session session = login();
             try {
                 String name = ISO9075.encode(Text.escapeIllegalJcrChars(key));
                 QueryManager manager = session.getWorkspace().getQueryManager();
@@ -281,15 +199,13 @@
                     session.save();
                     logger.info("Mail " + key + " removed from repository");
                 } else {
-                    logger.warning("Mail " + key + " not found");
+                    logger.warn("Mail " + key + " not found");
                 }
             } finally {
                 session.logout();
             }
         } catch (RepositoryException e) {
             throw new MessagingException("Unable to remove message: " + key, e);
-        } finally {
-            logger.exiting(getClass().getName(), "remove(" + key + ")");
         }
     }
 
@@ -298,9 +214,8 @@
     }
 
     public void remove(Collection mails) throws MessagingException {
-        logger.entering(getClass().getName(), "remove(collection)");
         try {
-            Session session = repository.login(credentials, workspace);
+            Session session = login();
             try {
                 QueryManager manager = session.getWorkspace().getQueryManager();
                 Iterator iterator = mails.iterator();
@@ -317,7 +232,7 @@
                             nodes.nextNode().remove();
                         }
                     } catch (PathNotFoundException e) {
-                        logger.warning("Mail " + mail.getName() + " not found");
+                        logger.warn("Mail " + mail.getName() + " not found");
                     }
                 }
                 session.save();
@@ -327,8 +242,6 @@
             }
         } catch (RepositoryException e) {
             throw new MessagingException("Unable to remove messages", e);
-        } finally {
-            logger.exiting(getClass().getName(), "remove(collection)");
         }
     }
 

Added: james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRUser.java
URL: http://svn.apache.org/viewvc/james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRUser.java?rev=711996&view=auto
==============================================================================
--- james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRUser.java (added)
+++ james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRUser.java Thu Nov  6 14:39:45 2008
@@ -0,0 +1,91 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jcr;
+
+import org.apache.jackrabbit.util.Text;
+import org.apache.james.api.user.User;
+
+/**
+ * User backed by JCR data. 
+ * Differs from standard James by improved hash.
+ * TODO: think about improving DefaultUser.
+ */
+class JCRUser implements User {
+
+    /** 
+     * Static salt for hashing password.
+     * Modifying this value will render all passwords unrecognizable.
+     */
+    public static final String SALT = "JCRUsersRepository";
+    
+    /**
+     * Hashes salted password.
+     * @param username not null
+     * @param password not null
+     * @return not null
+     */
+    public static String hashPassword(String username, String password) {
+        // Combine dynamic and static salt
+        final String hashedSaltedPassword = Text.md5(Text.md5(username + password) + SALT);
+        return hashedSaltedPassword;
+    }
+    
+    private final String userName;
+    private String hashedSaltedPassword;
+    
+    public JCRUser(final String userName, String hashedSaltedPassword) {
+        super();
+        this.userName = userName;
+        this.hashedSaltedPassword = hashedSaltedPassword;
+    }
+
+    public String getUserName() {
+        return userName;
+    }
+    
+    /**
+     * Gets salted, hashed password.
+     * @return the hashedSaltedPassword
+     */
+    public final String getHashedSaltedPassword() {
+        return hashedSaltedPassword;
+    }
+
+    public boolean setPassword(String newPass) {
+        final boolean result;
+        if (newPass == null) {
+            result = false;
+        } else {
+            hashedSaltedPassword = hashPassword(userName, newPass);
+            result = true;
+        }
+        return result;
+    }
+
+    public boolean verifyPassword(String pass) {
+        final boolean result;
+        if (pass == null) {
+            result = false;
+        } else {
+            result = hashedSaltedPassword == hashPassword(userName, pass);
+        }
+        return result;
+    }
+}

Added: james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRUsersRepository.java
URL: http://svn.apache.org/viewvc/james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRUsersRepository.java?rev=711996&view=auto
==============================================================================
--- james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRUsersRepository.java (added)
+++ james/server/trunk/jcr-backend-function/src/main/java/org/apache/james/jcr/JCRUsersRepository.java Thu Nov  6 14:39:45 2008
@@ -0,0 +1,462 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jcr;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.james.api.user.User;
+import org.apache.james.api.user.UsersRepository;
+
+
+public class JCRUsersRepository extends AbstractJCRRepository implements UsersRepository {
+    
+    //TODO: Add namespacing
+    private static final String PASSWD_PROPERTY = "passwd";
+
+    private static final String USERNAME_PROPERTY = "username";
+
+    private static final Log LOGGER = LogFactory.getLog(JCRMailRepository.class);
+    
+    /**
+     * For setter injection.
+     */    
+    public JCRUsersRepository() {
+        super(LOGGER);
+        this.path = "users";
+    }
+
+    /**
+     * Maximal constructor for injection.
+     * @param repository not null
+     * @param credentials login credentials for accessing the repository
+     * or null to use default credentials
+     * @param workspace name of the workspace used as the mail repository.
+     * or null to use default workspace
+     * @param path path (relative to root) of the user node within the workspace,
+     * or null to use default.
+     */
+    public JCRUsersRepository(Repository repository, Credentials credentials, String workspace, String path, Log logger) {
+        super(repository, credentials, workspace, path, logger);
+    }
+    
+    /**
+     * Minimal constructor for injection.
+     * @param repository not null
+     */
+    public JCRUsersRepository(Repository repository) {
+        super(repository, LOGGER);
+        this.path = "users";
+    }
+
+    /**
+     * Adds a user to the repository with the specified User object.
+     *
+     * @param user the user to be added
+     *
+     * @return true if succesful, false otherwise
+     * @since James 1.2.2
+     * 
+     * @deprecated James 2.4 user should be added using username/password
+     * because specific implementations of UsersRepository will support specific 
+     * implementations of users object.
+     */
+    public boolean addUser(User user) {
+        throw new UnsupportedOperationException("Unsupported by JCR");
+    }
+
+    /**
+     * Adds a user to the repository with the specified attributes.  In current
+     * implementations, the Object attributes is generally a String password.
+     *
+     * @param name the name of the user to be added
+     * @param attributes see decription
+     * 
+     * @deprecated James 2.4 user is always added using username/password and
+     * eventually modified by retrieving it later.
+     */
+    public void addUser(String name, Object attributes) {
+        if (attributes instanceof String) {
+            addUser(name, (String) attributes);
+        } else {
+            throw new IllegalArgumentException("Expected password string");
+        }
+    }
+    
+    /**
+     * Adds a user to the repository with the specified password
+     * 
+     * @param username the username of the user to be added
+     * @param password the password of the user to add
+     * @return true if succesful, false otherwise
+     * 
+     * @since James 2.3.0
+     */
+    public boolean addUser(String username, String password) {
+
+        try {
+            final Session session = login();
+            try {
+                final String name = toSafeName(username);
+                final String path = this.path + "/" + name;
+                final Node rootNode = session.getRootNode();
+                try {
+                    rootNode.getNode(path);
+                    logger.info("User already exists");
+                    return false;
+                } catch (PathNotFoundException e) {
+                    // user does not exist
+                }
+                Node parent;
+                try {
+                    parent = rootNode.getNode(this.path);
+                } catch (PathNotFoundException e) {
+                    // TODO: Need to consider whether should insist that parent
+                    // TODO: path exists.
+                    parent = rootNode.addNode(this.path);
+                }
+                
+                Node node = parent.addNode(name);
+                node.setProperty(USERNAME_PROPERTY, username);
+                final String hashedPassword;
+                if (password == null)
+                {
+                    // Support easy password reset
+                    hashedPassword = "";
+                }
+                else
+                {
+                    hashedPassword = JCRUser.hashPassword(username, password);
+                }
+                node.setProperty(PASSWD_PROPERTY, hashedPassword);
+                session.save();
+                return true;
+            } finally {
+                session.logout();
+            }
+            
+        } catch (RepositoryException e) {
+            if (logger.isInfoEnabled()) {
+                logger.info("Failed to add user: " + username, e);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Get the user object with the specified user name.  Return null if no
+     * such user.
+     *
+     * @param name the name of the user to retrieve
+     * @return the user being retrieved, null if the user doesn't exist
+     *
+     * @since James 1.2.2
+     */
+    public User getUserByName(String username) {
+        User user;
+        try {
+            final Session session = login();
+            try {
+                final String name = toSafeName(username);
+                final String path = this.path + "/" + name;
+                final Node rootNode = session.getRootNode();
+                
+                try {
+                    final Node node = rootNode.getNode(path);
+                    user = new JCRUser(node.getProperty(USERNAME_PROPERTY).getString(), 
+                            node.getProperty(PASSWD_PROPERTY).getString());
+                } catch (PathNotFoundException e) {
+                    // user not found
+                    user = null;
+                }
+            } finally {
+                session.logout();
+            }
+            
+        } catch (RepositoryException e) {
+            if (logger.isInfoEnabled()) {
+                logger.info("Failed to add user: " + username, e);
+            }
+            user = null;
+        }
+        return user;
+    }
+
+    /**
+     * Get the user object with the specified user name. Match user naems on
+     * a case insensitive basis.  Return null if no such user.
+     *
+     * @param name the name of the user to retrieve
+     * @return the user being retrieved, null if the user doesn't exist
+     *
+     * @since James 1.2.2
+     * @deprecated James 2.4 now caseSensitive is a property of the repository
+     * implementations and the getUserByName will search according to this property.
+     */
+    public User getUserByNameCaseInsensitive(String name) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns the user name of the user matching name on an equalsIgnoreCase
+     * basis. Returns null if no match.
+     *
+     * @param name the name to case-correct
+     * @return the case-correct name of the user, null if the user doesn't exist
+     */
+    public String getRealName(String name) {
+        return null;
+    }
+
+    /**
+     * Update the repository with the specified user object. A user object
+     * with this username must already exist.
+     *
+     * @return true if successful.
+     */
+    public boolean updateUser(final User user) {
+        if (user != null && user instanceof JCRUser)
+        {
+            final JCRUser jcrUser = (JCRUser) user;
+            final String userName = jcrUser.getUserName();
+            try {
+                final Session session = login();
+                try {
+                    final String name = toSafeName(userName);
+                    final String path = this.path + "/" + name;
+                    final Node rootNode = session.getRootNode();
+                    
+                    try {
+                        final String hashedSaltedPassword = jcrUser.getHashedSaltedPassword();
+                        rootNode.getNode(path).setProperty(PASSWD_PROPERTY, hashedSaltedPassword);
+                        session.save();
+                        return true;
+                    } catch (PathNotFoundException e) {
+                        // user not found
+                        logger.debug("User not found");
+                    }
+                } finally {
+                    session.logout();
+                }
+                
+            } catch (RepositoryException e) {
+                if (logger.isInfoEnabled()) {
+                    logger.info("Failed to add user: " + userName, e);
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Removes a user from the repository
+     *
+     * @param name the user to remove from the repository
+     */
+    public void removeUser(String username) {
+        try {
+            final Session session = login();
+            try {
+                final String name = toSafeName(username);
+                final String path = this.path + "/" + name;
+                try {
+                    session.getRootNode().getNode(path).remove();
+                    session.save();
+                } catch (PathNotFoundException e) {
+                    // user not found
+                }
+            } finally {
+                session.logout();
+            }
+            
+        } catch (RepositoryException e) {
+            if (logger.isInfoEnabled()) {
+                logger.info("Failed to add user: " + username, e);
+            }
+        }
+    }
+
+    /**
+     * Returns whether or not this user is in the repository
+     *
+     * @param name the name to check in the repository
+     * @return whether the user is in the repository
+     */
+    public boolean contains(String name) {
+        try {
+            final Session session = login();
+            try {
+                final Node rootNode = session.getRootNode();
+                final String path = this.path + "/" + toSafeName(name);                
+                rootNode.getNode(path);
+                return true;
+            } finally {
+                session.logout();
+            }
+            
+        } catch (RepositoryException e) {
+            if (logger.isDebugEnabled()) {
+                logger.debug("User not found: " + name, e);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Returns whether or not this user is in the repository. Names are
+     * matched on a case insensitive basis.
+     *
+     * @param name the name to check in the repository
+     * @return whether the user is in the repository
+     * 
+     * @deprecated James 2.4 now caseSensitive is a property of the repository
+     * implementations and the contains will search according to this property.
+     */
+    public boolean containsCaseInsensitive(String name) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Test if user with name 'name' has password 'password'.
+     *
+     * @param name the name of the user to be tested
+     * @param password the password to be tested
+     *
+     * @return true if the test is successful, false if the user
+     *              doesn't exist or if the password is incorrect
+     *
+     * @since James 1.2.2
+     */
+    public boolean test(String username, String password) {
+        try {
+            final Session session = login();
+            try {
+                final String name = toSafeName(username);
+                final String path = this.path + "/" + name;
+                final Node rootNode = session.getRootNode();
+                
+                try {
+                    final Node node = rootNode.getNode(path);
+                    final String current = node.getProperty(PASSWD_PROPERTY).getString();
+                    if (current == null || current == "")
+                    {
+                        return password == null || password == "";
+                    }
+                    final String hashPassword = JCRUser.hashPassword(username, password);
+                    return current.equals(hashPassword);
+                } catch (PathNotFoundException e) {
+                    // user not found
+                    logger.debug("User not found");
+                    return false;
+                }
+            } finally {
+                session.logout();
+            }
+            
+        } catch (RepositoryException e) {
+            if (logger.isInfoEnabled()) {
+                logger.info("Failed to add user: " + username, e);
+            }
+            return false;
+        }
+
+    }
+
+    /**
+     * Returns a count of the users in the repository.
+     *
+     * @return the number of users in the repository
+     */
+    public int countUsers() {
+        try {
+            final Session session = login();
+            try {
+                final Node rootNode = session.getRootNode();
+                try {
+                    final Node node = rootNode.getNode(path);
+                    //TODO: Use query
+                    //TODO: Use namespacing to avoid unwanted nodes
+                    NodeIterator it = node.getNodes();
+                    return (int) it.getSize();
+                } catch (PathNotFoundException e) {
+                    return 0;
+                }
+            } finally {
+                session.logout();
+            }
+        } catch (RepositoryException e) {
+            if (logger.isInfoEnabled()) {
+                logger.info("Failed to count user", e);
+            }
+            return 0;
+        }
+    }
+
+    /**
+     * List users in repository.
+     *
+     * @return Iterator over a collection of Strings, each being one user in the repository.
+     */
+    public Iterator list() {
+        final Collection userNames = new ArrayList();
+        try {
+            final Session session = login();
+            try {
+                final Node rootNode = session.getRootNode();
+                try {
+                    final Node baseNode = rootNode.getNode(path);
+                    //TODO: Use query
+                    final NodeIterator it = baseNode.getNodes();
+                    while(it.hasNext()) {
+                        final Node node = it.nextNode();
+                        try {
+                            final String userName = node.getProperty(USERNAME_PROPERTY).getString();
+                            userNames.add(userName);
+                        } catch (PathNotFoundException e) {
+                            logger.info("Node missing user name. Ignoring.");
+                        }
+                    }
+                } catch (PathNotFoundException e) {
+                    logger.info("Path not found. Forgotten to setup the repository?");
+                }
+            } finally {
+                session.logout();
+            }
+        } catch (RepositoryException e) {
+            if (logger.isInfoEnabled()) {
+                logger.info("Failed to count user", e);
+            }
+        }
+        return userNames.iterator();
+    }
+}

Added: james/server/trunk/jcr-backend-function/src/test/java/org/apache/james/jcr/JcrUserRepositoryTest.java
URL: http://svn.apache.org/viewvc/james/server/trunk/jcr-backend-function/src/test/java/org/apache/james/jcr/JcrUserRepositoryTest.java?rev=711996&view=auto
==============================================================================
--- james/server/trunk/jcr-backend-function/src/test/java/org/apache/james/jcr/JcrUserRepositoryTest.java (added)
+++ james/server/trunk/jcr-backend-function/src/test/java/org/apache/james/jcr/JcrUserRepositoryTest.java Thu Nov  6 14:39:45 2008
@@ -0,0 +1,118 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.jcr;
+
+import java.io.File;
+import java.io.StringReader;
+
+import javax.jcr.Repository;
+
+import org.apache.jackrabbit.core.RepositoryImpl;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.james.api.user.UsersRepository;
+import org.apache.james.userrepository.MockUsersRepositoryTest;
+import org.xml.sax.InputSource;
+
+public class JcrUserRepositoryTest extends MockUsersRepositoryTest {
+
+    private static final String JACKRABBIT_HOME = "target/jackrabbit";
+    
+    private static final String CONFIG = 
+            "<Repository>" +
+            "<FileSystem class='org.apache.jackrabbit.core.fs.mem.MemoryFileSystem'>" +
+            "    <param name='path' value='${rep.home}/repository'/>" +
+            "</FileSystem>" +
+            "<Security appName='Jackrabbit'>" +
+            " <AccessManager class='org.apache.jackrabbit.core.security.SimpleAccessManager'>" +
+            " </AccessManager>" +
+            " <LoginModule class='org.apache.jackrabbit.core.security.SimpleLoginModule'>" +
+            " </LoginModule>" +
+            "</Security>" +
+            "<Workspaces rootPath='${rep.home}/workspaces' defaultWorkspace='default'/>" +
+            "  <Workspace name='${wsp.name}'>" +
+            "    <FileSystem class='org.apache.jackrabbit.core.fs.mem.MemoryFileSystem'>" +
+            "       <param name='path' value='${wsp.home}'/>" +
+            "    </FileSystem>" +
+            "    <PersistenceManager" +
+            "             class='org.apache.jackrabbit.core.persistence.db.SimpleDbPersistenceManager'>" +
+            "            <param name='url' value='jdbc:h2:${wsp.home}/db'/>" +
+            "            <param name='driver' value='org.h2.Driver'/>" +
+            "            <param name='schema' value='h2'/>" +
+            "            <param name='schemaObjectPrefix' value='${wsp.name}_'/>" +
+            "    </PersistenceManager>" +
+            "    <SearchIndex class='org.apache.jackrabbit.core.query.lucene.SearchIndex'>" +
+            "     <param name='path' value='${wsp.home}/index'/>" +
+            "     <param name='textFilterClasses' value='org.apache.jackrabbit.extractor.HTMLTextExtractor,org.apache.jackrabbit.extractor.XMLTextExtractor'/>" +
+            "     <param name='extractorPoolSize' value='2'/>" +
+            "     <param name='supportHighlighting' value='true'/>" +
+            "   </SearchIndex>" +
+            "</Workspace>" +
+            "<Versioning rootPath='${rep.home}/version'>" +
+            "  <FileSystem class='org.apache.jackrabbit.core.fs.mem.MemoryFileSystem'>" +
+            "    <param name='path' value='${rep.home}/version' />" +
+            "  </FileSystem>" +
+            "    <PersistenceManager" +
+            "             class='org.apache.jackrabbit.core.persistence.db.SimpleDbPersistenceManager'>" +
+            "            <param name='url' value='jdbc:h2:${rep.home}/version/db'/>" +
+            "            <param name='driver' value='org.h2.Driver'/>" +
+            "            <param name='schema' value='h2'/>" +
+            "            <param name='schemaObjectPrefix' value='version_'/>" +
+            "    </PersistenceManager>" +
+            " </Versioning>" +
+            " <SearchIndex class='org.apache.jackrabbit.core.query.lucene.SearchIndex'>" +
+            "   <param name='path' value='${rep.home}/repository/index'/>" +
+            "   <param name='textFilterClasses' value='org.apache.jackrabbit.extractor.HTMLTextExtractor,org.apache.jackrabbit.extractor.XMLTextExtractor'/>" +
+            "   <param name='extractorPoolSize' value='2'/>" +
+            "   <param name='supportHighlighting' value='true'/>" +
+            " </SearchIndex>" +
+            "</Repository>";
+    
+    RepositoryImpl repository;
+        
+    protected UsersRepository getUsersRepository() throws Exception 
+    {
+        return new JCRUsersRepository(repository);
+    }
+
+    protected void setUp() throws Exception {
+        File home = new File(JACKRABBIT_HOME);
+        if (home.exists()) {
+            delete(home);
+        }
+        RepositoryConfig config = RepositoryConfig.create(new InputSource(new StringReader(CONFIG)), JACKRABBIT_HOME);
+        repository = RepositoryImpl.create(config);
+        super.setUp();
+    }
+
+    private void delete(File file) {
+        if (file.isDirectory()) {
+            File[] contents = file.listFiles();
+            for (int i = 0; i < contents.length; i++) {
+                delete(contents[i]);
+            }
+        } 
+        file.delete();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        repository.shutdown();
+    }
+}

Added: james/server/trunk/stage/com.h2database/jars/h2.jar
URL: http://svn.apache.org/viewvc/james/server/trunk/stage/com.h2database/jars/h2.jar?rev=711996&view=auto
==============================================================================
Binary file - no diff available.

Propchange: james/server/trunk/stage/com.h2database/jars/h2.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org