Split server Jackrabbit into JCR
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 30 Apr 2010 08:19:35 +0000 (08:19 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 30 Apr 2010 08:19:35 +0000 (08:19 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@3542 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

60 files changed:
server/runtime/org.argeo.server.jackrabbit/.classpath
server/runtime/org.argeo.server.jackrabbit/build.properties
server/runtime/org.argeo.server.jackrabbit/repository.xml [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/BeanNodeMapper.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/JcrUtils.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapper.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapperProvider.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/unit/AbstractJcrTestCase.java
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/DefaultJcrListener.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/JcrResourceAdapter.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/JcrBrowserController.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/JcrManagerController.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/JcrMvcConstants.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/JcrXmlServerSerializer.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/OpenSessionInViewJcrInterceptor.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/jcr/CollectionsObject.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/jcr/MapperTest.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/jcr/OtherObject.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/jcr/SimpleObject.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/log4j.properties [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/applicationContext.xml [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy00.xls [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy01.xls [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy02.xls [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy03.xls [deleted file]
server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/repository.xml [deleted file]
server/runtime/org.argeo.server.jcr/.classpath
server/runtime/org.argeo.server.jcr/META-INF/MANIFEST.MF
server/runtime/org.argeo.server.jcr/build.properties
server/runtime/org.argeo.server.jcr/pom.xml
server/runtime/org.argeo.server.jcr/repository.xml [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/BeanNodeMapper.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapper.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapperProvider.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/DefaultJcrListener.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/JcrResourceAdapter.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/JcrBrowserController.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/JcrManagerController.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/JcrMvcConstants.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/JcrXmlServerSerializer.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/OpenSessionInViewJcrInterceptor.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/CollectionsObject.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/MapperTest.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/OtherObject.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/SimpleObject.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/resources/log4j.properties [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/applicationContext.xml [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy00.xls [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy01.xls [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy02.xls [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy03.xls [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-inMemory.xml [new file with mode: 0644]
server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository.xml [new file with mode: 0644]

index 3e6ecf767d5519108c40bc9c9ea27c164872ca49..73ba12c2eada5b5a04bc37083084a28b61fb6272 100644 (file)
@@ -2,8 +2,6 @@
 <classpath>
        <classpathentry kind="src" output="target/classes" path="src/main/java"/>
        <classpathentry kind="src" output="target/classes" path="src/main/resources"/>
-       <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
-       <classpathentry kind="src" output="target/test-classes" 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.eclipse.pde.core.requiredPlugins"/>
        <classpathentry kind="output" path="bin"/>
index a90395047ea752c7c1c0cd38ad38e5c225f440e8..fdf424dbcdeba2277e71b1c308fd1402f513c1fc 100644 (file)
@@ -4,7 +4,8 @@ additional.bundles = com.springsource.slf4j.api,\
                      com.springsource.org.apache.commons.collections,\
                      com.springsource.edu.oswego.cs.dl.util.concurrent,\
                      com.springsource.org.apache.derby,\
-                     com.springsource.org.apache.lucene
+                     com.springsource.org.apache.lucene,\
+                     org.springframework.context
 source.. = src/main/java/,\
            src/test/java/,\
            src/test/resources/,\
diff --git a/server/runtime/org.argeo.server.jackrabbit/repository.xml b/server/runtime/org.argeo.server.jackrabbit/repository.xml
deleted file mode 100644 (file)
index 666919d..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-<?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/jcr/ArgeoJcrConstants.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java
deleted file mode 100644 (file)
index 4f12fa7..0000000
+++ /dev/null
@@ -1,306 +0,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.
- */
-package org.argeo.jcr;
-
-/**
- * Copied from org.apache.jackrabbit.JcrConstants v1.6.0 in order to avoid a
- * dependency to Jackrabbit.
- */
-public interface ArgeoJcrConstants {
-       /**
-        * jcr:autoCreated
-        */
-       public static final String JCR_AUTOCREATED = "jcr:autoCreated";
-       /**
-        * jcr:baseVersion
-        */
-       public static final String JCR_BASEVERSION = "jcr:baseVersion";
-       /**
-        * jcr:child
-        */
-       public static final String JCR_CHILD = "jcr:child";
-       /**
-        * jcr:childNodeDefinition
-        */
-       public static final String JCR_CHILDNODEDEFINITION = "jcr:childNodeDefinition";
-       /**
-        * jcr:content
-        */
-       public static final String JCR_CONTENT = "jcr:content";
-       /**
-        * jcr:created
-        */
-       public static final String JCR_CREATED = "jcr:created";
-       /**
-        * jcr:data
-        */
-       public static final String JCR_DATA = "jcr:data";
-       /**
-        * jcr:defaultPrimaryType
-        */
-       public static final String JCR_DEFAULTPRIMARYTYPE = "jcr:defaultPrimaryType";
-       /**
-        * jcr:defaultValues
-        */
-       public static final String JCR_DEFAULTVALUES = "jcr:defaultValues";
-       /**
-        * jcr:encoding
-        */
-       public static final String JCR_ENCODING = "jcr:encoding";
-       /**
-        * jcr:frozenMixinTypes
-        */
-       public static final String JCR_FROZENMIXINTYPES = "jcr:frozenMixinTypes";
-       /**
-        * jcr:frozenNode
-        */
-       public static final String JCR_FROZENNODE = "jcr:frozenNode";
-       /**
-        * jcr:frozenPrimaryType
-        */
-       public static final String JCR_FROZENPRIMARYTYPE = "jcr:frozenPrimaryType";
-       /**
-        * jcr:frozenUuid
-        */
-       public static final String JCR_FROZENUUID = "jcr:frozenUuid";
-       /**
-        * jcr:hasOrderableChildNodes
-        */
-       public static final String JCR_HASORDERABLECHILDNODES = "jcr:hasOrderableChildNodes";
-       /**
-        * jcr:isCheckedOut
-        */
-       public static final String JCR_ISCHECKEDOUT = "jcr:isCheckedOut";
-       /**
-        * jcr:isMixin
-        */
-       public static final String JCR_ISMIXIN = "jcr:isMixin";
-       /**
-        * jcr:language
-        */
-       public static final String JCR_LANGUAGE = "jcr:language";
-       /**
-        * jcr:lastModified
-        */
-       public static final String JCR_LASTMODIFIED = "jcr:lastModified";
-       /**
-        * jcr:lockIsDeep
-        */
-       public static final String JCR_LOCKISDEEP = "jcr:lockIsDeep";
-       /**
-        * jcr:lockOwner
-        */
-       public static final String JCR_LOCKOWNER = "jcr:lockOwner";
-       /**
-        * jcr:mandatory
-        */
-       public static final String JCR_MANDATORY = "jcr:mandatory";
-       /**
-        * jcr:mergeFailed
-        */
-       public static final String JCR_MERGEFAILED = "jcr:mergeFailed";
-       /**
-        * jcr:mimeType
-        */
-       public static final String JCR_MIMETYPE = "jcr:mimeType";
-       /**
-        * jcr:mixinTypes
-        */
-       public static final String JCR_MIXINTYPES = "jcr:mixinTypes";
-       /**
-        * jcr:multiple
-        */
-       public static final String JCR_MULTIPLE = "jcr:multiple";
-       /**
-        * jcr:name
-        */
-       public static final String JCR_NAME = "jcr:name";
-       /**
-        * jcr:nodeTypeName
-        */
-       public static final String JCR_NODETYPENAME = "jcr:nodeTypeName";
-       /**
-        * jcr:onParentVersion
-        */
-       public static final String JCR_ONPARENTVERSION = "jcr:onParentVersion";
-       /**
-        * jcr:predecessors
-        */
-       public static final String JCR_PREDECESSORS = "jcr:predecessors";
-       /**
-        * jcr:primaryItemName
-        */
-       public static final String JCR_PRIMARYITEMNAME = "jcr:primaryItemName";
-       /**
-        * jcr:primaryType
-        */
-       public static final String JCR_PRIMARYTYPE = "jcr:primaryType";
-       /**
-        * jcr:propertyDefinition
-        */
-       public static final String JCR_PROPERTYDEFINITION = "jcr:propertyDefinition";
-       /**
-        * jcr:protected
-        */
-       public static final String JCR_PROTECTED = "jcr:protected";
-       /**
-        * jcr:requiredPrimaryTypes
-        */
-       public static final String JCR_REQUIREDPRIMARYTYPES = "jcr:requiredPrimaryTypes";
-       /**
-        * jcr:requiredType
-        */
-       public static final String JCR_REQUIREDTYPE = "jcr:requiredType";
-       /**
-        * jcr:rootVersion
-        */
-       public static final String JCR_ROOTVERSION = "jcr:rootVersion";
-       /**
-        * jcr:sameNameSiblings
-        */
-       public static final String JCR_SAMENAMESIBLINGS = "jcr:sameNameSiblings";
-       /**
-        * jcr:statement
-        */
-       public static final String JCR_STATEMENT = "jcr:statement";
-       /**
-        * jcr:successors
-        */
-       public static final String JCR_SUCCESSORS = "jcr:successors";
-       /**
-        * jcr:supertypes
-        */
-       public static final String JCR_SUPERTYPES = "jcr:supertypes";
-       /**
-        * jcr:system
-        */
-       public static final String JCR_SYSTEM = "jcr:system";
-       /**
-        * jcr:uuid
-        */
-       public static final String JCR_UUID = "jcr:uuid";
-       /**
-        * jcr:valueConstraints
-        */
-       public static final String JCR_VALUECONSTRAINTS = "jcr:valueConstraints";
-       /**
-        * jcr:versionHistory
-        */
-       public static final String JCR_VERSIONHISTORY = "jcr:versionHistory";
-       /**
-        * jcr:versionLabels
-        */
-       public static final String JCR_VERSIONLABELS = "jcr:versionLabels";
-       /**
-        * jcr:versionStorage
-        */
-       public static final String JCR_VERSIONSTORAGE = "jcr:versionStorage";
-       /**
-        * jcr:versionableUuid
-        */
-       public static final String JCR_VERSIONABLEUUID = "jcr:versionableUuid";
-
-       /**
-        * Pseudo property jcr:path used with query results
-        */
-       public static final String JCR_PATH = "jcr:path";
-       /**
-        * Pseudo property jcr:score used with query results
-        */
-       public static final String JCR_SCORE = "jcr:score";
-
-       /**
-        * mix:lockable
-        */
-       public static final String MIX_LOCKABLE = "mix:lockable";
-       /**
-        * mix:referenceable
-        */
-       public static final String MIX_REFERENCEABLE = "mix:referenceable";
-       /**
-        * mix:versionable
-        */
-       public static final String MIX_VERSIONABLE = "mix:versionable";
-       /**
-        * mix:shareable
-        */
-       public static final String MIX_SHAREABLE = "mix:shareable";
-       /**
-        * nt:base
-        */
-       public static final String NT_BASE = "nt:base";
-       /**
-        * nt:childNodeDefinition
-        */
-       public static final String NT_CHILDNODEDEFINITION = "nt:childNodeDefinition";
-       /**
-        * nt:file
-        */
-       public static final String NT_FILE = "nt:file";
-       /**
-        * nt:folder
-        */
-       public static final String NT_FOLDER = "nt:folder";
-       /**
-        * nt:frozenNode
-        */
-       public static final String NT_FROZENNODE = "nt:frozenNode";
-       /**
-        * nt:hierarchyNode
-        */
-       public static final String NT_HIERARCHYNODE = "nt:hierarchyNode";
-       /**
-        * nt:linkedFile
-        */
-       public static final String NT_LINKEDFILE = "nt:linkedFile";
-       /**
-        * nt:nodeType
-        */
-       public static final String NT_NODETYPE = "nt:nodeType";
-       /**
-        * nt:propertyDefinition
-        */
-       public static final String NT_PROPERTYDEFINITION = "nt:propertyDefinition";
-       /**
-        * nt:query
-        */
-       public static final String NT_QUERY = "nt:query";
-       /**
-        * nt:resource
-        */
-       public static final String NT_RESOURCE = "nt:resource";
-       /**
-        * nt:unstructured
-        */
-       public static final String NT_UNSTRUCTURED = "nt:unstructured";
-       /**
-        * nt:version
-        */
-       public static final String NT_VERSION = "nt:version";
-       /**
-        * nt:versionHistory
-        */
-       public static final String NT_VERSIONHISTORY = "nt:versionHistory";
-       /**
-        * nt:versionLabels
-        */
-       public static final String NT_VERSIONLABELS = "nt:versionLabels";
-       /**
-        * nt:versionedChild
-        */
-       public static final String NT_VERSIONEDCHILD = "nt:versionedChild";
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/BeanNodeMapper.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/BeanNodeMapper.java
deleted file mode 100644 (file)
index a526bcf..0000000
+++ /dev/null
@@ -1,604 +0,0 @@
-package org.argeo.jcr;
-
-import java.beans.PropertyDescriptor;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.StringTokenizer;
-
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Value;
-import javax.jcr.ValueFactory;
-
-import org.argeo.ArgeoException;
-import org.springframework.beans.BeanWrapper;
-import org.springframework.beans.BeanWrapperImpl;
-
-public class BeanNodeMapper implements NodeMapper {
-       // private final static Log log = LogFactory.getLog(BeanNodeMapper.class);
-
-       private final static String NODE_VALUE = "value";
-
-       // private String keyNode = "bean:key";
-       private String uuidProperty = "uuid";
-       private String classProperty = "class";
-
-       private Boolean versioning = false;
-       private Boolean strictUuidReference = false;
-
-       // TODO define a primaryNodeType Strategy
-       private String primaryNodeType = null;
-
-       private ClassLoader classLoader = getClass().getClassLoader();
-
-       private NodeMapperProvider nodeMapperProvider;
-
-       /**
-        * exposed method to retrieve a bean from a node
-        */
-       public Object load(Node node) {
-               try {
-                       if (nodeMapperProvider != null) {
-                               NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node);
-                               if (nodeMapper != this) {
-                                       return nodeMapper.load(node);
-                               }
-                       }
-                       return nodeToBean(node);
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot load object from node " + node, e);
-               }
-       }
-
-       /** Update an existing node with an object */
-       public void update(Node node, Object obj) {
-               try {
-                       if (nodeMapperProvider != null) {
-
-                               NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node);
-                               if (nodeMapper != this) {
-                                       nodeMapper.update(node, obj);
-                               } else
-                                       beanToNode(createBeanWrapper(obj), node);
-                       } else
-                               beanToNode(createBeanWrapper(obj), node);
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot update node " + node + " with "
-                                       + obj, e);
-               }
-       }
-
-       /**
-        * if no storage path is given; we use canonical path
-        * 
-        * @see this.storagePath()
-        */
-       public Node save(Session session, Object obj) {
-               return save(session, storagePath(obj), obj);
-       }
-
-       /**
-        * Create a new node to store an object. If the parentNode doesn't exist, it
-        * is created
-        * 
-        * the primaryNodeType may be initialized before
-        */
-       public Node save(Session session, String path, Object obj) {
-               try {
-                       final Node node;
-                       String parentPath = JcrUtils.parentPath(path);
-                       // find or create parent node
-                       Node parentNode;
-                       if (session.itemExists(path))
-                               parentNode = (Node) session.getItem(parentPath);
-                       else {
-                               parentNode = JcrUtils.mkdirs(session, parentPath, null,
-                                               versioning);
-                       }
-                       // create node
-
-                       if (primaryNodeType != null)
-                               node = parentNode.addNode(JcrUtils.lastPathElement(path),
-                                               primaryNodeType);
-                       else
-                               node = parentNode.addNode(JcrUtils.lastPathElement(path));
-
-                       // Check specific cases
-                       if (nodeMapperProvider != null) {
-                               NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node);
-                               if (nodeMapper != this) {
-                                       nodeMapper.update(node, obj);
-                                       return node;
-                               }
-                       }
-                       update(node, obj);
-                       return node;
-               } catch (ArgeoException e) {
-                       throw e;
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot save or update " + obj + " under "
-                                       + path, e);
-               }
-       }
-
-       /**
-        * Parse the FQN of a class to string with '/' delimiters Prefix the
-        * returned string with "/objects/"
-        */
-       public String storagePath(Object obj) {
-               String clss = obj.getClass().getName();
-               StringBuffer buf = new StringBuffer("/objects/");
-               StringTokenizer st = new StringTokenizer(clss, ".");
-               while (st.hasMoreTokens()) {
-                       buf.append(st.nextToken()).append('/');
-               }
-               buf.append(obj.toString());
-               return buf.toString();
-       }
-
-       @SuppressWarnings("unchecked")
-       /** 
-        * Transforms a node into an object of the class defined by classProperty Property
-        */
-       protected Object nodeToBean(Node node) throws RepositoryException {
-
-               try {
-                       String clssName = node.getProperty(classProperty).getValue()
-                                       .getString();
-
-                       BeanWrapper beanWrapper = createBeanWrapper(loadClass(clssName));
-
-                       // process properties
-                       PropertyIterator propIt = node.getProperties();
-                       props: while (propIt.hasNext()) {
-                               Property prop = propIt.nextProperty();
-                               if (!beanWrapper.isWritableProperty(prop.getName()))
-                                       continue props;
-
-                               PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(prop
-                                               .getName());
-                               Class propClass = pd.getPropertyType();
-
-                               // Process case of List and its derived classes
-                               // primitive list
-                               if (propClass != null && List.class.isAssignableFrom(propClass)) {
-                                       List<Object> lst = new ArrayList<Object>();
-                                       Class<?> valuesClass = classFromProperty(prop);
-                                       if (valuesClass != null)
-                                               for (Value value : prop.getValues()) {
-                                                       lst.add(asObject(value, valuesClass));
-                                               }
-                                       continue props;
-                               }
-
-                               // Case of other type of property accepted by jcr
-                               // Long, Double, String, Binary, Date, Boolean, Name
-                               Object value = asObject(prop.getValue(), pd.getPropertyType());
-                               if (value != null)
-                                       beanWrapper.setPropertyValue(prop.getName(), value);
-                       }
-
-                       // process children nodes
-                       NodeIterator nodeIt = node.getNodes();
-                       nodes: while (nodeIt.hasNext()) {
-                               Node childNode = nodeIt.nextNode();
-                               String name = childNode.getName();
-                               if (!beanWrapper.isWritableProperty(name))
-                                       continue nodes;
-
-                               PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(name);
-                               Class propClass = pd.getPropertyType();
-
-                               // objects list
-                               if (propClass != null && List.class.isAssignableFrom(propClass)) {
-                                       String lstClass = childNode.getProperty(classProperty)
-                                                       .getString();
-                                       List<Object> lst;
-                                       try {
-                                               lst = (List<Object>) loadClass(lstClass).newInstance();
-                                       } catch (Exception e) {
-                                               lst = new ArrayList<Object>();
-                                       }
-
-                                       NodeIterator valuesIt = childNode.getNodes();
-                                       while (valuesIt.hasNext()) {
-                                               Node lstValueNode = valuesIt.nextNode();
-                                               Object lstValue = nodeToBean(lstValueNode);
-                                               lst.add(lstValue);
-                                       }
-
-                                       beanWrapper.setPropertyValue(name, lst);
-                                       continue nodes;
-                               }
-
-                               // objects map
-                               if (propClass != null && Map.class.isAssignableFrom(propClass)) {
-                                       String mapClass = childNode.getProperty(classProperty)
-                                                       .getString();
-                                       Map<Object, Object> map;
-                                       try {
-                                               map = (Map<Object, Object>) loadClass(mapClass)
-                                                               .newInstance();
-                                       } catch (Exception e) {
-                                               map = new HashMap<Object, Object>();
-                                       }
-
-                                       // properties
-                                       PropertyIterator keysPropIt = childNode.getProperties();
-                                       keyProps: while (keysPropIt.hasNext()) {
-                                               Property keyProp = keysPropIt.nextProperty();
-                                               // FIXME: use property editor
-                                               String key = keyProp.getName();
-                                               if (classProperty.equals(key))
-                                                       continue keyProps;
-
-                                               Class keyPropClass = classFromProperty(keyProp);
-                                               if (keyPropClass != null) {
-                                                       Object mapValue = asObject(keyProp.getValue(),
-                                                                       keyPropClass);
-                                                       map.put(key, mapValue);
-                                               }
-                                       }
-
-                                       // node
-                                       NodeIterator keysIt = childNode.getNodes();
-                                       while (keysIt.hasNext()) {
-                                               Node mapValueNode = keysIt.nextNode();
-                                               // FIXME: use property editor
-                                               Object key = mapValueNode.getName();
-
-                                               Object mapValue = nodeToBean(mapValueNode);
-
-                                               map.put(key, mapValue);
-                                       }
-                                       beanWrapper.setPropertyValue(name, map);
-                                       continue nodes;
-                               }
-
-                               // default
-                               Object value = nodeToBean(childNode);
-                               beanWrapper.setPropertyValue(name, value);
-
-                       }
-                       return beanWrapper.getWrappedInstance();
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot map node " + node, e);
-               }
-       }
-
-       /**
-        * Transforms an object to the specified jcr Node in order to persist it.
-        * 
-        * @param beanWrapper
-        * @param node
-        * @throws RepositoryException
-        */
-       protected void beanToNode(BeanWrapper beanWrapper, Node node)
-                       throws RepositoryException {
-               properties: for (PropertyDescriptor pd : beanWrapper
-                               .getPropertyDescriptors()) {
-                       String name = pd.getName();
-                       if (!beanWrapper.isReadableProperty(name))
-                               continue properties;// skip
-
-                       Object value = beanWrapper.getPropertyValue(name);
-                       if (value == null) {
-                               // remove values when updating
-                               if (node.hasProperty(name))
-                                       node.setProperty(name, (Value) null);
-                               if (node.hasNode(name))
-                                       node.getNode(name).remove();
-
-                               continue properties;
-                       }
-
-                       // if (uuidProperty != null && uuidProperty.equals(name)) {
-                       // // node.addMixin(ArgeoJcrConstants.MIX_REFERENCEABLE);
-                       // node.setProperty(ArgeoJcrConstants.JCR_UUID, value.toString());
-                       // continue properties;
-                       // }
-
-                       if ("class".equals(name)) {
-                               if (classProperty != null) {
-                                       node.setProperty(classProperty, ((Class<?>) value)
-                                                       .getName());
-                                       // TODO: store a class hierarchy?
-                               }
-                               continue properties;
-                       }
-
-                       // Some bean reference other classes. We must deal with this case
-                       if (value instanceof Class<?>) {
-                               node.setProperty(name, ((Class<?>) value).getName());
-                               continue properties;
-                       }
-
-                       Value val = asValue(node.getSession(), value);
-                       if (val != null) {
-                               node.setProperty(name, val);
-                               continue properties;
-                       }
-
-                       if (value instanceof List<?>) {
-                               List<?> lst = (List<?>) value;
-                               addList(node, name, lst);
-                               continue properties;
-                       }
-
-                       if (value instanceof Map<?, ?>) {
-                               Map<?, ?> map = (Map<?, ?>) value;
-                               addMap(node, name, map);
-                               continue properties;
-                       }
-
-                       BeanWrapper child = createBeanWrapper(value);
-                       // TODO: delegate to another mapper
-
-                       // TODO: deal with references
-                       // Node childNode = findChildReference(session, child);
-                       // if (childNode != null) {
-                       // node.setProperty(name, childNode);
-                       // continue properties;
-                       // }
-
-                       // default case (recursive)
-                       if (node.hasNode(name)) {// update
-                               // TODO: optimize
-                               node.getNode(name).remove();
-                       }
-                       Node childNode = node.addNode(name);
-                       beanToNode(child, childNode);
-               }
-       }
-
-       /**
-        * Process specific case of list
-        * 
-        * @param node
-        * @param name
-        * @param lst
-        * @throws RepositoryException
-        */
-       protected void addList(Node node, String name, List<?> lst)
-                       throws RepositoryException {
-               if (node.hasNode(name)) {// update
-                       // TODO: optimize
-                       node.getNode(name).remove();
-               }
-
-               Node listNode = node.addNode(name);
-               listNode.setProperty(classProperty, lst.getClass().getName());
-               Value[] values = new Value[lst.size()];
-               boolean atLeastOneSet = false;
-               for (int i = 0; i < lst.size(); i++) {
-                       Object lstValue = lst.get(i);
-                       values[i] = asValue(node.getSession(), lstValue);
-                       if (values[i] != null) {
-                               atLeastOneSet = true;
-                       } else {
-                               Node childNode = findChildReference(node.getSession(),
-                                               createBeanWrapper(lstValue));
-                               if (childNode != null) {
-                                       values[i] = node.getSession().getValueFactory()
-                                                       .createValue(childNode);
-                                       atLeastOneSet = true;
-                               }
-                       }
-               }
-
-               // will be either properties or nodes, not both
-               if (!atLeastOneSet && lst.size() != 0) {
-                       for (Object lstValue : lst) {
-                               Node childNode = listNode.addNode(NODE_VALUE);
-                               beanToNode(createBeanWrapper(lstValue), childNode);
-                       }
-               } else {
-                       listNode.setProperty(name, values);
-               }
-       }
-
-       /**
-        * Process specific case of maps.
-        * 
-        * @param node
-        * @param name
-        * @param map
-        * @throws RepositoryException
-        */
-       protected void addMap(Node node, String name, Map<?, ?> map)
-                       throws RepositoryException {
-               if (node.hasNode(name)) {// update
-                       // TODO: optimize
-                       node.getNode(name).remove();
-               }
-
-               Node mapNode = node.addNode(name);
-               mapNode.setProperty(classProperty, map.getClass().getName());
-               for (Object key : map.keySet()) {
-                       Object mapValue = map.get(key);
-                       // PropertyEditor pe = beanWrapper.findCustomEditor(key.getClass(),
-                       // null);
-                       String keyStr;
-                       // if (pe == null) {
-                       if (key instanceof CharSequence)
-                               keyStr = key.toString();
-                       else
-                               throw new ArgeoException(
-                                               "Cannot find property editor for class "
-                                                               + key.getClass());
-                       // } else {
-                       // pe.setValue(key);
-                       // keyStr = pe.getAsText();
-                       // }
-                       // TODO: check string format
-
-                       Value mapVal = asValue(node.getSession(), mapValue);
-                       if (mapVal != null)
-                               mapNode.setProperty(keyStr, mapVal);
-                       else {
-                               Node entryNode = mapNode.addNode(keyStr);
-                               beanToNode(createBeanWrapper(mapValue), entryNode);
-                       }
-
-               }
-
-       }
-
-       protected BeanWrapper createBeanWrapper(Object obj) {
-               return new BeanWrapperImpl(obj);
-       }
-
-       protected BeanWrapper createBeanWrapper(Class<?> clss) {
-               return new BeanWrapperImpl(clss);
-       }
-
-       /** Returns null if value cannot be found */
-       protected Value asValue(Session session, Object value)
-                       throws RepositoryException {
-               ValueFactory valueFactory = session.getValueFactory();
-               if (value instanceof Integer)
-                       return valueFactory.createValue((Integer) value);
-               else if (value instanceof Long)
-                       return valueFactory.createValue((Long) value);
-               else if (value instanceof Float)
-                       return valueFactory.createValue((Float) value);
-               else if (value instanceof Double)
-                       return valueFactory.createValue((Double) value);
-               else if (value instanceof Boolean)
-                       return valueFactory.createValue((Boolean) value);
-               else if (value instanceof Calendar)
-                       return valueFactory.createValue((Calendar) value);
-               else if (value instanceof Date) {
-                       Calendar cal = new GregorianCalendar();
-                       cal.setTime((Date) value);
-                       return valueFactory.createValue(cal);
-               } else if (value instanceof CharSequence)
-                       return valueFactory.createValue(value.toString());
-               else if (value instanceof InputStream)
-                       return valueFactory.createValue((InputStream) value);
-               else
-                       return null;
-       }
-
-       protected Class<?> classFromProperty(Property property)
-                       throws RepositoryException {
-               switch (property.getType()) {
-               case PropertyType.LONG:
-                       return Long.class;
-               case PropertyType.DOUBLE:
-                       return Double.class;
-               case PropertyType.STRING:
-                       return String.class;
-               case PropertyType.BOOLEAN:
-                       return Boolean.class;
-               case PropertyType.DATE:
-                       return Calendar.class;
-               case PropertyType.NAME:
-                       return null;
-               default:
-                       throw new ArgeoException("Cannot find class for property "
-                                       + property + ", type="
-                                       + PropertyType.nameFromValue(property.getType()));
-               }
-       }
-
-       protected Object asObject(Value value, Class<?> propClass)
-                       throws RepositoryException {
-               if (propClass.equals(Integer.class))
-                       return (int) value.getLong();
-               else if (propClass.equals(Long.class))
-                       return value.getLong();
-               else if (propClass.equals(Float.class))
-                       return (float) value.getDouble();
-               else if (propClass.equals(Double.class))
-                       return value.getDouble();
-               else if (propClass.equals(Boolean.class))
-                       return value.getBoolean();
-               else if (CharSequence.class.isAssignableFrom(propClass))
-                       return value.getString();
-               else if (InputStream.class.isAssignableFrom(propClass))
-                       return value.getStream();
-               else if (Calendar.class.isAssignableFrom(propClass))
-                       return value.getDate();
-               else if (Date.class.isAssignableFrom(propClass))
-                       return value.getDate().getTime();
-               else
-                       return null;
-       }
-
-       protected Node findChildReference(Session session, BeanWrapper child)
-                       throws RepositoryException {
-               if (child.isReadableProperty(uuidProperty)) {
-                       String childUuid = child.getPropertyValue(uuidProperty).toString();
-                       try {
-                               return session.getNodeByUUID(childUuid);
-                       } catch (ItemNotFoundException e) {
-                               if (strictUuidReference)
-                                       throw new ArgeoException("No node found with uuid "
-                                                       + childUuid, e);
-                       }
-               }
-               return null;
-       }
-
-       protected Class<?> loadClass(String name) {
-               // log.debug("Class loader: " + classLoader);
-               try {
-                       return classLoader.loadClass(name);
-               } catch (ClassNotFoundException e) {
-                       throw new ArgeoException("Cannot load class " + name, e);
-               }
-       }
-
-       protected String propertyName(String name) {
-               return name;
-       }
-
-       public void setVersioning(Boolean versioning) {
-               this.versioning = versioning;
-       }
-
-       public void setUuidProperty(String uuidProperty) {
-               this.uuidProperty = uuidProperty;
-       }
-
-       public void setClassProperty(String classProperty) {
-               this.classProperty = classProperty;
-       }
-
-       public void setStrictUuidReference(Boolean strictUuidReference) {
-               this.strictUuidReference = strictUuidReference;
-       }
-
-       public void setPrimaryNodeType(String primaryNodeType) {
-               this.primaryNodeType = primaryNodeType;
-       }
-
-       public void setClassLoader(ClassLoader classLoader) {
-               this.classLoader = classLoader;
-       }
-
-       public void setNodeMapperProvider(NodeMapperProvider nodeMapperProvider) {
-               this.nodeMapperProvider = nodeMapperProvider;
-       }
-
-       public String getPrimaryNodeType() {
-               return this.primaryNodeType;
-       }
-
-       public String getClassProperty() {
-               return this.classProperty;
-       }
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/JcrUtils.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/JcrUtils.java
deleted file mode 100644 (file)
index d3174a1..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-package org.argeo.jcr;
-
-import java.util.Calendar;
-import java.util.StringTokenizer;
-
-import javax.jcr.NamespaceRegistry;
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Property;
-import javax.jcr.PropertyIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Value;
-import javax.jcr.query.Query;
-import javax.jcr.query.QueryResult;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-
-public class JcrUtils {
-       private final static Log log = LogFactory.getLog(JcrUtils.class);
-
-       public static Node querySingleNode(Query query) {
-               NodeIterator nodeIterator;
-               try {
-                       QueryResult queryResult = query.execute();
-                       nodeIterator = queryResult.getNodes();
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot execute query " + query, e);
-               }
-               Node node;
-               if (nodeIterator.hasNext())
-                       node = nodeIterator.nextNode();
-               else
-                       return null;
-
-               if (nodeIterator.hasNext())
-                       throw new ArgeoException("Query returned more than one node.");
-               return node;
-       }
-
-       public static String removeForbiddenCharacters(String str) {
-               return str.replace('[', '_').replace(']', '_').replace('/', '_')
-                               .replace('*', '_');
-
-       }
-
-       public static String parentPath(String path) {
-               if (path.equals("/"))
-                       throw new ArgeoException("Root path '/' has no parent path");
-               if (path.charAt(0) != '/')
-                       throw new ArgeoException("Path " + path + " must start with a '/'");
-               String pathT = path;
-               if (pathT.charAt(pathT.length() - 1) == '/')
-                       pathT = pathT.substring(0, pathT.length() - 2);
-
-               int index = pathT.lastIndexOf('/');
-               return pathT.substring(0, index);
-       }
-
-       public static String dateAsPath(Calendar cal) {
-               StringBuffer buf = new StringBuffer(14);
-               buf.append('Y').append(cal.get(Calendar.YEAR));// 5
-               buf.append('/');// 1
-               int month = cal.get(Calendar.MONTH) + 1;
-               buf.append('M');
-               if (month < 10)
-                       buf.append(0);
-               buf.append(month);// 3
-               buf.append('/');// 1
-               int day = cal.get(Calendar.DAY_OF_MONTH);
-               if (day < 10)
-                       buf.append(0);
-               buf.append('D').append(day);// 3
-               buf.append('/');// 1
-               return buf.toString();
-
-       }
-
-       public static String hostAsPath(String host) {
-               // TODO : inverse order of the elements (to have org/argeo/test IO
-               // test/argeo/org
-               return host.replace('.', '/');
-       }
-
-       public static String lastPathElement(String path) {
-               if (path.charAt(path.length() - 1) == '/')
-                       throw new ArgeoException("Path " + path + " cannot end with '/'");
-               int index = path.lastIndexOf('/');
-               if (index < 0)
-                       throw new ArgeoException("Cannot find last path element for "
-                                       + path);
-               return path.substring(index + 1);
-       }
-
-       public static Node mkdirs(Session session, String path) {
-               return mkdirs(session, path, null, false);
-       }
-
-       public static Node mkdirs(Session session, String path, String type,
-                       Boolean versioning) {
-               try {
-                       if (path.equals('/'))
-                               return session.getRootNode();
-
-                       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())) {
-                                       if (type != null)
-                                               currentNode = currentNode.addNode(part, type);
-                                       else
-                                               currentNode = currentNode.addNode(part);
-                                       if (versioning)
-                                               currentNode.addMixin(ArgeoJcrConstants.MIX_VERSIONABLE);
-                                       if (log.isTraceEnabled())
-                                               log.debug("Added folder " + part + " as " + current);
-                               } else {
-                                       currentNode = (Node) session.getItem(current.toString());
-                               }
-                       }
-                       session.save();
-                       return currentNode;
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot mkdirs " + path, e);
-               }
-       }
-
-       public static void registerNamespaceSafely(Session session, String prefix,
-                       String uri) {
-               try {
-                       registerNamespaceSafely(session.getWorkspace()
-                                       .getNamespaceRegistry(), prefix, uri);
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot find namespace registry", e);
-               }
-       }
-
-       public static void registerNamespaceSafely(NamespaceRegistry nr,
-                       String prefix, String uri) {
-               try {
-                       String[] prefixes = nr.getPrefixes();
-                       for (String pref : prefixes)
-                               if (pref.equals(prefix)) {
-                                       String registeredUri = nr.getURI(pref);
-                                       if (!registeredUri.equals(uri))
-                                               throw new ArgeoException("Prefix " + pref
-                                                               + " already registered for URI "
-                                                               + registeredUri
-                                                               + " which is different from provided URI "
-                                                               + uri);
-                                       else
-                                               return;// skip
-                               }
-                       nr.registerNamespace(prefix, uri);
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot register namespace " + uri
-                                       + " under prefix " + prefix, e);
-               }
-       }
-
-       /** 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(ArgeoJcrConstants.JCR_SYSTEM)) {
-                       return;
-               }
-
-               // Then the children nodes (recursive)
-               NodeIterator it = node.getNodes();
-               while (it.hasNext()) {
-                       Node childNode = it.nextNode();
-                       debug(childNode);
-               }
-
-               // Then output the properties
-               PropertyIterator properties = node.getProperties();
-               // log.debug("Property are : ");
-
-               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());
-                       }
-               }
-
-       }
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapper.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapper.java
deleted file mode 100644 (file)
index 2b816c3..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.argeo.jcr;
-
-import javax.jcr.Node;
-import javax.jcr.Session;
-
-public interface NodeMapper {
-       public Object load(Node node);
-
-       public void update(Node node, Object obj);
-
-       public Node save(Session session, String path, Object obj);
-       
-       public void setNodeMapperProvider(NodeMapperProvider nmp);
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapperProvider.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/NodeMapperProvider.java
deleted file mode 100644 (file)
index 316a877..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.argeo.jcr;
-
-import javax.jcr.Node;
-
-/** Provides a node mapper relevant for this node. */
-public interface NodeMapperProvider {
-
-       /** 
-        * Node Mapper is chosen regarding the Jcr path of the node parameter 
-        * @param Node node
-        * @return the node mapper or null if no relevant node mapper can be found. */
-       public NodeMapper findNodeMapper(Node node);
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java
deleted file mode 100644 (file)
index 9996b7b..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-package org.argeo.jcr;
-
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.FactoryBean;
-
-public class ThreadBoundJcrSessionFactory implements FactoryBean,
-               DisposableBean {
-       private final static Log log = LogFactory
-                       .getLog(ThreadBoundJcrSessionFactory.class);
-
-       private Repository repository;
-       private List<Session> activeSessions = Collections
-                       .synchronizedList(new ArrayList<Session>());
-
-       private ThreadLocal<Session> session = new ThreadLocal<Session>();
-       private boolean destroying = false;
-       private final Session proxiedSession;
-
-       public ThreadBoundJcrSessionFactory() {
-               Class<?>[] interfaces = { Session.class };
-               proxiedSession = (Session) Proxy.newProxyInstance(getClass()
-                               .getClassLoader(), interfaces, new InvocationHandler() {
-
-                       public Object invoke(Object proxy, Method method, Object[] args)
-                                       throws Throwable {
-                               Session threadSession = session.get();
-                               if (threadSession == null) {
-                                       if ("logout".equals(method.getName()))// no need to login
-                                               return Void.TYPE;
-                                       threadSession = login();
-                                       session.set(threadSession);
-                               }
-
-                               Object ret = method.invoke(threadSession, args);
-                               if ("logout".equals(method.getName())) {
-                                       session.remove();
-                                       if (!destroying)
-                                               activeSessions.remove(threadSession);
-                                       if (log.isTraceEnabled())
-                                               log.trace("Logged out from JCR session "
-                                                               + threadSession + "; userId="
-                                                               + threadSession.getUserID());
-                               }
-                               return ret;
-                       }
-               });
-       }
-
-       protected Session login() {
-               try {
-                       Session sess = repository.login();
-                       if (log.isTraceEnabled())
-                               log.trace("Log in to JCR session " + sess + "; userId="
-                                               + sess.getUserID());
-                       // Thread.dumpStack();
-                       activeSessions.add(sess);
-                       return sess;
-               } catch (RepositoryException e) {
-                       throw new ArgeoException("Cannot log in to repository", e);
-               }
-       }
-
-       public Object getObject() {
-               return proxiedSession;
-       }
-
-       public void destroy() throws Exception {
-               if (log.isDebugEnabled())
-                       log.debug("Cleaning up " + activeSessions.size()
-                                       + " active JCR sessions...");
-
-               destroying = true;
-               for (Session sess : activeSessions) {
-                       sess.logout();
-               }
-               activeSessions.clear();
-       }
-
-       public Class<? extends Session> getObjectType() {
-               return Session.class;
-       }
-
-       public boolean isSingleton() {
-               return true;
-       }
-
-       public void setRepository(Repository repository) {
-               this.repository = repository;
-       }
-
-}
index a70c6e9d0784cb80d845187179bf1f2cc76a15ef..78c477a22a6d1c13936327012507350380a0d409 100644 (file)
@@ -11,13 +11,13 @@ import junit.framework.TestCase;
 import org.apache.commons.io.FileUtils;
 import org.apache.jackrabbit.core.TransientRepository;
 import org.argeo.ArgeoException;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
 
 public abstract class AbstractJcrTestCase extends TestCase {
        private TransientRepository repository;
        private Session session = null;
 
+       protected abstract File getRepositoryFile() throws Exception;
+
        @Override
        protected void setUp() throws Exception {
                File homeDir = new File(System.getProperty("java.io.tmpdir"),
@@ -44,12 +44,6 @@ public abstract class AbstractJcrTestCase extends TestCase {
                return session;
        }
 
-       protected File getRepositoryFile() throws Exception {
-               Resource res = new ClassPathResource(
-                               "org/argeo/server/jackrabbit/repository-inMemory.xml");
-               return res.getFile();
-       }
-
        protected Repository getRepository() {
                return repository;
        }
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/DefaultJcrListener.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/DefaultJcrListener.java
deleted file mode 100644 (file)
index 4b23308..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.argeo.server.jcr;
-
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-import javax.jcr.observation.Event;
-import javax.jcr.observation.EventIterator;
-import javax.jcr.observation.EventListener;
-import javax.jcr.observation.ObservationManager;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-
-/** To be overridden */
-public class DefaultJcrListener implements EventListener {
-       private final static Log log = LogFactory.getLog(DefaultJcrListener.class);
-       private Session session;
-       private Repository repository;
-       private String path = "/";
-       private Boolean deep = true;
-       private String username = "demo";
-       private String password = "demo";
-
-       public void start() {
-               try {
-                       addEventListener(session().getWorkspace().getObservationManager());
-                       if (log.isDebugEnabled())
-                               log.debug("Registered JCR event listener on " + path);
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot register event listener", e);
-               }
-       }
-
-       public void stop() {
-               try {
-                       session().getWorkspace().getObservationManager()
-                                       .removeEventListener(this);
-                       if (log.isDebugEnabled())
-                               log.debug("Unregistered JCR event listener on " + path);
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot unregister event listener", e);
-               }
-       }
-
-       /** Default is listen to all events */
-       protected Integer getEvents() {
-               return Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED
-                               | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED;
-       }
-
-       /** To be overidden */
-       public void onEvent(EventIterator events) {
-               while (events.hasNext()) {
-                       Event event = events.nextEvent();
-                       log.debug(event);
-               }
-       }
-
-       /** To be overidden */
-       protected void addEventListener(ObservationManager observationManager)
-                       throws RepositoryException {
-               observationManager.addEventListener(this, getEvents(), path, deep,
-                               null, null, false);
-       }
-
-       protected Session session() {
-               if (session == null)
-                       try {
-                               session = repository.login(new SimpleCredentials(username,
-                                               password.toCharArray()));
-                       } catch (Exception e) {
-                               throw new ArgeoException("Cannot open session", e);
-                       }
-               return session;
-       }
-
-       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 setPath(String path) {
-               this.path = path;
-       }
-
-       public void setDeep(Boolean deep) {
-               this.deep = deep;
-       }
-
-}
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
deleted file mode 100644 (file)
index 020672b..0000000
+++ /dev/null
@@ -1,246 +0,0 @@
-package org.argeo.server.jcr;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.List;
-
-import javax.activation.MimetypesFileTypeMap;
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.SimpleCredentials;
-import javax.jcr.version.Version;
-import javax.jcr.version.VersionHistory;
-import javax.jcr.version.VersionIterator;
-
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.JcrUtils;
-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) {
-               JcrUtils.mkdirs(session(), path, "nt:folder", versioning);
-       }
-
-       public void create(String path, Resource file, String mimeType) {
-               try {
-                       create(path, file.getInputStream(), mimeType);
-               } catch (IOException e) {
-                       throw new ArgeoException("Cannot read " + file, e);
-               }
-       }
-
-       public void create(String path, InputStream in, String mimeType) {
-               try {
-                       if (session().itemExists(path)) {
-                               throw new ArgeoException("Node " + path + " already exists.");
-                       }
-
-                       int index = path.lastIndexOf('/');
-                       String parentPath = path.substring(0, index);
-                       if (parentPath.equals(""))
-                               parentPath = "/";
-                       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");
-                       if (mimeType != null)
-                               contentNode.setProperty("jcr:mimeType", mimeType);
-                       contentNode.setProperty("jcr:encoding", defaultEncoding);
-                       contentNode.setProperty("jcr:data", in);
-                       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);
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot create node for " + path, e);
-               }
-
-       }
-
-       public void update(String path, Resource file) {
-               try {
-                       update(path, file.getInputStream());
-               } catch (IOException e) {
-                       throw new ArgeoException("Cannot read " + file, e);
-               }
-       }
-
-       public void update(String path, InputStream in) {
-               try {
-
-                       if (!session().itemExists(path)) {
-                               String type = new MimetypesFileTypeMap()
-                                               .getContentType(FilenameUtils.getName(path));
-                               create(path, in, type);
-                               return;
-                       }
-
-                       Node fileNode = (Node) session().getItem(path);
-                       Node contentNode = fileNode.getNode("jcr:content");
-                       fileNode.checkout();
-                       contentNode.setProperty("jcr:data", in);
-                       Calendar lastModified = Calendar.getInstance();
-                       // lastModified.setTimeInMillis(file.lastModified());
-                       contentNode.setProperty("jcr:lastModified", lastModified);
-
-                       session().save();
-                       fileNode.checkin();
-
-                       if (log.isDebugEnabled())
-                               log.debug("Updated " + path);
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot update node " + path, 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);
-                       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 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;
-       }
-
-       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/main/java/org/argeo/server/jcr/mvc/JcrBrowserController.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/JcrBrowserController.java
deleted file mode 100644 (file)
index cddc8b0..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.argeo.server.jcr.mvc;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.Item;
-import javax.jcr.NodeIterator;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.Value;
-import javax.jcr.query.Query;
-import javax.jcr.query.QueryResult;
-import javax.jcr.query.Row;
-import javax.jcr.query.RowIterator;
-
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.context.request.RequestAttributes;
-import org.springframework.web.context.request.WebRequest;
-
-@Controller
-public class JcrBrowserController implements JcrMvcConstants {
-
-       @RequestMapping("/getJcrItem.*")
-       public Item getJcrItem(WebRequest webRequest,
-                       @RequestParam("path") String path) throws RepositoryException {
-               return ((Session) webRequest.getAttribute(REQUEST_ATTR_SESSION,
-                               RequestAttributes.SCOPE_REQUEST)).getItem(path);
-       }
-
-       @RequestMapping("/queryJcrNodes.*")
-       public List<String> queryJcrNodes(WebRequest webRequest,
-                       @RequestParam("statement") String statement,
-                       @RequestParam("language") String language)
-                       throws RepositoryException {
-               Session session = ((Session) webRequest.getAttribute(
-                               REQUEST_ATTR_SESSION, RequestAttributes.SCOPE_REQUEST));
-               Query query = session.getWorkspace().getQueryManager().createQuery(
-                               statement, language);
-               NodeIterator nit = query.execute().getNodes();
-               List<String> paths = new ArrayList<String>();
-               while (nit.hasNext()) {
-                       paths.add(nit.nextNode().getPath());
-               }
-               return paths;
-       }
-
-       @RequestMapping("/queryJcrTable.*")
-       public List<List<String>> queryJcrTable(WebRequest webRequest,
-                       @RequestParam("statement") String statement,
-                       @RequestParam("language") String language)
-                       throws RepositoryException {
-               Session session = ((Session) webRequest.getAttribute(
-                               REQUEST_ATTR_SESSION, RequestAttributes.SCOPE_REQUEST));
-               Query query = session.getWorkspace().getQueryManager().createQuery(
-                               statement, language);
-               QueryResult queryResult = query.execute();
-               List<List<String>> results = new ArrayList<List<String>>();
-               results.add(Arrays.asList(queryResult.getColumnNames()));
-               RowIterator rit = queryResult.getRows();
-
-               while (rit.hasNext()) {
-                       Row row = rit.nextRow();
-                       List<String> lst = new ArrayList<String>();
-                       for (Value value : row.getValues()) {
-                               lst.add(value.getString());
-                       }
-               }
-               return results;
-       }
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/JcrManagerController.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/JcrManagerController.java
deleted file mode 100644 (file)
index 37fca84..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.argeo.server.jcr.mvc;
-
-import java.util.List;
-import java.util.StringTokenizer;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.fileupload.FileItem;
-import org.apache.commons.fileupload.FileItemFactory;
-import org.apache.commons.fileupload.disk.DiskFileItemFactory;
-import org.apache.commons.fileupload.servlet.ServletFileUpload;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.server.ServerAnswer;
-import org.argeo.server.jcr.JcrResourceAdapter;
-import org.argeo.server.mvc.MvcConstants;
-import org.springframework.core.io.ByteArrayResource;
-import org.springframework.stereotype.Controller;
-import org.springframework.web.bind.annotation.ModelAttribute;
-import org.springframework.web.bind.annotation.RequestMapping;
-
-@Controller
-public class JcrManagerController implements MvcConstants {
-       private final static Log log = LogFactory
-                       .getLog(JcrManagerController.class);
-
-       private JcrResourceAdapter resourceAdapter;
-
-       // Create a factory for disk-based file items
-       private FileItemFactory factory = new DiskFileItemFactory();
-
-       // Create a new file upload handler
-       private ServletFileUpload upload = new ServletFileUpload(factory);
-
-       @SuppressWarnings("unchecked")
-       @RequestMapping("/upload/**")
-       @ModelAttribute(ANSWER_MODEL_KEY_AS_HTML)
-       public ServerAnswer upload(HttpServletRequest request,
-                       HttpServletResponse response) throws Exception {
-               // Parse the request
-               List<FileItem> items = upload.parseRequest(request);
-
-               byte[] arr = null;
-               for (FileItem item : items) {
-                       if (!item.isFormField()) {
-                               arr = item.get();
-                               break;
-                       }
-               }
-
-               ByteArrayResource res = new ByteArrayResource(arr);
-               // String pathInfo = request.getPathInfo();
-
-               StringBuffer path = new StringBuffer("/");
-               StringTokenizer st = new StringTokenizer(request.getPathInfo(), "/");
-               st.nextToken();// skip /upload/
-               while (st.hasMoreTokens()) {
-                       String token = st.nextToken();
-                       if (!st.hasMoreTokens()) {
-                               resourceAdapter.mkdirs(path.toString());
-                               path.append(token);
-                       } else {
-                               path.append(token).append('/');
-                       }
-               }
-               // String path = '/' + pathInfo.substring(1).substring(
-               // pathInfo.indexOf('/'));
-               if (log.isDebugEnabled())
-                       log.debug("Upload to " + path);
-               resourceAdapter.update(path.toString(), res);
-               return ServerAnswer.ok("File " + path + " imported");
-       }
-
-       public void setResourceAdapter(JcrResourceAdapter resourceAdapter) {
-               this.resourceAdapter = resourceAdapter;
-       }
-
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/JcrMvcConstants.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/JcrMvcConstants.java
deleted file mode 100644 (file)
index 3f50e96..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-package org.argeo.server.jcr.mvc;
-
-public interface JcrMvcConstants {
-       public final static String REQUEST_ATTR_SESSION = "jcrSession";
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/JcrXmlServerSerializer.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/JcrXmlServerSerializer.java
deleted file mode 100644 (file)
index 54cc5b7..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.argeo.server.jcr.mvc;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.RepositoryException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-import org.argeo.ArgeoException;
-import org.argeo.server.ServerSerializer;
-import org.springframework.xml.dom.DomContentHandler;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
-
-public class JcrXmlServerSerializer implements ServerSerializer {
-       private String contentTypeCharset = "UTF-8";
-
-       private final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
-                       .newInstance();
-       private final TransformerFactory transformerFactory = TransformerFactory
-                       .newInstance();
-
-       public void serialize(Object obj, HttpServletRequest request,
-                       HttpServletResponse response) {
-               if (!(obj instanceof Node))
-                       throw new ArgeoException("Only " + Node.class + " is supported");
-
-               String noRecurseStr = request.getParameter("noRecurse");
-               boolean noRecurse = noRecurseStr != null && noRecurseStr.equals("true");
-
-               String depthStr = request.getParameter("depth");
-               String downloadStr = request.getParameter("download");
-
-               Node node = (Node) obj;
-
-               try {
-                       String contentType = "text/xml;charset=" + contentTypeCharset;
-                       // download case
-                       if (downloadStr != null && downloadStr.equals("true")) {
-                               String fileName = node.getName().replace(':', '_') + ".xml";
-                               contentType = contentType + ";name=\"" + fileName + "\"";
-                               response.setHeader("Content-Disposition",
-                                               "attachment; filename=\"" + fileName + "\"");
-                               response.setHeader("Expires", "0");
-                               response
-                                               .setHeader("Cache-Control", "no-cache, must-revalidate");
-                               response.setHeader("Pragma", "no-cache");
-                       }
-
-                       response.setContentType(contentType);
-                       if (depthStr == null) {
-                               node.getSession().exportDocumentView(node.getPath(),
-                                               response.getOutputStream(), true, noRecurse);
-                       } else {
-                               int depth = Integer.parseInt(depthStr);
-                               Document document = documentBuilderFactory.newDocumentBuilder()
-                                               .newDocument();
-                               serializeLevelToDom(node, document, 0, depth);
-                               Transformer transformer = transformerFactory.newTransformer();
-                               transformer.transform(new DOMSource(document),
-                                               new StreamResult(response.getOutputStream()));
-                       }
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot serialize " + node, e);
-               }
-       }
-
-       protected void serializeLevelToDom(Node currentJcrNode,
-                       org.w3c.dom.Node currentDomNode, int currentDepth, int targetDepth)
-                       throws RepositoryException, SAXException {
-               DomContentHandler domContentHandler = new DomContentHandler(
-                               currentDomNode);
-               currentJcrNode.getSession().exportDocumentView(
-                               currentJcrNode.getPath(), domContentHandler, true, true);
-
-               if (currentDepth == targetDepth)
-                       return;
-
-               // TODO: filter
-               NodeIterator nit = currentJcrNode.getNodes();
-               while (nit.hasNext()) {
-                       Node nextJcrNode = nit.nextNode();
-                       org.w3c.dom.Node nextDomNode;
-                       if (currentDomNode instanceof Document)
-                               nextDomNode = ((Document) currentDomNode).getDocumentElement();
-                       else {
-                               String name = currentJcrNode.getName();
-                               NodeList nodeList = ((Element) currentDomNode)
-                                               .getElementsByTagName(name);
-                               if (nodeList.getLength() < 1)
-                                       throw new ArgeoException("No elment named " + name
-                                                       + " under " + currentDomNode);
-                               // we know it is the last one added
-                               nextDomNode = nodeList.item(nodeList.getLength() - 1);
-                       }
-                       // recursive call
-                       serializeLevelToDom(nextJcrNode, nextDomNode, currentDepth + 1,
-                                       targetDepth);
-               }
-       }
-
-       public void setContentTypeCharset(String contentTypeCharset) {
-               this.contentTypeCharset = contentTypeCharset;
-       }
-
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/OpenSessionInViewJcrInterceptor.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jcr/mvc/OpenSessionInViewJcrInterceptor.java
deleted file mode 100644 (file)
index c91b66d..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.argeo.server.jcr.mvc;
-
-import javax.jcr.Session;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.ui.ModelMap;
-import org.springframework.web.context.request.RequestAttributes;
-import org.springframework.web.context.request.WebRequest;
-import org.springframework.web.context.request.WebRequestInterceptor;
-
-public class OpenSessionInViewJcrInterceptor implements WebRequestInterceptor,
-               JcrMvcConstants {
-       private final static Log log = LogFactory
-                       .getLog(OpenSessionInViewJcrInterceptor.class);
-
-       private Session session;
-
-       public void preHandle(WebRequest request) throws Exception {
-               if (log.isTraceEnabled())
-                       log.trace("preHandle: " + request);
-               // Authentication auth = SecurityContextHolder.getContext()
-               // .getAuthentication();
-               // if (auth != null)
-               // log.debug("auth=" + auth + ", authenticated="
-               // + auth.isAuthenticated() + ", name=" + auth.getName());
-               // else
-               // log.debug("No auth");
-
-               // FIXME: find a safer way to initialize
-               // FIXME: not really needed to initialize here
-               // session.getRepository();
-               request.setAttribute(REQUEST_ATTR_SESSION, session,
-                               RequestAttributes.SCOPE_REQUEST);
-       }
-
-       public void postHandle(WebRequest request, ModelMap model) throws Exception {
-               // if (log.isDebugEnabled())
-               // log.debug("postHandle: " + request);
-       }
-
-       public void afterCompletion(WebRequest request, Exception ex)
-                       throws Exception {
-               if (log.isTraceEnabled())
-                       log.trace("afterCompletion: " + request);
-               // FIXME: only close session that were open
-               session.logout();
-       }
-
-       public void setSession(Session session) {
-               this.session = session;
-       }
-
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/jcr/CollectionsObject.java b/server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/jcr/CollectionsObject.java
deleted file mode 100644 (file)
index 5d00c7a..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-package org.argeo.jcr;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class CollectionsObject {
-       private String id;
-       private String label;
-       private SimpleObject simpleObject;
-       private List<String> stringList = new ArrayList<String>();
-       private Map<String, Float> floatMap = new HashMap<String, Float>();
-       private Map<SimpleObject, String> objectMap = new HashMap<SimpleObject, String>();
-       private Map<String, Map<String, String>> mapOfMaps = new HashMap<String, Map<String, String>>();
-
-       public String getId() {
-               return id;
-       }
-
-       public void setId(String id) {
-               this.id = id;
-       }
-
-       public String getLabel() {
-               return label;
-       }
-
-       public void setLabel(String label) {
-               this.label = label;
-       }
-
-       public SimpleObject getSimpleObject() {
-               return simpleObject;
-       }
-
-       public void setSimpleObject(SimpleObject simpleObject) {
-               this.simpleObject = simpleObject;
-       }
-
-       public List<String> getStringList() {
-               return stringList;
-       }
-
-       public void setStringList(List<String> stringList) {
-               this.stringList = stringList;
-       }
-
-       public Map<String, Float> getFloatMap() {
-               return floatMap;
-       }
-
-       public void setFloatMap(Map<String, Float> floatMap) {
-               this.floatMap = floatMap;
-       }
-
-       public Map<SimpleObject, String> getObjectMap() {
-               return objectMap;
-       }
-
-       public void setObjectMap(Map<SimpleObject, String> objectMap) {
-               this.objectMap = objectMap;
-       }
-
-       public Map<String, Map<String, String>> getMapOfMaps() {
-               return mapOfMaps;
-       }
-
-       public void setMapOfMaps(Map<String, Map<String, String>> mapOfMaps) {
-               this.mapOfMaps = mapOfMaps;
-       }
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/jcr/MapperTest.java b/server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/jcr/MapperTest.java
deleted file mode 100644 (file)
index 1b22582..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-package org.argeo.jcr;
-
-import javax.jcr.Node;
-
-import org.argeo.server.jackrabbit.unit.AbstractJcrTestCase;
-
-public class MapperTest extends AbstractJcrTestCase {
-       public void testSimpleObject() throws Exception {
-               SimpleObject mySo = new SimpleObject();
-               mySo.setInteger(100);
-               mySo.setString("hello world");
-
-               OtherObject oo1 = new OtherObject();
-               oo1.setKey("someKey");
-               oo1.setValue("stringValue");
-               mySo.setOtherObject(oo1);
-
-               OtherObject oo2 = new OtherObject();
-               oo2.setKey("anotherSimpleObject");
-               oo2.setValue(new SimpleObject());
-               mySo.setAnotherObject(oo2);
-
-               BeanNodeMapper bnm = new BeanNodeMapper();
-
-               Node node = bnm.save(session(), mySo);
-               session().save();
-               JcrUtils.debug(node);
-       }
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/jcr/OtherObject.java b/server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/jcr/OtherObject.java
deleted file mode 100644 (file)
index a9a49d7..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-package org.argeo.jcr;
-
-public class OtherObject {
-       private String key;
-       private Object value;
-
-       public String getKey() {
-               return key;
-       }
-
-       public void setKey(String key) {
-               this.key = key;
-       }
-
-       public Object getValue() {
-               return value;
-       }
-
-       public void setValue(Object value) {
-               this.value = value;
-       }
-}
diff --git a/server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/jcr/SimpleObject.java b/server/runtime/org.argeo.server.jackrabbit/src/test/java/org/argeo/jcr/SimpleObject.java
deleted file mode 100644 (file)
index 2971880..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.argeo.jcr;
-
-import java.util.UUID;
-
-public class SimpleObject {
-       private String string;
-       private String uuid = UUID.randomUUID().toString();
-       private Integer integer;
-       private OtherObject otherObject;
-       private OtherObject anotherObject;
-
-       public String getString() {
-               return string;
-       }
-
-       public void setString(String sting) {
-               this.string = sting;
-       }
-
-       public Integer getInteger() {
-               return integer;
-       }
-
-       public void setInteger(Integer integer) {
-               this.integer = integer;
-       }
-
-       public OtherObject getOtherObject() {
-               return otherObject;
-       }
-
-       public void setOtherObject(OtherObject otherObject) {
-               this.otherObject = otherObject;
-       }
-
-       public OtherObject getAnotherObject() {
-               return anotherObject;
-       }
-
-       public void setAnotherObject(OtherObject anotherObject) {
-               this.anotherObject = anotherObject;
-       }
-
-       @Override
-       public boolean equals(Object obj) {
-               return string.equals(((SimpleObject) obj).string);
-       }
-
-       @Override
-       public int hashCode() {
-               return string.hashCode();
-       }
-
-       public void setUuid(String uuid) {
-               this.uuid = uuid;
-       }
-
-       public String getUuid() {
-               return uuid;
-       }
-
-}
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
deleted file mode 100644 (file)
index f7e22b9..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-package org.argeo.server.jcr;
-
-import java.io.InputStream;
-import java.text.SimpleDateFormat;
-import java.util.Calendar;
-import java.util.List;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.server.jackrabbit.unit.AbstractJcrTestCase;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.core.io.Resource;
-
-public class JcrResourceAdapterTest extends AbstractJcrTestCase {
-       private static SimpleDateFormat sdf = new SimpleDateFormat(
-                       "yyyyMMdd:hhmmss.SSS");
-
-       private final static Log log = LogFactory
-                       .getLog(JcrResourceAdapterTest.class);
-
-       private JcrResourceAdapter jra;
-
-       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);
-               log.debug("Versions of " + filePath);
-               int count = 0;
-               for (Calendar version : versions) {
-                       log.debug(" " + (count == 0 ? "base" : count - 1) + "\t"
-                                       + sdf.format(version.getTime()));
-                       count++;
-               }
-
-               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 {
-               super.setUp();
-               jra = new JcrResourceAdapter();
-               jra.setRepository(getRepository());
-               jra.setUsername("demo");
-               jra.setPassword("demo");
-               jra.afterPropertiesSet();
-       }
-
-       @Override
-       protected void tearDown() throws Exception {
-               jra.destroy();
-               super.tearDown();
-       }
-
-}
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
deleted file mode 100644 (file)
index ca995af..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-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/applicationContext.xml b/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/applicationContext.xml
deleted file mode 100644 (file)
index 78a34af..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>\r
-<beans xmlns="http://www.springframework.org/schema/beans"\r
-       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
-       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
-\r
-       <bean\r
-               class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">\r
-               <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />\r
-               <property name="ignoreUnresolvablePlaceholders" value="true" />\r
-       </bean>\r
-\r
-       <bean id="nodeMapperProvider" class="org.argeo.slc.jcr.dao.SlcNodeMapperProvider"\r
-               init-method="init">\r
-               <property name="defaultNodeMapper" ref="nodeMapper" />\r
-               <property name="treeTestResultNodeMapper" ref="treeTestResultNodeMapper" />\r
-       </bean>\r
-\r
-       <bean id="nodeMapper" class="org.argeo.jcr.BeanNodeMapper">\r
-       </bean>\r
-\r
-       <bean id="treeTestResultNodeMapper" class="org.argeo.slc.jcr.dao.TreeTestResultNodeMapper">\r
-       </bean>\r
-\r
-       <bean id="argeo.jcr.session.inMemory" factory-bean="argeo.jcr.repository.inMemory"\r
-               factory-method="login" destroy-method="logout">\r
-               <constructor-arg>\r
-                       <bean class="javax.jcr.SimpleCredentials">\r
-                               <constructor-arg value="demo" />\r
-                               <constructor-arg value="demo" />\r
-                       </bean>\r
-               </constructor-arg>\r
-       </bean>\r
-\r
-       <bean id="argeo.jcr.repository.inMemory" class="org.argeo.server.jackrabbit.JackrabbitContainer">\r
-               <property name="homeDirectory" value="${java.io.tmpdir}/jackrabbit-slc-unit" />\r
-               <property name="configuration"\r
-                       value="classpath:/org/argeo/server/jackrabbit/repository-inMemory.xml" />\r
-       </bean>\r
-\r
-</beans>
\ No newline at end of file
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
deleted file mode 100644 (file)
index e5846fe..0000000
Binary files a/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy00.xls and /dev/null 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
deleted file mode 100644 (file)
index b5c6b55..0000000
Binary files a/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy01.xls and /dev/null 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
deleted file mode 100644 (file)
index d73bc66..0000000
Binary files a/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy02.xls and /dev/null 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
deleted file mode 100644 (file)
index 0759cb9..0000000
Binary files a/server/runtime/org.argeo.server.jackrabbit/src/test/resources/org/argeo/server/jcr/dummy03.xls and /dev/null 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
deleted file mode 100644 (file)
index f051923..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-<?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 8b978d9ede4d96fb47cbd858fc3b6607968c677f..6cb01891884adf525d5bb2cf4448bdfe3b337e28 100644 (file)
@@ -1,6 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <classpath>
        <classpathentry kind="src" 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.eclipse.pde.core.requiredPlugins"/>
        <classpathentry kind="output" path="target/classes"/>
index 202455e146e4c0470a1ea8dc31436b55304a4dbf..39e03ff767944bf5cd623bcd4dafadf5f4f0b93b 100644 (file)
@@ -1,13 +1,45 @@
 Manifest-Version: 1.0\r
 Created-By: 1.5.0_16 (Sun Microsystems Inc.)\r
 Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt\r
+Import-Package: javax.activation;version="1.1",javax.jcr;version="1.0"\r
+ ,javax.jcr.nodetype;version="1.0",javax.jcr.observation;version="1.0"\r
+ ,javax.jcr.query;version="1.0",javax.jcr.version;version="1.0",javax.\r
+ servlet;version="2.5",javax.servlet.http;version="2.5",javax.xml.pars\r
+ ers,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.s\r
+ tream,org.apache.commons.fileupload;version="1.2",org.apache.commons.\r
+ fileupload.disk;version="1.2",org.apache.commons.fileupload.servlet;v\r
+ ersion="1.2",org.apache.commons.io;version="1.4",org.apache.commons.l\r
+ ogging;version="1.1",org.argeo;version="0.1",org.argeo.jcr;version="0\r
+ .1",org.argeo.server;version="0.1",org.argeo.server.jcr;version="0.1"\r
+ ,org.argeo.server.jcr.mvc;version="0.1",org.argeo.server.mvc;version=\r
+ "0.1",org.springframework.beans;version="2.5",org.springframework.bea\r
+ ns.factory;version="2.5",org.springframework.core.io;version="2.5",or\r
+ g.springframework.stereotype;version="2.5",org.springframework.ui;ver\r
+ sion="2.5",org.springframework.web.bind.annotation;version="2.5",org.\r
+ springframework.web.context.request;version="2.5",org.springframework\r
+ .xml.dom;version="1.5",org.w3c.dom,org.xml.sax\r
 Bundle-RequiredExecutionEnvironment: J2SE-1.5\r
-Bundle-Version: 0.1.3.SNAPSHOT-r3539\r
+Export-Package: org.argeo.jcr;uses:="org.springframework.beans,javax.j\r
+ cr,org.argeo,javax.jcr.query,org.apache.commons.logging,javax.jcr.nod\r
+ etype,org.springframework.beans.factory";version="0.1.3.SNAPSHOT-r354\r
+ 0",org.argeo.server.jcr.mvc;uses:="org.springframework.web.context.re\r
+ quest,org.springframework.web.bind.annotation,org.springframework.ste\r
+ reotype,javax.jcr.query,javax.jcr,javax.servlet.http,org.apache.commo\r
+ ns.logging,org.argeo.server,org.apache.commons.fileupload,org.argeo.s\r
+ erver.jcr,org.springframework.core.io,org.apache.commons.fileupload.s\r
+ ervlet,org.argeo.server.mvc,org.apache.commons.fileupload.disk,org.xm\r
+ l.sax,org.w3c.dom,org.argeo,javax.xml.transform,javax.xml.transform.d\r
+ om,javax.servlet,org.springframework.xml.dom,javax.xml.parsers,javax.\r
+ xml.transform.stream,org.springframework.ui";version="0.1.3.SNAPSHOT-\r
+ r3540",org.argeo.server.jcr;uses:="javax.jcr.observation,org.apache.c\r
+ ommons.logging,javax.jcr,org.argeo,javax.activation,org.argeo.jcr,org\r
+ .springframework.core.io,org.apache.commons.io,javax.jcr.version,org.\r
+ springframework.beans.factory";version="0.1.3.SNAPSHOT-r3540"\r
+Bundle-Version: 0.1.3.SNAPSHOT-r3540\r
 Bundle-Name: Commons Server JCR\r
 Bundle-DocURL: http://www.argeo.org\r
 Bundle-ManifestVersion: 2\r
 Bundle-Vendor: Argeo\r
-Fragment-Host: org.argeo.dep.osgi.jackrabbit\r
 Bundle-SymbolicName: org.argeo.server.jcr\r
 Tool: Bnd-0.0.357\r
 \r
index 5fc538bc83f35ba123c9f84f2eb6124dd65c8789..500039909c0479012fc92d8219e83ceebf0a9073 100644 (file)
@@ -1,4 +1,16 @@
-source.. = src/main/java/
+source.. = src/main/java/,\
+           src/test/java/,\
+           src/test/resources/
 output.. = target/classes/
 bin.includes = META-INF/,\
                .
+additional.bundles = org.argeo.server.jackrabbit,\
+                     com.springsource.slf4j.api,\
+                     com.springsource.slf4j.log4j,\
+                     com.springsource.org.apache.log4j,\
+                     com.springsource.org.apache.commons.collections,\
+                     com.springsource.edu.oswego.cs.dl.util.concurrent,\
+                     com.springsource.org.apache.derby,\
+                     com.springsource.org.apache.lucene,\
+                     com.springsource.junit
+
index 44b1a1b2f398e0f803552b00660bb8805b259adc..d4ba29fd8b0c99733666359b795ba3916647827c 100644 (file)
@@ -29,7 +29,6 @@
                                <version>${version.maven-bundle-plugin}</version>
                                <configuration>
                                        <instructions>
-                                               <Fragment-Host>org.argeo.dep.osgi.jackrabbit</Fragment-Host>
                                                <Export-Package>
                                                        org.argeo.jcr.*,
                                                        org.argeo.server.jcr.*
                        <version>0.1.3-SNAPSHOT</version>
                </dependency>
 
-               <!-- Jack Rabbit -->
+               <!-- JCR -->
                <dependency>
-                       <groupId>org.argeo.dep.osgi</groupId>
-                       <artifactId>org.argeo.dep.osgi.jackrabbit</artifactId>
-               </dependency>
-               <dependency>
-                       <groupId>javax.servlet</groupId>
-                       <artifactId>com.springsource.javax.servlet</artifactId>
-               </dependency>
-
-               <!-- Apache Commons -->
-               <dependency>
-                       <groupId>org.apache.commons</groupId>
-                       <artifactId>com.springsource.org.apache.commons.io</artifactId>
-               </dependency>
-
-               <dependency>
-                       <groupId>javax.activation</groupId>
-                       <artifactId>com.springsource.javax.activation</artifactId>
+                       <groupId>javax.jcr</groupId>
+                       <artifactId>com.springsource.javax.jcr</artifactId>
                </dependency>
 
                <!-- Spring -->
                        <artifactId>org.springframework.xml</artifactId>
                </dependency>
 
+               <dependency>
+                       <groupId>javax.activation</groupId>
+                       <artifactId>com.springsource.javax.activation</artifactId>
+               </dependency>
+
                <!-- Logging -->
                <dependency>
                        <groupId>org.slf4j</groupId>
                </dependency>
 
                <!-- TEST -->
+               <dependency>
+                       <groupId>org.argeo.commons.server</groupId>
+                       <artifactId>org.argeo.server.jackrabbit</artifactId>
+                       <version>0.1.3-SNAPSHOT</version>
+                       <scope>test</scope>
+               </dependency>
                <dependency>
                        <groupId>org.argeo.commons.basic</groupId>
                        <artifactId>org.argeo.support.junit</artifactId>
diff --git a/server/runtime/org.argeo.server.jcr/repository.xml b/server/runtime/org.argeo.server.jcr/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.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java
new file mode 100644 (file)
index 0000000..4f12fa7
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.jcr;
+
+/**
+ * Copied from org.apache.jackrabbit.JcrConstants v1.6.0 in order to avoid a
+ * dependency to Jackrabbit.
+ */
+public interface ArgeoJcrConstants {
+       /**
+        * jcr:autoCreated
+        */
+       public static final String JCR_AUTOCREATED = "jcr:autoCreated";
+       /**
+        * jcr:baseVersion
+        */
+       public static final String JCR_BASEVERSION = "jcr:baseVersion";
+       /**
+        * jcr:child
+        */
+       public static final String JCR_CHILD = "jcr:child";
+       /**
+        * jcr:childNodeDefinition
+        */
+       public static final String JCR_CHILDNODEDEFINITION = "jcr:childNodeDefinition";
+       /**
+        * jcr:content
+        */
+       public static final String JCR_CONTENT = "jcr:content";
+       /**
+        * jcr:created
+        */
+       public static final String JCR_CREATED = "jcr:created";
+       /**
+        * jcr:data
+        */
+       public static final String JCR_DATA = "jcr:data";
+       /**
+        * jcr:defaultPrimaryType
+        */
+       public static final String JCR_DEFAULTPRIMARYTYPE = "jcr:defaultPrimaryType";
+       /**
+        * jcr:defaultValues
+        */
+       public static final String JCR_DEFAULTVALUES = "jcr:defaultValues";
+       /**
+        * jcr:encoding
+        */
+       public static final String JCR_ENCODING = "jcr:encoding";
+       /**
+        * jcr:frozenMixinTypes
+        */
+       public static final String JCR_FROZENMIXINTYPES = "jcr:frozenMixinTypes";
+       /**
+        * jcr:frozenNode
+        */
+       public static final String JCR_FROZENNODE = "jcr:frozenNode";
+       /**
+        * jcr:frozenPrimaryType
+        */
+       public static final String JCR_FROZENPRIMARYTYPE = "jcr:frozenPrimaryType";
+       /**
+        * jcr:frozenUuid
+        */
+       public static final String JCR_FROZENUUID = "jcr:frozenUuid";
+       /**
+        * jcr:hasOrderableChildNodes
+        */
+       public static final String JCR_HASORDERABLECHILDNODES = "jcr:hasOrderableChildNodes";
+       /**
+        * jcr:isCheckedOut
+        */
+       public static final String JCR_ISCHECKEDOUT = "jcr:isCheckedOut";
+       /**
+        * jcr:isMixin
+        */
+       public static final String JCR_ISMIXIN = "jcr:isMixin";
+       /**
+        * jcr:language
+        */
+       public static final String JCR_LANGUAGE = "jcr:language";
+       /**
+        * jcr:lastModified
+        */
+       public static final String JCR_LASTMODIFIED = "jcr:lastModified";
+       /**
+        * jcr:lockIsDeep
+        */
+       public static final String JCR_LOCKISDEEP = "jcr:lockIsDeep";
+       /**
+        * jcr:lockOwner
+        */
+       public static final String JCR_LOCKOWNER = "jcr:lockOwner";
+       /**
+        * jcr:mandatory
+        */
+       public static final String JCR_MANDATORY = "jcr:mandatory";
+       /**
+        * jcr:mergeFailed
+        */
+       public static final String JCR_MERGEFAILED = "jcr:mergeFailed";
+       /**
+        * jcr:mimeType
+        */
+       public static final String JCR_MIMETYPE = "jcr:mimeType";
+       /**
+        * jcr:mixinTypes
+        */
+       public static final String JCR_MIXINTYPES = "jcr:mixinTypes";
+       /**
+        * jcr:multiple
+        */
+       public static final String JCR_MULTIPLE = "jcr:multiple";
+       /**
+        * jcr:name
+        */
+       public static final String JCR_NAME = "jcr:name";
+       /**
+        * jcr:nodeTypeName
+        */
+       public static final String JCR_NODETYPENAME = "jcr:nodeTypeName";
+       /**
+        * jcr:onParentVersion
+        */
+       public static final String JCR_ONPARENTVERSION = "jcr:onParentVersion";
+       /**
+        * jcr:predecessors
+        */
+       public static final String JCR_PREDECESSORS = "jcr:predecessors";
+       /**
+        * jcr:primaryItemName
+        */
+       public static final String JCR_PRIMARYITEMNAME = "jcr:primaryItemName";
+       /**
+        * jcr:primaryType
+        */
+       public static final String JCR_PRIMARYTYPE = "jcr:primaryType";
+       /**
+        * jcr:propertyDefinition
+        */
+       public static final String JCR_PROPERTYDEFINITION = "jcr:propertyDefinition";
+       /**
+        * jcr:protected
+        */
+       public static final String JCR_PROTECTED = "jcr:protected";
+       /**
+        * jcr:requiredPrimaryTypes
+        */
+       public static final String JCR_REQUIREDPRIMARYTYPES = "jcr:requiredPrimaryTypes";
+       /**
+        * jcr:requiredType
+        */
+       public static final String JCR_REQUIREDTYPE = "jcr:requiredType";
+       /**
+        * jcr:rootVersion
+        */
+       public static final String JCR_ROOTVERSION = "jcr:rootVersion";
+       /**
+        * jcr:sameNameSiblings
+        */
+       public static final String JCR_SAMENAMESIBLINGS = "jcr:sameNameSiblings";
+       /**
+        * jcr:statement
+        */
+       public static final String JCR_STATEMENT = "jcr:statement";
+       /**
+        * jcr:successors
+        */
+       public static final String JCR_SUCCESSORS = "jcr:successors";
+       /**
+        * jcr:supertypes
+        */
+       public static final String JCR_SUPERTYPES = "jcr:supertypes";
+       /**
+        * jcr:system
+        */
+       public static final String JCR_SYSTEM = "jcr:system";
+       /**
+        * jcr:uuid
+        */
+       public static final String JCR_UUID = "jcr:uuid";
+       /**
+        * jcr:valueConstraints
+        */
+       public static final String JCR_VALUECONSTRAINTS = "jcr:valueConstraints";
+       /**
+        * jcr:versionHistory
+        */
+       public static final String JCR_VERSIONHISTORY = "jcr:versionHistory";
+       /**
+        * jcr:versionLabels
+        */
+       public static final String JCR_VERSIONLABELS = "jcr:versionLabels";
+       /**
+        * jcr:versionStorage
+        */
+       public static final String JCR_VERSIONSTORAGE = "jcr:versionStorage";
+       /**
+        * jcr:versionableUuid
+        */
+       public static final String JCR_VERSIONABLEUUID = "jcr:versionableUuid";
+
+       /**
+        * Pseudo property jcr:path used with query results
+        */
+       public static final String JCR_PATH = "jcr:path";
+       /**
+        * Pseudo property jcr:score used with query results
+        */
+       public static final String JCR_SCORE = "jcr:score";
+
+       /**
+        * mix:lockable
+        */
+       public static final String MIX_LOCKABLE = "mix:lockable";
+       /**
+        * mix:referenceable
+        */
+       public static final String MIX_REFERENCEABLE = "mix:referenceable";
+       /**
+        * mix:versionable
+        */
+       public static final String MIX_VERSIONABLE = "mix:versionable";
+       /**
+        * mix:shareable
+        */
+       public static final String MIX_SHAREABLE = "mix:shareable";
+       /**
+        * nt:base
+        */
+       public static final String NT_BASE = "nt:base";
+       /**
+        * nt:childNodeDefinition
+        */
+       public static final String NT_CHILDNODEDEFINITION = "nt:childNodeDefinition";
+       /**
+        * nt:file
+        */
+       public static final String NT_FILE = "nt:file";
+       /**
+        * nt:folder
+        */
+       public static final String NT_FOLDER = "nt:folder";
+       /**
+        * nt:frozenNode
+        */
+       public static final String NT_FROZENNODE = "nt:frozenNode";
+       /**
+        * nt:hierarchyNode
+        */
+       public static final String NT_HIERARCHYNODE = "nt:hierarchyNode";
+       /**
+        * nt:linkedFile
+        */
+       public static final String NT_LINKEDFILE = "nt:linkedFile";
+       /**
+        * nt:nodeType
+        */
+       public static final String NT_NODETYPE = "nt:nodeType";
+       /**
+        * nt:propertyDefinition
+        */
+       public static final String NT_PROPERTYDEFINITION = "nt:propertyDefinition";
+       /**
+        * nt:query
+        */
+       public static final String NT_QUERY = "nt:query";
+       /**
+        * nt:resource
+        */
+       public static final String NT_RESOURCE = "nt:resource";
+       /**
+        * nt:unstructured
+        */
+       public static final String NT_UNSTRUCTURED = "nt:unstructured";
+       /**
+        * nt:version
+        */
+       public static final String NT_VERSION = "nt:version";
+       /**
+        * nt:versionHistory
+        */
+       public static final String NT_VERSIONHISTORY = "nt:versionHistory";
+       /**
+        * nt:versionLabels
+        */
+       public static final String NT_VERSIONLABELS = "nt:versionLabels";
+       /**
+        * nt:versionedChild
+        */
+       public static final String NT_VERSIONEDCHILD = "nt:versionedChild";
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/BeanNodeMapper.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/BeanNodeMapper.java
new file mode 100644 (file)
index 0000000..a526bcf
--- /dev/null
@@ -0,0 +1,604 @@
+package org.argeo.jcr;
+
+import java.beans.PropertyDescriptor;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+
+import org.argeo.ArgeoException;
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+
+public class BeanNodeMapper implements NodeMapper {
+       // private final static Log log = LogFactory.getLog(BeanNodeMapper.class);
+
+       private final static String NODE_VALUE = "value";
+
+       // private String keyNode = "bean:key";
+       private String uuidProperty = "uuid";
+       private String classProperty = "class";
+
+       private Boolean versioning = false;
+       private Boolean strictUuidReference = false;
+
+       // TODO define a primaryNodeType Strategy
+       private String primaryNodeType = null;
+
+       private ClassLoader classLoader = getClass().getClassLoader();
+
+       private NodeMapperProvider nodeMapperProvider;
+
+       /**
+        * exposed method to retrieve a bean from a node
+        */
+       public Object load(Node node) {
+               try {
+                       if (nodeMapperProvider != null) {
+                               NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node);
+                               if (nodeMapper != this) {
+                                       return nodeMapper.load(node);
+                               }
+                       }
+                       return nodeToBean(node);
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot load object from node " + node, e);
+               }
+       }
+
+       /** Update an existing node with an object */
+       public void update(Node node, Object obj) {
+               try {
+                       if (nodeMapperProvider != null) {
+
+                               NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node);
+                               if (nodeMapper != this) {
+                                       nodeMapper.update(node, obj);
+                               } else
+                                       beanToNode(createBeanWrapper(obj), node);
+                       } else
+                               beanToNode(createBeanWrapper(obj), node);
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot update node " + node + " with "
+                                       + obj, e);
+               }
+       }
+
+       /**
+        * if no storage path is given; we use canonical path
+        * 
+        * @see this.storagePath()
+        */
+       public Node save(Session session, Object obj) {
+               return save(session, storagePath(obj), obj);
+       }
+
+       /**
+        * Create a new node to store an object. If the parentNode doesn't exist, it
+        * is created
+        * 
+        * the primaryNodeType may be initialized before
+        */
+       public Node save(Session session, String path, Object obj) {
+               try {
+                       final Node node;
+                       String parentPath = JcrUtils.parentPath(path);
+                       // find or create parent node
+                       Node parentNode;
+                       if (session.itemExists(path))
+                               parentNode = (Node) session.getItem(parentPath);
+                       else {
+                               parentNode = JcrUtils.mkdirs(session, parentPath, null,
+                                               versioning);
+                       }
+                       // create node
+
+                       if (primaryNodeType != null)
+                               node = parentNode.addNode(JcrUtils.lastPathElement(path),
+                                               primaryNodeType);
+                       else
+                               node = parentNode.addNode(JcrUtils.lastPathElement(path));
+
+                       // Check specific cases
+                       if (nodeMapperProvider != null) {
+                               NodeMapper nodeMapper = nodeMapperProvider.findNodeMapper(node);
+                               if (nodeMapper != this) {
+                                       nodeMapper.update(node, obj);
+                                       return node;
+                               }
+                       }
+                       update(node, obj);
+                       return node;
+               } catch (ArgeoException e) {
+                       throw e;
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot save or update " + obj + " under "
+                                       + path, e);
+               }
+       }
+
+       /**
+        * Parse the FQN of a class to string with '/' delimiters Prefix the
+        * returned string with "/objects/"
+        */
+       public String storagePath(Object obj) {
+               String clss = obj.getClass().getName();
+               StringBuffer buf = new StringBuffer("/objects/");
+               StringTokenizer st = new StringTokenizer(clss, ".");
+               while (st.hasMoreTokens()) {
+                       buf.append(st.nextToken()).append('/');
+               }
+               buf.append(obj.toString());
+               return buf.toString();
+       }
+
+       @SuppressWarnings("unchecked")
+       /** 
+        * Transforms a node into an object of the class defined by classProperty Property
+        */
+       protected Object nodeToBean(Node node) throws RepositoryException {
+
+               try {
+                       String clssName = node.getProperty(classProperty).getValue()
+                                       .getString();
+
+                       BeanWrapper beanWrapper = createBeanWrapper(loadClass(clssName));
+
+                       // process properties
+                       PropertyIterator propIt = node.getProperties();
+                       props: while (propIt.hasNext()) {
+                               Property prop = propIt.nextProperty();
+                               if (!beanWrapper.isWritableProperty(prop.getName()))
+                                       continue props;
+
+                               PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(prop
+                                               .getName());
+                               Class propClass = pd.getPropertyType();
+
+                               // Process case of List and its derived classes
+                               // primitive list
+                               if (propClass != null && List.class.isAssignableFrom(propClass)) {
+                                       List<Object> lst = new ArrayList<Object>();
+                                       Class<?> valuesClass = classFromProperty(prop);
+                                       if (valuesClass != null)
+                                               for (Value value : prop.getValues()) {
+                                                       lst.add(asObject(value, valuesClass));
+                                               }
+                                       continue props;
+                               }
+
+                               // Case of other type of property accepted by jcr
+                               // Long, Double, String, Binary, Date, Boolean, Name
+                               Object value = asObject(prop.getValue(), pd.getPropertyType());
+                               if (value != null)
+                                       beanWrapper.setPropertyValue(prop.getName(), value);
+                       }
+
+                       // process children nodes
+                       NodeIterator nodeIt = node.getNodes();
+                       nodes: while (nodeIt.hasNext()) {
+                               Node childNode = nodeIt.nextNode();
+                               String name = childNode.getName();
+                               if (!beanWrapper.isWritableProperty(name))
+                                       continue nodes;
+
+                               PropertyDescriptor pd = beanWrapper.getPropertyDescriptor(name);
+                               Class propClass = pd.getPropertyType();
+
+                               // objects list
+                               if (propClass != null && List.class.isAssignableFrom(propClass)) {
+                                       String lstClass = childNode.getProperty(classProperty)
+                                                       .getString();
+                                       List<Object> lst;
+                                       try {
+                                               lst = (List<Object>) loadClass(lstClass).newInstance();
+                                       } catch (Exception e) {
+                                               lst = new ArrayList<Object>();
+                                       }
+
+                                       NodeIterator valuesIt = childNode.getNodes();
+                                       while (valuesIt.hasNext()) {
+                                               Node lstValueNode = valuesIt.nextNode();
+                                               Object lstValue = nodeToBean(lstValueNode);
+                                               lst.add(lstValue);
+                                       }
+
+                                       beanWrapper.setPropertyValue(name, lst);
+                                       continue nodes;
+                               }
+
+                               // objects map
+                               if (propClass != null && Map.class.isAssignableFrom(propClass)) {
+                                       String mapClass = childNode.getProperty(classProperty)
+                                                       .getString();
+                                       Map<Object, Object> map;
+                                       try {
+                                               map = (Map<Object, Object>) loadClass(mapClass)
+                                                               .newInstance();
+                                       } catch (Exception e) {
+                                               map = new HashMap<Object, Object>();
+                                       }
+
+                                       // properties
+                                       PropertyIterator keysPropIt = childNode.getProperties();
+                                       keyProps: while (keysPropIt.hasNext()) {
+                                               Property keyProp = keysPropIt.nextProperty();
+                                               // FIXME: use property editor
+                                               String key = keyProp.getName();
+                                               if (classProperty.equals(key))
+                                                       continue keyProps;
+
+                                               Class keyPropClass = classFromProperty(keyProp);
+                                               if (keyPropClass != null) {
+                                                       Object mapValue = asObject(keyProp.getValue(),
+                                                                       keyPropClass);
+                                                       map.put(key, mapValue);
+                                               }
+                                       }
+
+                                       // node
+                                       NodeIterator keysIt = childNode.getNodes();
+                                       while (keysIt.hasNext()) {
+                                               Node mapValueNode = keysIt.nextNode();
+                                               // FIXME: use property editor
+                                               Object key = mapValueNode.getName();
+
+                                               Object mapValue = nodeToBean(mapValueNode);
+
+                                               map.put(key, mapValue);
+                                       }
+                                       beanWrapper.setPropertyValue(name, map);
+                                       continue nodes;
+                               }
+
+                               // default
+                               Object value = nodeToBean(childNode);
+                               beanWrapper.setPropertyValue(name, value);
+
+                       }
+                       return beanWrapper.getWrappedInstance();
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot map node " + node, e);
+               }
+       }
+
+       /**
+        * Transforms an object to the specified jcr Node in order to persist it.
+        * 
+        * @param beanWrapper
+        * @param node
+        * @throws RepositoryException
+        */
+       protected void beanToNode(BeanWrapper beanWrapper, Node node)
+                       throws RepositoryException {
+               properties: for (PropertyDescriptor pd : beanWrapper
+                               .getPropertyDescriptors()) {
+                       String name = pd.getName();
+                       if (!beanWrapper.isReadableProperty(name))
+                               continue properties;// skip
+
+                       Object value = beanWrapper.getPropertyValue(name);
+                       if (value == null) {
+                               // remove values when updating
+                               if (node.hasProperty(name))
+                                       node.setProperty(name, (Value) null);
+                               if (node.hasNode(name))
+                                       node.getNode(name).remove();
+
+                               continue properties;
+                       }
+
+                       // if (uuidProperty != null && uuidProperty.equals(name)) {
+                       // // node.addMixin(ArgeoJcrConstants.MIX_REFERENCEABLE);
+                       // node.setProperty(ArgeoJcrConstants.JCR_UUID, value.toString());
+                       // continue properties;
+                       // }
+
+                       if ("class".equals(name)) {
+                               if (classProperty != null) {
+                                       node.setProperty(classProperty, ((Class<?>) value)
+                                                       .getName());
+                                       // TODO: store a class hierarchy?
+                               }
+                               continue properties;
+                       }
+
+                       // Some bean reference other classes. We must deal with this case
+                       if (value instanceof Class<?>) {
+                               node.setProperty(name, ((Class<?>) value).getName());
+                               continue properties;
+                       }
+
+                       Value val = asValue(node.getSession(), value);
+                       if (val != null) {
+                               node.setProperty(name, val);
+                               continue properties;
+                       }
+
+                       if (value instanceof List<?>) {
+                               List<?> lst = (List<?>) value;
+                               addList(node, name, lst);
+                               continue properties;
+                       }
+
+                       if (value instanceof Map<?, ?>) {
+                               Map<?, ?> map = (Map<?, ?>) value;
+                               addMap(node, name, map);
+                               continue properties;
+                       }
+
+                       BeanWrapper child = createBeanWrapper(value);
+                       // TODO: delegate to another mapper
+
+                       // TODO: deal with references
+                       // Node childNode = findChildReference(session, child);
+                       // if (childNode != null) {
+                       // node.setProperty(name, childNode);
+                       // continue properties;
+                       // }
+
+                       // default case (recursive)
+                       if (node.hasNode(name)) {// update
+                               // TODO: optimize
+                               node.getNode(name).remove();
+                       }
+                       Node childNode = node.addNode(name);
+                       beanToNode(child, childNode);
+               }
+       }
+
+       /**
+        * Process specific case of list
+        * 
+        * @param node
+        * @param name
+        * @param lst
+        * @throws RepositoryException
+        */
+       protected void addList(Node node, String name, List<?> lst)
+                       throws RepositoryException {
+               if (node.hasNode(name)) {// update
+                       // TODO: optimize
+                       node.getNode(name).remove();
+               }
+
+               Node listNode = node.addNode(name);
+               listNode.setProperty(classProperty, lst.getClass().getName());
+               Value[] values = new Value[lst.size()];
+               boolean atLeastOneSet = false;
+               for (int i = 0; i < lst.size(); i++) {
+                       Object lstValue = lst.get(i);
+                       values[i] = asValue(node.getSession(), lstValue);
+                       if (values[i] != null) {
+                               atLeastOneSet = true;
+                       } else {
+                               Node childNode = findChildReference(node.getSession(),
+                                               createBeanWrapper(lstValue));
+                               if (childNode != null) {
+                                       values[i] = node.getSession().getValueFactory()
+                                                       .createValue(childNode);
+                                       atLeastOneSet = true;
+                               }
+                       }
+               }
+
+               // will be either properties or nodes, not both
+               if (!atLeastOneSet && lst.size() != 0) {
+                       for (Object lstValue : lst) {
+                               Node childNode = listNode.addNode(NODE_VALUE);
+                               beanToNode(createBeanWrapper(lstValue), childNode);
+                       }
+               } else {
+                       listNode.setProperty(name, values);
+               }
+       }
+
+       /**
+        * Process specific case of maps.
+        * 
+        * @param node
+        * @param name
+        * @param map
+        * @throws RepositoryException
+        */
+       protected void addMap(Node node, String name, Map<?, ?> map)
+                       throws RepositoryException {
+               if (node.hasNode(name)) {// update
+                       // TODO: optimize
+                       node.getNode(name).remove();
+               }
+
+               Node mapNode = node.addNode(name);
+               mapNode.setProperty(classProperty, map.getClass().getName());
+               for (Object key : map.keySet()) {
+                       Object mapValue = map.get(key);
+                       // PropertyEditor pe = beanWrapper.findCustomEditor(key.getClass(),
+                       // null);
+                       String keyStr;
+                       // if (pe == null) {
+                       if (key instanceof CharSequence)
+                               keyStr = key.toString();
+                       else
+                               throw new ArgeoException(
+                                               "Cannot find property editor for class "
+                                                               + key.getClass());
+                       // } else {
+                       // pe.setValue(key);
+                       // keyStr = pe.getAsText();
+                       // }
+                       // TODO: check string format
+
+                       Value mapVal = asValue(node.getSession(), mapValue);
+                       if (mapVal != null)
+                               mapNode.setProperty(keyStr, mapVal);
+                       else {
+                               Node entryNode = mapNode.addNode(keyStr);
+                               beanToNode(createBeanWrapper(mapValue), entryNode);
+                       }
+
+               }
+
+       }
+
+       protected BeanWrapper createBeanWrapper(Object obj) {
+               return new BeanWrapperImpl(obj);
+       }
+
+       protected BeanWrapper createBeanWrapper(Class<?> clss) {
+               return new BeanWrapperImpl(clss);
+       }
+
+       /** Returns null if value cannot be found */
+       protected Value asValue(Session session, Object value)
+                       throws RepositoryException {
+               ValueFactory valueFactory = session.getValueFactory();
+               if (value instanceof Integer)
+                       return valueFactory.createValue((Integer) value);
+               else if (value instanceof Long)
+                       return valueFactory.createValue((Long) value);
+               else if (value instanceof Float)
+                       return valueFactory.createValue((Float) value);
+               else if (value instanceof Double)
+                       return valueFactory.createValue((Double) value);
+               else if (value instanceof Boolean)
+                       return valueFactory.createValue((Boolean) value);
+               else if (value instanceof Calendar)
+                       return valueFactory.createValue((Calendar) value);
+               else if (value instanceof Date) {
+                       Calendar cal = new GregorianCalendar();
+                       cal.setTime((Date) value);
+                       return valueFactory.createValue(cal);
+               } else if (value instanceof CharSequence)
+                       return valueFactory.createValue(value.toString());
+               else if (value instanceof InputStream)
+                       return valueFactory.createValue((InputStream) value);
+               else
+                       return null;
+       }
+
+       protected Class<?> classFromProperty(Property property)
+                       throws RepositoryException {
+               switch (property.getType()) {
+               case PropertyType.LONG:
+                       return Long.class;
+               case PropertyType.DOUBLE:
+                       return Double.class;
+               case PropertyType.STRING:
+                       return String.class;
+               case PropertyType.BOOLEAN:
+                       return Boolean.class;
+               case PropertyType.DATE:
+                       return Calendar.class;
+               case PropertyType.NAME:
+                       return null;
+               default:
+                       throw new ArgeoException("Cannot find class for property "
+                                       + property + ", type="
+                                       + PropertyType.nameFromValue(property.getType()));
+               }
+       }
+
+       protected Object asObject(Value value, Class<?> propClass)
+                       throws RepositoryException {
+               if (propClass.equals(Integer.class))
+                       return (int) value.getLong();
+               else if (propClass.equals(Long.class))
+                       return value.getLong();
+               else if (propClass.equals(Float.class))
+                       return (float) value.getDouble();
+               else if (propClass.equals(Double.class))
+                       return value.getDouble();
+               else if (propClass.equals(Boolean.class))
+                       return value.getBoolean();
+               else if (CharSequence.class.isAssignableFrom(propClass))
+                       return value.getString();
+               else if (InputStream.class.isAssignableFrom(propClass))
+                       return value.getStream();
+               else if (Calendar.class.isAssignableFrom(propClass))
+                       return value.getDate();
+               else if (Date.class.isAssignableFrom(propClass))
+                       return value.getDate().getTime();
+               else
+                       return null;
+       }
+
+       protected Node findChildReference(Session session, BeanWrapper child)
+                       throws RepositoryException {
+               if (child.isReadableProperty(uuidProperty)) {
+                       String childUuid = child.getPropertyValue(uuidProperty).toString();
+                       try {
+                               return session.getNodeByUUID(childUuid);
+                       } catch (ItemNotFoundException e) {
+                               if (strictUuidReference)
+                                       throw new ArgeoException("No node found with uuid "
+                                                       + childUuid, e);
+                       }
+               }
+               return null;
+       }
+
+       protected Class<?> loadClass(String name) {
+               // log.debug("Class loader: " + classLoader);
+               try {
+                       return classLoader.loadClass(name);
+               } catch (ClassNotFoundException e) {
+                       throw new ArgeoException("Cannot load class " + name, e);
+               }
+       }
+
+       protected String propertyName(String name) {
+               return name;
+       }
+
+       public void setVersioning(Boolean versioning) {
+               this.versioning = versioning;
+       }
+
+       public void setUuidProperty(String uuidProperty) {
+               this.uuidProperty = uuidProperty;
+       }
+
+       public void setClassProperty(String classProperty) {
+               this.classProperty = classProperty;
+       }
+
+       public void setStrictUuidReference(Boolean strictUuidReference) {
+               this.strictUuidReference = strictUuidReference;
+       }
+
+       public void setPrimaryNodeType(String primaryNodeType) {
+               this.primaryNodeType = primaryNodeType;
+       }
+
+       public void setClassLoader(ClassLoader classLoader) {
+               this.classLoader = classLoader;
+       }
+
+       public void setNodeMapperProvider(NodeMapperProvider nodeMapperProvider) {
+               this.nodeMapperProvider = nodeMapperProvider;
+       }
+
+       public String getPrimaryNodeType() {
+               return this.primaryNodeType;
+       }
+
+       public String getClassProperty() {
+               return this.classProperty;
+       }
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java
new file mode 100644 (file)
index 0000000..d3174a1
--- /dev/null
@@ -0,0 +1,201 @@
+package org.argeo.jcr;
+
+import java.util.Calendar;
+import java.util.StringTokenizer;
+
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.Property;
+import javax.jcr.PropertyIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+
+public class JcrUtils {
+       private final static Log log = LogFactory.getLog(JcrUtils.class);
+
+       public static Node querySingleNode(Query query) {
+               NodeIterator nodeIterator;
+               try {
+                       QueryResult queryResult = query.execute();
+                       nodeIterator = queryResult.getNodes();
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot execute query " + query, e);
+               }
+               Node node;
+               if (nodeIterator.hasNext())
+                       node = nodeIterator.nextNode();
+               else
+                       return null;
+
+               if (nodeIterator.hasNext())
+                       throw new ArgeoException("Query returned more than one node.");
+               return node;
+       }
+
+       public static String removeForbiddenCharacters(String str) {
+               return str.replace('[', '_').replace(']', '_').replace('/', '_')
+                               .replace('*', '_');
+
+       }
+
+       public static String parentPath(String path) {
+               if (path.equals("/"))
+                       throw new ArgeoException("Root path '/' has no parent path");
+               if (path.charAt(0) != '/')
+                       throw new ArgeoException("Path " + path + " must start with a '/'");
+               String pathT = path;
+               if (pathT.charAt(pathT.length() - 1) == '/')
+                       pathT = pathT.substring(0, pathT.length() - 2);
+
+               int index = pathT.lastIndexOf('/');
+               return pathT.substring(0, index);
+       }
+
+       public static String dateAsPath(Calendar cal) {
+               StringBuffer buf = new StringBuffer(14);
+               buf.append('Y').append(cal.get(Calendar.YEAR));// 5
+               buf.append('/');// 1
+               int month = cal.get(Calendar.MONTH) + 1;
+               buf.append('M');
+               if (month < 10)
+                       buf.append(0);
+               buf.append(month);// 3
+               buf.append('/');// 1
+               int day = cal.get(Calendar.DAY_OF_MONTH);
+               if (day < 10)
+                       buf.append(0);
+               buf.append('D').append(day);// 3
+               buf.append('/');// 1
+               return buf.toString();
+
+       }
+
+       public static String hostAsPath(String host) {
+               // TODO : inverse order of the elements (to have org/argeo/test IO
+               // test/argeo/org
+               return host.replace('.', '/');
+       }
+
+       public static String lastPathElement(String path) {
+               if (path.charAt(path.length() - 1) == '/')
+                       throw new ArgeoException("Path " + path + " cannot end with '/'");
+               int index = path.lastIndexOf('/');
+               if (index < 0)
+                       throw new ArgeoException("Cannot find last path element for "
+                                       + path);
+               return path.substring(index + 1);
+       }
+
+       public static Node mkdirs(Session session, String path) {
+               return mkdirs(session, path, null, false);
+       }
+
+       public static Node mkdirs(Session session, String path, String type,
+                       Boolean versioning) {
+               try {
+                       if (path.equals('/'))
+                               return session.getRootNode();
+
+                       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())) {
+                                       if (type != null)
+                                               currentNode = currentNode.addNode(part, type);
+                                       else
+                                               currentNode = currentNode.addNode(part);
+                                       if (versioning)
+                                               currentNode.addMixin(ArgeoJcrConstants.MIX_VERSIONABLE);
+                                       if (log.isTraceEnabled())
+                                               log.debug("Added folder " + part + " as " + current);
+                               } else {
+                                       currentNode = (Node) session.getItem(current.toString());
+                               }
+                       }
+                       session.save();
+                       return currentNode;
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot mkdirs " + path, e);
+               }
+       }
+
+       public static void registerNamespaceSafely(Session session, String prefix,
+                       String uri) {
+               try {
+                       registerNamespaceSafely(session.getWorkspace()
+                                       .getNamespaceRegistry(), prefix, uri);
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot find namespace registry", e);
+               }
+       }
+
+       public static void registerNamespaceSafely(NamespaceRegistry nr,
+                       String prefix, String uri) {
+               try {
+                       String[] prefixes = nr.getPrefixes();
+                       for (String pref : prefixes)
+                               if (pref.equals(prefix)) {
+                                       String registeredUri = nr.getURI(pref);
+                                       if (!registeredUri.equals(uri))
+                                               throw new ArgeoException("Prefix " + pref
+                                                               + " already registered for URI "
+                                                               + registeredUri
+                                                               + " which is different from provided URI "
+                                                               + uri);
+                                       else
+                                               return;// skip
+                               }
+                       nr.registerNamespace(prefix, uri);
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot register namespace " + uri
+                                       + " under prefix " + prefix, e);
+               }
+       }
+
+       /** 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(ArgeoJcrConstants.JCR_SYSTEM)) {
+                       return;
+               }
+
+               // Then the children nodes (recursive)
+               NodeIterator it = node.getNodes();
+               while (it.hasNext()) {
+                       Node childNode = it.nextNode();
+                       debug(childNode);
+               }
+
+               // Then output the properties
+               PropertyIterator properties = node.getProperties();
+               // log.debug("Property are : ");
+
+               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());
+                       }
+               }
+
+       }
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapper.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapper.java
new file mode 100644 (file)
index 0000000..2b816c3
--- /dev/null
@@ -0,0 +1,14 @@
+package org.argeo.jcr;
+
+import javax.jcr.Node;
+import javax.jcr.Session;
+
+public interface NodeMapper {
+       public Object load(Node node);
+
+       public void update(Node node, Object obj);
+
+       public Node save(Session session, String path, Object obj);
+       
+       public void setNodeMapperProvider(NodeMapperProvider nmp);
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapperProvider.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/NodeMapperProvider.java
new file mode 100644 (file)
index 0000000..316a877
--- /dev/null
@@ -0,0 +1,13 @@
+package org.argeo.jcr;
+
+import javax.jcr.Node;
+
+/** Provides a node mapper relevant for this node. */
+public interface NodeMapperProvider {
+
+       /** 
+        * Node Mapper is chosen regarding the Jcr path of the node parameter 
+        * @param Node node
+        * @return the node mapper or null if no relevant node mapper can be found. */
+       public NodeMapper findNodeMapper(Node node);
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ThreadBoundJcrSessionFactory.java
new file mode 100644 (file)
index 0000000..9996b7b
--- /dev/null
@@ -0,0 +1,105 @@
+package org.argeo.jcr;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.FactoryBean;
+
+public class ThreadBoundJcrSessionFactory implements FactoryBean,
+               DisposableBean {
+       private final static Log log = LogFactory
+                       .getLog(ThreadBoundJcrSessionFactory.class);
+
+       private Repository repository;
+       private List<Session> activeSessions = Collections
+                       .synchronizedList(new ArrayList<Session>());
+
+       private ThreadLocal<Session> session = new ThreadLocal<Session>();
+       private boolean destroying = false;
+       private final Session proxiedSession;
+
+       public ThreadBoundJcrSessionFactory() {
+               Class<?>[] interfaces = { Session.class };
+               proxiedSession = (Session) Proxy.newProxyInstance(getClass()
+                               .getClassLoader(), interfaces, new InvocationHandler() {
+
+                       public Object invoke(Object proxy, Method method, Object[] args)
+                                       throws Throwable {
+                               Session threadSession = session.get();
+                               if (threadSession == null) {
+                                       if ("logout".equals(method.getName()))// no need to login
+                                               return Void.TYPE;
+                                       threadSession = login();
+                                       session.set(threadSession);
+                               }
+
+                               Object ret = method.invoke(threadSession, args);
+                               if ("logout".equals(method.getName())) {
+                                       session.remove();
+                                       if (!destroying)
+                                               activeSessions.remove(threadSession);
+                                       if (log.isTraceEnabled())
+                                               log.trace("Logged out from JCR session "
+                                                               + threadSession + "; userId="
+                                                               + threadSession.getUserID());
+                               }
+                               return ret;
+                       }
+               });
+       }
+
+       protected Session login() {
+               try {
+                       Session sess = repository.login();
+                       if (log.isTraceEnabled())
+                               log.trace("Log in to JCR session " + sess + "; userId="
+                                               + sess.getUserID());
+                       // Thread.dumpStack();
+                       activeSessions.add(sess);
+                       return sess;
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot log in to repository", e);
+               }
+       }
+
+       public Object getObject() {
+               return proxiedSession;
+       }
+
+       public void destroy() throws Exception {
+               if (log.isDebugEnabled())
+                       log.debug("Cleaning up " + activeSessions.size()
+                                       + " active JCR sessions...");
+
+               destroying = true;
+               for (Session sess : activeSessions) {
+                       sess.logout();
+               }
+               activeSessions.clear();
+       }
+
+       public Class<? extends Session> getObjectType() {
+               return Session.class;
+       }
+
+       public boolean isSingleton() {
+               return true;
+       }
+
+       public void setRepository(Repository repository) {
+               this.repository = repository;
+       }
+
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/DefaultJcrListener.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/DefaultJcrListener.java
new file mode 100644 (file)
index 0000000..4b23308
--- /dev/null
@@ -0,0 +1,99 @@
+package org.argeo.server.jcr;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import javax.jcr.observation.ObservationManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+
+/** To be overridden */
+public class DefaultJcrListener implements EventListener {
+       private final static Log log = LogFactory.getLog(DefaultJcrListener.class);
+       private Session session;
+       private Repository repository;
+       private String path = "/";
+       private Boolean deep = true;
+       private String username = "demo";
+       private String password = "demo";
+
+       public void start() {
+               try {
+                       addEventListener(session().getWorkspace().getObservationManager());
+                       if (log.isDebugEnabled())
+                               log.debug("Registered JCR event listener on " + path);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot register event listener", e);
+               }
+       }
+
+       public void stop() {
+               try {
+                       session().getWorkspace().getObservationManager()
+                                       .removeEventListener(this);
+                       if (log.isDebugEnabled())
+                               log.debug("Unregistered JCR event listener on " + path);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot unregister event listener", e);
+               }
+       }
+
+       /** Default is listen to all events */
+       protected Integer getEvents() {
+               return Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED
+                               | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED;
+       }
+
+       /** To be overidden */
+       public void onEvent(EventIterator events) {
+               while (events.hasNext()) {
+                       Event event = events.nextEvent();
+                       log.debug(event);
+               }
+       }
+
+       /** To be overidden */
+       protected void addEventListener(ObservationManager observationManager)
+                       throws RepositoryException {
+               observationManager.addEventListener(this, getEvents(), path, deep,
+                               null, null, false);
+       }
+
+       protected Session session() {
+               if (session == null)
+                       try {
+                               session = repository.login(new SimpleCredentials(username,
+                                               password.toCharArray()));
+                       } catch (Exception e) {
+                               throw new ArgeoException("Cannot open session", e);
+                       }
+               return session;
+       }
+
+       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 setPath(String path) {
+               this.path = path;
+       }
+
+       public void setDeep(Boolean deep) {
+               this.deep = deep;
+       }
+
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/JcrResourceAdapter.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/JcrResourceAdapter.java
new file mode 100644 (file)
index 0000000..020672b
--- /dev/null
@@ -0,0 +1,246 @@
+package org.argeo.server.jcr;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import javax.activation.MimetypesFileTypeMap;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionIterator;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+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) {
+               JcrUtils.mkdirs(session(), path, "nt:folder", versioning);
+       }
+
+       public void create(String path, Resource file, String mimeType) {
+               try {
+                       create(path, file.getInputStream(), mimeType);
+               } catch (IOException e) {
+                       throw new ArgeoException("Cannot read " + file, e);
+               }
+       }
+
+       public void create(String path, InputStream in, String mimeType) {
+               try {
+                       if (session().itemExists(path)) {
+                               throw new ArgeoException("Node " + path + " already exists.");
+                       }
+
+                       int index = path.lastIndexOf('/');
+                       String parentPath = path.substring(0, index);
+                       if (parentPath.equals(""))
+                               parentPath = "/";
+                       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");
+                       if (mimeType != null)
+                               contentNode.setProperty("jcr:mimeType", mimeType);
+                       contentNode.setProperty("jcr:encoding", defaultEncoding);
+                       contentNode.setProperty("jcr:data", in);
+                       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);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot create node for " + path, e);
+               }
+
+       }
+
+       public void update(String path, Resource file) {
+               try {
+                       update(path, file.getInputStream());
+               } catch (IOException e) {
+                       throw new ArgeoException("Cannot read " + file, e);
+               }
+       }
+
+       public void update(String path, InputStream in) {
+               try {
+
+                       if (!session().itemExists(path)) {
+                               String type = new MimetypesFileTypeMap()
+                                               .getContentType(FilenameUtils.getName(path));
+                               create(path, in, type);
+                               return;
+                       }
+
+                       Node fileNode = (Node) session().getItem(path);
+                       Node contentNode = fileNode.getNode("jcr:content");
+                       fileNode.checkout();
+                       contentNode.setProperty("jcr:data", in);
+                       Calendar lastModified = Calendar.getInstance();
+                       // lastModified.setTimeInMillis(file.lastModified());
+                       contentNode.setProperty("jcr:lastModified", lastModified);
+
+                       session().save();
+                       fileNode.checkin();
+
+                       if (log.isDebugEnabled())
+                               log.debug("Updated " + path);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot update node " + path, 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);
+                       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 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;
+       }
+
+       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.jcr/src/main/java/org/argeo/server/jcr/mvc/JcrBrowserController.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/JcrBrowserController.java
new file mode 100644 (file)
index 0000000..cddc8b0
--- /dev/null
@@ -0,0 +1,74 @@
+package org.argeo.server.jcr.mvc;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Item;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.Row;
+import javax.jcr.query.RowIterator;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.WebRequest;
+
+@Controller
+public class JcrBrowserController implements JcrMvcConstants {
+
+       @RequestMapping("/getJcrItem.*")
+       public Item getJcrItem(WebRequest webRequest,
+                       @RequestParam("path") String path) throws RepositoryException {
+               return ((Session) webRequest.getAttribute(REQUEST_ATTR_SESSION,
+                               RequestAttributes.SCOPE_REQUEST)).getItem(path);
+       }
+
+       @RequestMapping("/queryJcrNodes.*")
+       public List<String> queryJcrNodes(WebRequest webRequest,
+                       @RequestParam("statement") String statement,
+                       @RequestParam("language") String language)
+                       throws RepositoryException {
+               Session session = ((Session) webRequest.getAttribute(
+                               REQUEST_ATTR_SESSION, RequestAttributes.SCOPE_REQUEST));
+               Query query = session.getWorkspace().getQueryManager().createQuery(
+                               statement, language);
+               NodeIterator nit = query.execute().getNodes();
+               List<String> paths = new ArrayList<String>();
+               while (nit.hasNext()) {
+                       paths.add(nit.nextNode().getPath());
+               }
+               return paths;
+       }
+
+       @RequestMapping("/queryJcrTable.*")
+       public List<List<String>> queryJcrTable(WebRequest webRequest,
+                       @RequestParam("statement") String statement,
+                       @RequestParam("language") String language)
+                       throws RepositoryException {
+               Session session = ((Session) webRequest.getAttribute(
+                               REQUEST_ATTR_SESSION, RequestAttributes.SCOPE_REQUEST));
+               Query query = session.getWorkspace().getQueryManager().createQuery(
+                               statement, language);
+               QueryResult queryResult = query.execute();
+               List<List<String>> results = new ArrayList<List<String>>();
+               results.add(Arrays.asList(queryResult.getColumnNames()));
+               RowIterator rit = queryResult.getRows();
+
+               while (rit.hasNext()) {
+                       Row row = rit.nextRow();
+                       List<String> lst = new ArrayList<String>();
+                       for (Value value : row.getValues()) {
+                               lst.add(value.getString());
+                       }
+               }
+               return results;
+       }
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/JcrManagerController.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/JcrManagerController.java
new file mode 100644 (file)
index 0000000..37fca84
--- /dev/null
@@ -0,0 +1,79 @@
+package org.argeo.server.jcr.mvc;
+
+import java.util.List;
+import java.util.StringTokenizer;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.server.ServerAnswer;
+import org.argeo.server.jcr.JcrResourceAdapter;
+import org.argeo.server.mvc.MvcConstants;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+public class JcrManagerController implements MvcConstants {
+       private final static Log log = LogFactory
+                       .getLog(JcrManagerController.class);
+
+       private JcrResourceAdapter resourceAdapter;
+
+       // Create a factory for disk-based file items
+       private FileItemFactory factory = new DiskFileItemFactory();
+
+       // Create a new file upload handler
+       private ServletFileUpload upload = new ServletFileUpload(factory);
+
+       @SuppressWarnings("unchecked")
+       @RequestMapping("/upload/**")
+       @ModelAttribute(ANSWER_MODEL_KEY_AS_HTML)
+       public ServerAnswer upload(HttpServletRequest request,
+                       HttpServletResponse response) throws Exception {
+               // Parse the request
+               List<FileItem> items = upload.parseRequest(request);
+
+               byte[] arr = null;
+               for (FileItem item : items) {
+                       if (!item.isFormField()) {
+                               arr = item.get();
+                               break;
+                       }
+               }
+
+               ByteArrayResource res = new ByteArrayResource(arr);
+               // String pathInfo = request.getPathInfo();
+
+               StringBuffer path = new StringBuffer("/");
+               StringTokenizer st = new StringTokenizer(request.getPathInfo(), "/");
+               st.nextToken();// skip /upload/
+               while (st.hasMoreTokens()) {
+                       String token = st.nextToken();
+                       if (!st.hasMoreTokens()) {
+                               resourceAdapter.mkdirs(path.toString());
+                               path.append(token);
+                       } else {
+                               path.append(token).append('/');
+                       }
+               }
+               // String path = '/' + pathInfo.substring(1).substring(
+               // pathInfo.indexOf('/'));
+               if (log.isDebugEnabled())
+                       log.debug("Upload to " + path);
+               resourceAdapter.update(path.toString(), res);
+               return ServerAnswer.ok("File " + path + " imported");
+       }
+
+       public void setResourceAdapter(JcrResourceAdapter resourceAdapter) {
+               this.resourceAdapter = resourceAdapter;
+       }
+
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/JcrMvcConstants.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/JcrMvcConstants.java
new file mode 100644 (file)
index 0000000..3f50e96
--- /dev/null
@@ -0,0 +1,5 @@
+package org.argeo.server.jcr.mvc;
+
+public interface JcrMvcConstants {
+       public final static String REQUEST_ATTR_SESSION = "jcrSession";
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/JcrXmlServerSerializer.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/JcrXmlServerSerializer.java
new file mode 100644 (file)
index 0000000..54cc5b7
--- /dev/null
@@ -0,0 +1,113 @@
+package org.argeo.server.jcr.mvc;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.argeo.ArgeoException;
+import org.argeo.server.ServerSerializer;
+import org.springframework.xml.dom.DomContentHandler;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+public class JcrXmlServerSerializer implements ServerSerializer {
+       private String contentTypeCharset = "UTF-8";
+
+       private final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
+                       .newInstance();
+       private final TransformerFactory transformerFactory = TransformerFactory
+                       .newInstance();
+
+       public void serialize(Object obj, HttpServletRequest request,
+                       HttpServletResponse response) {
+               if (!(obj instanceof Node))
+                       throw new ArgeoException("Only " + Node.class + " is supported");
+
+               String noRecurseStr = request.getParameter("noRecurse");
+               boolean noRecurse = noRecurseStr != null && noRecurseStr.equals("true");
+
+               String depthStr = request.getParameter("depth");
+               String downloadStr = request.getParameter("download");
+
+               Node node = (Node) obj;
+
+               try {
+                       String contentType = "text/xml;charset=" + contentTypeCharset;
+                       // download case
+                       if (downloadStr != null && downloadStr.equals("true")) {
+                               String fileName = node.getName().replace(':', '_') + ".xml";
+                               contentType = contentType + ";name=\"" + fileName + "\"";
+                               response.setHeader("Content-Disposition",
+                                               "attachment; filename=\"" + fileName + "\"");
+                               response.setHeader("Expires", "0");
+                               response
+                                               .setHeader("Cache-Control", "no-cache, must-revalidate");
+                               response.setHeader("Pragma", "no-cache");
+                       }
+
+                       response.setContentType(contentType);
+                       if (depthStr == null) {
+                               node.getSession().exportDocumentView(node.getPath(),
+                                               response.getOutputStream(), true, noRecurse);
+                       } else {
+                               int depth = Integer.parseInt(depthStr);
+                               Document document = documentBuilderFactory.newDocumentBuilder()
+                                               .newDocument();
+                               serializeLevelToDom(node, document, 0, depth);
+                               Transformer transformer = transformerFactory.newTransformer();
+                               transformer.transform(new DOMSource(document),
+                                               new StreamResult(response.getOutputStream()));
+                       }
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot serialize " + node, e);
+               }
+       }
+
+       protected void serializeLevelToDom(Node currentJcrNode,
+                       org.w3c.dom.Node currentDomNode, int currentDepth, int targetDepth)
+                       throws RepositoryException, SAXException {
+               DomContentHandler domContentHandler = new DomContentHandler(
+                               currentDomNode);
+               currentJcrNode.getSession().exportDocumentView(
+                               currentJcrNode.getPath(), domContentHandler, true, true);
+
+               if (currentDepth == targetDepth)
+                       return;
+
+               // TODO: filter
+               NodeIterator nit = currentJcrNode.getNodes();
+               while (nit.hasNext()) {
+                       Node nextJcrNode = nit.nextNode();
+                       org.w3c.dom.Node nextDomNode;
+                       if (currentDomNode instanceof Document)
+                               nextDomNode = ((Document) currentDomNode).getDocumentElement();
+                       else {
+                               String name = currentJcrNode.getName();
+                               NodeList nodeList = ((Element) currentDomNode)
+                                               .getElementsByTagName(name);
+                               if (nodeList.getLength() < 1)
+                                       throw new ArgeoException("No elment named " + name
+                                                       + " under " + currentDomNode);
+                               // we know it is the last one added
+                               nextDomNode = nodeList.item(nodeList.getLength() - 1);
+                       }
+                       // recursive call
+                       serializeLevelToDom(nextJcrNode, nextDomNode, currentDepth + 1,
+                                       targetDepth);
+               }
+       }
+
+       public void setContentTypeCharset(String contentTypeCharset) {
+               this.contentTypeCharset = contentTypeCharset;
+       }
+
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/OpenSessionInViewJcrInterceptor.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/server/jcr/mvc/OpenSessionInViewJcrInterceptor.java
new file mode 100644 (file)
index 0000000..c91b66d
--- /dev/null
@@ -0,0 +1,54 @@
+package org.argeo.server.jcr.mvc;
+
+import javax.jcr.Session;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.WebRequest;
+import org.springframework.web.context.request.WebRequestInterceptor;
+
+public class OpenSessionInViewJcrInterceptor implements WebRequestInterceptor,
+               JcrMvcConstants {
+       private final static Log log = LogFactory
+                       .getLog(OpenSessionInViewJcrInterceptor.class);
+
+       private Session session;
+
+       public void preHandle(WebRequest request) throws Exception {
+               if (log.isTraceEnabled())
+                       log.trace("preHandle: " + request);
+               // Authentication auth = SecurityContextHolder.getContext()
+               // .getAuthentication();
+               // if (auth != null)
+               // log.debug("auth=" + auth + ", authenticated="
+               // + auth.isAuthenticated() + ", name=" + auth.getName());
+               // else
+               // log.debug("No auth");
+
+               // FIXME: find a safer way to initialize
+               // FIXME: not really needed to initialize here
+               // session.getRepository();
+               request.setAttribute(REQUEST_ATTR_SESSION, session,
+                               RequestAttributes.SCOPE_REQUEST);
+       }
+
+       public void postHandle(WebRequest request, ModelMap model) throws Exception {
+               // if (log.isDebugEnabled())
+               // log.debug("postHandle: " + request);
+       }
+
+       public void afterCompletion(WebRequest request, Exception ex)
+                       throws Exception {
+               if (log.isTraceEnabled())
+                       log.trace("afterCompletion: " + request);
+               // FIXME: only close session that were open
+               session.logout();
+       }
+
+       public void setSession(Session session) {
+               this.session = session;
+       }
+
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/CollectionsObject.java b/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/CollectionsObject.java
new file mode 100644 (file)
index 0000000..5d00c7a
--- /dev/null
@@ -0,0 +1,72 @@
+package org.argeo.jcr;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class CollectionsObject {
+       private String id;
+       private String label;
+       private SimpleObject simpleObject;
+       private List<String> stringList = new ArrayList<String>();
+       private Map<String, Float> floatMap = new HashMap<String, Float>();
+       private Map<SimpleObject, String> objectMap = new HashMap<SimpleObject, String>();
+       private Map<String, Map<String, String>> mapOfMaps = new HashMap<String, Map<String, String>>();
+
+       public String getId() {
+               return id;
+       }
+
+       public void setId(String id) {
+               this.id = id;
+       }
+
+       public String getLabel() {
+               return label;
+       }
+
+       public void setLabel(String label) {
+               this.label = label;
+       }
+
+       public SimpleObject getSimpleObject() {
+               return simpleObject;
+       }
+
+       public void setSimpleObject(SimpleObject simpleObject) {
+               this.simpleObject = simpleObject;
+       }
+
+       public List<String> getStringList() {
+               return stringList;
+       }
+
+       public void setStringList(List<String> stringList) {
+               this.stringList = stringList;
+       }
+
+       public Map<String, Float> getFloatMap() {
+               return floatMap;
+       }
+
+       public void setFloatMap(Map<String, Float> floatMap) {
+               this.floatMap = floatMap;
+       }
+
+       public Map<SimpleObject, String> getObjectMap() {
+               return objectMap;
+       }
+
+       public void setObjectMap(Map<SimpleObject, String> objectMap) {
+               this.objectMap = objectMap;
+       }
+
+       public Map<String, Map<String, String>> getMapOfMaps() {
+               return mapOfMaps;
+       }
+
+       public void setMapOfMaps(Map<String, Map<String, String>> mapOfMaps) {
+               this.mapOfMaps = mapOfMaps;
+       }
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/MapperTest.java b/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/MapperTest.java
new file mode 100644 (file)
index 0000000..cdc8b64
--- /dev/null
@@ -0,0 +1,40 @@
+package org.argeo.jcr;
+
+import java.io.File;
+
+import javax.jcr.Node;
+
+import org.argeo.server.jackrabbit.unit.AbstractJcrTestCase;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+public class MapperTest extends AbstractJcrTestCase {
+       public void testSimpleObject() throws Exception {
+               SimpleObject mySo = new SimpleObject();
+               mySo.setInteger(100);
+               mySo.setString("hello world");
+
+               OtherObject oo1 = new OtherObject();
+               oo1.setKey("someKey");
+               oo1.setValue("stringValue");
+               mySo.setOtherObject(oo1);
+
+               OtherObject oo2 = new OtherObject();
+               oo2.setKey("anotherSimpleObject");
+               oo2.setValue(new SimpleObject());
+               mySo.setAnotherObject(oo2);
+
+               BeanNodeMapper bnm = new BeanNodeMapper();
+
+               Node node = bnm.save(session(), mySo);
+               session().save();
+               JcrUtils.debug(node);
+       }
+
+       protected File getRepositoryFile() throws Exception {
+               Resource res = new ClassPathResource(
+                               "org/argeo/server/jcr/repository-inMemory.xml");
+               return res.getFile();
+       }
+
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/OtherObject.java b/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/OtherObject.java
new file mode 100644 (file)
index 0000000..a9a49d7
--- /dev/null
@@ -0,0 +1,22 @@
+package org.argeo.jcr;
+
+public class OtherObject {
+       private String key;
+       private Object value;
+
+       public String getKey() {
+               return key;
+       }
+
+       public void setKey(String key) {
+               this.key = key;
+       }
+
+       public Object getValue() {
+               return value;
+       }
+
+       public void setValue(Object value) {
+               this.value = value;
+       }
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/SimpleObject.java b/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/jcr/SimpleObject.java
new file mode 100644 (file)
index 0000000..2971880
--- /dev/null
@@ -0,0 +1,62 @@
+package org.argeo.jcr;
+
+import java.util.UUID;
+
+public class SimpleObject {
+       private String string;
+       private String uuid = UUID.randomUUID().toString();
+       private Integer integer;
+       private OtherObject otherObject;
+       private OtherObject anotherObject;
+
+       public String getString() {
+               return string;
+       }
+
+       public void setString(String sting) {
+               this.string = sting;
+       }
+
+       public Integer getInteger() {
+               return integer;
+       }
+
+       public void setInteger(Integer integer) {
+               this.integer = integer;
+       }
+
+       public OtherObject getOtherObject() {
+               return otherObject;
+       }
+
+       public void setOtherObject(OtherObject otherObject) {
+               this.otherObject = otherObject;
+       }
+
+       public OtherObject getAnotherObject() {
+               return anotherObject;
+       }
+
+       public void setAnotherObject(OtherObject anotherObject) {
+               this.anotherObject = anotherObject;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               return string.equals(((SimpleObject) obj).string);
+       }
+
+       @Override
+       public int hashCode() {
+               return string.hashCode();
+       }
+
+       public void setUuid(String uuid) {
+               this.uuid = uuid;
+       }
+
+       public String getUuid() {
+               return uuid;
+       }
+
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java b/server/runtime/org.argeo.server.jcr/src/test/java/org/argeo/server/jcr/JcrResourceAdapterTest.java
new file mode 100644 (file)
index 0000000..1588fd7
--- /dev/null
@@ -0,0 +1,95 @@
+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 org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.server.jackrabbit.unit.AbstractJcrTestCase;
+import org.springframework.core.io.ClassPathResource;
+import org.springframework.core.io.Resource;
+
+public class JcrResourceAdapterTest extends AbstractJcrTestCase {
+       private static SimpleDateFormat sdf = new SimpleDateFormat(
+                       "yyyyMMdd:hhmmss.SSS");
+
+       private final static Log log = LogFactory
+                       .getLog(JcrResourceAdapterTest.class);
+
+       private JcrResourceAdapter jra;
+
+       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);
+               log.debug("Versions of " + filePath);
+               int count = 0;
+               for (Calendar version : versions) {
+                       log.debug(" " + (count == 0 ? "base" : count - 1) + "\t"
+                                       + sdf.format(version.getTime()));
+                       count++;
+               }
+
+               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 {
+               super.setUp();
+               jra = new JcrResourceAdapter();
+               jra.setRepository(getRepository());
+               jra.setUsername("demo");
+               jra.setPassword("demo");
+               jra.afterPropertiesSet();
+       }
+
+       @Override
+       protected void tearDown() throws Exception {
+               jra.destroy();
+               super.tearDown();
+       }
+
+       protected File getRepositoryFile() throws Exception {
+               Resource res = new ClassPathResource(
+                               "org/argeo/server/jcr/repository-inMemory.xml");
+               return res.getFile();
+       }
+
+}
diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/log4j.properties b/server/runtime/org.argeo.server.jcr/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.jcr/src/test/resources/org/argeo/server/jcr/applicationContext.xml b/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/applicationContext.xml
new file mode 100644 (file)
index 0000000..d40c465
--- /dev/null
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">\r
+\r
+       <bean\r
+               class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">\r
+               <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />\r
+               <property name="ignoreUnresolvablePlaceholders" value="true" />\r
+       </bean>\r
+\r
+       <bean id="nodeMapperProvider" class="org.argeo.slc.jcr.dao.SlcNodeMapperProvider"\r
+               init-method="init">\r
+               <property name="defaultNodeMapper" ref="nodeMapper" />\r
+               <property name="treeTestResultNodeMapper" ref="treeTestResultNodeMapper" />\r
+       </bean>\r
+\r
+       <bean id="nodeMapper" class="org.argeo.jcr.BeanNodeMapper">\r
+       </bean>\r
+\r
+       <bean id="treeTestResultNodeMapper" class="org.argeo.slc.jcr.dao.TreeTestResultNodeMapper">\r
+       </bean>\r
+\r
+       <bean id="argeo.jcr.session.inMemory" factory-bean="argeo.jcr.repository.inMemory"\r
+               factory-method="login" destroy-method="logout">\r
+               <constructor-arg>\r
+                       <bean class="javax.jcr.SimpleCredentials">\r
+                               <constructor-arg value="demo" />\r
+                               <constructor-arg value="demo" />\r
+                       </bean>\r
+               </constructor-arg>\r
+       </bean>\r
+\r
+       <bean id="argeo.jcr.repository.inMemory" class="org.argeo.server.jackrabbit.JackrabbitContainer">\r
+               <property name="homeDirectory" value="${java.io.tmpdir}/jackrabbit-slc-unit" />\r
+               <property name="configuration"\r
+                       value="classpath:/org/argeo/server/jcr/repository-inMemory.xml" />\r
+       </bean>\r
+\r
+</beans>
\ No newline at end of file
diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy00.xls b/server/runtime/org.argeo.server.jcr/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.jcr/src/test/resources/org/argeo/server/jcr/dummy00.xls differ
diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy01.xls b/server/runtime/org.argeo.server.jcr/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.jcr/src/test/resources/org/argeo/server/jcr/dummy01.xls differ
diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy02.xls b/server/runtime/org.argeo.server.jcr/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.jcr/src/test/resources/org/argeo/server/jcr/dummy02.xls differ
diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/dummy03.xls b/server/runtime/org.argeo.server.jcr/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.jcr/src/test/resources/org/argeo/server/jcr/dummy03.xls differ
diff --git a/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-inMemory.xml b/server/runtime/org.argeo.server.jcr/src/test/resources/org/argeo/server/jcr/repository-inMemory.xml
new file mode 100644 (file)
index 0000000..d980f8b
--- /dev/null
@@ -0,0 +1,152 @@
+<?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="url" value="jdbc:derby:${wsp.home}/db;create=true" />
+                       <param name="driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
+                       <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="url" value="jdbc:derby:${rep.home}/version/db;create=true" />
+                       <param name="driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
+                       <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.jcr/src/test/resources/org/argeo/server/jcr/repository.xml b/server/runtime/org.argeo.server.jcr/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>