Introduce JcrResource adapter
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 25 Nov 2009 21:51:18 +0000 (21:51 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 25 Nov 2009 21:51:18 +0000 (21:51 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@3167 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

13 files changed:
sandbox/runtime/org.argeo.sandbox.jackrabbit/src/main/resources/log4j.properties
server/runtime/org.argeo.server.jackrabbit/.classpath
server/runtime/org.argeo.server.jackrabbit/pom.xml
server/runtime/org.argeo.server.jackrabbit/repository.xml [new file with mode: 0644]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/JcrResourceAdapter.java [new file with mode: 0644]
server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java [new file with mode: 0644]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/log4j.properties [new file with mode: 0644]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy00.xls [new file with mode: 0644]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy01.xls [new file with mode: 0644]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy02.xls [new file with mode: 0644]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy03.xls [new file with mode: 0644]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/repository.xml [new file with mode: 0644]
server/runtime/org.argeo.server.jxl/src/main/java/org/argeo/server/jxl/dao/JxlDaoSupport.java

index c2edab75e673271862f217035ea63d04a1983af7..94ceb6ebbc11b1a197d44d20e97c119902f81fa5 100644 (file)
@@ -1,10 +1,13 @@
-# ***** Set root logger level to DEBUG and its only appender to A.
-log4j.rootLogger=WARN, A
+log4j.rootLogger=WARN, console
 
+## Levels
 log4j.logger.org.argeo=DEBUG
+log4j.logger.org.apache.jackrabbit=INFO
 
-# ***** A is set to be a ConsoleAppender.
-log4j.appender.A=org.apache.log4j.ConsoleAppender
-# ***** A uses PatternLayout.
-log4j.appender.A.layout=org.apache.log4j.PatternLayout
-log4j.appender.A.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+## Appenders
+# console is set to be a ConsoleAppender.
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+
+# console uses PatternLayout.
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n
index 16f01e2ee7b671c44c26c453773dab706e98da1e..d3bdab048d3853c88e149d2a817875863ced1631 100644 (file)
@@ -1,6 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
        <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+       <classpathentry kind="src" path="src/test/java"/>
+       <classpathentry kind="src" path="src/test/resources"/>
        <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
        <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
        <classpathentry kind="output" path="target/classes"/>
index d48451e01b3c31a9c40e02eedcd76c622bd7b5d0..a00612998e29ee3613812d38a84d42e5a26adfe4 100644 (file)
@@ -30,7 +30,8 @@
                                <configuration>
                                        <instructions>
                                                <Export-Package>
-                                                       org.argeo.server.jackrabbit.*
+                                                       org.argeo.server.jackrabbit.*,
+                                                       org.argeo.server.jcr.*
                                                </Export-Package>
                                        </instructions>
                                </configuration>
                        <groupId>org.slf4j</groupId>
                        <artifactId>com.springsource.slf4j.org.apache.commons.logging</artifactId>
                </dependency>
+
+               <!-- TEST -->
+               <dependency>
+                       <groupId>org.argeo.commons.basic</groupId>
+                       <artifactId>org.argeo.support.junit</artifactId>
+                       <version>0.1.2-SNAPSHOT</version>
+                       <scope>test</scope>
+               </dependency>
+               <dependency>
+                       <groupId>org.argeo.commons.basic</groupId>
+                       <artifactId>org.argeo.basic.dep.log4j</artifactId>
+                       <version>0.1.2-SNAPSHOT</version>
+                       <type>pom</type>
+                       <scope>test</scope>
+               </dependency>
+
        </dependencies>
 </project>
diff --git a/server/runtime/org.argeo.server.jackrabbit/repository.xml b/server/runtime/org.argeo.server.jackrabbit/repository.xml
new file mode 100644 (file)
index 0000000..666919d
--- /dev/null
@@ -0,0 +1,139 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.6//EN"
+                            "http://jackrabbit.apache.org/dtd/repository-1.6.dtd">
+<!-- Example Repository Configuration File
+     Used by
+     - org.apache.jackrabbit.core.config.RepositoryConfigTest.java
+     -
+-->
+<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>
+
+    <!--
+        security configuration
+    -->
+    <Security appName="Jackrabbit">
+        <!--
+            security manager:
+            class: FQN of class implementing the JackrabbitSecurityManager interface
+        -->
+        <SecurityManager class="org.apache.jackrabbit.core.security.simple.SimpleSecurityManager" workspaceName="security">
+            <!--
+            workspace access:
+            class: FQN of class implementing the WorkspaceAccessManager interface
+            -->
+            <!-- <WorkspaceAccessManager class="..."/> -->
+            <!-- <param name="config" value="${rep.home}/security.xml"/> -->
+        </SecurityManager>
+
+        <!--
+            access manager:
+            class: FQN of class implementing the AccessManager interface
+        -->
+        <AccessManager class="org.apache.jackrabbit.core.security.simple.SimpleAccessManager">
+            <!-- <param name="config" value="${rep.home}/access.xml"/> -->
+        </AccessManager>
+
+        <LoginModule class="org.apache.jackrabbit.core.security.simple.SimpleLoginModule">
+           <!-- 
+              anonymous user name ('anonymous' is the default value)
+            -->
+           <param name="anonymousId" value="anonymous"/>
+           <!--
+              administrator user id (default value if param is missing is 'admin')
+            -->
+           <param name="adminId" value="admin"/>
+        </LoginModule>
+    </Security>
+
+    <!--
+        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:
+            class: FQN of class implementing the FileSystem interface
+        -->
+        <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+            <param name="path" value="${wsp.home}"/>
+        </FileSystem>
+        <!--
+            persistence manager of the workspace:
+            class: FQN of class implementing the PersistenceManager interface
+        -->
+        <PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.DerbyPersistenceManager">
+          <param name="url" value="jdbc:derby:${wsp.home}/db;create=true"/>
+          <param name="schemaObjectPrefix" value="${wsp.name}_"/>
+        </PersistenceManager>
+        <!--
+            Search index and the file system it uses.
+            class: FQN of class implementing the QueryHandler interface
+        -->
+        <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+            <param name="path" value="${wsp.home}/index"/>
+            <param name="extractorPoolSize" value="2"/>
+            <param name="supportHighlighting" value="true"/>
+        </SearchIndex>
+    </Workspace>
+
+    <!--
+        Configures the versioning
+    -->
+    <Versioning rootPath="${rep.home}/version">
+        <!--
+            Configures the filesystem to use for versioning for the respective
+            persistence manager
+        -->
+        <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+            <param name="path" value="${rep.home}/version" />
+        </FileSystem>
+
+        <!--
+            Configures the persistence manager to be used for persisting version state.
+            Please note that the current versioning implementation is based on
+            a 'normal' persistence manager, but this could change in future
+            implementations.
+        -->
+        <PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.DerbyPersistenceManager">
+          <param name="url" value="jdbc:derby:${rep.home}/version/db;create=true"/>
+          <param name="schemaObjectPrefix" value="version_"/>
+        </PersistenceManager>
+    </Versioning>
+
+    <!--
+        Search index for content that is shared repository wide
+        (/jcr:system tree, contains mainly versions)
+    -->
+    <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+        <param name="path" value="${rep.home}/repository/index"/>
+        <param name="extractorPoolSize" value="2"/>
+        <param name="supportHighlighting" value="true"/>
+    </SearchIndex>
+</Repository>
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/JcrResourceAdapter.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/JcrResourceAdapter.java
new file mode 100644 (file)
index 0000000..b770a89
--- /dev/null
@@ -0,0 +1,291 @@
+package org.argeo.server.jcr;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.Value;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionIterator;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.core.io.Resource;
+
+public class JcrResourceAdapter implements InitializingBean, DisposableBean {
+       private final static Log log = LogFactory.getLog(JcrResourceAdapter.class);
+
+       private Repository repository;
+
+       private String username;
+       private String password;
+
+       private Session session;
+
+       private Boolean versioning = true;
+       private String defaultEncoding = "UTF-8";
+
+       // private String restoreBase = "/.restore";
+
+       public void mkdirs(String path) {
+               try {
+                       StringTokenizer st = new StringTokenizer(path, "/");
+                       StringBuffer current = new StringBuffer("/");
+                       Node currentNode = session().getRootNode();
+                       while (st.hasMoreTokens()) {
+                               String part = st.nextToken();
+                               current.append(part).append('/');
+                               if (!session().itemExists(current.toString())) {
+                                       currentNode = currentNode.addNode(part, "nt:folder");
+                                       if (versioning)
+                                               currentNode.addMixin("mix:versionable");
+                                       if (log.isTraceEnabled())
+                                               log.debug("Added folder " + part + " as " + current);
+                               } else {
+                                       currentNode = (Node) session().getItem(current.toString());
+                               }
+                       }
+                       session().save();
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot mkdirs " + path, e);
+               }
+       }
+
+       public void create(String path, Resource file, String mimeType) {
+               try {
+                       if (session().itemExists(path))
+                               throw new ArgeoException("Node " + path + " already exists.");
+
+                       int index = path.lastIndexOf('/');
+                       String parentPath = path.substring(0, index);
+                       String fileName = path.substring(index + 1);
+                       if (!session().itemExists(parentPath))
+                               throw new ArgeoException("Parent folder of node " + path
+                                               + " does not exist: " + parentPath);
+
+                       Node folderNode = (Node) session().getItem(parentPath);
+                       Node fileNode = folderNode.addNode(fileName, "nt:file");
+
+                       Node contentNode = fileNode.addNode("jcr:content", "nt:resource");
+                       contentNode.setProperty("jcr:mimeType", mimeType);
+                       contentNode.setProperty("jcr:encoding", defaultEncoding);
+                       contentNode.setProperty("jcr:data", file.getInputStream());
+                       Calendar lastModified = Calendar.getInstance();
+                       lastModified.setTimeInMillis(file.lastModified());
+                       contentNode.setProperty("jcr:lastModified", lastModified);
+                       // resNode.addMixin("mix:referenceable");
+
+                       if (versioning)
+                               fileNode.addMixin("mix:versionable");
+
+                       session().save();
+
+                       if (versioning)
+                               fileNode.checkin();
+
+                       if (log.isDebugEnabled())
+                               log.debug("Created " + path + " from " + file);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot create node from resource " + file
+                                       + " under " + path, e);
+               }
+
+       }
+
+       public void update(String path, Resource file) {
+               try {
+                       Node fileNode = (Node) session().getItem(path);
+                       Node contentNode = fileNode.getNode("jcr:content");
+                       fileNode.checkout();
+                       contentNode.setProperty("jcr:data", file.getInputStream());
+                       Calendar lastModified = Calendar.getInstance();
+                       lastModified.setTimeInMillis(file.lastModified());
+                       contentNode.setProperty("jcr:lastModified", lastModified);
+
+                       session().save();
+                       fileNode.checkin();
+
+                       if (log.isDebugEnabled())
+                               log.debug("Updated " + path + " from " + file);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot update node " + path
+                                       + " from resource" + file, e);
+               }
+       }
+
+       public List<Calendar> listVersions(String path) {
+               if (!versioning)
+                       throw new ArgeoException("Versioning is not activated");
+
+               try {
+                       List<Calendar> versions = new ArrayList<Calendar>();
+                       Node fileNode = (Node) session().getItem(path);
+                       VersionHistory history = fileNode.getVersionHistory();
+                       for (VersionIterator it = history.getAllVersions(); it.hasNext();) {
+                               Version version = (Version) it.next();
+                               versions.add(version.getCreated());
+                               if (log.isTraceEnabled()) {
+                                       log.debug(version);
+                                       // debug(version);
+                               }
+                       }
+                       return versions;
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot list version of node " + path, e);
+               }
+       }
+
+       public InputStream retrieve(String path) {
+               try {
+                       Node node = (Node) session().getItem(path + "/jcr:content");
+                       Property property = node.getProperty("jcr:data");
+                       return property.getStream();
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot retrieve " + path, e);
+               }
+       }
+
+       public synchronized InputStream retrieve(String path, Integer revision) {
+               if (!versioning)
+                       throw new ArgeoException("Versioning is not activated");
+
+               try {
+                       Node fileNode = (Node) session().getItem(path);
+
+                       // if (revision == 0) {
+                       // InputStream in = fromVersion(fileNode.getBaseVersion());
+                       // if (log.isDebugEnabled())
+                       // log.debug("Retrieved " + path + " at base revision ");
+                       // return in;
+                       // }
+
+                       VersionHistory history = fileNode.getVersionHistory();
+                       int count = 0;
+                       Version version = null;
+                       for (VersionIterator it = history.getAllVersions(); it.hasNext();) {
+                               version = (Version) it.next();
+                               if (count == revision + 1) {
+                                       InputStream in = fromVersion(version);
+                                       if (log.isDebugEnabled())
+                                               log.debug("Retrieved " + path + " at revision "
+                                                               + revision);
+                                       return in;
+                               }
+                               count++;
+                       }
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot retrieve version " + revision
+                                       + " of " + path, e);
+               }
+
+               throw new ArgeoException("Version " + revision
+                               + " does not exist for node " + path);
+       }
+
+       protected InputStream fromVersion(Version version)
+                       throws RepositoryException {
+               Node frozenNode = version.getNode("jcr:frozenNode");
+               InputStream in = frozenNode.getNode("jcr:content").getProperty(
+                               "jcr:data").getStream();
+               return in;
+       }
+
+       // protected InputStream restoreOrGetRevision(Node fileNode, Version
+       // version,
+       // Integer revision) throws RepositoryException {
+       // Node parentFolder = (Node) fileNode
+       // .getAncestor(fileNode.getDepth() - 1);
+       // String restoreFolderPath = restoreBase + parentFolder.getPath();
+       // mkdirs(restoreFolderPath);
+       // String subNodeName = fileNode.getName() + "__" + fill(revision);
+       // Node restoreFolder = (Node) session().getItem(restoreFolderPath);
+       // if (!restoreFolder.hasNode(subNodeName)) {
+       // parentFolder.restore(version, subNodeName, true);
+       // }
+       // return parentFolder.getNode(subNodeName + "/jcr:content").getProperty(
+       // "jcr:data").getStream();
+       // }
+
+       protected Session session() {
+               return session;
+       }
+
+       public void afterPropertiesSet() throws Exception {
+               session = repository.login(new SimpleCredentials(username, password
+                               .toCharArray()));
+       }
+
+       public void destroy() throws Exception {
+               session.logout();
+       }
+
+       public void setRepository(Repository repository) {
+               this.repository = repository;
+       }
+
+       public void setUsername(String username) {
+               this.username = username;
+       }
+
+       public void setPassword(String password) {
+               this.password = password;
+       }
+
+       public void setVersioning(Boolean versioning) {
+               this.versioning = versioning;
+       }
+
+       public void setDefaultEncoding(String defaultEncoding) {
+               this.defaultEncoding = defaultEncoding;
+       }
+
+       /** Recursively outputs the contents of the given node. */
+       public static void debug(Node node) throws RepositoryException {
+               // First output the node path
+               log.debug(node.getPath());
+               // Skip the virtual (and large!) jcr:system subtree
+               if (node.getName().equals("jcr:system")) {
+                       return;
+               }
+
+               // Then output the properties
+               PropertyIterator properties = node.getProperties();
+               while (properties.hasNext()) {
+                       Property property = properties.nextProperty();
+                       if (property.getDefinition().isMultiple()) {
+                               // A multi-valued property, print all values
+                               Value[] values = property.getValues();
+                               for (int i = 0; i < values.length; i++) {
+                                       log.debug(property.getPath() + " = "
+                                                       + values[i].getString());
+                               }
+                       } else {
+                               // A single-valued property
+                               log.debug(property.getPath() + " = " + property.getString());
+                       }
+               }
+
+       }
+
+       protected String fill(Integer number) {
+               int size = 4;
+               String str = number.toString();
+               for (int i = str.length(); i < size; i++) {
+                       str = "0" + str;
+               }
+               return str;
+       }
+}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java b/server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java
new file mode 100644 (file)
index 0000000..9c72a1e
--- /dev/null
@@ -0,0 +1,93 @@
+package org.argeo.server.jcr;
+
+import java.io.File;
+import java.io.InputStream;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.core.TransientRepository;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+public class JcrResourceAdapterTest extends TestCase {
+       private static SimpleDateFormat sdf = new SimpleDateFormat(
+                       "yyyyMMdd:hhmmss.SSS");
+
+       private final static Log log = LogFactory
+                       .getLog(JcrResourceAdapterTest.class);
+
+       private JcrResourceAdapter jra;
+       private TransientRepository repository;
+
+       public void testCreate() throws Exception {
+               String basePath = "/test/subdir";
+               jra.mkdirs(basePath);
+               Resource res = new ClassPathResource("org/argeo/server/jcr/dummy00.xls");
+               String filePath = basePath + "/dummy.xml";
+               jra.create(filePath, res, "application/vnd.ms-excel");
+               InputStream in = jra.retrieve(filePath);
+               assertTrue(IOUtils.contentEquals(res.getInputStream(), in));
+       }
+
+       public void testVersioning() throws Exception {
+               String basePath = "/test/versions";
+               jra.mkdirs(basePath);
+               String filePath = basePath + "/dummy.xml";
+               Resource res00 = new ClassPathResource(
+                               "org/argeo/server/jcr/dummy00.xls");
+               jra.create(filePath, res00, "application/vnd.ms-excel");
+               Resource res01 = new ClassPathResource(
+                               "org/argeo/server/jcr/dummy01.xls");
+               jra.update(filePath, res01);
+               Resource res02 = new ClassPathResource(
+                               "org/argeo/server/jcr/dummy02.xls");
+               jra.update(filePath, res02);
+
+               List<Calendar> versions = jra.listVersions(filePath);
+               for (Calendar version : versions)
+                       log.debug(sdf.format(version.getTime()));
+               assertEquals(4, versions.size());
+
+               InputStream in = jra.retrieve(filePath, 1);
+               assertTrue(IOUtils.contentEquals(res01.getInputStream(), in));
+               in = jra.retrieve(filePath, 0);
+               assertTrue(IOUtils.contentEquals(res00.getInputStream(), in));
+               in = jra.retrieve(filePath, 2);
+               assertTrue(IOUtils.contentEquals(res02.getInputStream(), in));
+               Resource res03 = new ClassPathResource(
+                               "org/argeo/server/jcr/dummy03.xls");
+               jra.update(filePath, res03);
+               in = jra.retrieve(filePath, 1);
+               assertTrue(IOUtils.contentEquals(res01.getInputStream(), in));
+       }
+
+       @Override
+       protected void setUp() throws Exception {
+               File homeDir = new File(System.getProperty("java.io.tmpdir"),
+                               JcrResourceAdapterTest.class.getSimpleName());
+               FileUtils.deleteDirectory(homeDir);
+               Resource res = new ClassPathResource(
+                               "org/argeo/server/jcr/repository.xml");
+               repository = new TransientRepository(res.getFile(), homeDir);
+
+               jra = new JcrResourceAdapter();
+               jra.setRepository(repository);
+               jra.setUsername("demo");
+               jra.setPassword("demo");
+               jra.afterPropertiesSet();
+       }
+
+       @Override
+       protected void tearDown() throws Exception {
+               jra.destroy();
+               // repository.shutdown();
+       }
+
+}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/test/resources/log4j.properties b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/log4j.properties
new file mode 100644 (file)
index 0000000..ca995af
--- /dev/null
@@ -0,0 +1,13 @@
+log4j.rootLogger=WARN, console
+
+## Levels
+log4j.logger.org.argeo=DEBUG
+log4j.logger.org.apache.jackrabbit=OFF
+
+## Appenders
+# console is set to be a ConsoleAppender.
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+
+# console uses PatternLayout.
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern= %-5p %d{ISO8601} %m - %c%n
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy00.xls b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy00.xls
new file mode 100644 (file)
index 0000000..e5846fe
Binary files /dev/null and b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy00.xls differ
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy01.xls b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy01.xls
new file mode 100644 (file)
index 0000000..b5c6b55
Binary files /dev/null and b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy01.xls differ
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy02.xls b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy02.xls
new file mode 100644 (file)
index 0000000..d73bc66
Binary files /dev/null and b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy02.xls differ
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy03.xls b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy03.xls
new file mode 100644 (file)
index 0000000..0759cb9
Binary files /dev/null and b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy03.xls differ
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/repository.xml b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/repository.xml
new file mode 100644 (file)
index 0000000..f051923
--- /dev/null
@@ -0,0 +1,139 @@
+<?xml version="1.0"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<!DOCTYPE Repository PUBLIC "-//The Apache Software Foundation//DTD Jackrabbit 1.6//EN"
+                            "http://jackrabbit.apache.org/dtd/repository-1.6.dtd">
+<!-- Example Repository Configuration File
+     Used by
+     - org.apache.jackrabbit.core.config.RepositoryConfigTest.java
+     -
+-->
+<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>
+
+    <!--
+        security configuration
+    -->
+    <Security appName="Jackrabbit">
+        <!--
+            security manager:
+            class: FQN of class implementing the JackrabbitSecurityManager interface
+        -->
+        <SecurityManager class="org.apache.jackrabbit.core.security.simple.SimpleSecurityManager" workspaceName="security">
+            <!--
+            workspace access:
+            class: FQN of class implementing the WorkspaceAccessManager interface
+            -->
+            <!-- <WorkspaceAccessManager class="..."/> -->
+            <!-- <param name="config" value="${rep.home}/security.xml"/> -->
+        </SecurityManager>
+
+        <!--
+            access manager:
+            class: FQN of class implementing the AccessManager interface
+        -->
+        <AccessManager class="org.apache.jackrabbit.core.security.simple.SimpleAccessManager">
+            <!-- <param name="config" value="${rep.home}/access.xml"/> -->
+        </AccessManager>
+
+        <LoginModule class="org.apache.jackrabbit.core.security.simple.SimpleLoginModule">
+           <!-- 
+              anonymous user name ('anonymous' is the default value)
+            -->
+           <param name="anonymousId" value="anonymous"/>
+           <!--
+              administrator user id (default value if param is missing is 'admin')
+            -->
+           <param name="adminId" value="admin"/>
+        </LoginModule>
+    </Security>
+
+    <!--
+        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:
+            class: FQN of class implementing the FileSystem interface
+        -->
+        <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+            <param name="path" value="${wsp.home}"/>
+        </FileSystem>
+        <!--
+            persistence manager of the workspace:
+            class: FQN of class implementing the PersistenceManager interface
+        -->
+        <PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.DerbyPersistenceManager">
+          <param name="url" value="jdbc:derby:memory:db;create=true"/>
+          <param name="schemaObjectPrefix" value="${wsp.name}_"/>
+        </PersistenceManager>
+        <!--
+            Search index and the file system it uses.
+            class: FQN of class implementing the QueryHandler interface
+        -->
+        <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+            <param name="path" value="${wsp.home}/index"/>
+            <param name="extractorPoolSize" value="2"/>
+            <param name="supportHighlighting" value="true"/>
+        </SearchIndex>
+    </Workspace>
+
+    <!--
+        Configures the versioning
+    -->
+    <Versioning rootPath="${rep.home}/version">
+        <!--
+            Configures the filesystem to use for versioning for the respective
+            persistence manager
+        -->
+        <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
+            <param name="path" value="${rep.home}/version" />
+        </FileSystem>
+
+        <!--
+            Configures the persistence manager to be used for persisting version state.
+            Please note that the current versioning implementation is based on
+            a 'normal' persistence manager, but this could change in future
+            implementations.
+        -->
+        <PersistenceManager class="org.apache.jackrabbit.core.persistence.bundle.DerbyPersistenceManager">
+          <param name="url" value="jdbc:derby:memory:version;create=true"/>
+          <param name="schemaObjectPrefix" value="version_"/>
+        </PersistenceManager>
+    </Versioning>
+
+    <!--
+        Search index for content that is shared repository wide
+        (/jcr:system tree, contains mainly versions)
+    -->
+    <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
+        <param name="path" value="${rep.home}/repository/index"/>
+        <param name="extractorPoolSize" value="2"/>
+        <param name="supportHighlighting" value="true"/>
+    </SearchIndex>
+</Repository>
index 76ac7dd55d4f23466536ad57eae8799346ea44e0..e8bb7107f1df353b2133bf5c8d3b5fe1822dad09 100644 (file)
@@ -20,13 +20,12 @@ import jxl.WorkbookSettings;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.argeo.server.ArgeoServerException;
+import org.argeo.ArgeoException;
 import org.argeo.server.dao.AbstractTabularDaoSupport;
 import org.argeo.server.dao.LightDaoSupport;
 import org.springframework.beans.BeanWrapper;
 import org.springframework.beans.factory.InitializingBean;
 import org.springframework.context.ApplicationContextAware;
-import org.springframework.core.io.Resource;
 import org.springframework.util.StringUtils;
 
 public class JxlDaoSupport extends AbstractTabularDaoSupport implements
@@ -47,7 +46,7 @@ public class JxlDaoSupport extends AbstractTabularDaoSupport implements
                                loadSheet(sheet, references);
                        }
                } catch (Exception e) {
-                       throw new ArgeoServerException("Cannot load workbook", e);
+                       throw new ArgeoException("Cannot load workbook", e);
                }
        }
 
@@ -79,7 +78,7 @@ public class JxlDaoSupport extends AbstractTabularDaoSupport implements
                                if (keyProperty == null)
                                        keyProperty = fieldName;
                                if (!espSt.hasMoreTokens())
-                                       throw new ArgeoServerException("Badly formatted sheetname "
+                                       throw new ArgeoException("Badly formatted sheetname "
                                                        + sheetName);
                                String fieldValue = espSt.nextToken();
                                bw.setPropertyValue(fieldName, fieldValue);
@@ -272,7 +271,7 @@ public class JxlDaoSupport extends AbstractTabularDaoSupport implements
                        String formula = ((FormulaCell) cell).getFormula();
                        int index = formula.indexOf('!');
                        if (index < 0)
-                               throw new ArgeoServerException("Cannot interpret formula "
+                               throw new ArgeoException("Cannot interpret formula "
                                                + formula);
                        ;
                        String targetSheet = formula.substring(0, index);