jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ste...@apache.org
Subject svn commit: rev 53989 - in incubator/jackrabbit/trunk: . src/conf src/java/org/apache/jackrabbit/core src/java/org/apache/jackrabbit/core/config src/java/org/apache/jackrabbit/core/jndi
Date Thu, 07 Oct 2004 15:36:57 GMT
Author: stefan
Date: Thu Oct  7 08:36:56 2004
New Revision: 53989

Added:
   incubator/jackrabbit/trunk/src/conf/repository.xml   (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/AbstractConfig.java
  (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/RepositoryConfig.java
  (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/WorkspaceConfig.java
  (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/config.dtd   (contents,
props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/jndi/
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/jndi/BindableRepository.java
  (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/jndi/BindableRepositoryFactory.java
  (contents, props changed)
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/jndi/RegistryHelper.java
  (contents, props changed)
Modified:
   incubator/jackrabbit/trunk/ToDo.txt
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java
Log:
changing repository bootstrapping/configuration layout 
and adding jndi support
(work in progress)


Modified: incubator/jackrabbit/trunk/ToDo.txt
==============================================================================
--- incubator/jackrabbit/trunk/ToDo.txt	(original)
+++ incubator/jackrabbit/trunk/ToDo.txt	Thu Oct  7 08:36:56 2004
@@ -4,7 +4,6 @@
 the following list is not yet categorized/prioritized, neither 
 is it complete :(
 
-- search
 - locking
 - jta support
 - access control
@@ -12,7 +11,7 @@
   files) leads to *very* slow performance in a normal filesystem;
   see next issues for solutions 
 - use jdbc as an alternative to virtual filesystem persistence layer
-- use an alternative journaling filesystem as (transactional) persistence layer 
+- use an alternative journaling store as (transactional) persistence layer 
 - provide clean abstraction for persistence grouping (nodes & properties 
   that should be stored/loaded together in the persistence layer);
   (e.g. properties are stored within .node.xml)
@@ -25,12 +24,12 @@
     operation (move, remove, copy)
 - HierarchyManager: cache Path objects (key: ItemId, value: Path[]);
   update cache on hierarchy changes (move, hardlink, remove, etc) 
-- inline @todo comments: resolve/implement
 - gracefull repository shutdown:
   - shutdown repository
   - close workspaces
   - close abstract file systems (e.g. flush dirty buffers, etc.)
   - trap JVM shutdown in RepositoryFactory? (Runtime#addShutdownHook)
+- inline @todo comments: resolve/implement
 - ItemState: hide STATUS_* flags, use set* and is* methods instead
 - javaDoc, javaDoc, javaDoc
 - logging: use commons logging instead of log4j

Added: incubator/jackrabbit/trunk/src/conf/repository.xml
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/conf/repository.xml	Thu Oct  7 08:36:56 2004
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- <!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Repository//EN"
"file://config.dtd"> -->
+<Repository>
+    <!--
+        virtual file system where the repository stores global state
+        (e.g. registered namespaces, custom node types, etc.)
+    -->
+    <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+    	<param name="path" value="${rep.home}/repository"/>
+    </FileSystem>
+    <!--
+        location of workspaces root directory and name of default workspace
+    -->
+    <Workspaces rootPath="${rep.home}/workspaces" defaultWorkspace="default" />
+    <!--
+        workspace configuration template:
+        used to create the initial workspace if there's no workspace yet
+    -->
+    <Workspace name="${wsp.name}">
+        <!--
+            virtual file system of the workspace
+        -->
+        <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+            <param name="path" value="${wsp.home}"/>
+        </FileSystem>
+        <PersistenceManager class="org.apache.jackrabbit.core.state.xml.XMLPersistenceManager">
+            <!-- <param name="someParam" value="someValue"/> -->
+        </PersistenceManager>
+        <SearchIndex path="${wsp.home}/index"/>
+    </Workspace>
+</Repository>
\ No newline at end of file

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/RepositoryImpl.java	Thu
Oct  7 08:36:56 2004
@@ -190,16 +190,16 @@
                     // persist uuid of the repository's root node
                     OutputStream out = uuidFile.getOutputStream();
 /*
-		    // store uuid in binary format
-		    try {
-			out.write(rootUUID.getBytes());
-		    } finally {
-			try {
-			    out.close();
-			} catch (IOException ioe) {
-			    // ignore
-			}
-		    }
+                    // store uuid in binary format
+                    try {
+                        out.write(rootUUID.getBytes());
+                    } finally {
+                        try {
+                            out.close();
+                        } catch (IOException ioe) {
+                            // ignore
+                        }
+                    }
 */
                     // store uuid in text format for better readability
                     OutputStreamWriter writer = new OutputStreamWriter(out);
@@ -454,15 +454,15 @@
      * @throws RepositoryException
      */
     private PersistenceManager createPersistenceManager(WorkspaceDef wspDef) throws RepositoryException
{
-        PersistenceManager perstistMgr;
+        PersistenceManager persistMgr;
         String className = wspDef.getPersistenceManagerClass();
         try {
             // Create the persistence manager object
             Class c = Class.forName(className);
-            perstistMgr = (PersistenceManager) c.newInstance();
+            persistMgr = (PersistenceManager) c.newInstance();
             // set the properties of the persistence manager object from the
             // param hashmap
-            BeanMap bm = new BeanMap(perstistMgr);
+            BeanMap bm = new BeanMap(persistMgr);
             HashMap params = wspDef.getPersistenceManagerParams();
             Iterator iter = params.keySet().iterator();
             while (iter.hasNext()) {
@@ -470,12 +470,12 @@
                 Object value = params.get(name);
                 bm.put(name, value);
             }
-            perstistMgr.init(wspDef);
+            persistMgr.init(wspDef);
         } catch (Exception e) {
             log.error("Cannot instantiate implementing class " + className, e);
             throw new RepositoryException("Cannot instantiate implementing class " + className,
e);
         }
-        return perstistMgr;
+        return persistMgr;
     }
 
     /**

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/Test.java	Thu Oct  7 08:36:56
2004
@@ -16,6 +16,8 @@
 package org.apache.jackrabbit.core;
 
 import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
+import org.apache.jackrabbit.core.jndi.RegistryHelper;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
 import org.apache.log4j.Logger;
 import org.apache.log4j.PropertyConfigurator;
 
@@ -24,10 +26,11 @@
 import javax.jcr.nodetype.NodeTypeIterator;
 import javax.jcr.nodetype.NodeTypeManager;
 import javax.jcr.util.TraversingItemVisitor;
+import javax.naming.InitialContext;
+import javax.naming.Context;
+import javax.naming.Reference;
 import java.io.*;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Properties;
+import java.util.*;
 
 public class Test {
     private static Logger log = Logger.getLogger(Test.class);
@@ -49,7 +52,25 @@
             // fallback to cwd
             factoryHomeDir = System.getProperty("user.dir");
         }
+/*
+        RepositoryConfig repConf = RepositoryConfig.create(configDir + "/" + "repository.xml",
factoryHomeDir);
+        Collection wspConfigs = repConf.getWorkspaceConfigs();
+*/
+/*
+        // Set up the environment for creating the initial context
+        Hashtable env = new Hashtable();
+        //env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
+        //env.put(Context.PROVIDER_URL, "file:./jndi");
 
+        //env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ervacon.xnam.XMLInitialContextFactory");
+        //env.put(Context.PROVIDER_URL, "d:/temp/jndi.xml");
+
+        env.put(Context.INITIAL_CONTEXT_FACTORY, "org.codehaus.spice.jndikit.memory.StaticMemoryInitialContextFactory");
+        InitialContext ctx = new InitialContext(env);
+        RegistryHelper.registerRepository(ctx, "blah", configFile, factoryHomeDir, true);
+        Repository repo1 = (Repository) ctx.lookup("blah");
+        Repository repo2 = (Repository) ctx.lookup("blah");
+*/
         RepositoryFactory rf = RepositoryFactory.create(configFile, factoryHomeDir);
         Repository r = rf.getRepository("localfs");
         Session session = r.login(new SimpleCredentials("anonymous", "".toCharArray()), null);

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/AbstractConfig.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/AbstractConfig.java
Thu Oct  7 08:36:56 2004
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2004 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.core.config;
+
+import org.apache.commons.collections.BeanMap;
+import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.log4j.Logger;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.input.SAXBuilder;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import javax.jcr.RepositoryException;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <code>AbstractConfig</code> is the superclass of
+ * <code>RepositoryConfig</code> and <code>WorkspaceConfig</code>.
+ */
+abstract class AbstractConfig implements EntityResolver {
+    private static Logger log = Logger.getLogger(AbstractConfig.class);
+
+    public static final String CONFIG_DTD_RESOURCE_PATH =
+            "org/apache/jackrabbit/core/config/config.dtd";
+
+    protected static final String FILE_SYSTEM_ELEMENT = "FileSystem";
+    protected static final String PATH_ATTRIB = "path";
+    protected static final String PARAM_ELEMENT = "param";
+    protected static final String CLASS_ATTRIB = "class";
+    protected static final String NAME_ATTRIB = "name";
+    protected static final String VALUE_ATTRIB = "value";
+
+    protected final String configId;
+    protected final Document config;
+
+    /**
+     * constructor
+     *
+     * @param is
+     */
+    protected AbstractConfig(InputSource is) throws RepositoryException {
+        configId = is.getSystemId() == null ? "[???]" : is.getSystemId();
+        try {
+            SAXBuilder parser = new SAXBuilder();
+            parser.setEntityResolver(this);
+            config = parser.build(is);
+        } catch (Exception e) {
+            String msg = "error while parsing config file " + is.getSystemId();
+            log.error(msg, e);
+            throw new RepositoryException(msg, e);
+        }
+    }
+
+    /**
+     * @param fsConfig
+     * @param variables
+     * @return
+     * @throws RepositoryException
+     */
+    protected FileSystem createFileSystem(Element fsConfig, Map variables)
+            throws RepositoryException {
+        FileSystem fs;
+        String className = "";
+        try {
+            // create the file system object
+            className = fsConfig.getAttributeValue(CLASS_ATTRIB);
+            Class c = Class.forName(className);
+            fs = (FileSystem) c.newInstance();
+
+            // set the properties of the file system object from the
+            // param elements in the config
+            BeanMap bm = new BeanMap(fs);
+            List paramList = fsConfig.getChildren(PARAM_ELEMENT);
+            for (Iterator i = paramList.iterator(); i.hasNext();) {
+                Element param = (Element) i.next();
+                String paramName = param.getAttributeValue(NAME_ATTRIB);
+                String paramValue = param.getAttributeValue(VALUE_ATTRIB);
+                // replace variables in param value
+                bm.put(paramName, replaceVars(paramValue, variables));
+            }
+            fs.init();
+        } catch (Exception e) {
+            String msg = "Cannot instantiate implementing class " + className;
+            log.error(msg, e);
+            throw new RepositoryException(msg, e);
+        }
+        return fs;
+    }
+
+    /**
+     * Helper method that replaces in the given string any occurences of the keys
+     * in the specified map with their associated values.
+     *
+     * @param s
+     * @param vars
+     * @return
+     */
+    protected static String replaceVars(String s, Map vars) {
+        if (vars.size() == 0) {
+            return s;
+        }
+        Iterator iter = vars.keySet().iterator();
+        while (iter.hasNext()) {
+            String varName = (String) iter.next();
+            String varValue = (String) vars.get(varName);
+            int pos;
+            int lastPos = 0;
+            StringBuffer sb = new StringBuffer(s.length());
+            while ((pos = s.indexOf(varName, lastPos)) != -1) {
+                sb.append(s.substring(lastPos, pos));
+                sb.append(varValue);
+                lastPos = pos + varName.length();
+            }
+            if (lastPos < s.length()) {
+                sb.append(s.substring(lastPos));
+            }
+            s = sb.toString();
+        }
+        return s;
+    }
+
+    //------------------------------------------------------< EntityResolver >
+    /**
+     * @see EntityResolver#resolveEntity(String, String)
+     */
+    public abstract InputSource resolveEntity(String publicId, String systemId)
+            throws SAXException, IOException;
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/RepositoryConfig.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/RepositoryConfig.java
Thu Oct  7 08:36:56 2004
@@ -0,0 +1,325 @@
+/*
+ * Copyright 2004 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.core.config;
+
+import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.log4j.Logger;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.DocType;
+import org.jdom.output.XMLOutputter;
+import org.jdom.output.Format;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import javax.jcr.RepositoryException;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.FileOutputStream;
+import java.util.Collection;
+import java.util.HashMap;
+
+/**
+ * A <code>RepositoryConfig</code> ...
+ */
+public class RepositoryConfig extends AbstractConfig {
+    private static Logger log = Logger.getLogger(RepositoryConfig.class);
+
+    /**
+     * name of repository configuration file
+     */
+    public static final String CONFIG_FILE_NAME = "repository.xml";
+
+    /**
+     * public id
+     */
+    public static final String PUBLIC_ID = "-//The Apache Software Foundation//DTD Repository//EN";
+
+    private static final String WORKSPACES_ELEMENT = "Workspaces";
+    private static final String ROOT_PATH_ATTRIB = "rootPath";
+    private static final String DEFAULT_WORKSPACE_ATTRIB = "defaultWorkspace";
+
+    private static final String WORKSPACE_ELEMENT = "Workspace";
+
+    /**
+     * wellknown variables (will be replaced with their respective values
+     * whereever they occur within the configuration)
+     */
+    public static final String REPOSITORY_HOME_VARIABLE = "${rep.home}";
+
+    /**
+     * map of variable names and their respective values
+     */
+    private final HashMap vars;
+
+    /**
+     * map of workspace names and workspace configurations
+     */
+    private final HashMap wspConfigs;
+
+    /**
+     * repository home directory
+     */
+    private String repHomeDir;
+
+    /**
+     * virtual file system where the repository stores global state
+     */
+    private FileSystem repFS;
+
+    /**
+     * workspaces config root directory (i.e. folder that contains
+     * a subfolder with a workspace configuration file for every workspace
+     * in the repository)
+     */
+    private String wspConfigRootDir;
+
+    /**
+     * name of default workspace
+     */
+    private String defaultWspName;
+
+    /**
+     * private constructor.
+     *
+     * @param is
+     * @param repHomeDir
+     * @throws RepositoryException
+     */
+    private RepositoryConfig(InputSource is, String repHomeDir)
+            throws RepositoryException {
+        super(is);
+        this.repHomeDir = repHomeDir;
+        wspConfigs = new HashMap();
+        // initialize variables
+        vars = new HashMap();
+        vars.put(REPOSITORY_HOME_VARIABLE, repHomeDir);
+        // read config
+        init(config);
+    }
+
+    /**
+     * Initializes this <code>RepositoryConfig</code> object.
+     *
+     * @param config
+     * @throws RepositoryException
+     */
+    protected void init(Document config) throws RepositoryException {
+        // file system
+        Element fsConfig = config.getRootElement().getChild(FILE_SYSTEM_ELEMENT);
+        repFS = createFileSystem(fsConfig, vars);
+
+        // workspaces
+        Element wspsElem = config.getRootElement().getChild(WORKSPACES_ELEMENT);
+        wspConfigRootDir = replaceVars(wspsElem.getAttributeValue(ROOT_PATH_ATTRIB), vars);
+        defaultWspName = replaceVars(wspsElem.getAttributeValue(DEFAULT_WORKSPACE_ATTRIB),
vars);
+
+        // load wsp configs
+        File wspRoot = new File(wspConfigRootDir);
+        if (!wspRoot.exists()) {
+            wspRoot.mkdir();
+        }
+        File[] files = wspRoot.listFiles();
+        if (files == null) {
+            String msg = "invalid repsitory home directory";
+            log.error(msg);
+            throw new RepositoryException(msg);
+        }
+        for (int i = 0; i < files.length; i++) {
+            // check if <subfolder>/workspace.xml exists
+            File configFile = new File(files[i], WorkspaceConfig.CONFIG_FILE_NAME);
+            if (configFile.isFile()) {
+                // create workspace config
+                WorkspaceConfig wspConfig = WorkspaceConfig.create(configFile.getPath(),
configFile.getParent());
+                String wspName = wspConfig.getName();
+                if (wspConfigs.containsKey(wspName)) {
+                    String msg = "duplicate workspace name: " + wspName;
+                    log.error(msg);
+                    throw new RepositoryException(msg);
+                }
+                wspConfigs.put(wspName, wspConfig);
+            }
+        }
+        if (wspConfigs.isEmpty()) {
+            // create initial default workspace
+            createWorkspaceConfig(defaultWspName);
+        }
+    }
+
+    /**
+     * Creates a new <code>RepositoryFactory</code> instance. The configuration
+     * is read from the specified configuration file.
+     *
+     * @param configFilePath path to the configuration file
+     * @param repHomeDir     repository home directory
+     * @return a new <code>RepositoryConfig</code> instance
+     * @throws RepositoryException If an error occurs
+     */
+    public static RepositoryConfig create(String configFilePath, String repHomeDir) throws
RepositoryException {
+        try {
+            File config = new File(configFilePath);
+            InputSource is = new InputSource(new FileReader(config));
+            is.setSystemId(config.toURI().toString());
+            return new RepositoryConfig(is, repHomeDir);
+        } catch (IOException ioe) {
+            String msg = "error while reading config file " + configFilePath;
+            log.error(msg, ioe);
+            throw new RepositoryException(msg, ioe);
+        }
+    }
+
+    /**
+     * Creates a new <code>RepositoryConfig</code> instance. The configuration
+     * is read from the specified input source.
+     *
+     * @param is         <code>InputSource</code> where the configuration is
read from
+     * @param repHomeDir repository home directory
+     * @return a new <code>RepositoryConfig</code> instance
+     * @throws RepositoryException If an error occurs
+     */
+    public static RepositoryConfig create(InputSource is, String repHomeDir) throws RepositoryException
{
+        return new RepositoryConfig(is, repHomeDir);
+    }
+
+    /**
+     * Returns the home directory of the repository.
+     *
+     * @return the home directory of the repository
+     */
+    public String getHomeDir() {
+        return repHomeDir;
+    }
+
+    /**
+     * Returns the virtual file system where the repository stores global state.
+     *
+     * @return the virtual file system where the repository stores global state
+     */
+    public FileSystem getFileSystem() {
+        return repFS;
+    }
+
+    /**
+     * Returns workspaces config root directory (i.e. the folder that contains
+     * a subfolder with a workspace configuration file for every workspace
+     * in the repository).
+     *
+     * @return the workspaces config root directory
+     */
+    public String getWorkspacesConfigRootDir() {
+        return wspConfigRootDir;
+    }
+
+    /**
+     * Returns the name of the default workspace.
+     *
+     * @return the name of the default workspace
+     */
+    public String getDefaultWorkspaceName() {
+        return defaultWspName;
+    }
+
+    /**
+     * Returns all workspace configurations.
+     *
+     * @return a collection of <code>WorkspaceConfig</code> objects.
+     */
+    public Collection getWorkspaceConfigs() {
+        return wspConfigs.values();
+    }
+
+    /**
+     * Returns the configuration of the specified workspace.
+     *
+     * @param name workspace name
+     * @return a <code>WorkspaceConfig</code> object or <code>null</code>
+     *         if no such workspace exists.
+     */
+    public WorkspaceConfig getWorkspaceConfig(String name) {
+        return (WorkspaceConfig) wspConfigs.get(name);
+    }
+
+    /**
+     * Creates a new workspace configuration with the specified name.
+     *
+     * @param name workspace name
+     * @throws RepositoryException if the specified name already exists or
+     *                             if an error occured during the creation.
+     */
+    public void createWorkspaceConfig(String name) throws RepositoryException {
+        if (wspConfigs.containsKey(name)) {
+            String msg = "A workspace with the specified name alreay exists";
+            log.error(msg);
+            throw new RepositoryException(msg);
+        }
+        // create the workspace folder (i.e. the workspace home directory)
+        File wspFolder = new File(wspConfigRootDir, name);
+        if (!wspFolder.mkdir()) {
+            String msg = "Failed to create the workspace home directory: " + wspFolder.getPath();
+            log.error(msg);
+            throw new RepositoryException(msg);
+        }
+        // clone the workspace definition template
+        Element wspCongigElem = (Element) config.getRootElement().getChild(WORKSPACE_ELEMENT).clone();
+        wspCongigElem.setAttribute(NAME_ATTRIB, name);
+
+        // create workspace.xml file
+/*
+        DocType docType = new DocType(WORKSPACE_ELEMENT, null, WorkspaceConfig.PUBLIC_ID);
+        Document doc = new Document(wspCongigElem, docType);
+*/
+        Document doc = new Document(wspCongigElem);
+        XMLOutputter out = new XMLOutputter(Format.getPrettyFormat());
+        File configFile = new File(wspFolder, WorkspaceConfig.CONFIG_FILE_NAME);
+        FileOutputStream fos = null;
+        try {
+            fos = new FileOutputStream(configFile);
+            out.output(doc, fos);
+        } catch (IOException ioe) {
+            String msg = "Failed to create workspace configuration file: " + configFile.getPath();
+            log.error(msg, ioe);
+            throw new RepositoryException(msg, ioe);
+        } finally {
+            if (fos != null) {
+                try {
+                    fos.close();
+                } catch (IOException e) {
+                    // ignore
+                }
+            }
+        }
+
+        // create workspace config object
+        WorkspaceConfig wspConfig = WorkspaceConfig.create(configFile.getPath(), configFile.getParent());
+        wspConfigs.put(name, wspConfig);
+    }
+
+    //------------------------------------------------------< EntityResolver >
+    /**
+     * @see org.xml.sax.EntityResolver#resolveEntity(String, String)
+     */
+    public InputSource resolveEntity(String publicId, String systemId)
+            throws SAXException, IOException {
+        if (publicId.equals(PUBLIC_ID)) {
+            // load dtd resource
+            return new InputSource(getClass().getClassLoader().getResourceAsStream(CONFIG_DTD_RESOURCE_PATH));
+        } else {
+            // use the default behaviour
+            return null;
+        }
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/WorkspaceConfig.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/WorkspaceConfig.java
Thu Oct  7 08:36:56 2004
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2004 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.core.config;
+
+import org.apache.commons.collections.BeanMap;
+import org.apache.jackrabbit.core.fs.FileSystem;
+import org.apache.jackrabbit.core.state.PersistenceManager;
+import org.apache.log4j.Logger;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import javax.jcr.RepositoryException;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A <code>WorkspaceConfig</code> ...
+ */
+public class WorkspaceConfig extends AbstractConfig {
+    private static Logger log = Logger.getLogger(WorkspaceConfig.class);
+
+    /**
+     * name of workspace configuration file
+     */
+    public static final String CONFIG_FILE_NAME = "workspace.xml";
+
+    /**
+     * public id
+     */
+    public static final String PUBLIC_ID = "-//The Apache Software Foundation//DTD Workspace//EN";
+
+    private static final String PERSISTENCE_MANAGER_ELEMENT = "PersistenceManager";
+    private static final String SEARCH_INDEX_ELEMENT = "SearchIndex";
+
+    /**
+     * wellknown variables (will be replaced with their respective values
+     * whereever they occur within the configuration)
+     */
+    public static final String WORKSPACE_HOME_VARIABLE = "${wsp.home}";
+    public static final String WORKSPACE_NAME_VARIABLE = "${wsp.name}";
+
+    private final HashMap vars;
+
+    /**
+     * workspace home directory
+     */
+    private String wspHomeDir;
+
+    /**
+     * virtual file system where the workspace stores meta data etc.
+     */
+    private FileSystem wspFS;
+
+    /**
+     * workspace name
+     */
+    private String wspName;
+
+    /**
+     * persistence manager of the workspace
+     */
+    private PersistenceManager persistMgr;
+
+    /**
+     * search index direcorty
+     */
+    private String searchIndexDir;
+
+    /**
+     * private constructor.
+     *
+     * @param is
+     * @param wspHomeDir
+     * @throws RepositoryException
+     */
+    private WorkspaceConfig(InputSource is, String wspHomeDir)
+            throws RepositoryException {
+        super(is);
+        this.wspHomeDir = wspHomeDir;
+        // initialize variables
+        vars = new HashMap();
+        vars.put(WORKSPACE_HOME_VARIABLE, wspHomeDir);
+        // read config
+        init(config);
+    }
+
+    /**
+     * Initializes this <code>WorkspaceConfig</code> object.
+     *
+     * @param config
+     * @throws RepositoryException
+     */
+    protected void init(Document config) throws RepositoryException {
+        Element wspElem = config.getRootElement();
+        // name
+        wspName = replaceVars(wspElem.getAttributeValue(NAME_ATTRIB), vars);
+        // set name variable
+        vars.put(WORKSPACE_NAME_VARIABLE, wspName);
+
+        // file system
+        Element fsConfig = wspElem.getChild(FILE_SYSTEM_ELEMENT);
+        wspFS = createFileSystem(fsConfig, vars);
+
+        // search index directory
+        searchIndexDir = replaceVars(wspElem.getChild(SEARCH_INDEX_ELEMENT).getAttributeValue(PATH_ATTRIB),
vars);
+
+        // persistence manager
+        String className = wspElem.getChild(PERSISTENCE_MANAGER_ELEMENT).getAttributeValue(CLASS_ATTRIB);
+        // read the PersistenceManager properties from the
+        // param elements in the config
+        HashMap params = new HashMap();
+        List paramList = wspElem.getChild(PERSISTENCE_MANAGER_ELEMENT).getChildren(PARAM_ELEMENT);
+        for (Iterator i = paramList.iterator(); i.hasNext();) {
+            Element param = (Element) i.next();
+            String paramName = param.getAttributeValue(NAME_ATTRIB);
+            String paramValue = param.getAttributeValue(VALUE_ATTRIB);
+            // replace variables in param value
+            params.put(paramName, replaceVars(paramValue, vars));
+        }
+        // finally do create the persistence manager
+        try {
+            Class c = Class.forName(className);
+            persistMgr = (PersistenceManager) c.newInstance();
+            // set the properties of the persistence manager object from the
+            // param hashmap
+            BeanMap bm = new BeanMap(persistMgr);
+            Iterator iter = params.keySet().iterator();
+            while (iter.hasNext()) {
+                Object name = iter.next();
+                Object value = params.get(name);
+                bm.put(name, value);
+            }
+            // @todo fix PersistenceManager initialization
+            //persistMgr.init(this);
+        } catch (Exception e) {
+            log.error("Cannot instantiate implementing class " + className, e);
+            throw new RepositoryException("Cannot instantiate implementing class " + className,
e);
+        }
+    }
+
+    /**
+     * Creates a new <code>WorkspaceConfig</code> instance. The configuration
+     * is read from the specified configuration file.
+     *
+     * @param configFilePath path to the configuration file
+     * @param wspHomeDir     workspace home directory
+     * @return a new <code>WorkspaceConfig</code> instance
+     * @throws RepositoryException If an error occurs
+     */
+    public static WorkspaceConfig create(String configFilePath, String wspHomeDir)
+            throws RepositoryException {
+        try {
+            File config = new File(configFilePath);
+            InputSource is = new InputSource(new FileReader(config));
+            is.setSystemId(config.toURI().toString());
+            return new WorkspaceConfig(is, wspHomeDir);
+        } catch (IOException ioe) {
+            String msg = "error while reading config file " + configFilePath;
+            log.error(msg, ioe);
+            throw new RepositoryException(msg, ioe);
+        }
+    }
+
+    /**
+     * Creates a new <code>WorkspaceConfig</code> instance. The configuration
+     * is read from the specified input source.
+     *
+     * @param is         <code>InputSource</code> where the configuration is
read from
+     * @param wspHomeDir workspace home directory
+     * @return a new <code>WorkspaceConfig</code> instance
+     * @throws RepositoryException If an error occurs
+     */
+    public static WorkspaceConfig create(InputSource is, String wspHomeDir)
+            throws RepositoryException {
+        return new WorkspaceConfig(is, wspHomeDir);
+    }
+
+    /**
+     * Returns the home directory of the workspace.
+     *
+     * @return the home directory of the workspace
+     */
+    public String getHomeDir() {
+        return wspHomeDir;
+    }
+
+    /**
+     * Returns the workspace name.
+     *
+     * @return the workspace name
+     */
+    public String getName() {
+        return wspName;
+    }
+
+    /**
+     * Returns the virtual file system where the workspace stores global state.
+     *
+     * @return the virtual file system where the workspace stores global state
+     */
+    public FileSystem getFileSystem() {
+        return wspFS;
+    }
+
+    /**
+     * Returns the workspace's persistence manager.
+     *
+     * @return the persistence manager
+     */
+    public PersistenceManager getPersistenceManager() {
+        return persistMgr;
+    }
+
+    /**
+     * Returns the search index directory
+     *
+     * @return the search index directory
+     */
+    public String getSearchIndexDir() {
+        return searchIndexDir;
+    }
+
+    //------------------------------------------------------< EntityResolver >
+    /**
+     * @see org.xml.sax.EntityResolver#resolveEntity(String, String)
+     */
+    public InputSource resolveEntity(String publicId, String systemId)
+            throws SAXException, IOException {
+        if (publicId.equals(PUBLIC_ID)) {
+            // load dtd resource
+            return new InputSource(getClass().getClassLoader().getResourceAsStream(CONFIG_DTD_RESOURCE_PATH));
+        } else {
+            // use the default behaviour
+            return null;
+        }
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/config.dtd
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/config/config.dtd	Thu Oct
 7 08:36:56 2004
@@ -0,0 +1,52 @@
+<!--
+/*
+ * Copyright 2004 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.
+ */
+-->
+<!-- -->
+<!ELEMENT Repository (FileSystem)>
+
+<!-- -->
+<!ELEMENT FileSystem (param*)>
+<!ATTLIST FileSystem
+  class CDATA #REQUIRED>
+
+<!-- -->
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+  name CDATA #REQUIRED
+  value CDATA #REQUIRED>
+
+<!-- -->
+<!ELEMENT Workspaces EMPTY>
+<!ATTLIST Workspaces
+  rootPath CDATA #REQUIRED
+  name CDATA #REQUIRED>
+
+<!-- -->
+<!ELEMENT Workspace (FileSystem,PersistenceManager)>
+<!ATTLIST Workspace
+  name CDATA #REQUIRED>
+
+<!-- -->
+<!ELEMENT PersistenceManager (param*)>
+<!ATTLIST PersistenceManager
+  class CDATA #REQUIRED>
+
+<!-- -->
+<!ELEMENT SearchIndex EMPTY>
+<!ATTLIST SearchIndex
+  path CDATA #REQUIRED>
+

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/jndi/BindableRepository.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/jndi/BindableRepository.java
Thu Oct  7 08:36:56 2004
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2004 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.core.jndi;
+
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+
+import javax.jcr.*;
+import javax.naming.NamingException;
+import javax.naming.Reference;
+import javax.naming.Referenceable;
+import javax.naming.StringRefAddr;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Properties;
+
+/**
+ * <code>BindableRepository</code> ...
+ */
+class BindableRepository implements Repository, Referenceable, Serializable {
+
+    static final long serialVersionUID = -2298220550793843166L;
+
+    /**
+     * path to the configuration file of the repository
+     */
+    private final String configFilePath;
+    /**
+     * repository home directory
+     */
+    private final String repHomeDir;
+
+    /**
+     * type of <code>configFilePath</code> reference address (@see <code>{@link
Reference#get(String)}</code>
+     */
+    static final String CONFIGFILEPATH_ADDRTYPE = "configFilePath";
+    /**
+     * type of <code>repHomeDir</code> reference address (@see <code>{@link
Reference#get(String)}</code>
+     */
+    static final String REPHOMEDIR_ADDRTYPE = "repHomeDir";
+
+    private transient Repository delegatee;
+
+    private BindableRepository(String configFilePath, String repHomeDir) {
+        this.configFilePath = configFilePath;
+        this.repHomeDir = repHomeDir;
+        delegatee = null;
+    }
+
+    static BindableRepository create(String configFilePath, String repHomeDir)
+            throws RepositoryException {
+        BindableRepository rep = new BindableRepository(configFilePath, repHomeDir);
+        rep.init();
+        return rep;
+    }
+
+    private void init() throws RepositoryException {
+        RepositoryConfig config = RepositoryConfig.create(configFilePath, repHomeDir);
+        // @todo fix repository instantiation
+        //delegatee = new RepositoryImpl(config);
+    }
+
+    //-----------------------------------------------------------< Repository >
+    /**
+     * @see Repository#getProperties()
+     */
+    public Properties getProperties() {
+        return delegatee.getProperties();
+    }
+
+    /**
+     * @see Repository#getProperty(String)
+     */
+    public String getProperty(String s) {
+        return delegatee.getProperty(s);
+    }
+
+    /**
+     * @see Repository#login(Credentials, String)
+     */
+    public Session login(Credentials credentials, String s)
+            throws LoginException, NoSuchWorkspaceException, RepositoryException {
+        return delegatee.login(credentials, s);
+    }
+
+    //--------------------------------------------------------< Referenceable >
+    /**
+     * @see Referenceable#getReference()
+     */
+    public Reference getReference() throws NamingException {
+        Reference ref = new Reference(BindableRepository.class.getName(),
+                BindableRepositoryFactory.class.getName(),
+                null);  // factory location
+        ref.add(new StringRefAddr(CONFIGFILEPATH_ADDRTYPE, configFilePath));
+        ref.add(new StringRefAddr(REPHOMEDIR_ADDRTYPE, repHomeDir));
+        return ref;
+    }
+
+    //-------------------------------------------------< Serializable support >
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        // delegate to default implementation
+        out.defaultWriteObject();
+    }
+
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
+        // delegate deserialization to default implementation
+        in.defaultReadObject();
+        // initialize reconstructed instance
+        try {
+            init();
+        } catch (RepositoryException re) {
+            // failed to reinstantiate repository
+            throw new IOException(re.getMessage());
+        }
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/jndi/BindableRepositoryFactory.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/jndi/BindableRepositoryFactory.java
Thu Oct  7 08:36:56 2004
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2004 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.core.jndi;
+
+import org.apache.commons.collections.ReferenceMap;
+
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.Reference;
+import javax.naming.spi.ObjectFactory;
+import java.util.Hashtable;
+import java.util.Map;
+
+/**
+ * <code>BindableRepositoryFactory</code> is an object factory that when given
+ * a reference for a <code>BindableRepository</code> object, will create an
+ * instance of the corresponding  <code>BindableRepository</code>.
+ */
+public class BindableRepositoryFactory implements ObjectFactory {
+
+    /**
+     * cache using <code>java.naming.Reference</code> objects as keys and
+     * storing soft references to <code>BindableRepository</code> instances
+     */
+    private static Map cache = new ReferenceMap(ReferenceMap.HARD, ReferenceMap.SOFT);
+
+    /**
+     * empty default constructor
+     */
+    public BindableRepositoryFactory() {
+    }
+
+    //--------------------------------------------------------< ObjectFactory >
+    /**
+     * @see ObjectFactory#getObjectInstance(Object, Name, Context, Hashtable)
+     */
+    public Object getObjectInstance(Object obj, Name name, Context nameCtx,
+                                    Hashtable environment)
+            throws Exception {
+        if (obj instanceof Reference) {
+            Reference ref = (Reference) obj;
+            synchronized (cache) {
+                if (cache.containsKey(ref)) {
+                    return cache.get(ref);
+                }
+                if (ref.getClassName().equals(BindableRepository.class.getName())) {
+                    String configFilePath =
+                            (String) ref.get(BindableRepository.CONFIGFILEPATH_ADDRTYPE).getContent();
+                    String repHomeDir =
+                            (String) ref.get(BindableRepository.REPHOMEDIR_ADDRTYPE).getContent();
+                    BindableRepository rep = BindableRepository.create(configFilePath, repHomeDir);
+                    cache.put(ref, rep);
+                    return rep;
+                }
+            }
+        }
+        return null;
+    }
+}

Added: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/jndi/RegistryHelper.java
==============================================================================
--- (empty file)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/core/jndi/RegistryHelper.java
Thu Oct  7 08:36:56 2004
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2004 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.core.jndi;
+
+import javax.naming.NamingException;
+import javax.naming.Context;
+import javax.jcr.RepositoryException;
+
+/**
+ * <code>RegistryHelper</code> ...
+ */
+public class RegistryHelper {
+
+    /**
+     * hidden constructor
+     */
+    private RegistryHelper() {
+    }
+
+    /**
+     *
+     * @param ctx context where the repository should be registered (i.e. bound)
+     * @param name the name to register the repository with
+     * @param configFilePath path to the configuration file of the repository
+     * @param repHomeDir repository home directory
+     * @param overwrite if <code>true</code>, any existing binding with the given
+     * name will be overwritten; otherwise a <code>NamingException</code> will
+     * be thrown if the name is already bound
+     * @throws NamingException
+     * @throws RepositoryException
+     */
+    public static void registerRepository(Context ctx, String name,
+                                         String configFilePath,
+                                         String repHomeDir,
+                                         boolean overwrite)
+            throws NamingException, RepositoryException {
+        Object obj = BindableRepository.create(configFilePath, repHomeDir);
+        if (overwrite) {
+            ctx.rebind(name, obj);
+        } else {
+            ctx.bind(name, obj);
+        }
+    }
+
+    /**
+     *
+     * @param ctx context where the repository should be unregistered (i.e. unbound)
+     * @param name the name of the repository to unregister
+     * @throws NamingException
+     */
+    public static void unregisterRepository(Context ctx, String name)
+            throws NamingException {
+        ctx.unbind(name);
+    }
+}

Mime
View raw message