jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tri...@apache.org
Subject svn commit: r180346 [9/9] - in /incubator/jackrabbit/trunk/contrib/jcr-server: ./ client/ client/src/java/org/apache/jackrabbit/client/ client/src/java/org/apache/jackrabbit/webdav/client/methods/ commons/ commons/src/ commons/src/java/ commons/src/java/org/ commons/src/java/org/apache/ commons/src/java/org/apache/jackrabbit/ commons/src/java/org/apache/jackrabbit/nodetype/ commons/src/java/org/apache/jackrabbit/nodetype/xml/ commons/src/java/org/apache/jackrabbit/util/ commons/src/java/org/apache/jackrabbit/util/uuid/ commons/src/java/org/apache/jackrabbit/value/ server/ server/src/java/org/apache/jackrabbit/server/ server/src/java/org/apache/jackrabbit/server/io/ server/src/java/org/apache/jackrabbit/server/jcr/ server/src/java/org/apache/jackrabbit/server/simple/ server/src/java/org/apache/jackrabbit/webdav/jcr/ server/src/java/org/apache/jackrabbit/webdav/jcr/lock/ server/src/java/org/apache/jackrabbit/webdav/jcr/nodetype/ server/src/java/org/apache/jackrabbit/webdav/jcr/observation/ server/src/java/org/apache/jackrabbit/webdav/jcr/property/ server/src/java/org/apache/jackrabbit/webdav/jcr/search/ server/src/java/org/apache/jackrabbit/webdav/jcr/transaction/ server/src/java/org/apache/jackrabbit/webdav/jcr/version/ server/src/java/org/apache/jackrabbit/webdav/jcr/version/report/ server/src/java/org/apache/jackrabbit/webdav/simple/ webapp/ webapp/src/java/ webapp/src/java/org/ webapp/src/java/org/apache/ webapp/src/java/org/apache/jackrabbit/ webapp/src/java/org/apache/jackrabbit/j2ee/ webapp/src/webapp/ webapp/src/webapp/WEB-INF/ webdav/ webdav/src/java/org/apache/jackrabbit/webdav/ webdav/src/java/org/apache/jackrabbit/webdav/jcr/ webdav/src/java/org/apache/jackrabbit/webdav/lock/ webdav/src/java/org/apache/jackrabbit/webdav/property/ webdav/src/java/org/apache/jackrabbit/webdav/util/ webdav/src/java/org/apache/jackrabbit/webdav/version/report/
Date Mon, 06 Jun 2005 17:36:13 GMT
Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/project.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webapp/project.xml?rev=180346&r1=180345&r2=180346&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webapp/project.xml (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webapp/project.xml Mon Jun  6 10:36:09 2005
@@ -23,12 +23,13 @@
     <id>jackrabbit-server</id>
     <groupId>jcr-server</groupId>
     <type>war</type>
-    <name>Jackrabbit-Server WebApplication</name>
+    <name>JCRWebdavServer WebApplication</name>
     
     <!-- ====================================================================== -->
     <!-- D E P E N D E N C I E S                                                -->
     <!-- ====================================================================== -->
     <dependencies>
+        <!-- internal dependencies -->
         <dependency>
             <artifactId>jcr-server</artifactId>
             <groupId>jcr-server</groupId>
@@ -53,24 +54,32 @@
                 <war.bundle>true</war.bundle>
             </properties>
         </dependency>
-
         <dependency>
-            <groupId>jsr170</groupId>
-            <artifactId>jcr</artifactId>
-            <version>0.16.4.1</version>
-            <url>http://www.day.com/maven/jsr170/jars/jcr-0.16.4.1.jar</url>
+            <artifactId>commons-jcr</artifactId>
+            <groupId>jcr-server</groupId>
+            <version>${pom.currentVersion}</version>
             <properties>
                 <war.bundle>true</war.bundle>
             </properties>
         </dependency>
+        
+        <!-- external dependencies -->
+        <dependency>
+            <groupId>jsr170</groupId>
+            <artifactId>jcr</artifactId>
+            <version>${jackrabbit.build.version.jcr}</version>
+        </dependency>
         <dependency>
             <id>jackrabbit</id>
-            <version>0.16.4.1-dev</version>
-            <properties>
-                <war.bundle>true</war.bundle>
-            </properties>
+            <version>${jackrabbit.build.version.jackrabbit}</version>
         </dependency>
         <dependency>
+            <id>jcr-rmi</id>
+            <version>${jackrabbit.build.version.jcr.rmi}</version>
+        </dependency>
+        
+        <!-- non-jackrabbit dependencies -->
+        <dependency>
             <id>jdom</id>
             <version>1.0</version>
             <properties>
@@ -89,12 +98,18 @@
             <version>3.8.1</version>
         </dependency>
         <dependency>
-            <id>jcr-rmi</id>
-            <version>0.16.4.1</version>
-            <properties>
-                <war.bundle>false</war.bundle>
-            </properties>
+            <id>commons-chain</id>
+            <version>1.0</version>
         </dependency>
+        <dependency>
+            <id>commons-digester</id>
+            <version>1.6</version>
+        </dependency>
+        <dependency>
+            <id>commons-beanutils</id>
+            <version>1.7.0</version>
+        </dependency>
+
         <!-- dependencies of jackrabbit -->
         <dependency>
           <id>concurrent</id>
@@ -134,6 +149,7 @@
                 <war.bundle>true</war.bundle>
             </properties>
         </dependency>
+
         <!--
           cqfs-jackrabbit and cqfs are optional runtime dependencies 
           (an alternative FileSystem implementation); 
@@ -142,8 +158,8 @@
         <dependency>
           <groupId>cqfs</groupId>
           <artifactId>cqfs-jackrabbit</artifactId>
-          <version>3.5.6-SNAPSHOT</version>
-          <url>http://www.day.com/maven/cqfs/jars/cqfs-jackrabbit-3.5.6-SNAPSHOT.jar</url>
+          <version>3.5.6</version>
+          <url>http://www.day.com/maven/cqfs/jars/cqfs-jackrabbit-3.5.6.jar</url>
             <properties>
                 <war.bundle>true</war.bundle>
             </properties>
@@ -151,8 +167,8 @@
         <dependency>
           <groupId>cqfs</groupId>
           <artifactId>cqfs</artifactId>
-          <version>3.5.6-SNAPSHOT</version>
-          <url>http://www.day.com/maven/cqfs/jars/cqfs-3.5.6-SNAPSHOT.jar</url>
+          <version>3.5.6</version>
+          <url>http://www.day.com/maven/cqfs/jars/cqfs-3.5.6.jar</url>
             <properties>
                 <war.bundle>true</war.bundle>
             </properties>

Added: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java?rev=180346&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java Mon Jun  6 10:36:09 2005
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j2ee;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.webdav.*;
+import org.apache.jackrabbit.webdav.observation.*;
+import org.apache.jackrabbit.webdav.jcr.*;
+import org.apache.jackrabbit.webdav.jcr.observation.SubscriptionManagerImpl;
+import org.apache.jackrabbit.webdav.jcr.transaction.TxLockManagerImpl;
+import org.apache.jackrabbit.server.jcr.JCRWebdavServer;
+import org.apache.jackrabbit.server.CredentialsProvider;
+import org.apache.jackrabbit.server.SessionProviderImpl;
+import org.apache.jackrabbit.server.AbstractWebdavServlet;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.jcr.Repository;
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+
+/**
+ * JCRWebdavServerServlet provides request/response handling for the JCRWebdavServer.
+ */
+public class JCRWebdavServerServlet extends AbstractWebdavServlet implements DavConstants {
+
+    /**
+     * the default logger
+     */
+    private static Logger log = Logger.getLogger(JCRWebdavServerServlet.class);
+
+    /**
+     * Init parameter specifying the prefix used with the resource path.
+     */
+    public static final String INIT_PARAM_PREFIX = "resource-path-prefix";
+
+    private JCRWebdavServer server;
+    private DavResourceFactory resourceFactory;
+    private DavLocatorFactory locatorFactory;
+    private TxLockManagerImpl txMgr;
+    private SubscriptionManager subscriptionMgr;
+
+    /**
+     * Initializes the servlet set reads the following parameter from the
+     * servlet configuration:
+     * <ul>
+     * <li>resource-path-prefix: optional prefix for all resources.</li>
+     * </ul>
+     *
+     * @throws ServletException
+     */
+    public void init() throws ServletException {
+        super.init();
+
+	// set resource path prefix
+	String pathPrefix = getInitParameter(INIT_PARAM_PREFIX);
+	log.debug(INIT_PARAM_PREFIX + " = " + pathPrefix);
+
+	Repository repository = RepositoryAccessServlet.getRepository();
+	if (repository == null) {
+	    throw new ServletException("Repository could not be retrieved. Check config of 'RepositoryAccessServlet'.");
+	}
+        CredentialsProvider cp = new CredentialsProvider() {
+            public Credentials getCredentials(HttpServletRequest request) throws LoginException, ServletException {
+                return RepositoryAccessServlet.getCredentialsFromHeader(request.getHeader(DavConstants.HEADER_AUTHORIZATION));
+            }
+        };
+
+	server = new JCRWebdavServer(repository, new SessionProviderImpl(cp));
+        txMgr = new TxLockManagerImpl();
+        subscriptionMgr = new SubscriptionManagerImpl();
+
+        // todo: ev. make configurable
+        resourceFactory = new DavResourceFactoryImpl(txMgr, subscriptionMgr);
+        locatorFactory = new DavLocatorFactoryImpl(pathPrefix);
+    }
+
+    /**
+     *
+     * @param request
+     * @param resource
+     * @return
+     */
+    protected boolean isPreconditionValid(WebdavRequest request, DavResource resource) {
+        // first check matching If header
+        if (!request.matchesIfHeader(resource)) {
+            return false;
+        }
+
+        // test if the requested path matches to the existing session
+        // this may occur if the session was retrieved from the cache.
+        String wsName = request.getDavSession().getRepositorySession().getWorkspace().getName();
+        if (!resource.getLocator().isSameWorkspace(wsName)) {
+            return false;
+        }
+
+        // make sure, the TransactionId header is valid
+        String txId = request.getTransactionId();
+        if (txId != null && !txMgr.hasLock(txId, resource)) {
+           return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DavSessionProvider getSessionProvider() {
+        return server;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DavLocatorFactory getLocatorFactory() {
+        return locatorFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DavResourceFactory getResourceFactory() {
+        return resourceFactory;
+    }
+
+    /**
+     * Returns {@link #DEFAULT_AUTHENTICATE_HEADER}.
+     *
+     * @return {@link #DEFAULT_AUTHENTICATE_HEADER}.
+     */
+    public String getAuthenticateHeaderValue() {
+        return DEFAULT_AUTHENTICATE_HEADER;
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/JCRWebdavServerServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java?rev=180346&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java Mon Jun  6 10:36:09 2005
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation or its licensors,
+ *                     as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j2ee;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.jackrabbit.rmi.client.ClientRepositoryFactory;
+import org.apache.jackrabbit.util.Base64;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.ServletException;
+import javax.jcr.*;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import java.util.Properties;
+import java.util.Enumeration;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.rmi.RemoteException;
+import java.rmi.NotBoundException;
+import java.net.MalformedURLException;
+
+/**
+ * This Class implements a servlet that is used as unified mechanism to retrieve
+ * a jcr repository either through JNID, RMI or JCRWebdavServer.
+ */
+public class RepositoryAccessServlet extends HttpServlet {
+
+    /** default logger */
+    private static Logger log;
+
+    // todo: implement correctly
+    public final static String INIT_PARAM_LOG4J_CONFIG = "log4j-config";
+
+    /** the 'repository-name' init parameter */
+    public final static String INIT_PARAM_REPOSITORY_NAME = "repository-name";
+
+    /** the 'rmi-uri' init parameter */
+    public final static String INIT_PARAM_RMI_URI = "rmi-uri";
+
+    /** the 'missing-auth-mapping' init parameter */
+    public final static String INIT_PARAM_MISSING_AUTH_MAPPING = "missing-auth-mapping";
+
+    /** Authorization header name */
+    private static final String HEADER_AUTHORIZATION = "Authorization";
+
+    /** the configured repository name */
+    private static String repositoryName;
+
+    private static String rmiURI;
+
+    private static InitialContext jndiContext;
+
+    private static Repository repository;
+
+    private static String missingAuthMapping;
+
+    /**
+     * Initializes this servlet
+     *
+     * @throws javax.servlet.ServletException
+     */
+    public void init() throws ServletException {
+	initLog4J();
+	log.info("RepositoryAccessServlet initializing...");
+	initJNDI();
+	initRMI();
+	initRepository();
+        missingAuthMapping = getServletConfig().getInitParameter(INIT_PARAM_MISSING_AUTH_MAPPING);
+        log.info("  " + INIT_PARAM_MISSING_AUTH_MAPPING + " = " + missingAuthMapping);
+
+	log.info("RepositoryAccessServlet initialized.");
+    }
+
+    private void initLog4J() throws ServletException {
+	// setup log4j
+	String log4jConfig = getServletConfig().getInitParameter(INIT_PARAM_LOG4J_CONFIG);
+	InputStream in =getServletContext().getResourceAsStream(log4jConfig);
+	if (in==null) {
+	    // try normal init
+	    PropertyConfigurator.configure(log4jConfig);
+	} else {
+	    try {
+		Properties log4jProperties = new Properties();
+		log4jProperties.load(in);
+		in.close();
+		PropertyConfigurator.configure(log4jProperties);
+	    } catch (IOException e) {
+		throw new ServletException("Unable to load log4jProperties: " + e.toString());
+	    }
+	}
+	log = Logger.getLogger(RepositoryAccessServlet.class);
+    }
+
+    private void initJNDI() throws ServletException {
+	// setup repository name
+	repositoryName = getServletConfig().getInitParameter(INIT_PARAM_REPOSITORY_NAME);
+	if (repositoryName==null) {
+	    repositoryName="default";
+	}
+	log.info("  repository-name = " + repositoryName);
+
+	// retrieve JNDI Context environment
+	try {
+	    Properties env = new Properties();
+	    Enumeration names = getServletConfig().getInitParameterNames();
+	    while (names.hasMoreElements()) {
+		String name = (String) names.nextElement();
+		if (name.startsWith("java.naming.")) {
+		    env.put(name, getServletConfig().getInitParameter(name));
+		    log.info("  adding property to JNDI environment: " + name + "=" + env.getProperty(name));
+		}
+	    }
+	    jndiContext = new InitialContext(env);
+	} catch (NamingException e) {
+	    log.error("Create initial context: " + e.toString());
+	    throw new ServletException(e);
+	}
+    }
+
+    private void initRMI() {
+	// setup repository name
+	rmiURI = getServletConfig().getInitParameter(INIT_PARAM_RMI_URI);
+	if (rmiURI != null) {
+	    log.info("  rmi-uri = " + rmiURI);
+	}
+    }
+
+    /**
+     * tries to retrieve the repository
+     */
+    private void initRepository() throws ServletException {
+	getRepositoryByRMI();
+	if (repository == null) {
+	    getRepositoryByJNDI();
+	}
+	if (repository == null) {
+	    log.error("Unable to retrieve repository");
+	    throw new ServletException("Unable to retrieve repository");
+	}
+	log.info(repository.getDescriptor(Repository.REP_NAME_DESC) + " v" + repository.getDescriptor(Repository.REP_VERSION_DESC));
+    }
+
+    /**
+     * tries to retrieve the repository using RMI
+     */
+    private void getRepositoryByJNDI() {
+	if (jndiContext != null) {
+	    // acquire via JNDI
+	    try {
+		repository = (Repository) jndiContext.lookup(repositoryName);
+	    } catch (NamingException e) {
+		log.error("Error while retrieving repository using JNDI: " + e);
+		return;
+	    }
+	    log.info("Acquired repository via JNDI.");
+	}
+    }
+
+    /**
+     * tries to retrieve the repository using RMI
+     */
+    private void getRepositoryByRMI() {
+	if (rmiURI != null) {
+	    // acquire via RMI
+	    ClientFactoryDelegater cfd = null;
+	    try {
+		Class clazz = Class.forName("org.apache.jackrabbit.j2ee.RMIClientFactoryDelegater");
+		cfd = (ClientFactoryDelegater) clazz.newInstance();
+	    } catch (NoClassDefFoundError e) {
+		log.error("Unable to locate RMI ClientRepositoryFactory. jcr-rmi.jar missing? " + e.toString());
+		return;
+	    } catch (Exception e) {
+		log.error("Unable to locate RMI ClientRepositoryFactory. jcr-rmi.jar missing?" + e.toString());
+		return;
+	    }
+
+	    try {
+		repository = cfd.getRepository(rmiURI);
+	    } catch (Exception e) {
+		log.error("Error while retrieving repository using RMI: " + e);
+		return;
+	    }
+	    log.info("Acquired repository via RMI.");
+	}
+    }
+
+    /**
+     * Returns the JSR170 repository
+     *
+     * @return a jsr170 repository
+     */
+    public static Repository getRepository() {
+	return repository;
+    }
+
+    /**
+     * Build a {@link Credentials} object for the given authorization header.
+     * The creds may be used to login to the repository. If the specified header
+     * string is <code>null</code> or not of the required format the behaviour
+     * depends on the {@link #INIT_PARAM_MISSING_AUTH_MAPPING} param:<br>
+     * <ul>
+     * <li> if this init-param is missing, a LoginException is thrown.
+     *      This is suiteable for clients (eg. webdav clients) for with
+     *      sending a proper authorization header is not possible, if the
+     *      server never send a 401.
+     * <li> if this init-param is present, but with an empty value,
+     *      null-credentials are returned, thus forcing an null login
+     *      on the repository
+     * <li> if this init-param has a 'user:password' value, the respective
+     *      simple credentials are generated.
+     * </ul>
+     *
+     * @param authHeader Authorization header as present in the Http request
+     * @return credentials or <code>null</code>.
+     * @throws ServletException If an IOException occured while decoding the
+     * Authorization header.
+     * @throws LoginException if no suitable auth header and missing-auth-mapping
+     * is not present
+     * @see #getRepository()
+     * @see #login(HttpServletRequest)
+     */
+    public static Credentials getCredentialsFromHeader(String authHeader)
+	    throws ServletException, LoginException {
+	try {
+	    if (authHeader != null) {
+		String[] authStr = authHeader.split(" ");
+		if (authStr.length >= 2 && authStr[0].equalsIgnoreCase(HttpServletRequest.BASIC_AUTH)) {
+		    ByteArrayOutputStream out = new ByteArrayOutputStream();
+		    Base64.decode(authStr[1].toCharArray(), out);
+		    String decAuthStr = out.toString("ISO-8859-1");
+		    int pos = decAuthStr.indexOf(':');
+		    String userid = decAuthStr.substring(0, pos);
+		    String passwd = decAuthStr.substring(pos + 1);
+		    return new SimpleCredentials(userid, passwd.toCharArray());
+		}
+	    }
+            // check special handling
+            if (missingAuthMapping == null) {
+                throw new LoginException();
+            } else if (missingAuthMapping.equals("")) {
+                return null;
+            } else {
+                int pos = missingAuthMapping.indexOf(':');
+                if (pos<0) {
+                    return new SimpleCredentials(missingAuthMapping, null);
+                } else {
+                    return new SimpleCredentials(
+                            missingAuthMapping.substring(0, pos),
+                            missingAuthMapping.substring(pos+1).toCharArray()
+                    );
+                }
+            }
+	} catch (IOException e) {
+	    throw new ServletException("Unable to decode authorization: " + e.toString());
+	}
+    }
+
+    /**
+     * Simple login to the {@link Repository} accessed by this servlet using the
+     * Authorization header present in the given request.<p/>
+     * Please note, that no workspace information is provided to the repository
+     * login ({@link Repository#login(javax.jcr.Credentials)}), thus the default
+     * workspace will be selected. In order to provide a specific workspace name,
+     * manual {@link Repository#login(Credentials, String) login} is required (see
+     * also {@link #getRepository()}).
+     *
+     * @param request
+     * @return  Session object obtained upon {@link Repository#login(javax.jcr.Credentials)}.
+     * @throws ServletException
+     * @throws LoginException if credentials are invalid
+     * @see #getRepository() in order to be able to login to a specific workspace.
+     * @see #getCredentialsFromHeader(String) for a utility method to retrieve
+     * credentials from the Authorization header string.
+     */
+    public static Session login(HttpServletRequest request)
+            throws LoginException, ServletException {
+        String authHeader = request.getHeader(HEADER_AUTHORIZATION);
+	try {
+	    return repository.login(getCredentialsFromHeader(authHeader));
+        } catch (LoginException e) {
+            throw e;
+	} catch (RepositoryException e) {
+	    throw new ServletException("Failed to login to the repository: " + e.toString());
+	}
+    }
+}
+
+/**
+ * optional class for RMI, will only be used, if RMI client is present
+ */
+abstract class ClientFactoryDelegater {
+
+    public abstract Repository getRepository(String uri)
+	    throws RemoteException, MalformedURLException, NotBoundException;
+}
+
+/**
+ * optional class for RMI, will only be used, if RMI server is present
+ */
+class RMIClientFactoryDelegater extends ClientFactoryDelegater {
+
+    // only used to enforce linking upon Class.forName()
+    static String FactoryClassName = ClientRepositoryFactory.class.getName();
+
+    public Repository getRepository(String uri)
+	    throws MalformedURLException, NotBoundException, RemoteException {
+	System.setProperty("java.rmi.server.useCodebaseOnly", "true");
+	return new ClientRepositoryFactory().getRepository(uri);
+   }
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/RepositoryAccessServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java?rev=180346&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java Mon Jun  6 10:36:09 2005
@@ -0,0 +1,324 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j2ee;
+
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.jackrabbit.core.RepositoryImpl;
+import org.apache.jackrabbit.rmi.server.ServerAdapterFactory;
+import org.xml.sax.InputSource;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.ServletException;
+import javax.jcr.*;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import java.io.*;
+import java.util.Properties;
+import java.util.Enumeration;
+import java.rmi.registry.Registry;
+import java.rmi.registry.LocateRegistry;
+import java.rmi.Naming;
+import java.rmi.RemoteException;
+import java.rmi.AlreadyBoundException;
+import java.rmi.Remote;
+import java.net.MalformedURLException;
+
+/**
+ * The RepositoryStartupServlet starts a jackrabbit repository and registers it
+ * to the JNDI environment and optional to the RMI registry.
+ */
+public class RepositoryStartupServlet extends HttpServlet {
+
+    /** the default logger */
+    private static Logger log;
+
+    /** initial param name for the repository config location */
+    public final static String INIT_PARAM_REPOSITORY_CONFIG = "repository-config";
+
+    /** initial param name for the repository home directory */
+    public final static String INIT_PARAM_REPOSITORY_HOME = "repository-home";
+
+    /** initial param name for the repository name */
+    public final static String INIT_PARAM_REPOSITORY_NAME = "repository-name";
+
+    /** initial param name for the rmi port */
+    public final static String INIT_PARAM_RMI_PORT = "rmi-port";
+
+    /** initial param name for the log4j config properties */
+    public final static String INIT_PARAM_LOG4J_CONFIG = "log4j-config";
+
+    /** the registered repository */
+    private static Repository repository;
+
+    /** the name of the repository as configured */
+    private static String repositoryName;
+
+    /** the jndi context, created base on configuration */
+    private static InitialContext jndiContext;
+
+    /** the rmi uri, in the form of  '//:${rmi-port}/${repository-name}' */
+    private static String rmiURI;
+
+    /**
+     * Initializes the servlet
+     * @throws ServletException
+     */
+    public void init() throws ServletException {
+	super.init();
+	initLog4J();
+	log.info("RepositoryStartupServlet initializing...");
+	initRepository();
+	registerJNDI();
+	registerRMI();
+	log.info("RepositoryStartupServlet initialized.");
+    }
+
+    /**
+     * destroy the servlet
+     */
+    public void destroy() {
+	super.destroy();
+	if (log == null) {
+	    log("RepositoryStartupServlet shutting down...");
+	} else {
+	    log.info("RepositoryStartupServlet shutting down...");
+	}
+	unregisterRMI();
+	unregisterJNDI();
+	log("RepositoryStartupServlet shut down.");
+    }
+
+    /**
+     * Initializes Log4J
+     * @throws ServletException
+     */
+    private void initLog4J() throws ServletException {
+	// setup log4j
+	String log4jConfig = getServletConfig().getInitParameter(INIT_PARAM_LOG4J_CONFIG);
+	InputStream in =getServletContext().getResourceAsStream(log4jConfig);
+	if (in==null) {
+	    // try normal init
+	    PropertyConfigurator.configure(log4jConfig);
+	} else {
+	    try {
+		Properties log4jProperties = new Properties();
+		log4jProperties.load(in);
+		in.close();
+		PropertyConfigurator.configure(log4jProperties);
+	    } catch (IOException e) {
+		throw new ServletException("Unable to load log4jProperties: " + e.toString());
+	    }
+	}
+	log = Logger.getLogger(RepositoryStartupServlet.class);
+    }
+
+    /**
+     * Creates a new Repository based on configuration
+     * @throws ServletException
+     */
+    private void initRepository() throws ServletException {
+	// setup home directory
+	String repHome = getServletConfig().getInitParameter(INIT_PARAM_REPOSITORY_HOME);
+	if (repHome==null) {
+	    log.error(INIT_PARAM_REPOSITORY_HOME + " missing.");
+	    throw new ServletException(INIT_PARAM_REPOSITORY_HOME + " missing.");
+	}
+	File repositoryHome;
+	try {
+	    repositoryHome = new File(repHome).getCanonicalFile();
+	} catch (IOException e) {
+	    log.error(INIT_PARAM_REPOSITORY_HOME + " invalid." + e.toString());
+	    throw new ServletException(INIT_PARAM_REPOSITORY_HOME + " invalid." + e.toString());
+	}
+	log.info("  repository-home = " + repositoryHome.getPath());
+
+	// get repository config
+	String repConfig = getServletConfig().getInitParameter(INIT_PARAM_REPOSITORY_CONFIG);
+	if (repConfig==null) {
+	    log.error(INIT_PARAM_REPOSITORY_CONFIG + " missing.");
+	    throw new ServletException(INIT_PARAM_REPOSITORY_CONFIG + " missing.");
+	}
+	log.info("  repository-config = " + repConfig);
+
+	InputStream in = getServletContext().getResourceAsStream(repConfig);
+	if (in==null) {
+	    try {
+		in = new FileInputStream(new File(repositoryHome, repConfig));
+	    } catch (FileNotFoundException e) {
+		log.error(INIT_PARAM_REPOSITORY_CONFIG + " invalid." + e.toString());
+		throw new ServletException(INIT_PARAM_REPOSITORY_CONFIG + " invalid." + e.toString());
+	    }
+	}
+
+	// get repository name
+	repositoryName = getServletConfig().getInitParameter(INIT_PARAM_REPOSITORY_NAME);
+	if (repositoryName==null) {
+	    repositoryName="default";
+	}
+	log.info("  repository-name = " + repositoryName);
+
+	try {
+	    repository = createRepository(new InputSource(in), repositoryHome);
+	} catch (RepositoryException e) {
+	    throw new ServletException("Error while creating repository", e);
+	}
+    }
+
+    /**
+     * Creates the repository for the given config and homedir.
+     *
+     * @param is
+     * @param homedir
+     * @return
+     * @throws RepositoryException
+     */
+    protected Repository createRepository(InputSource is, File homedir)
+            throws RepositoryException {
+        RepositoryConfig config = RepositoryConfig.create(is, homedir.getAbsolutePath());
+        return RepositoryImpl.create(config);
+    }
+
+    /**
+     * Registers the repository in the JNDI context
+     * @throws ServletException
+     */
+    private void registerJNDI() throws ServletException {
+	// registering via jndi
+	Properties env = new Properties();
+	Enumeration names = getServletConfig().getInitParameterNames();
+	while (names.hasMoreElements()) {
+	    String name = (String) names.nextElement();
+	    if (name.startsWith("java.naming.")) {
+		env.put(name, getServletConfig().getInitParameter(name));
+		log.info("  adding property to JNDI environment: " + name + "=" + env.getProperty(name));
+	    }
+	}
+	try {
+	    jndiContext = new InitialContext(env);
+	    jndiContext.bind(repositoryName, repository);
+	} catch (NamingException e) {
+	    throw new ServletException(e);
+	}
+	log.info("Repository bound to JNDI with name: " + repositoryName);
+    }
+
+    /**
+     * Unregisters the repository from the JNDI context
+     */
+    private void unregisterJNDI() {
+	if (jndiContext != null) {
+	    try {
+		jndiContext.unbind(repositoryName);
+	    } catch (NamingException e) {
+		log("Error while unbinding repository from JNDI: " + e);
+	    }
+	}
+    }
+
+    /**
+     * Registers the repositroy to the RMI registry
+     * @throws ServletException
+     */
+    private void registerRMI() throws ServletException {
+	// check registering via RMI
+	String rmiPortStr = getServletConfig().getInitParameter(INIT_PARAM_RMI_PORT);
+	if (rmiPortStr != null) {
+	    int rmiPort = 0;
+	    try {
+		rmiPort = Integer.parseInt(rmiPortStr);
+	    } catch (NumberFormatException e) {
+		log.warn("Invalid port in rmi-port param: " + e);
+	    }
+	    if (rmiPort == 0) {
+		rmiPort = Registry.REGISTRY_PORT;
+	    }
+
+	    // try to create remote repository
+	    Remote remote;
+	    try {
+		Class clazz = Class.forName("org.apache.jackrabbit.j2ee.RMIRemoteFactoryDelegater");
+		RemoteFactoryDelegater rmf = (RemoteFactoryDelegater) clazz.newInstance();
+		remote = rmf.createRemoteRepository(repository);
+	    } catch (RemoteException e) {
+		throw new ServletException("Unable to create remote repository: " + e.toString(), e);
+	    } catch (NoClassDefFoundError e) {
+		log.warn("Unable to create RMI repository. jcr-rmi.jar might be missing.: " + e.toString());
+		return;
+	    } catch (Exception e) {
+		log.warn("Unable to create RMI repository. jcr-rmi.jar might be missing.: " + e.toString());
+		return;
+	    }
+
+	    try {
+		System.setProperty("java.rmi.server.useCodebaseOnly", "true");
+		try {
+		    // start registry
+		    LocateRegistry.createRegistry(rmiPort);
+		} catch (RemoteException e) {
+		    // ignore
+		}
+		rmiURI = "//:" + rmiPort + "/" + repositoryName;
+		Naming.bind(rmiURI, remote);
+
+		log.info("Repository bound via RMI with name: " + rmiURI);
+	    } catch (MalformedURLException e) {
+		throw new ServletException("Unable to bind repository via RMI: " + e.toString(), e);
+	    } catch (RemoteException e) {
+		throw new ServletException("Unable to bind repository via RMI: " + e.toString(), e);
+	    } catch (AlreadyBoundException e) {
+		throw new ServletException("Unable to bind repository via RMI: " + e.toString(), e);
+	    }
+	}
+    }
+
+    /**
+     * Unregisters the repository from the RMI registry
+     */
+    private void unregisterRMI() {
+	if (rmiURI != null) {
+	    try {
+		Naming.unbind(rmiURI);
+	    } catch (Exception e) {
+		log("Error while unbinding repository from JNDI: " + e);
+	    }
+	}
+    }
+
+}
+
+/**
+ * optional class for RMI, will only be used, if RMI server is present
+ */
+abstract class RemoteFactoryDelegater {
+
+    public abstract Remote createRemoteRepository(Repository repository)
+	    throws RemoteException;
+}
+/**
+ * optional class for RMI, will only be used, if RMI server is present
+ */
+class RMIRemoteFactoryDelegater extends RemoteFactoryDelegater {
+
+    // only used to enforce linking upon Class.forName()
+    static String FactoryClassName = ServerAdapterFactory.class.getName();
+
+    public Remote createRemoteRepository(Repository repository)
+	    throws RemoteException {
+	return new ServerAdapterFactory().getRemoteRepository(repository);
+    }
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/RepositoryStartupServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java?rev=180346&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java Mon Jun  6 10:36:09 2005
@@ -0,0 +1,357 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.j2ee;
+
+import org.apache.commons.chain.Catalog;
+import org.apache.commons.chain.config.ConfigParser;
+import org.apache.commons.chain.impl.CatalogFactoryBase;
+import org.apache.jackrabbit.server.CredentialsProvider;
+import org.apache.jackrabbit.server.SessionProvider;
+import org.apache.jackrabbit.server.SessionProviderImpl;
+import org.apache.jackrabbit.server.AbstractWebdavServlet;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavLocatorFactory;
+import org.apache.jackrabbit.webdav.DavMethods;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavResourceFactory;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavSessionProvider;
+import org.apache.jackrabbit.webdav.WebdavRequest;
+import org.apache.jackrabbit.webdav.WebdavResponse;
+import org.apache.jackrabbit.webdav.lock.LockManager;
+import org.apache.jackrabbit.webdav.lock.SimpleLockManager;
+import org.apache.jackrabbit.webdav.simple.DavSessionProviderImpl;
+import org.apache.jackrabbit.webdav.simple.LocatorFactoryImpl;
+import org.apache.jackrabbit.webdav.simple.ResourceFactoryImpl;
+import org.apache.log4j.Logger;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.Repository;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.net.URL;
+
+/**
+ * WebdavServlet provides webdav support (level 1 and 2 complient) for repository
+ * resources.
+ */
+public class SimpleWebdavServlet extends AbstractWebdavServlet {
+
+    /**
+     * the default logger
+     */
+    private static final Logger log = Logger.getLogger(SimpleWebdavServlet.class);
+
+    /**
+     * init param name of the repository prefix
+     */
+    public static final String INIT_PARAM_RESOURCE_PATH_PREFIX = "resource-path-prefix";
+
+    /**
+     * init param file of the commons chain catalog
+     */
+    public static final String INIT_PARAM_CHAIN_CATALOG = "chain-catalog";
+
+    /**
+     * Name of the optional init parameter that defines the value of the
+     * 'WWW-Authenticate' header.<p/>
+     * If the parameter is omitted the default value
+     * {@link #DEFAULT_AUTHENTICATE_HEADER "Basic Realm=Jackrabbit Webdav Server"}
+     * is used.
+     *
+     * @see #getAuthenticateHeaderValue()
+     */
+    public static final String INIT_PARAM_AUTHENTICATE_HEADER = "authenticate-header";
+
+    /**
+     * the repository prefix retrieved from config
+     */
+    private static String resourcePathPrefix;
+
+    /**
+     * the chain catalog for i/o operations
+     */
+    private static Catalog chainCatalog;
+
+    /**
+     * Header value as specified in the {@link #INIT_PARAM_AUTHENTICATE_HEADER} parameter.
+     */
+    private static String authenticate_header;
+
+    /**
+     * Map used to remember any webdav lock created without being reflected
+     * in the underlaying repository.
+     * This is needed because some clients rely on a successful locking
+     * mechanism in order to perform properly (e.g. mac OSX built-in dav client)
+     */
+    private LockManager lockManager;
+
+    /**
+     * the resource factory
+     */
+    private DavResourceFactory resourceFactory;
+
+    /**
+     * the locator factory
+     */
+    private DavLocatorFactory locatorFactory;
+
+    /**
+     * the jcr repository
+     */
+    private Repository repository;
+
+    /**
+     * the session provider
+     */
+    private DavSessionProvider davSessionProvider;
+
+    /**
+     * the session provider
+     */
+    private SessionProvider sessionProvider;
+
+    /**
+     * Init this servlet
+     *
+     * @throws ServletException
+     */
+    public void init() throws ServletException {
+        super.init();
+
+        resourcePathPrefix = getInitParameter(INIT_PARAM_RESOURCE_PATH_PREFIX);
+        if (resourcePathPrefix == null) {
+            log.debug("Missing path prefix > setting to empty string.");
+            resourcePathPrefix = "";
+        } else if (resourcePathPrefix.endsWith("/")) {
+            log.debug("Path prefix ends with '/' > removing trailing slash.");
+            resourcePathPrefix = resourcePathPrefix.substring(0, resourcePathPrefix.length() - 1);
+        }
+        log.info(INIT_PARAM_RESOURCE_PATH_PREFIX + " = '" + resourcePathPrefix + "'");
+
+        // init repository
+        repository = RepositoryAccessServlet.getRepository();
+        if (repository == null) {
+            throw new ServletException("Repository could not be retrieved. Check config of 'RepositoryAccessServlet'.");
+        }
+        try {
+            String chain = getInitParameter(INIT_PARAM_CHAIN_CATALOG);
+            URL chainUrl = getServletContext().getResource(chain);
+            ConfigParser parser = new ConfigParser();
+            parser.parse(chainUrl);
+            chainCatalog = CatalogFactoryBase.getInstance().getCatalog();
+        } catch (Exception e) {
+            throw new ServletException(e);
+        }
+        log.info(INIT_PARAM_CHAIN_CATALOG + " = '" + chainCatalog + "'");
+
+        authenticate_header = getInitParameter(INIT_PARAM_AUTHENTICATE_HEADER);
+        if (authenticate_header == null) {
+            authenticate_header = DEFAULT_AUTHENTICATE_HEADER;
+        }
+        log.info("WWW-Authenticate header = '" + authenticate_header + "'");
+    }
+
+    /**
+     * Executes the respective method in the given webdav context.
+     * The method is overridden since not all webdav methods should be
+     * supported by this servlet.
+     *
+     * @param request
+     * @param response
+     * @param method
+     * @param resource
+     * @return
+     * @throws ServletException
+     * @throws IOException
+     * @throws DavException
+     */
+    protected boolean execute(WebdavRequest request, WebdavResponse response,
+                              int method, DavResource resource)
+            throws ServletException, IOException, DavException {
+        /* set cache control headers in order to deal with non-dav complient
+        * http1.1 or http1.0 proxies. >> see RFC2518 9.4.5 */
+        response.addHeader("Pragma", "No-cache");  // http1.0
+        response.addHeader("Cache-Control", "no-cache"); // http1.1
+
+        switch (method) {
+            case DavMethods.DAV_HEAD:
+                doHead(request, response, resource);
+                break;
+            case DavMethods.DAV_GET:
+                doGet(request, response, resource);
+                break;
+            case DavMethods.DAV_OPTIONS:
+                doOptions(request, response, resource);
+                break;
+            case DavMethods.DAV_PROPFIND:
+                doPropFind(request, response, resource);
+                break;
+            case DavMethods.DAV_PROPPATCH:
+                doPropPatch(request, response, resource);
+                break;
+            case DavMethods.DAV_PUT:
+                doPut(request, response, resource);
+                break;
+            case DavMethods.DAV_POST:
+                doPost(request, response, resource);
+                break;
+            case DavMethods.DAV_DELETE:
+                doDelete(request, response, resource);
+                break;
+            case DavMethods.DAV_COPY:
+                doCopy(request, response, resource);
+                break;
+            case DavMethods.DAV_MOVE:
+                doMove(request, response, resource);
+                break;
+            case DavMethods.DAV_MKCOL:
+                doMkCol(request, response, resource);
+                break;
+            case DavMethods.DAV_LOCK:
+                doLock(request, response, resource);
+                break;
+            case DavMethods.DAV_UNLOCK:
+                doUnlock(request, response, resource);
+                break;
+            default:
+                // any other method
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected boolean isPreconditionValid(WebdavRequest request,
+                                          DavResource resource) {
+        return !resource.exists() || request.matchesIfHeader(resource);
+    }
+
+    /**
+     * The MKCOL method
+     *
+     * @throws IOException
+     */
+    protected void doMkCol(WebdavRequest request, WebdavResponse response,
+                           DavResource resource) throws IOException, DavException {
+        // mkcol request with request.body is not supported.
+        if (request.getContentLength() > 0 || request.getHeader("Transfer-Encoding") != null) {
+            response.sendError(DavServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
+            return;
+        }
+        super.doMkCol(request, response, resource);
+    }
+
+    /**
+     * Returns the configured path prefix
+     *
+     * @return resourcePathPrefix
+     * @see #INIT_PARAM_RESOURCE_PATH_PREFIX
+     */
+    public static String getPathPrefix() {
+        return resourcePathPrefix;
+    }
+
+    /**
+     * Returns the <code>DavLocatorFactory</code>. If no locator factory has
+     * been set or created a new instance of {@link org.apache.jackrabbit.webdav.simple.LocatorFactoryImpl} is
+     * returned.
+     *
+     * @return the locator factory
+     */
+    public DavLocatorFactory getLocatorFactory() {
+        if (locatorFactory == null) {
+            locatorFactory = new LocatorFactoryImpl(resourcePathPrefix);
+        }
+        return locatorFactory;
+    }
+
+    /**
+     * Returns the <code>LockManager</code>. If no lock manager has
+     * been set or created a new instance of {@link SimpleLockManager} is
+     * returned.
+     *
+     * @return the lock manager
+     */
+    public LockManager getLockManager() {
+        if (lockManager == null) {
+            lockManager = new SimpleLockManager();
+        }
+        return lockManager;
+    }
+
+    /**
+     * Returns the <code>DavResourceFactory</code>. If no request factory has
+     * been set or created a new instance of {@link ResourceFactoryImpl} is
+     * returned.
+     *
+     * @return the resource factory
+     */
+    public DavResourceFactory getResourceFactory() {
+        if (resourceFactory == null) {
+            resourceFactory = new ResourceFactoryImpl(getLockManager());
+        }
+        return resourceFactory;
+    }
+
+    /**
+     * Returns the header value retrieved from the {@link #INIT_PARAM_AUTHENTICATE_HEADER}
+     * init parameter. If the parameter is missing, the value defaults to
+     * {@link #DEFAULT_AUTHENTICATE_HEADER}.
+     *
+     * @return the header value retrieved from the corresponding init parameter
+     * or {@link #DEFAULT_AUTHENTICATE_HEADER}.
+     */
+    public String getAuthenticateHeaderValue() {
+        return authenticate_header;
+    }
+
+    /**
+     * Returns the <code>DavSessionProvider</code>.
+     *
+     * @return the session provider
+     */
+    public synchronized SessionProvider getRepositorySessionProvider() {
+        if (sessionProvider == null) {
+            CredentialsProvider cp = new CredentialsProvider() {
+                public Credentials getCredentials(HttpServletRequest request) throws LoginException, ServletException {
+                    return RepositoryAccessServlet.getCredentialsFromHeader(request.getHeader(DavConstants.HEADER_AUTHORIZATION));
+                }
+            };
+            sessionProvider = new SessionProviderImpl(cp);
+        }
+        return sessionProvider;
+    }
+
+    /**
+     * Returns the <code>DavSessionProvider</code>.
+     *
+     * @return the session provider
+     */
+    public synchronized DavSessionProvider getSessionProvider() {
+        if (davSessionProvider == null) {
+            davSessionProvider =
+                    new DavSessionProviderImpl(repository, getRepositorySessionProvider());
+        }
+        return davSessionProvider;
+    }
+
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/java/org/apache/jackrabbit/j2ee/SimpleWebdavServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/WEB-INF/catalog.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/WEB-INF/catalog.xml?rev=180346&r1=180345&r2=180346&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/WEB-INF/catalog.xml (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/WEB-INF/catalog.xml Mon Jun  6 10:36:09 2005
@@ -45,30 +45,6 @@
         />
 
         <!--
-            create a new node with the given node type using the systemid of
-            the resource to be imported. the current node of the import context
-            is set to the newly created node.
-            @param nodeType the node type of the node to be created
-            @return false
-        -->
-        <command
-            id="add-file"
-            className="org.apache.jackrabbit.server.io.AddNodeCommand"
-            nodeType="nt:file"
-        />
-
-        <!--
-            adds a mixin nodetype to the current node
-            @param nodeType the mixin node type to add
-            @return false
-        -->
-        <command
-            id="make-versionable"
-            className="org.apache.jackrabbit.server.io.AddMixinCommand"
-            nodeType="mix:versionable"
-        />
-
-        <!--
             if the content type matches 'text/xml' the content of the resource
             i considered as xml and deserialized into the jcr repository.
             @return false
@@ -86,6 +62,18 @@
             id="import-file"
             className="org.apache.jackrabbit.server.io.FileImportCommand"
         />
+        
+        <!--
+            adds a mixin nodetype to the current node
+            @param nodeType the mixin node type to add
+            @return false
+        -->
+        <command
+            id="make-versionable"
+            className="org.apache.jackrabbit.server.io.AddMixinCommand"
+            nodeType="mix:versionable"
+        />
+
     </chain>
 
     <!--
@@ -94,15 +82,17 @@
     <chain name="export-collection">
         <!--
             exports a HTML listing of the child nodes of the exported collection.
-            nodes having the 'collectionNodeType' node type are displayed as
-            directory links.
-            @param collectionNodeType node type for collections
+            nodes are displayed as directory links if they are either explicitely listed in the
+            'collectionNodeTypes' parameter or if they are NOT listed in the 'nonCollectionNodeTypes' 
+            parameter. if both parameters are omitted any child node is displayed as directory link.
+            @param collectionNodeTypes optional node type names for collections (comma separated)
+            @param nonCollectionNodeTypes optional node type names for non-collections (comma separated)
             @return true
         -->
         <command
             id="export-dirlisting"
             className="org.apache.jackrabbit.server.io.DirListingExportCommand"
-            collectionNodeType="nt:folder"
+            nonCollectionNodeTypes = "nt:resource, nt:file"
         />
     </chain>
 

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/WEB-INF/web.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/WEB-INF/web.xml?rev=180346&r1=180345&r2=180346&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/WEB-INF/web.xml (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/WEB-INF/web.xml Mon Jun  6 10:36:09 2005
@@ -14,7 +14,7 @@
             If you already have the repository registered in this appservers JNDI context,
             or if its accessible via RMI, you do not need to use this servlet.
         </description>
-        <servlet-class>org.apache.jackrabbit.server.RepositoryStartupServlet</servlet-class>
+        <servlet-class>org.apache.jackrabbit.j2ee.RepositoryStartupServlet</servlet-class>
 
         <init-param>
             <param-name>log4j-config</param-name>
@@ -77,7 +77,7 @@
             This servlet provides other servlets and jsps a common way to access
             the repository. The repository can be accessed via JNDI, RMI or Webdav.
         </description>
-        <servlet-class>org.apache.jackrabbit.client.RepositoryAccessServlet</servlet-class>
+        <servlet-class>org.apache.jackrabbit.j2ee.RepositoryAccessServlet</servlet-class>
 
         <init-param>
             <param-name>log4j-config</param-name>
@@ -126,11 +126,13 @@
         <!--
             RMI url, if RMI remoting is needed
         -->
+        <!--
         <init-param>
             <param-name>rmi-uri</param-name>
             <param-value>///jackrabbit.repository</param-value>
             <description>The URI for the RMI connection.</description>
         </init-param>
+        -->
 
         <load-on-startup>2</load-on-startup>
     </servlet>
@@ -143,7 +145,7 @@
         <description>
             The webdav servlet that connects HTTP request to the repository.
         </description>
-        <servlet-class>org.apache.jackrabbit.server.simple.WebdavServlet</servlet-class>
+        <servlet-class>org.apache.jackrabbit.j2ee.SimpleWebdavServlet</servlet-class>
 
         <init-param>
             <param-name>resource-path-prefix</param-name>
@@ -152,6 +154,18 @@
                 defines the prefix for spooling resources out of the repository.
             </description>
         </init-param>
+        <!--
+            Optional parameter to define the value of the 'WWW-Authenticate' header
+        -->
+        <!--
+        <init-param>
+            <param-name>authenticate-header</param-name>
+            <param-value>Basic Realm=Jackrabbit Webdav Server</param-value>
+            <description>
+                Defines the value of the 'WWW-Authenticate' header.
+            </description>
+        </init-param>
+        -->
         <init-param>
             <param-name>chain-catalog</param-name>
             <param-value>/WEB-INF/catalog.xml</param-value>
@@ -170,7 +184,7 @@
         <description>
             The webdav servlet that connects HTTP request to the repository.
         </description>
-        <servlet-class>org.apache.jackrabbit.server.jcr.JCRWebdavServerServlet</servlet-class>
+        <servlet-class>org.apache.jackrabbit.j2ee.JCRWebdavServerServlet</servlet-class>
 
         <init-param>
             <param-name>resource-path-prefix</param-name>

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/index.jsp
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/index.jsp?rev=180346&r1=180345&r2=180346&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/index.jsp (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webapp/src/webapp/index.jsp Mon Jun  6 10:36:09 2005
@@ -1,13 +1,13 @@
-<%@ page import="org.apache.jackrabbit.server.simple.WebdavServlet,
+<%@ page import="org.apache.jackrabbit.j2ee.SimpleWebdavServlet,
 		 javax.jcr.Repository,
-		 org.apache.jackrabbit.client.RepositoryAccessServlet"%><%
+		 org.apache.jackrabbit.j2ee.RepositoryAccessServlet"%><%
 %><html>
 <head>
 <title>Jackrabbit Examples</title>
 </head>
 <body>
 <ul>
-<li><a href="<%= request.getContextPath() %><%= WebdavServlet.getPathPrefix() %>/">Repository Browser</a></li>
+<li><a href="<%= request.getContextPath() %><%= SimpleWebdavServlet.getPathPrefix() %>/">Repository Browser</a></li>
 <%--
 <li><a href="<%= request.getContextPath() %>/example.jsp">Repository Servlet Example</a></li>
 --%>

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/project.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/project.xml?rev=180346&r1=180345&r2=180346&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/project.xml (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/project.xml Mon Jun  6 10:36:09 2005
@@ -29,16 +29,21 @@
     <!-- D E P E N D E N C I E S                                                -->
     <!-- ====================================================================== -->
     <dependencies>
+        <!-- internal dependencies -->
         <dependency>
-            <groupId>jsr170</groupId>
-            <artifactId>jcr</artifactId>
-            <version>0.16.4.1</version>
-            <url>http://www.day.com/maven/jsr170/jars/jcr-0.16.4.1.jar</url>
+            <artifactId>commons-jcr</artifactId>
+            <groupId>jcr-server</groupId>
+            <version>${pom.currentVersion}</version>
         </dependency>
+
+        <!-- external dependencies -->
         <dependency>
-            <id>jackrabbit</id>
-            <version>0.16.4.1-dev</version>
+            <groupId>jsr170</groupId>
+            <artifactId>jcr</artifactId>
+            <version>${jackrabbit.build.version.jcr}</version>
         </dependency>
+        
+        <!-- non-jackrabbit dependencies -->
         <dependency>
             <id>jdom</id>
             <version>1.0</version>

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/DavSessionProvider.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/DavSessionProvider.java?rev=180346&r1=180345&r2=180346&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/DavSessionProvider.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/DavSessionProvider.java Mon Jun  6 10:36:09 2005
@@ -32,9 +32,11 @@
      * A session will not be available if an exception is thrown.
      *
      * @param request
+     * @return <code>true</code> if the session was attached to the request;
+     *         <code>false</code> otherwise.
      * @throws DavException if a problem occurred while obtaining the session
      */
-    public void acquireSession(WebdavRequest request) throws DavException;
+    public boolean attachSession(WebdavRequest request) throws DavException;
 
     /**
      * Releases the reference from the request to the session.

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java?rev=180346&r1=180345&r2=180346&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java Mon Jun  6 10:36:09 2005
@@ -16,7 +16,6 @@
 package org.apache.jackrabbit.webdav;
 
 import org.apache.log4j.Logger;
-import org.apache.jackrabbit.webdav.util.Text;
 import org.apache.jackrabbit.webdav.lock.LockInfo;
 import org.apache.jackrabbit.webdav.lock.Type;
 import org.apache.jackrabbit.webdav.lock.Scope;
@@ -29,6 +28,7 @@
 import org.apache.jackrabbit.webdav.header.DepthHeader;
 import org.apache.jackrabbit.webdav.header.IfHeader;
 import org.apache.jackrabbit.webdav.header.CodedUrlHeader;
+import org.apache.jackrabbit.util.Text;
 import org.jdom.input.SAXBuilder;
 import org.jdom.JDOMException;
 import org.jdom.Document;
@@ -252,9 +252,9 @@
                 requestDocument = builder.build(in);
             }
         } catch (IOException e) {
-            log.warn("Error while reading the request body: " + e.getMessage());
+            log.debug("Unable to build an XML Document from the request body: " + e.getMessage());
         } catch (JDOMException e) {
-            log.warn("Error while building xml document from request body: " + e.getMessage());
+            log.debug("Unable to build an XML Document from the request body: " + e.getMessage());
         }
         return requestDocument;
     }

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java?rev=180346&r1=180345&r2=180346&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavResponseImpl.java Mon Jun  6 10:36:09 2005
@@ -61,17 +61,11 @@
      * @see DavServletResponse#sendErrorResponse(org.apache.jackrabbit.webdav.DavException)
      */
     public void sendErrorResponse(DavException exception) throws IOException {
-        // special handling for unauthorized, should be done nicer
-        if (exception.getErrorCode() == HttpServletResponse.SC_UNAUTHORIZED) {
-            httpResponse.setHeader("WWW-Authenticate", "Basic Realm=Jackrabbit Webdav Server");
+        Element errorElem = exception.getError();
+        if (errorElem == null || errorElem.getChildren().size() == 0) {
             httpResponse.sendError(exception.getErrorCode(), exception.getStatusPhrase());
         } else {
-            Element errorElem = exception.getError();
-            if (errorElem == null || errorElem.getChildren().size() == 0) {
-                httpResponse.sendError(exception.getErrorCode(), exception.getStatusPhrase());
-            } else {
-                sendXmlResponse(new Document(exception.getError()), exception.getErrorCode());
-            }
+            sendXmlResponse(new Document(exception.getError()), exception.getErrorCode());
         }
     }
 

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java?rev=180346&r1=180345&r2=180346&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/lock/DefaultActiveLock.java Mon Jun  6 10:36:09 2005
@@ -15,7 +15,7 @@
  */
 package org.apache.jackrabbit.webdav.lock;
 
-import org.apache.jackrabbit.core.util.uuid.UUID;
+import org.apache.jackrabbit.util.uuid.UUID;
 import org.apache.jackrabbit.webdav.DavConstants;
 
 /**

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java?rev=180346&r1=180345&r2=180346&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/lock/SimpleLockManager.java Mon Jun  6 10:36:09 2005
@@ -19,7 +19,7 @@
 import java.util.Iterator;
 
 import org.apache.jackrabbit.webdav.*;
-import org.apache.jackrabbit.webdav.util.Text;
+import org.apache.jackrabbit.util.Text;
 
 /**
  * Simple manager for webdav locks.<br>

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java?rev=180346&r1=180345&r2=180346&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/property/DavPropertyNameSet.java Mon Jun  6 10:36:09 2005
@@ -22,6 +22,7 @@
 import java.util.HashSet;
 import java.util.Collection;
 import java.util.List;
+import java.util.Iterator;
 
 /**
  * <code>DavPropertyNameSet</code> represents a Set of {@link DavPropertyName}
@@ -99,5 +100,25 @@
         } else {
             return false;
         }
+    }
+
+    /**
+     * Returns the xml representation of this property name set with the
+     * following format:
+     * <pre>
+     * &lt;!ELEMENT prop (ANY) &gt;
+     * where ANY consists of a list of elements each reflecting the xml
+     * representation of an entry in this set.
+     * </pre>
+     *
+     * @return xml representation
+     */
+    public Element toXml() {
+        Element prop = new Element(DavConstants.XML_PROP, DavConstants.NAMESPACE);
+        Iterator it = super.iterator();
+        while (it.hasNext()) {
+            prop.addContent(((DavPropertyName)it.next()).toXml());
+        }
+        return prop;
     }
 }

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ReportType.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ReportType.java?rev=180346&r1=180345&r2=180346&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ReportType.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ReportType.java Mon Jun  6 10:36:09 2005
@@ -47,9 +47,9 @@
      * @see #register(String, Namespace, Class)
      */
     private ReportType(String name, Namespace namespace, Class reportClass) {
-	this.name = name;
-	this.namespace = namespace;
-	this.reportClass = reportClass;
+        this.name = name;
+        this.namespace = namespace;
+        this.reportClass = reportClass;
     }
 
     /**
@@ -59,21 +59,22 @@
      * @throws DavException
      */
     public Report createReport() throws DavException {
-	try {
-	    return (Report) reportClass.getConstructor(new Class[0]).newInstance(new Object[0]);
-	} catch (Exception e) {
-	    // should never occur
-	    throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to register Report.");
-	}
-    }    
+        try {
+            return (Report) reportClass.getConstructor(new Class[0]).newInstance(new Object[0]);
+        } catch (Exception e) {
+            // should never occur
+            throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to register Report.");
+        }
+    }
 
     /**
-     * Returns an Xml element representing this report type
+     * Returns an Xml element representing this report type. It may be used to
+     * build the body for a REPORT request.
      *
      * @return Xml representation
      */
     public Element toXml() {
-	return new Element(name, namespace);
+        return new Element(name, namespace);
     }
 
     /**
@@ -84,13 +85,13 @@
      * @return
      */
     public boolean isRequestedReportType(ReportInfo reqInfo) {
-	if (reqInfo != null) {
-	    Element elem = reqInfo.getReportElement();
-	    if (elem != null) {
-		return name.equals(elem.getName()) && namespace.equals(elem.getNamespace());
-	    }
-	}
-	return false;
+        if (reqInfo != null) {
+            Element elem = reqInfo.getReportElement();
+            if (elem != null) {
+                return name.equals(elem.getName()) && namespace.equals(elem.getNamespace());
+            }
+        }
+        return false;
     }
 
     /**
@@ -106,34 +107,34 @@
      * it does not provide an empty constructor.
      */
     public static ReportType register(String name, Namespace namespace, Class reportClass) {
-	if (name == null || namespace == null || reportClass == null) {
-	    throw new IllegalArgumentException("A ReportType cannot be registered with a null name, namespace or report class");
-	}
-
-	String key = buildKey(namespace, name);
-	if (types.containsKey(key)) {
-	    return (ReportType) types.get(key);
-	} else {
-	    // test if this report class has an empty constructor and implements Report interface
-	    boolean isValidClass = false;
-	    Class[] interfaces = reportClass.getInterfaces();
-	    for (int i = 0; i < interfaces.length && !isValidClass; i++) {
-		isValidClass = (interfaces[i] == Report.class);
-	    }
-	    if (!isValidClass) {
-		throw new IllegalArgumentException("The specified report class must implement the Report interface.");
-	    }
-
-	    try {
-		reportClass.getConstructor(new Class[0]);
-	    } catch (NoSuchMethodException e) {
-		throw new IllegalArgumentException("The specified report class must provide a default constructor.");
-	    }
-
-	    ReportType type = new ReportType(name, namespace, reportClass);
-	    types.put(key, type);
-	    return type;
-	}
+        if (name == null || namespace == null || reportClass == null) {
+            throw new IllegalArgumentException("A ReportType cannot be registered with a null name, namespace or report class");
+        }
+
+        String key = buildKey(namespace, name);
+        if (types.containsKey(key)) {
+            return (ReportType) types.get(key);
+        } else {
+            // test if this report class has an empty constructor and implements Report interface
+            boolean isValidClass = false;
+            Class[] interfaces = reportClass.getInterfaces();
+            for (int i = 0; i < interfaces.length && !isValidClass; i++) {
+                isValidClass = (interfaces[i] == Report.class);
+            }
+            if (!isValidClass) {
+                throw new IllegalArgumentException("The specified report class must implement the Report interface.");
+            }
+
+            try {
+                reportClass.getConstructor(new Class[0]);
+            } catch (NoSuchMethodException e) {
+                throw new IllegalArgumentException("The specified report class must provide a default constructor.");
+            }
+
+            ReportType type = new ReportType(name, namespace, reportClass);
+            types.put(key, type);
+            return type;
+        }
     }
 
     /**
@@ -145,15 +146,15 @@
      * if the requested report type has not been registered yet.
      */
     public static ReportType getType(ReportInfo reportInfo) {
-	if (reportInfo == null) {
-	    throw new IllegalArgumentException("ReportInfo must not be null.");
-	}
-	String key = buildKey(reportInfo.getReportElement().getNamespace(), reportInfo.getReportElement().getName());
-	if (types.containsKey(key)) {
-	    return (ReportType) types.get(key);
-	} else {
-	    throw new IllegalArgumentException("The request report '"+key+"' has not been registered yet.");
-	}
+        if (reportInfo == null) {
+            throw new IllegalArgumentException("ReportInfo must not be null.");
+        }
+        String key = buildKey(reportInfo.getReportElement().getNamespace(), reportInfo.getReportElement().getName());
+        if (types.containsKey(key)) {
+            return (ReportType) types.get(key);
+        } else {
+            throw new IllegalArgumentException("The request report '"+key+"' has not been registered yet.");
+        }
     }
 
     /**
@@ -164,6 +165,6 @@
      * @return key identifying the report with the given namespace and name
      */
     private static String buildKey(Namespace namespace, String name) {
-	return "{" + namespace.getURI() + "}" + name;
+        return "{" + namespace.getURI() + "}" + name;
     }
 }



Mime
View raw message