Working Argeo 2 deployment (with UI)
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 9 Aug 2016 16:39:43 +0000 (16:39 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 9 Aug 2016 16:39:43 +0000 (16:39 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@9074 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

55 files changed:
demo/argeo_node_rap.properties
org.argeo.cms.api/src/org/argeo/node/EnumAD.java [new file with mode: 0644]
org.argeo.cms.api/src/org/argeo/node/EnumOCD.java [new file with mode: 0644]
org.argeo.cms.api/src/org/argeo/node/NodeConstants.java
org.argeo.cms.api/src/org/argeo/node/NodeDeployment.java
org.argeo.cms.api/src/org/argeo/node/NodeOID.java [new file with mode: 0644]
org.argeo.cms.api/src/org/argeo/node/NodeState.java
org.argeo.cms.api/src/org/argeo/node/RepoConf.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsDeployment.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/CmsState.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitNodeType.java [deleted file]
org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitRepositoryServiceFactory.java [deleted file]
org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitType.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeRepositoryFactory.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeSecurity.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/PkiUtils.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryBuilder.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryService.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryServiceFactory.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas.cfg
org.argeo.cms/src/org/argeo/cms/internal/kernel/repository-h2.xml
org.argeo.cms/src/org/argeo/cms/internal/kernel/repository-localfs.xml
org.argeo.cms/src/org/argeo/cms/internal/kernel/repository-memory.xml
org.argeo.cms/src/org/argeo/cms/internal/kernel/repository-postgresql-ds.xml
org.argeo.cms/src/org/argeo/cms/internal/kernel/repository-postgresql.xml
org.argeo.cms/src/org/argeo/cms/maintenance/AbstractOsgiComposite.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/maintenance/ConnectivityDeploymentUi.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/maintenance/DataDeploymentUi.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/maintenance/DeploymentEntryPoint.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/maintenance/LogDeploymentUi.java [new file with mode: 0644]
org.argeo.cms/src/org/argeo/cms/maintenance/MaintenanceUi.java
org.argeo.cms/src/org/argeo/cms/maintenance/MigrationEntryPoint.java [deleted file]
org.argeo.cms/src/org/argeo/cms/maintenance/SecurityDeploymentUi.java [new file with mode: 0644]
org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/model/MaintainedRepositoryElem.java
org.argeo.eclipse.ui.workbench/src/org/argeo/eclipse/ui/workbench/internal/jcr/model/RepositoriesElem.java
org.argeo.server.jcr/ext/test/org/argeo/jcr/spring/CollectionsObject.java [deleted file]
org.argeo.server.jcr/ext/test/org/argeo/jcr/spring/MapperTest.java [deleted file]
org.argeo.server.jcr/ext/test/org/argeo/jcr/spring/OtherObject.java [deleted file]
org.argeo.server.jcr/ext/test/org/argeo/jcr/spring/SimpleObject.java [deleted file]
org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitAuthorizations.java [deleted file]
org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitContainer.java
org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitDataModel.java [deleted file]
org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitNodeType.java [deleted file]
org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitRepositoryFactory.java
org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitWrapper.java
org.argeo.server.jcr/src/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java [deleted file]
org.argeo.server.jcr/src/org/argeo/jcr/MaintainedRepository.java [deleted file]
org.argeo.server.jcr/src/org/argeo/jcr/NodeMapper.java [deleted file]
org.argeo.server.jcr/src/org/argeo/jcr/NodeMapperProvider.java [deleted file]
org.argeo.server.jcr/src/org/argeo/jcr/ThreadBoundJcrSessionFactory.java
org.argeo.server.jcr/src/org/argeo/jcr/spring/BeanNodeMapper.java [deleted file]

index e0805f8a1243eae4758e1aa741031cc0e79a0939..3e7ec66518173db14abda17eb9bb984c87303a33 100644 (file)
@@ -1,10 +1,10 @@
 argeo.osgi.start.2.node=\
 org.eclipse.equinox.http.servlet,\
 org.eclipse.equinox.http.jetty,\
+org.eclipse.equinox.metatype,\
 org.eclipse.equinox.cm,\
 org.eclipse.rap.rwt.osgi
 
-#org.eclipse.equinox.metatype,\
 
 argeo.osgi.start.3.node=\
 org.argeo.cms
diff --git a/org.argeo.cms.api/src/org/argeo/node/EnumAD.java b/org.argeo.cms.api/src/org/argeo/node/EnumAD.java
new file mode 100644 (file)
index 0000000..1ee6d39
--- /dev/null
@@ -0,0 +1,59 @@
+package org.argeo.node;
+
+import org.osgi.service.metatype.AttributeDefinition;
+
+interface EnumAD extends AttributeDefinition {
+       String name();
+
+       default Object getDefault() {
+               return null;
+       }
+
+       @Override
+       default String getName() {
+               return name();
+       }
+
+       @Override
+       default String getID() {
+               return getClass().getName() + "." + name();
+       }
+
+       @Override
+       default String getDescription() {
+               return null;
+       }
+
+       @Override
+       default int getCardinality() {
+               return 0;
+       }
+
+       @Override
+       default int getType() {
+               return STRING;
+       }
+
+       @Override
+       default String[] getOptionValues() {
+               return null;
+       }
+
+       @Override
+       default String[] getOptionLabels() {
+               return null;
+       }
+
+       @Override
+       default String validate(String value) {
+               return null;
+       }
+
+       @Override
+       default String[] getDefaultValue() {
+               Object value = getDefault();
+               if (value == null)
+                       return null;
+               return new String[] { value.toString() };
+       }
+}
diff --git a/org.argeo.cms.api/src/org/argeo/node/EnumOCD.java b/org.argeo.cms.api/src/org/argeo/node/EnumOCD.java
new file mode 100644 (file)
index 0000000..daa2f54
--- /dev/null
@@ -0,0 +1,50 @@
+package org.argeo.node;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+
+import org.osgi.service.metatype.AttributeDefinition;
+import org.osgi.service.metatype.ObjectClassDefinition;
+
+class EnumOCD<T extends Enum<T>> implements ObjectClassDefinition {
+       private final Class<T> enumClass;
+       private String locale;
+
+       public EnumOCD(Class<T> clazz, String locale) {
+               this.enumClass = clazz;
+               this.locale = locale;
+       }
+
+       @Override
+       public String getName() {
+               return null;
+       }
+
+       @Override
+       public String getID() {
+               return enumClass.getName();
+       }
+
+       @Override
+       public String getDescription() {
+               return null;
+       }
+
+       @Override
+       public AttributeDefinition[] getAttributeDefinitions(int filter) {
+               EnumSet<T> set = EnumSet.allOf(enumClass);
+               List<AttributeDefinition> attrs = new ArrayList<>();
+               for (T key : set)
+                       attrs.add((AttributeDefinition) key);
+               return attrs.toArray(new AttributeDefinition[attrs.size()]);
+       }
+
+       @Override
+       public InputStream getIcon(int size) throws IOException {
+               return null;
+       }
+
+}
index 7b7d6dc357ca1d3dde7b5588df67218a035458d1..13897920508d1a055b9cfa223e70477ac2d25b35 100644 (file)
@@ -10,7 +10,7 @@ public interface NodeConstants {
 
        String NODE_REPO_PID = "org.argeo.node.repo";
        String NODE_USER_ADMIN_PID = "org.argeo.node.userAdmin";
-       
+
        /*
         * FACTORY PIDs
         */
@@ -30,4 +30,9 @@ public interface NodeConstants {
        /** Properties configuring the node repository */
        String NODE_REPO_PROP_PREFIX = "argeo.node.repo.";
 
+       /*
+        * STANDARD ATTRIBUTES
+        */
+       String CN = "cn";
+       String LABELED_URI = "labeledUri";
 }
index 5889e50543d88b474f71c0f90c03568c0ab1ae59..1b04d68098b8517388b5495cfed6e5b3fb36e3ae 100644 (file)
@@ -1,5 +1,5 @@
 package org.argeo.node;
 
 public interface NodeDeployment {
-
+       long getAvailableSince();
 }
diff --git a/org.argeo.cms.api/src/org/argeo/node/NodeOID.java b/org.argeo.cms.api/src/org/argeo/node/NodeOID.java
new file mode 100644 (file)
index 0000000..9d8ff3d
--- /dev/null
@@ -0,0 +1,18 @@
+package org.argeo.node;
+
+interface NodeOID {
+       String BASE = "1.3.6.1.4.1" + ".48308" + ".1";
+
+       // ATTRIBUTE TYPES
+       String ATTRIBUTE_TYPES = BASE + ".4";
+       String URI = ATTRIBUTE_TYPES + ".1";
+       String HTTP_PORT = ATTRIBUTE_TYPES + ".2";
+       String HTTPS_PORT = ATTRIBUTE_TYPES + ".3";
+
+       // OBJECT CLASSES
+       String OBJECT_CLASSES = BASE + ".6";
+       String JCR_REPOSITORY = OBJECT_CLASSES + ".1";
+
+       // EXTERNAL
+       String LABELED_URI = "1.3.6.1.4.1.250.1.57";
+}
index f7d7042a8a2a444cf0a04058ea811e91f061b620..572d7eea4436d1a5460ed36d63d1b255764d6e8b 100644 (file)
@@ -4,7 +4,9 @@ import java.util.List;
 import java.util.Locale;
 
 public interface NodeState {
-       public Locale getDefaultLocale();
+       Locale getDefaultLocale();
 
-       public List<Locale> getLocales();
+       List<Locale> getLocales();
+
+       String getHostname();
 }
index 39f72c03527cb9d93032c62b079f14edc65f3010..90d33322fa6b8fb2befd2447db3851ad61500f95 100644 (file)
@@ -1,7 +1,7 @@
 package org.argeo.node;
 
 /** JCR repository configuration */
-public enum RepoConf {
+public enum RepoConf implements EnumAD {
        /** Repository type */
        type("localfs"),
        /** Default workspace */
@@ -14,8 +14,9 @@ public enum RepoConf {
        dbpassword(null),
 
        /** The identifier (can be an URL locating the repo) */
-       uri(null),
+       labeledUri(null),
 
+       httpPort(8080),
        //
        // JACKRABBIT SPECIFIC
        //
@@ -34,6 +35,12 @@ public enum RepoConf {
 
        /** The default value. */
        private Object def;
+       private String oid;
+
+       RepoConf(String oid, Object def) {
+               this.oid = oid;
+               this.def = def;
+       }
 
        RepoConf(Object def) {
                this.def = def;
@@ -42,4 +49,18 @@ public enum RepoConf {
        public Object getDefault() {
                return def;
        }
+
+       @Override
+       public String getID() {
+               if (oid != null)
+                       return oid;
+               return EnumAD.super.getID();
+       }
+
+       public static class OCD extends EnumOCD<RepoConf> {
+               public OCD(String locale) {
+                       super(RepoConf.class, locale);
+               }
+       }
+
 }
index 1997b73ce21bd3c58043ef993a2103c9c055a07f..3546647dda2f79355dec99deb42095c4caa60dd9 100644 (file)
@@ -4,6 +4,8 @@ import java.io.IOException;
 import java.net.URL;
 import java.util.Dictionary;
 import java.util.Hashtable;
+import java.util.List;
+import java.util.Locale;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -17,7 +19,6 @@ import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.Configuration;
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.osgi.service.cm.ManagedService;
@@ -38,7 +39,7 @@ public class Activator implements BundleActivator {
        // System.setProperty(SYSTEM_KEY_PROPERTY, systemKey);
        // }
 
-//     private static Kernel kernel;
+       // private static Kernel kernel;
        private static Activator instance;
 
        private BundleContext bc;
@@ -83,18 +84,20 @@ public class Activator implements BundleActivator {
 
        private void initNodeState() throws IOException {
                nodeState = new CmsState();
-               bc.registerService(LangUtils.names(NodeState.class, ManagedService.class), nodeState,
-                               LangUtils.init(Constants.SERVICE_PID, NodeConstants.NODE_STATE_PID));
 
+               Object cn;
                Configuration nodeConf = configurationAdmin.getConfiguration(NodeConstants.NODE_STATE_PID);
                Dictionary<String, Object> props = nodeConf.getProperties();
                if (props == null) {
                        if (log.isDebugEnabled())
                                log.debug("Clean node state");
                        Dictionary<String, Object> envProps = getStatePropertiesFromEnvironment();
+                       // Use the UUID of the first framework run as state UUID
+                       cn = KernelUtils.getFrameworkProp(Constants.FRAMEWORK_UUID);
+                       envProps.put(NodeConstants.CN, cn);
                        nodeConf.update(envProps);
                } else {
-                       // Check id state is in line with environment
+                       // Check if state is in line with environment
                        Dictionary<String, Object> envProps = getStatePropertiesFromEnvironment();
                        for (String key : LangUtils.keys(envProps)) {
                                Object envValue = envProps.get(key);
@@ -106,8 +109,15 @@ public class Activator implements BundleActivator {
                                        throw new CmsException("State value for " + key + "=" + storedValue
                                                        + " is different from env value =" + envValue + ", please clean the OSGi configuration.");
                        }
+                       cn = props.get(NodeConstants.CN);
+                       if (cn == null)
+                               throw new CmsException("No state UUID available");
                }
 
+               Dictionary<String, Object> regProps = LangUtils.init(Constants.SERVICE_PID, NodeConstants.NODE_STATE_PID);
+               regProps.put(NodeConstants.CN, cn);
+               bc.registerService(LangUtils.names(NodeState.class, ManagedService.class), nodeState, regProps);
+
        }
 
        @Override
@@ -120,10 +130,10 @@ public class Activator implements BundleActivator {
                this.logReaderService = null;
                this.configurationAdmin = null;
 
-//             if (kernel != null) {
-//                     kernel.destroy();
-//                     kernel = null;
-//             }
+               // if (kernel != null) {
+               // kernel.destroy();
+               // kernel = null;
+               // }
 
        }
 
@@ -158,4 +168,14 @@ public class Activator implements BundleActivator {
        public static NodeState getNodeState() {
                return instance.nodeState;
        }
+
+       public String[] getLocales() {
+               // TODO optimize?
+               List<Locale> locales = getNodeState().getLocales();
+               String[] res = new String[locales.size()];
+               for (int i = 0; i < locales.size(); i++)
+                       res[i] = locales.get(i).toString();
+               return res;
+       }
+
 }
index 6fbe7a95c50964d5a4489b978456359fb879303d..b36e0f4c56b293b9391493bbb53aa550666548e2 100644 (file)
@@ -38,19 +38,32 @@ public class CmsDeployment implements NodeDeployment, ManagedService {
 
        private Repository deployedNodeRepository;
        private HomeRepository homeRepository;
-       
+
+       private Long availableSince;
+
        @Override
        public void updated(Dictionary<String, ?> properties) throws ConfigurationException {
                if (properties == null)
                        return;
 
-               prepareDataModel(KernelUtils.openAdminSession(deployedNodeRepository));
-               Hashtable<String, String> regProps = new Hashtable<String, String>();
-               regProps.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, ArgeoJcrConstants.ALIAS_HOME);
-               homeRepository = new HomeRepository(deployedNodeRepository);
-               // register
-               bc.registerService(Repository.class, homeRepository, regProps);
-}
+               if (deployedNodeRepository != null) {
+                       if (availableSince != null) {
+                               throw new CmsException("Deployment is already available");
+                       }
+
+                       availableSince = System.currentTimeMillis();
+
+                       prepareDataModel(KernelUtils.openAdminSession(deployedNodeRepository));
+                       Hashtable<String, String> regProps = new Hashtable<String, String>();
+                       regProps.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, ArgeoJcrConstants.ALIAS_HOME);
+                       homeRepository = new HomeRepository(deployedNodeRepository);
+                       // register
+                       bc.registerService(Repository.class, homeRepository, regProps);
+
+               } else {
+                       throw new CmsException("No node repository available");
+               }
+       }
 
        /** Session is logged out. */
        private void prepareDataModel(Session adminSession) {
@@ -113,5 +126,9 @@ public class CmsDeployment implements NodeDeployment, ManagedService {
                this.deployedNodeRepository = deployedNodeRepository;
        }
 
-       
+       @Override
+       public long getAvailableSince() {
+               return availableSince;
+       }
+
 }
index ca6341aed2c5dca116d12ef97964f6ee2f506aee..f975d6cf861f319d4d8ab04f06cec98108c3cd18 100644 (file)
@@ -9,7 +9,12 @@ import static org.osgi.framework.Constants.FRAMEWORK_UUID;
 
 import java.io.File;
 import java.io.IOException;
+import java.net.InetAddress;
 import java.net.URI;
+import java.net.UnknownHostException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.Dictionary;
 import java.util.Hashtable;
 import java.util.List;
@@ -22,9 +27,9 @@ import javax.transaction.UserTransaction;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.core.RepositoryContext;
 import org.argeo.cms.CmsException;
-import org.argeo.jackrabbit.OsgiJackrabbitRepositoryFactory;
+import org.argeo.cms.maintenance.MaintenanceUi;
 import org.argeo.jcr.ArgeoJcrConstants;
 import org.argeo.node.NodeConstants;
 import org.argeo.node.NodeDeployment;
@@ -33,6 +38,7 @@ import org.argeo.node.RepoConf;
 import org.argeo.util.LangUtils;
 import org.eclipse.equinox.http.jetty.JettyConfigurator;
 import org.eclipse.equinox.http.jetty.JettyConstants;
+import org.eclipse.rap.rwt.application.ApplicationConfiguration;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -44,6 +50,7 @@ import org.osgi.service.cm.ConfigurationException;
 import org.osgi.service.cm.ManagedService;
 import org.osgi.service.cm.ManagedServiceFactory;
 import org.osgi.service.http.HttpService;
+import org.osgi.service.metatype.MetaTypeProvider;
 import org.osgi.service.useradmin.UserAdmin;
 import org.osgi.util.tracker.ServiceTracker;
 import org.osgi.util.tracker.ServiceTrackerCustomizer;
@@ -56,6 +63,9 @@ public class CmsState implements NodeState, ManagedService {
        private final Log log = LogFactory.getLog(CmsState.class);
        private final BundleContext bc = FrameworkUtil.getBundle(CmsState.class).getBundleContext();
 
+       // avoid dependency to RWT OSGi
+       private final static String PROPERTY_CONTEXT_NAME="contextName";
+       
        // REFERENCES
        private ConfigurationAdmin configurationAdmin;
 
@@ -66,11 +76,12 @@ public class CmsState implements NodeState, ManagedService {
        // Standalone services
        private BitronixTransactionManager transactionManager;
        private BitronixTransactionSynchronizationRegistry transactionSynchronizationRegistry;
-       private OsgiJackrabbitRepositoryFactory repositoryFactory;
+       private NodeRepositoryFactory repositoryFactory;
 
        // Security
        private NodeUserAdmin userAdmin;
-       private JackrabbitRepositoryServiceFactory repositoryServiceFactory;
+       private RepositoryServiceFactory repositoryServiceFactory;
+       private RepositoryService repositoryService;
 
        // Deployment
        private final CmsDeployment nodeDeployment = new CmsDeployment();
@@ -78,29 +89,68 @@ public class CmsState implements NodeState, ManagedService {
        private boolean cleanState = false;
        private URI nodeRepoUri = null;
 
+       private String hostname;
+
+       public CmsState() {
+               try {
+                       this.hostname = InetAddress.getLocalHost().getHostName();
+               } catch (UnknownHostException e) {
+                       log.error("Cannot set hostname", e);
+               }
+       }
+
        @Override
        public void updated(Dictionary<String, ?> properties) throws ConfigurationException {
                if (properties == null) {
+                       // TODO this should not happen anymore
                        this.cleanState = true;
                        if (log.isTraceEnabled())
                                log.trace("Clean state");
                        return;
                }
+               String stateUuid = properties.get(NodeConstants.CN).toString();
+               String frameworkUuid = KernelUtils.getFrameworkProp(Constants.FRAMEWORK_UUID);
+               this.cleanState = stateUuid.equals(frameworkUuid);
 
                try {
                        if (log.isDebugEnabled())
-                               log.debug(
-                                               "## CMS STARTED " + (cleanState ? " (clean state) " : "") + LangUtils.toJson(properties, true));
+                               log.debug("## CMS STARTED " + stateUuid + (cleanState ? " (clean state) " : " ")
+                                               + LangUtils.toJson(properties, true));
                        configurationAdmin = bc.getService(bc.getServiceReference(ConfigurationAdmin.class));
 
+                       nodeRepoUri = KernelUtils.getOsgiInstanceUri("repos/node");
+
+                       // pre-requisite
                        initI18n(properties);
                        initTrackers();
+                       // standalone services
                        initTransactionManager();
                        initRepositoryFactory();
+                       // UI
+                       initUi();
+                       // Deployment
+                       initDeployConfigs(properties);
                        initUserAdmin();
                        initRepositories(properties);
                        initWebServer();
                        initNodeDeployment();
+
+                       // MetaTypeService metaTypeService =
+                       // bc.getService(bc.getServiceReference(MetaTypeService.class));
+                       // MetaTypeInformation metaInfo =
+                       // metaTypeService.getMetaTypeInformation(bc.getBundle());
+                       // String[] pids = metaInfo.getPids();
+                       // for (String pid : pids) {
+                       // log.debug("MetaType PID : " + pid);
+                       // ObjectClassDefinition ocd =
+                       // metaInfo.getObjectClassDefinition(pid, null);
+                       // log.debug(ocd.getID());
+                       // for (AttributeDefinition attr :
+                       // ocd.getAttributeDefinitions(ObjectClassDefinition.ALL)) {
+                       // log.debug(attr.getID());
+                       // }
+                       // }
+
                } catch (Exception e) {
                        throw new CmsException("Cannot get configuration", e);
                }
@@ -108,7 +158,7 @@ public class CmsState implements NodeState, ManagedService {
 
        private void initTrackers() {
                new ServiceTracker<HttpService, HttpService>(bc, HttpService.class, new PrepareHttpStc()).open();
-               new ServiceTracker<>(bc, JackrabbitRepository.class, new JackrabbitrepositoryStc()).open();
+               new ServiceTracker<>(bc, RepositoryContext.class, new RepositoryContextStc()).open();
        }
 
        private void initI18n(Dictionary<String, ?> stateProps) {
@@ -140,43 +190,72 @@ public class CmsState implements NodeState, ManagedService {
 
        private void initRepositoryFactory() {
                // TODO rationalise RepositoryFactory
-               repositoryFactory = new OsgiJackrabbitRepositoryFactory();
-               repositoryFactory.setBundleContext(bc);
+               repositoryFactory = new NodeRepositoryFactory();
                // register
                bc.registerService(RepositoryFactory.class, repositoryFactory, null);
        }
 
+       private void initUi() {
+               bc.registerService(ApplicationConfiguration.class, new MaintenanceUi(),
+                               LangUtils.init(PROPERTY_CONTEXT_NAME, "system"));
+               bc.registerService(ApplicationConfiguration.class, new UserUi(),
+                               LangUtils.init(PROPERTY_CONTEXT_NAME, "user"));
+       }
+
+       private void initDeployConfigs(Dictionary<String, ?> stateProps) throws IOException {
+               Path deployPath = KernelUtils.getOsgiInstancePath(KernelConstants.DIR_NODE + '/' + KernelConstants.DIR_DEPLOY);
+               Files.createDirectories(deployPath);
+
+               Path nodeConfigPath = deployPath.resolve(NodeConstants.NODE_REPO_PID + ".properties");
+               if (!Files.exists(nodeConfigPath)) {
+                       Dictionary<String, Object> nodeConfig = getNodeConfig(stateProps);
+                       nodeConfig.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, ArgeoJcrConstants.ALIAS_NODE);
+                       nodeConfig.put(RepoConf.labeledUri.name(), nodeRepoUri.toString());
+                       LangUtils.storeAsProperties(nodeConfig, nodeConfigPath);
+               }
+
+               if (cleanState) {
+                       try (DirectoryStream<Path> ds = Files.newDirectoryStream(deployPath)) {
+                               for (Path path : ds) {
+                                       if (Files.isDirectory(path)) {// managed factories
+                                               try (DirectoryStream<Path> factoryDs = Files.newDirectoryStream(path)) {
+                                                       for (Path confPath : factoryDs) {
+                                                               Configuration conf = configurationAdmin
+                                                                               .createFactoryConfiguration(path.getFileName().toString());
+                                                               Dictionary<String, Object> props = LangUtils.loadFromProperties(confPath);
+                                                               conf.update(props);
+                                                       }
+                                               }
+                                       } else {// managed services
+                                               String pid = path.getFileName().toString();
+                                               pid = pid.substring(0, pid.length() - ".properties".length());
+                                               Configuration conf = configurationAdmin.getConfiguration(pid);
+                                               Dictionary<String, Object> props = LangUtils.loadFromProperties(path);
+                                               conf.update(props);
+                                       }
+                               }
+                       }
+               }
+       }
+
        private void initUserAdmin() {
                userAdmin = new NodeUserAdmin();
                // register
                Dictionary<String, Object> props = userAdmin.currentState();
-               props.put(Constants.SERVICE_PID, NodeConstants.NODE_REPO_PID);
+               props.put(Constants.SERVICE_PID, NodeConstants.NODE_USER_ADMIN_PID);
                // TODO use ManagedService
                bc.registerService(UserAdmin.class, userAdmin, props);
        }
 
        private void initRepositories(Dictionary<String, ?> stateProps) throws IOException {
-               nodeRepoUri = KernelUtils.getOsgiInstanceUri("repos/node");
                // register
-               repositoryServiceFactory = new JackrabbitRepositoryServiceFactory();
+               repositoryServiceFactory = new RepositoryServiceFactory();
                bc.registerService(ManagedServiceFactory.class, repositoryServiceFactory,
                                LangUtils.init(Constants.SERVICE_PID, NodeConstants.JACKRABBIT_FACTORY_PID));
 
-               if (cleanState) {
-                       Configuration newNodeConf = configurationAdmin
-                                       .createFactoryConfiguration(NodeConstants.JACKRABBIT_FACTORY_PID);
-                       Dictionary<String, Object> props = getNodeConfig(stateProps);
-                       if (props == null) {
-                               if (log.isDebugEnabled())
-                                       log.debug("No argeo.node.repo.type=localfs|h2|postgresql|memory"
-                                                       + " property defined, entering interactive mode...");
-                               // TODO interactive configuration
-                               return;
-                       }
-                       // props.put(Constants.SERVICE_PID, NodeConstants.NODE_REPO_PID);
-                       props.put(RepoConf.uri.name(), nodeRepoUri.toString());
-                       newNodeConf.update(props);
-               }
+               repositoryService = new RepositoryService();
+               Dictionary<String, Object> regProps = LangUtils.init(Constants.SERVICE_PID, NodeConstants.NODE_REPO_PID);
+               bc.registerService(LangUtils.names(ManagedService.class, MetaTypeProvider.class), repositoryService, regProps);
        }
 
        private void initWebServer() {
@@ -231,15 +310,16 @@ public class CmsState implements NodeState, ManagedService {
 
                // Clean hanging Gogo shell thread
                new GogoShellKiller().start();
-               
+
                if (log.isDebugEnabled())
                        log.debug("## CMS STOPPED");
        }
 
        private Dictionary<String, Object> getNodeConfig(Dictionary<String, ?> properties) {
-               Object repoType = properties.get(NodeConstants.NODE_REPO_PROP_PREFIX + RepoConf.type.name());
-               if (repoType == null)
-                       return null;
+               // Object repoType = properties.get(NodeConstants.NODE_REPO_PROP_PREFIX
+               // + RepoConf.type.name());
+               // if (repoType == null)
+               // return null;
 
                Hashtable<String, Object> props = new Hashtable<String, Object>();
                for (RepoConf repoConf : RepoConf.values()) {
@@ -250,29 +330,30 @@ public class CmsState implements NodeState, ManagedService {
                return props;
        }
 
-       private class JackrabbitrepositoryStc
-                       implements ServiceTrackerCustomizer<JackrabbitRepository, JackrabbitRepository> {
+       private class RepositoryContextStc implements ServiceTrackerCustomizer<RepositoryContext, RepositoryContext> {
 
                @Override
-               public JackrabbitRepository addingService(ServiceReference<JackrabbitRepository> reference) {
-                       JackrabbitRepository nodeRepo = bc.getService(reference);
+               public RepositoryContext addingService(ServiceReference<RepositoryContext> reference) {
+                       RepositoryContext nodeRepo = bc.getService(reference);
                        Object repoUri = reference.getProperty(ArgeoJcrConstants.JCR_REPOSITORY_URI);
                        if (repoUri != null && repoUri.equals(nodeRepoUri.toString())) {
-                               nodeDeployment.setDeployedNodeRepository(nodeRepo);
+                               nodeDeployment.setDeployedNodeRepository(nodeRepo.getRepository());
+                               Dictionary<String, Object> props = LangUtils.init(Constants.SERVICE_PID,
+                                               NodeConstants.NODE_DEPLOYMENT_PID);
+                               props.put("uid", nodeRepo.getRootNodeId().toString());
                                // register
-                               bc.registerService(LangUtils.names(NodeDeployment.class, ManagedService.class), nodeDeployment,
-                                               LangUtils.init(Constants.SERVICE_PID, NodeConstants.NODE_DEPLOYMENT_PID));
+                               bc.registerService(LangUtils.names(NodeDeployment.class, ManagedService.class), nodeDeployment, props);
                        }
 
                        return nodeRepo;
                }
 
                @Override
-               public void modifiedService(ServiceReference<JackrabbitRepository> reference, JackrabbitRepository service) {
+               public void modifiedService(ServiceReference<RepositoryContext> reference, RepositoryContext service) {
                }
 
                @Override
-               public void removedService(ServiceReference<JackrabbitRepository> reference, JackrabbitRepository service) {
+               public void removedService(ServiceReference<RepositoryContext> reference, RepositoryContext service) {
                }
 
        }
@@ -322,6 +403,10 @@ public class CmsState implements NodeState, ManagedService {
                return locales;
        }
 
+       public String getHostname() {
+               return hostname;
+       }
+
        /*
         * STATIC
         */
diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitNodeType.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitNodeType.java
deleted file mode 100644 (file)
index f737f8a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.argeo.cms.internal.kernel;
-
-/** The available Jackrabbit node types */
-public enum JackrabbitNodeType {
-       NOT_CONFIGURED, h2, postgresql, memory, localfs;
-}
diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitRepositoryServiceFactory.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitRepositoryServiceFactory.java
deleted file mode 100644 (file)
index d10b78b..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-package org.argeo.cms.internal.kernel;
-
-import java.io.File;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.jcr.RepositoryException;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.api.JackrabbitRepository;
-import org.apache.jackrabbit.core.RepositoryContext;
-import org.apache.jackrabbit.core.RepositoryImpl;
-import org.apache.jackrabbit.core.cache.CacheManager;
-import org.apache.jackrabbit.core.config.RepositoryConfig;
-import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
-import org.argeo.ArgeoException;
-import org.argeo.cms.CmsException;
-import org.argeo.jackrabbit.JackrabbitNodeType;
-import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.jcr.ArgeoJcrException;
-import org.argeo.node.RepoConf;
-import org.argeo.util.LangUtils;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedServiceFactory;
-import org.xml.sax.InputSource;
-
-public class JackrabbitRepositoryServiceFactory implements ManagedServiceFactory {
-       private final static Log log = LogFactory.getLog(JackrabbitRepositoryServiceFactory.class);
-       private final BundleContext bc = FrameworkUtil.getBundle(JackrabbitRepositoryServiceFactory.class)
-                       .getBundleContext();
-
-       // Node
-       final static String REPO_TYPE = "repoType";
-
-       private Map<String, RepositoryContext> repositories = new HashMap<String, RepositoryContext>();
-
-       @Override
-       public String getName() {
-               return "Jackrabbit repository service factory";
-       }
-
-       @Override
-       public void updated(String pid, Dictionary<String, ?> properties) throws ConfigurationException {
-               if (repositories.containsKey(pid))
-                       throw new ArgeoException("Already a repository registered for " + pid);
-
-               if (properties == null)
-                       return;
-
-               if (repositories.containsKey(pid)) {
-                       log.warn("Ignore update of Jackrabbit repository " + pid);
-                       return;
-               }
-
-               try {
-                       RepositoryContext repositoryContext = createNode(properties);
-                       repositories.put(pid, repositoryContext);
-                       Dictionary<String, Object> props = LangUtils.init(Constants.SERVICE_PID, pid);
-                       props.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, properties.get(RepoConf.uri.name()));
-                       bc.registerService(JackrabbitRepository.class, repositoryContext.getRepository(), props);
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot create Jackrabbit repository " + pid, e);
-               }
-
-       }
-
-       @Override
-       public void deleted(String pid) {
-               RepositoryContext repositoryContext = repositories.remove(pid);
-               repositoryContext.getRepository().shutdown();
-               if (log.isDebugEnabled())
-                       log.debug("Deleted repository " + pid);
-       }
-
-       public void shutdown() {
-               for (String pid : repositories.keySet()) {
-                       try {
-                               repositories.get(pid).getRepository().shutdown();
-                       } catch (Exception e) {
-                               log.error("Error when shutting down Jackrabbit repository " + pid, e);
-                       }
-               }
-       }
-
-       private RepositoryConfig getConfiguration(Dictionary<String, ?> properties) throws RepositoryException {
-               JackrabbitNodeType type = JackrabbitNodeType.valueOf(prop(properties, RepoConf.type).toString());
-               ClassLoader cl = getClass().getClassLoader();
-               InputStream in = null;
-               try {
-                       final String base = "/org/argeo/jackrabbit";
-                       switch (type) {
-                       case h2:
-                               in = cl.getResourceAsStream(base + "/repository-h2.xml");
-                               break;
-                       case postgresql:
-                               in = cl.getResourceAsStream(base + "/repository-postgresql.xml");
-                               break;
-                       case memory:
-                               in = cl.getResourceAsStream(base + "/repository-memory.xml");
-                               break;
-                       case localfs:
-                               in = cl.getResourceAsStream(base + "/repository-localfs.xml");
-                               break;
-                       default:
-                               throw new ArgeoJcrException("Unsupported node type " + type);
-                       }
-
-                       if (in == null)
-                               throw new ArgeoJcrException("Repository configuration not found");
-                       InputSource config = new InputSource(in);
-                       Properties jackrabbitVars = getConfigurationProperties(type, properties);
-                       RepositoryConfig repositoryConfig = RepositoryConfig.create(config, jackrabbitVars);
-                       return repositoryConfig;
-               } finally {
-                       IOUtils.closeQuietly(in);
-               }
-       }
-
-       private Properties getConfigurationProperties(JackrabbitNodeType type, Dictionary<String, ?> properties) {
-               Properties props = new Properties();
-               keys: for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements();) {
-                       String key = keys.nextElement();
-                       if (key.equals(ConfigurationAdmin.SERVICE_FACTORYPID) || key.equals(Constants.SERVICE_PID))
-                               continue keys;
-                       String value = prop(properties, RepoConf.valueOf(key));
-                       if (value != null)
-                               props.put(key, value);
-               }
-
-               // home
-               // File osgiInstanceDir = getOsgiInstanceDir();
-               String homeUri = props.getProperty(RepoConf.uri.name());
-               Path homePath;
-               try {
-                       homePath = Paths.get(new URI(homeUri));
-               } catch (URISyntaxException e) {
-                       throw new CmsException("Invalid repository home URI", e);
-               }
-               // File homeDir = new File(osgiInstanceDir, "repos/node");
-               File homeDir = homePath.toFile();
-               homeDir.mkdirs();
-               // home cannot be overridden
-               props.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, homeDir.getAbsolutePath());
-
-               // common
-               setProp(props, RepoConf.defaultWorkspace);
-               setProp(props, RepoConf.maxPoolSize);
-               // Jackrabbit defaults
-               setProp(props, RepoConf.bundleCacheMB);
-               // See http://wiki.apache.org/jackrabbit/Search
-               setProp(props, RepoConf.extractorPoolSize);
-               setProp(props, RepoConf.searchCacheSize);
-               setProp(props, RepoConf.maxVolatileIndexSize);
-
-               // specific
-               String dburl;
-               switch (type) {
-               case h2:
-                       dburl = "jdbc:h2:" + homeDir.getPath() + "/h2/repository";
-                       setProp(props, RepoConf.dburl, dburl);
-                       setProp(props, RepoConf.dbuser, "sa");
-                       setProp(props, RepoConf.dbpassword, "");
-                       break;
-               case postgresql:
-                       dburl = "jdbc:postgresql://localhost/demo";
-                       setProp(props, RepoConf.dburl, dburl);
-                       setProp(props, RepoConf.dbuser, "argeo");
-                       setProp(props, RepoConf.dbpassword, "argeo");
-                       break;
-               case memory:
-                       break;
-               case localfs:
-                       break;
-               default:
-                       throw new ArgeoJcrException("Unsupported node type " + type);
-               }
-               return props;
-       }
-
-       private void setProp(Properties props, RepoConf key, String def) {
-               Object value = props.get(key.name());
-               if (value == null)
-                       value = def;
-               if (value == null)
-                       value = key.getDefault();
-               if (value != null)
-                       props.put(key.name(), value.toString());
-       }
-
-       private void setProp(Properties props, RepoConf key) {
-               setProp(props, key, null);
-       }
-
-       private String prop(Dictionary<String, ?> properties, RepoConf key) {
-               Object value = properties.get(key.name());
-               if (value == null)
-                       return key.getDefault() != null ? key.getDefault().toString() : null;
-               else
-                       return value.toString();
-       }
-
-       private RepositoryContext createNode(Dictionary<String, ?> properties) throws RepositoryException {
-               RepositoryConfig repositoryConfig = getConfiguration(properties);
-               RepositoryContext repositoryContext = createJackrabbitRepository(repositoryConfig);
-               RepositoryImpl repository = repositoryContext.getRepository();
-
-               // cache
-               Object maxCacheMbStr = prop(properties, RepoConf.maxCacheMB);
-               if (maxCacheMbStr != null) {
-                       Integer maxCacheMB = Integer.parseInt(maxCacheMbStr.toString());
-                       CacheManager cacheManager = repository.getCacheManager();
-                       cacheManager.setMaxMemory(maxCacheMB * 1024l * 1024l);
-                       cacheManager.setMaxMemoryPerCache((maxCacheMB / 4) * 1024l * 1024l);
-               }
-
-               return repositoryContext;
-       }
-
-       private RepositoryContext createJackrabbitRepository(RepositoryConfig repositoryConfig) throws RepositoryException {
-               ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
-               Thread.currentThread().setContextClassLoader(JackrabbitRepositoryServiceFactory.class.getClassLoader());
-               try {
-                       long begin = System.currentTimeMillis();
-                       //
-                       // Actual repository creation
-                       //
-                       RepositoryContext repositoryContext = RepositoryContext.create(repositoryConfig);
-
-                       double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
-                       if (log.isTraceEnabled())
-                               log.trace(
-                                               "Created Jackrabbit repository in " + duration + " s, home: " + repositoryConfig.getHomeDir());
-
-                       return repositoryContext;
-               } finally {
-                       Thread.currentThread().setContextClassLoader(currentContextCl);
-               }
-       }
-
-}
diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitType.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/JackrabbitType.java
new file mode 100644 (file)
index 0000000..b10fd4e
--- /dev/null
@@ -0,0 +1,6 @@
+package org.argeo.cms.internal.kernel;
+
+/** The available Jackrabbit node types */
+public enum JackrabbitType {
+       localfs, h2, postgresql, postgresql_ds, memory;
+}
index 65e38912c410319af23b20886cbb027e277297fd..7f0197412939123634b60c36d96c6f9f58c97493 100644 (file)
@@ -54,7 +54,6 @@ import org.argeo.ArgeoException;
 import org.argeo.ArgeoLogger;
 import org.argeo.cms.CmsException;
 import org.argeo.cms.maintenance.MaintenanceUi;
-import org.argeo.jackrabbit.OsgiJackrabbitRepositoryFactory;
 import org.argeo.jcr.ArgeoJcrConstants;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.node.DataModelNamespace;
@@ -106,6 +105,7 @@ import bitronix.tm.TransactionManagerServices;
  * <li>OS access</li>
  * </ul>
  */
+@Deprecated
 final class Kernel implements KernelHeader, KernelConstants {
        /*
         * SERVICE REFERENCES
@@ -132,7 +132,7 @@ final class Kernel implements KernelHeader, KernelConstants {
        private NodeLogger logger;
        private BitronixTransactionManager transactionManager;
        private BitronixTransactionSynchronizationRegistry transactionSynchronizationRegistry;
-       private OsgiJackrabbitRepositoryFactory repositoryFactory;
+       private NodeRepositoryFactory repositoryFactory;
        private Repository repository;
        private NodeUserAdmin userAdmin;
 
@@ -499,7 +499,7 @@ final class Kernel implements KernelHeader, KernelConstants {
                // Initialise services
                initTransactionManager();
 
-               JackrabbitRepositoryServiceFactory jrsf = new JackrabbitRepositoryServiceFactory();
+               RepositoryServiceFactory jrsf = new RepositoryServiceFactory();
                String[] clazzes = { ManagedServiceFactory.class.getName() };
                Hashtable<String, String> serviceProps = new Hashtable<String, String>();
                serviceProps.put(Constants.SERVICE_PID, ArgeoJcrConstants.JACKRABBIT_REPO_FACTORY_PID);
@@ -549,11 +549,11 @@ final class Kernel implements KernelHeader, KernelConstants {
                                                JackrabbitRepository nodeRepo = bc.getService(reference);
                                                // new
                                                // JackrabbitDataModel(bc).prepareDataModel(nodeRepo);
-                                               prepareDataModel(KernelUtils.openAdminSession( nodeRepo));
+                                               prepareDataModel(KernelUtils.openAdminSession(nodeRepo));
 
                                                // repository = (JackrabbitRepository)
                                                // bc.getService(repositoryReg.getReference());
-                                               repository = new HomeRepository( nodeRepo);
+                                               repository = new HomeRepository(nodeRepo);
                                                Hashtable<String, String> regProps = new Hashtable<String, String>();
                                                regProps.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, ArgeoJcrConstants.ALIAS_NODE);
                                                repositoryReg = (ServiceRegistration<? extends Repository>) bc.registerService(Repository.class,
@@ -562,8 +562,8 @@ final class Kernel implements KernelHeader, KernelConstants {
                                                // if (repository == null)
                                                // repository = new NodeRepository();
                                                if (repositoryFactory == null) {
-                                                       repositoryFactory = new OsgiJackrabbitRepositoryFactory();
-                                                       repositoryFactory.setBundleContext(bc);
+                                                       repositoryFactory = new NodeRepositoryFactory();
+                                                       // repositoryFactory.setBundleContext(bc);
                                                        repositoryFactoryReg = bc.registerService(RepositoryFactory.class, repositoryFactory, null);
                                                }
                                                userAdmin = new NodeUserAdmin(transactionManager, repository);
index fa746521fb44b9a4995c45d25b583c265818637c..344a154c5411d2de609c7d54cea96d2a4e299d94 100644 (file)
@@ -9,6 +9,7 @@ public interface KernelConstants {
 
        // Directories
        final static String DIR_NODE = "node";
+       final static String DIR_DEPLOY = "deploy";
        final static String DIR_TRANSACTIONS = "transactions";
        final static String DIR_PKI = "pki";
        final static String DIR_PKI_PRIVATE = DIR_PKI + "/private";
index 9b220f20af418355142fd8284fd1cc73fb904b11..49f8c20a50be2580e8751683224a9fea25d367cb 100644 (file)
@@ -4,6 +4,8 @@ import java.io.File;
 import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.security.PrivilegedAction;
 import java.util.Dictionary;
 import java.util.Enumeration;
@@ -65,25 +67,25 @@ class KernelUtils implements KernelConstants {
                                .getAbsoluteFile();
        }
 
+       static Path getOsgiInstancePath(String relativePath) {
+               return Paths.get(getOsgiInstanceUri(relativePath));
+       }
+
        static URI getOsgiInstanceUri(String relativePath) {
                String osgiInstanceBaseUri = getFrameworkProp(OSGI_INSTANCE_AREA);
-               try {
-                       return new URI(osgiInstanceBaseUri + (relativePath != null ? relativePath : ""));
-               } catch (URISyntaxException e) {
-                       throw new CmsException("Cannot get OSGi instance URI for " + relativePath, e);
-               }
+                       return safeUri(osgiInstanceBaseUri + (relativePath != null ? relativePath : ""));
        }
 
-       static String getOsgiInstancePath(String relativePath) {
-               try {
-                       if (relativePath == null)
-                               return getOsgiInstanceDir().getCanonicalPath();
-                       else
-                               return new File(getOsgiInstanceDir(), relativePath).getCanonicalPath();
-               } catch (IOException e) {
-                       throw new CmsException("Cannot get instance path for " + relativePath, e);
-               }
-       }
+//     static String getOsgiInstancePath(String relativePath) {
+//             try {
+//                     if (relativePath == null)
+//                             return getOsgiInstanceDir().getCanonicalPath();
+//                     else
+//                             return new File(getOsgiInstanceDir(), relativePath).getCanonicalPath();
+//             } catch (IOException e) {
+//                     throw new CmsException("Cannot get instance path for " + relativePath, e);
+//             }
+//     }
 
        static File getOsgiConfigurationFile(String relativePath) {
                try {
@@ -118,26 +120,6 @@ class KernelUtils implements KernelConstants {
                }
        }
 
-       // @Deprecated
-       // static void anonymousLogin(AuthenticationManager authenticationManager) {
-       // try {
-       // List<GrantedAuthorityPrincipal> anonAuthorities = Collections
-       // .singletonList(new GrantedAuthorityPrincipal(
-       // KernelHeader.ROLE_ANONYMOUS));
-       // UserDetails anonUser = new User(KernelHeader.USERNAME_ANONYMOUS,
-       // "", true, true, true, true, anonAuthorities);
-       // AnonymousAuthenticationToken anonToken = new
-       // AnonymousAuthenticationToken(
-       // DEFAULT_SECURITY_KEY, anonUser, anonAuthorities);
-       // Authentication authentication = authenticationManager
-       // .authenticate(anonToken);
-       // SecurityContextHolder.getContext()
-       // .setAuthentication(authentication);
-       // } catch (Exception e) {
-       // throw new CmsException("Cannot authenticate", e);
-       // }
-       // }
-
        // HTTP
        static void logRequestHeaders(Log log, HttpServletRequest request) {
                if (!log.isDebugEnabled())
@@ -213,6 +195,16 @@ class KernelUtils implements KernelConstants {
        private static BundleContext getBundleContext() {
                return getBundleContext(KernelUtils.class);
        }
+       
+       private static URI safeUri(String uri){
+               if(uri==null)
+                       throw new CmsException("URI cannot be null");
+               try {
+                       return new URI(uri);
+               } catch (URISyntaxException e) {
+                       throw new CmsException("Dadly formatted URI "+uri, e);
+               }
+       }
 
        private KernelUtils() {
 
diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeRepositoryFactory.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeRepositoryFactory.java
new file mode 100644 (file)
index 0000000..74a9208
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.cms.internal.kernel;
+
+import java.util.Collection;
+
+import javax.jcr.Repository;
+
+import org.argeo.jackrabbit.JackrabbitRepositoryFactory;
+import org.argeo.jcr.ArgeoJcrException;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * OSGi-aware Jackrabbit repository factory which can retrieve/publish
+ * {@link Repository} as OSGi services.
+ */
+class NodeRepositoryFactory extends JackrabbitRepositoryFactory {
+       private final BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
+
+       @Override
+       protected Repository getRepositoryByAlias(String alias) {
+               try {
+                       Collection<ServiceReference<Repository>> srs = bundleContext.getServiceReferences(Repository.class,
+                                       "(" + JCR_REPOSITORY_ALIAS + "=" + alias + ")");
+                       if (srs.size() == 0)
+                               throw new ArgeoJcrException("No repository with alias " + alias + " found in OSGi registry");
+                       else if (srs.size() > 1)
+                               throw new ArgeoJcrException(
+                                               srs.size() + " repositories with alias " + alias + " found in OSGi registry");
+                       return bundleContext.getService(srs.iterator().next());
+               } catch (InvalidSyntaxException e) {
+                       throw new ArgeoJcrException("Cannot find repository with alias " + alias, e);
+               }
+       }
+
+//     private void publish(String alias, Repository repository, Properties properties) {
+//             if (bundleContext != null) {
+//                     // do not modify reference
+//                     Hashtable<String, String> props = new Hashtable<String, String>();
+//                     props.putAll(props);
+//                     props.put(JCR_REPOSITORY_ALIAS, alias);
+//                     bundleContext.registerService(Repository.class.getName(), repository, props);
+//             }
+//     }
+}
index 87ba070243cab111170fac0ad83e47436a2fbf8b..94579be185d10fe55f055112a839c59741a8eda1 100644 (file)
@@ -137,7 +137,8 @@ class NodeSecurity implements KernelConstants {
                        try {
                                keyStoreFile.getParentFile().mkdirs();
                                KeyStore keyStore = PkiUtils.getKeyStore(keyStoreFile, ksPwd);
-                               PkiUtils.generateSelfSignedCertificate(keyStore, new X500Principal(AuthConstants.ROLE_KERNEL), keyPwd);
+                               PkiUtils.generateSelfSignedCertificate(keyStore, new X500Principal(AuthConstants.ROLE_KERNEL), 1024,
+                                               keyPwd);
                                PkiUtils.saveKeyStore(keyStoreFile, ksPwd, keyStore);
                                if (log.isDebugEnabled())
                                        log.debug("Created keystore " + keyStoreFile);
index f36fc89f5710b29f323354540ae964a4494a33f5..67f8f01c65ee8ca5a62bb236ef046e7a3f7bc57d 100644 (file)
@@ -35,10 +35,10 @@ class PkiUtils {
        }
 
        public static X509Certificate generateSelfSignedCertificate(KeyStore keyStore, X500Principal x500Principal,
-                       char[] keyPassword) {
+                       int keySize, char[] keyPassword) {
                try {
                        KeyPairGenerator kpGen = KeyPairGenerator.getInstance("RSA", SECURITY_PROVIDER);
-                       kpGen.initialize(1024, new SecureRandom());
+                       kpGen.initialize(keySize, new SecureRandom());
                        KeyPair pair = kpGen.generateKeyPair();
                        Date notBefore = new Date(System.currentTimeMillis() - 10000);
                        Date notAfter = new Date(System.currentTimeMillis() + 24L * 3600 * 1000);
@@ -85,4 +85,75 @@ class PkiUtils {
                }
        }
 
+       public static void main(String[] args) {
+               final String ALGORITHM = "RSA";
+               final String provider = "BC";
+               SecureRandom secureRandom = new SecureRandom();
+               long begin = System.currentTimeMillis();
+               for (int i = 512; i < 1024; i = i + 2) {
+                       try {
+                               KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM,provider);
+                               keyGen.initialize(i, secureRandom);
+                               keyGen.generateKeyPair();
+                       } catch (Exception e) {
+                               System.err.println(i + " : " + e.getMessage());
+                       }
+               }
+               System.out.println( (System.currentTimeMillis() - begin) + " ms");
+
+//             // String text = "a";
+//             String text = "testtesttesttesttesttesttesttesttesttesttesttesttesttesttest";
+//             try {
+//                     System.out.println(text);
+//                     PrivateKey privateKey;
+//                     PublicKey publicKey;
+//                     char[] password = "changeit".toCharArray();
+//                     String alias = "CN=test";
+//                     KeyStore keyStore = KeyStore.getInstance("pkcs12");
+//                     File p12file = new File("test.p12");
+//                     p12file.delete();
+//                     if (!p12file.exists()) {
+//                             keyStore.load(null);
+//                             generateSelfSignedCertificate(keyStore, new X500Principal(alias), 513, password);
+//                             try (OutputStream out = new FileOutputStream(p12file)) {
+//                                     keyStore.store(out, password);
+//                             }
+//                     }
+//                     try (InputStream in = new FileInputStream(p12file)) {
+//                             keyStore.load(in, password);
+//                             privateKey = (PrivateKey) keyStore.getKey(alias, password);
+//                             publicKey = keyStore.getCertificateChain(alias)[0].getPublicKey();
+//                     }
+//                     // KeyPair key;
+//                     // final KeyPairGenerator keyGen =
+//                     // KeyPairGenerator.getInstance(ALGORITHM);
+//                     // keyGen.initialize(4096, new SecureRandom());
+//                     // long begin = System.currentTimeMillis();
+//                     // key = keyGen.generateKeyPair();
+//                     // System.out.println((System.currentTimeMillis() - begin) + " ms");
+//                     // keyStore.load(null);
+//                     // keyStore.setKeyEntry("test", key.getPrivate(), password, null);
+//                     // try(OutputStream out=new FileOutputStream(p12file)) {
+//                     // keyStore.store(out, password);
+//                     // }
+//                     // privateKey = key.getPrivate();
+//                     // publicKey = key.getPublic();
+//
+//                     Cipher encrypt = Cipher.getInstance(ALGORITHM);
+//                     encrypt.init(Cipher.ENCRYPT_MODE, publicKey);
+//                     byte[] encrypted = encrypt.doFinal(text.getBytes());
+//                     String encryptedBase64 = Base64.getEncoder().encodeToString(encrypted);
+//                     System.out.println(encryptedBase64);
+//                     byte[] encryptedFromBase64 = Base64.getDecoder().decode(encryptedBase64);
+//
+//                     Cipher decrypt = Cipher.getInstance(ALGORITHM);
+//                     decrypt.init(Cipher.DECRYPT_MODE, privateKey);
+//                     byte[] decrypted = decrypt.doFinal(encryptedFromBase64);
+//                     System.out.println(new String(decrypted));
+//             } catch (Exception e) {
+//                     e.printStackTrace();
+//             }
+
+       }
+
 }
diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryBuilder.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryBuilder.java
new file mode 100644 (file)
index 0000000..94b8c05
--- /dev/null
@@ -0,0 +1,201 @@
+package org.argeo.cms.internal.kernel;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.UUID;
+
+import javax.jcr.RepositoryException;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.core.RepositoryContext;
+import org.apache.jackrabbit.core.RepositoryImpl;
+import org.apache.jackrabbit.core.cache.CacheManager;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
+import org.argeo.cms.CmsException;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.ArgeoJcrException;
+import org.argeo.node.RepoConf;
+import org.osgi.framework.Constants;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.xml.sax.InputSource;
+
+/** Can interpret properties in order to create an actual JCR repository. */
+class RepositoryBuilder {
+       private final static Log log = LogFactory.getLog(RepositoryBuilder.class);
+
+       RepositoryContext createRepositoryContext(Dictionary<String, ?> properties) throws RepositoryException {
+               RepositoryConfig repositoryConfig = createRepositoryConfig(properties);
+               RepositoryContext repositoryContext = createJackrabbitRepository(repositoryConfig);
+               RepositoryImpl repository = repositoryContext.getRepository();
+
+               // cache
+               Object maxCacheMbStr = prop(properties, RepoConf.maxCacheMB);
+               if (maxCacheMbStr != null) {
+                       Integer maxCacheMB = Integer.parseInt(maxCacheMbStr.toString());
+                       CacheManager cacheManager = repository.getCacheManager();
+                       cacheManager.setMaxMemory(maxCacheMB * 1024l * 1024l);
+                       cacheManager.setMaxMemoryPerCache((maxCacheMB / 4) * 1024l * 1024l);
+               }
+
+               return repositoryContext;
+       }
+
+       RepositoryConfig createRepositoryConfig(Dictionary<String, ?> properties) throws RepositoryException {
+               JackrabbitType type = JackrabbitType.valueOf(prop(properties, RepoConf.type).toString());
+               ClassLoader cl = getClass().getClassLoader();
+               InputStream in = null;
+               try {
+                       final String base = "/org/argeo/jackrabbit";
+                       switch (type) {
+                       case h2:
+                               in = cl.getResourceAsStream(base + "/repository-h2.xml");
+                               break;
+                       case postgresql:
+                               in = cl.getResourceAsStream(base + "/repository-postgresql.xml");
+                               break;
+                       case memory:
+                               in = cl.getResourceAsStream(base + "/repository-memory.xml");
+                               break;
+                       case localfs:
+                               in = cl.getResourceAsStream(base + "/repository-localfs.xml");
+                               break;
+                       default:
+                               throw new ArgeoJcrException("Unsupported node type " + type);
+                       }
+
+                       if (in == null)
+                               throw new ArgeoJcrException("Repository configuration not found");
+                       InputSource config = new InputSource(in);
+                       Properties jackrabbitVars = getConfigurationProperties(type, properties);
+                       RepositoryConfig repositoryConfig = RepositoryConfig.create(config, jackrabbitVars);
+                       return repositoryConfig;
+               } finally {
+                       IOUtils.closeQuietly(in);
+               }
+       }
+
+       private Properties getConfigurationProperties(JackrabbitType type, Dictionary<String, ?> properties) {
+               Properties props = new Properties();
+               keys: for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements();) {
+                       String key = keys.nextElement();
+                       if (key.equals(ConfigurationAdmin.SERVICE_FACTORYPID) || key.equals(Constants.SERVICE_PID)
+                                       || key.equals(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS))
+                               continue keys;
+                       String value = prop(properties, RepoConf.valueOf(key));
+                       if (value != null)
+                               props.put(key, value);
+               }
+
+               // home
+               String homeUri = props.getProperty(RepoConf.labeledUri.name());
+               Path homePath;
+               try {
+                       homePath = Paths.get(new URI(homeUri)).toAbsolutePath();
+               } catch (URISyntaxException e) {
+                       throw new CmsException("Invalid repository home URI", e);
+               }
+               Path rootUuidPath = homePath.resolve("repository/meta/rootUUID");
+               if (!Files.exists(rootUuidPath)) {
+                       try {
+                               Files.createDirectories(rootUuidPath.getParent());
+                               Files.write(rootUuidPath, UUID.randomUUID().toString().getBytes());
+                       } catch (IOException e) {
+                               log.error("Could not set rootUUID", e);
+                       }
+               }
+               File homeDir = homePath.toFile();
+               homeDir.mkdirs();
+               // home cannot be overridden
+               props.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, homePath.toString());
+
+               // common
+               setProp(props, RepoConf.defaultWorkspace);
+               setProp(props, RepoConf.maxPoolSize);
+               // Jackrabbit defaults
+               setProp(props, RepoConf.bundleCacheMB);
+               // See http://wiki.apache.org/jackrabbit/Search
+               setProp(props, RepoConf.extractorPoolSize);
+               setProp(props, RepoConf.searchCacheSize);
+               setProp(props, RepoConf.maxVolatileIndexSize);
+
+               // specific
+               String dburl;
+               switch (type) {
+               case h2:
+                       dburl = "jdbc:h2:" + homeDir.getPath() + "/h2/repository";
+                       setProp(props, RepoConf.dburl, dburl);
+                       setProp(props, RepoConf.dbuser, "sa");
+                       setProp(props, RepoConf.dbpassword, "");
+                       break;
+               case postgresql:
+                       dburl = "jdbc:postgresql://localhost/demo";
+                       setProp(props, RepoConf.dburl, dburl);
+                       setProp(props, RepoConf.dbuser, "argeo");
+                       setProp(props, RepoConf.dbpassword, "argeo");
+                       break;
+               case memory:
+                       break;
+               case localfs:
+                       break;
+               default:
+                       throw new ArgeoJcrException("Unsupported node type " + type);
+               }
+               return props;
+       }
+
+       private void setProp(Properties props, RepoConf key, String def) {
+               Object value = props.get(key.name());
+               if (value == null)
+                       value = def;
+               if (value == null)
+                       value = key.getDefault();
+               if (value != null)
+                       props.put(key.name(), value.toString());
+       }
+
+       private void setProp(Properties props, RepoConf key) {
+               setProp(props, key, null);
+       }
+
+       private String prop(Dictionary<String, ?> properties, RepoConf key) {
+               Object value = properties.get(key.name());
+               if (value == null)
+                       return key.getDefault() != null ? key.getDefault().toString() : null;
+               else
+                       return value.toString();
+       }
+
+       private RepositoryContext createJackrabbitRepository(RepositoryConfig repositoryConfig) throws RepositoryException {
+               ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
+               Thread.currentThread().setContextClassLoader(RepositoryBuilder.class.getClassLoader());
+               try {
+                       long begin = System.currentTimeMillis();
+                       //
+                       // Actual repository creation
+                       //
+                       RepositoryContext repositoryContext = RepositoryContext.create(repositoryConfig);
+
+                       double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
+                       if (log.isTraceEnabled())
+                               log.trace(
+                                               "Created Jackrabbit repository in " + duration + " s, home: " + repositoryConfig.getHomeDir());
+
+                       return repositoryContext;
+               } finally {
+                       Thread.currentThread().setContextClassLoader(currentContextCl);
+               }
+       }
+
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryService.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryService.java
new file mode 100644 (file)
index 0000000..ed8be17
--- /dev/null
@@ -0,0 +1,152 @@
+package org.argeo.cms.internal.kernel;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Locale;
+
+import org.apache.jackrabbit.core.RepositoryContext;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.node.RepoConf;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.osgi.service.metatype.MetaTypeProvider;
+import org.osgi.service.metatype.ObjectClassDefinition;
+
+public class RepositoryService implements ManagedService, MetaTypeProvider {
+       private BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
+       // private RepositoryContext repositoryContext = null;
+       private ServiceRegistration<RepositoryContext> repositoryContextReg;
+
+       @Override
+       public synchronized void updated(Dictionary<String, ?> properties) throws ConfigurationException {
+               if (properties == null)
+                       return;
+
+               if (repositoryContextReg != null) {
+                       shutdown();
+               }
+
+//             for (String key : LangUtils.keys(properties)) {
+//                     Object value = properties.get(key);
+//                     System.out.println(key + " : " + value.getClass().getName());
+//             }
+
+               try {
+                       RepositoryBuilder repositoryBuilder = new RepositoryBuilder();
+                       RepositoryContext repositoryContext = repositoryBuilder.createRepositoryContext(properties);
+                       Dictionary<String, Object> props = new Hashtable<>();
+                       props.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, properties.get(RepoConf.labeledUri.name()));
+                       Object cn = properties.get(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS);
+                       if (cn != null) {
+                               props.put(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS, cn);
+                       }
+                       repositoryContextReg = bc.registerService(RepositoryContext.class, repositoryContext, props);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot create Jackrabbit repository", e);
+               }
+
+       }
+
+       public synchronized void shutdown() {
+               if (repositoryContextReg == null)
+                       return;
+               RepositoryContext repositoryContext = bc.getService(repositoryContextReg.getReference());
+               repositoryContext.getRepository().shutdown();
+               repositoryContextReg.unregister();
+               repositoryContextReg = null;
+       }
+
+       /*
+        * METATYPE
+        */
+       @Override
+       public ObjectClassDefinition getObjectClassDefinition(String id, String locale) {
+               return new RepoConf.OCD(locale);
+               // return new EnumOCD<>(RepoConf.class);
+               // return new JcrRepositoryOCD(locale);
+       }
+
+       @Override
+       public String[] getLocales() {
+               // TODO optimize?
+               List<Locale> locales = Activator.getNodeState().getLocales();
+               String[] res = new String[locales.size()];
+               for (int i = 0; i < locales.size(); i++)
+                       res[i] = locales.get(i).toString();
+               return res;
+       }
+
+       /*
+        * JACKRABBIT REPOSITORY
+        */
+
+       // private RepositoryImpl repo() {
+       // return repositoryContext.getRepository();
+       // }
+       //
+       // @Override
+       // public String[] getDescriptorKeys() {
+       // return repo().getDescriptorKeys();
+       // }
+       //
+       // @Override
+       // public boolean isStandardDescriptor(String key) {
+       // return repo().isStandardDescriptor(key);
+       // }
+       //
+       // @Override
+       // public boolean isSingleValueDescriptor(String key) {
+       // return repo().isSingleValueDescriptor(key);
+       // }
+       //
+       // @Override
+       // public Value getDescriptorValue(String key) {
+       // return repo().getDescriptorValue(key);
+       // }
+       //
+       // @Override
+       // public Value[] getDescriptorValues(String key) {
+       // return repo().getDescriptorValues(key);
+       // }
+       //
+       // @Override
+       // public String getDescriptor(String key) {
+       // return repo().getDescriptor(key);
+       // }
+       //
+       // @Override
+       // public Session login(Credentials credentials, String workspaceName)
+       // throws LoginException, NoSuchWorkspaceException, RepositoryException {
+       // return repo().login();
+       // }
+       //
+       // @Override
+       // public Session login(Credentials credentials) throws LoginException,
+       // RepositoryException {
+       // return repo().login(credentials);
+       // }
+       //
+       // @Override
+       // public Session login(String workspaceName) throws LoginException,
+       // NoSuchWorkspaceException, RepositoryException {
+       // return repo().login(workspaceName);
+       // }
+       //
+       // @Override
+       // public Session login() throws LoginException, RepositoryException {
+       // return repo().login();
+       // }
+       //
+       // @Override
+       // public Session login(Credentials credentials, String workspaceName,
+       // Map<String, Object> attributes)
+       // throws LoginException, NoSuchWorkspaceException, RepositoryException {
+       // return repo().login(credentials, workspaceName, attributes);
+       // }
+
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryServiceFactory.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/RepositoryServiceFactory.java
new file mode 100644 (file)
index 0000000..a4e3a9b
--- /dev/null
@@ -0,0 +1,75 @@
+package org.argeo.cms.internal.kernel;
+
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.core.RepositoryContext;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.node.RepoConf;
+import org.argeo.util.LangUtils;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedServiceFactory;
+
+class RepositoryServiceFactory implements ManagedServiceFactory {
+       private final static Log log = LogFactory.getLog(RepositoryServiceFactory.class);
+       private final BundleContext bc = FrameworkUtil.getBundle(RepositoryServiceFactory.class).getBundleContext();
+
+       private Map<String, RepositoryContext> repositories = new HashMap<String, RepositoryContext>();
+
+       @Override
+       public String getName() {
+               return "Jackrabbit repository service factory";
+       }
+
+       @Override
+       public void updated(String pid, Dictionary<String, ?> properties) throws ConfigurationException {
+               if (repositories.containsKey(pid))
+                       throw new ArgeoException("Already a repository registered for " + pid);
+
+               if (properties == null)
+                       return;
+
+               if (repositories.containsKey(pid)) {
+                       log.warn("Ignore update of Jackrabbit repository " + pid);
+                       return;
+               }
+
+               try {
+                       RepositoryBuilder repositoryBuilder = new RepositoryBuilder();
+                       RepositoryContext repositoryContext = repositoryBuilder.createRepositoryContext(properties);
+                       repositories.put(pid, repositoryContext);
+                       Dictionary<String, Object> props = LangUtils.init(Constants.SERVICE_PID, pid);
+                       props.put(ArgeoJcrConstants.JCR_REPOSITORY_URI, properties.get(RepoConf.labeledUri.name()));
+                       bc.registerService(JackrabbitRepository.class, repositoryContext.getRepository(), props);
+               } catch (Exception e) {
+                       throw new ArgeoException("Cannot create Jackrabbit repository " + pid, e);
+               }
+
+       }
+
+       @Override
+       public void deleted(String pid) {
+               RepositoryContext repositoryContext = repositories.remove(pid);
+               repositoryContext.getRepository().shutdown();
+               if (log.isDebugEnabled())
+                       log.debug("Deleted repository " + pid);
+       }
+
+       public void shutdown() {
+               for (String pid : repositories.keySet()) {
+                       try {
+                               repositories.get(pid).getRepository().shutdown();
+                       } catch (Exception e) {
+                               log.error("Error when shutting down Jackrabbit repository " + pid, e);
+                       }
+               }
+       }
+}
index 2bb1ab48170320bed1acaa977d11715de5f6ab9b..88b2cd8e4e88c83ffacf6b995719d6683f0c7634 100644 (file)
@@ -13,6 +13,10 @@ DATA_ADMIN {
     org.argeo.cms.auth.DataAdminLoginModule requisite;
 };
 
+SYSTEM {
+    org.argeo.cms.auth.DataAdminLoginModule requisite;
+};
+
 KERNEL {
     org.argeo.cms.internal.auth.KernelLoginModule requisite;
 };
index 822b1fa25adee372d160e9acda06e90ddaaf2afc..05267621f7d951046b16a70fd7399821bd986ff5 100644 (file)
@@ -5,11 +5,11 @@
        <DataSources>
                <DataSource name="dataSource">
                        <param name="driver" value="org.h2.Driver" />
-                       <param name="url" value="${argeo.node.repo.dburl}" />
-                       <param name="user" value="${argeo.node.repo.dbuser}" />
-                       <param name="password" value="${argeo.node.repo.dbpassword}" />
+                       <param name="url" value="${dburl}" />
+                       <param name="user" value="${dbuser}" />
+                       <param name="password" value="${dbpassword}" />
                        <param name="databaseType" value="h2" />
-                       <param name="maxPoolSize" value="${argeo.node.repo.maxPoolSize}" />
+                       <param name="maxPoolSize" value="${maxPoolSize}" />
                </DataSource>
        </DataSources>
 
@@ -25,7 +25,7 @@
 
        <!-- Workspace templates -->
        <Workspaces rootPath="${rep.home}/workspaces"
-               defaultWorkspace="${argeo.node.repo.defaultWorkspace}" />
+               defaultWorkspace="${defaultWorkspace}" />
        <Workspace name="${wsp.name}">
                <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem">
                        <param name="dataSourceName" value="dataSource" />
                        class="org.apache.jackrabbit.core.persistence.pool.H2PersistenceManager">
                        <param name="dataSourceName" value="dataSource" />
                        <param name="schemaObjectPrefix" value="${wsp.name}_pm_" />
-                       <param name="bundleCacheSize" value="${argeo.node.repo.bundleCacheMB}" />
+                       <param name="bundleCacheSize" value="${bundleCacheMB}" />
                </PersistenceManager>
                <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
                        <param name="path" value="${wsp.home}/index" />
-                       <param name="extractorPoolSize" value="${argeo.node.repo.extractorPoolSize}" />
-                       <param name="cacheSize" value="${argeo.node.repo.searchCacheSize}" />
-                       <param name="maxVolatileIndexSize" value="${argeo.node.repo.maxVolatileIndexSize}" />
+                       <param name="extractorPoolSize" value="${extractorPoolSize}" />
+                       <param name="cacheSize" value="${searchCacheSize}" />
+                       <param name="maxVolatileIndexSize" value="${maxVolatileIndexSize}" />
                </SearchIndex>
                <WorkspaceSecurity>
                        <AccessControlProvider
                        class="org.apache.jackrabbit.core.persistence.pool.H2PersistenceManager">
                        <param name="dataSourceName" value="dataSource" />
                        <param name="schemaObjectPrefix" value="pm_ver_" />
-                       <param name="bundleCacheSize" value="${argeo.node.repo.bundleCacheMB}" />
+                       <param name="bundleCacheSize" value="${bundleCacheMB}" />
                </PersistenceManager>
        </Versioning>
 
        <!-- Indexing -->
        <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
                <param name="path" value="${rep.home}/index" />
-               <param name="extractorPoolSize" value="${argeo.node.repo.extractorPoolSize}" />
-               <param name="cacheSize" value="${argeo.node.repo.searchCacheSize}" />
-               <param name="maxVolatileIndexSize" value="${argeo.node.repo.maxVolatileIndexSize}" />
+               <param name="extractorPoolSize" value="${extractorPoolSize}" />
+               <param name="cacheSize" value="${searchCacheSize}" />
+               <param name="maxVolatileIndexSize" value="${maxVolatileIndexSize}" />
        </SearchIndex>
 
        <!-- Security -->
index 3ab8a2906fb2fc702971f69d4a963bd45df6b956..3d2470863760e372474549dcf3f014f32e7959d1 100644 (file)
 
        <!-- Workspace templates -->
        <Workspaces rootPath="${rep.home}/workspaces"
-               defaultWorkspace="${argeo.node.repo.defaultWorkspace}" />
+               defaultWorkspace="${defaultWorkspace}" />
        <Workspace name="${wsp.name}">
                <FileSystem class="org.apache.jackrabbit.core.fs.local.LocalFileSystem">
                        <param name="path" value="${wsp.home}" />
                </FileSystem>
                <PersistenceManager
                        class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager">
-                       <param name="bundleCacheSize" value="${argeo.node.repo.bundleCacheMB}" />
+                       <param name="bundleCacheSize" value="${bundleCacheMB}" />
                </PersistenceManager>
                <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
                        <param name="path" value="${wsp.home}/index" />
-                       <param name="extractorPoolSize" value="${argeo.node.repo.extractorPoolSize}" />
-                       <param name="cacheSize" value="${argeo.node.repo.searchCacheSize}" />
-                       <param name="maxVolatileIndexSize" value="${argeo.node.repo.maxVolatileIndexSize}" />
+                       <param name="extractorPoolSize" value="${extractorPoolSize}" />
+                       <param name="cacheSize" value="${searchCacheSize}" />
+                       <param name="maxVolatileIndexSize" value="${maxVolatileIndexSize}" />
                </SearchIndex>
                <WorkspaceSecurity>
                        <AccessControlProvider
                </FileSystem>
                <PersistenceManager
                        class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager">
-                       <param name="bundleCacheSize" value="${argeo.node.repo.bundleCacheMB}" />
+                       <param name="bundleCacheSize" value="${bundleCacheMB}" />
                </PersistenceManager>
        </Versioning>
 
        <!-- Indexing -->
        <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
                <param name="path" value="${rep.home}/index" />
-               <param name="extractorPoolSize" value="${argeo.node.repo.extractorPoolSize}" />
-               <param name="cacheSize" value="${argeo.node.repo.searchCacheSize}" />
-               <param name="maxVolatileIndexSize" value="${argeo.node.repo.maxVolatileIndexSize}" />
+               <param name="extractorPoolSize" value="${extractorPoolSize}" />
+               <param name="cacheSize" value="${searchCacheSize}" />
+               <param name="maxVolatileIndexSize" value="${maxVolatileIndexSize}" />
        </SearchIndex>
 
        <!-- Security -->
index 3215969e8d3e0a59f17345c249a83ed526d1cb5c..ecee5bdad02607fe429c46b526b2511935074709 100644 (file)
@@ -6,21 +6,21 @@
 
        <!-- Workspace templates -->
        <Workspaces rootPath="${rep.home}/workspaces"
-               defaultWorkspace="${argeo.node.repo.defaultWorkspace}" configRootPath="/workspaces" />
+               defaultWorkspace="${defaultWorkspace}" configRootPath="/workspaces" />
        <Workspace name="${wsp.name}">
                <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
                <PersistenceManager
                        class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager">
                        <param name="blobFSBlockSize" value="1" />
-                       <param name="bundleCacheSize" value="${argeo.node.repo.bundleCacheMB}" />
+                       <param name="bundleCacheSize" value="${bundleCacheMB}" />
                </PersistenceManager>
                <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
                        <param name="path" value="${wsp.home}/index" />
                        <param name="directoryManagerClass"
                                value="org.apache.jackrabbit.core.query.lucene.directory.RAMDirectoryManager" />
-                       <param name="extractorPoolSize" value="${argeo.node.repo.extractorPoolSize}" />
-                       <param name="cacheSize" value="${argeo.node.repo.searchCacheSize}" />
-                       <param name="maxVolatileIndexSize" value="${argeo.node.repo.maxVolatileIndexSize}" />
+                       <param name="extractorPoolSize" value="${extractorPoolSize}" />
+                       <param name="cacheSize" value="${searchCacheSize}" />
+                       <param name="maxVolatileIndexSize" value="${maxVolatileIndexSize}" />
                        <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
                </SearchIndex>
        </Workspace>
@@ -31,7 +31,7 @@
                <PersistenceManager
                        class="org.apache.jackrabbit.core.persistence.bundle.BundleFsPersistenceManager">
                        <param name="blobFSBlockSize" value="1" />
-                       <param name="bundleCacheSize" value="${argeo.node.repo.bundleCacheMB}" />
+                       <param name="bundleCacheSize" value="${bundleCacheMB}" />
                </PersistenceManager>
        </Versioning>
 
@@ -40,9 +40,9 @@
                <param name="path" value="${rep.home}/index" />
                <param name="directoryManagerClass"
                        value="org.apache.jackrabbit.core.query.lucene.directory.RAMDirectoryManager" />
-               <param name="extractorPoolSize" value="${argeo.node.repo.extractorPoolSize}" />
-               <param name="cacheSize" value="${argeo.node.repo.searchCacheSize}" />
-               <param name="maxVolatileIndexSize" value="${argeo.node.repo.maxVolatileIndexSize}" />
+               <param name="extractorPoolSize" value="${extractorPoolSize}" />
+               <param name="cacheSize" value="${searchCacheSize}" />
+               <param name="maxVolatileIndexSize" value="${maxVolatileIndexSize}" />
                <FileSystem class="org.apache.jackrabbit.core.fs.mem.MemoryFileSystem" />
        </SearchIndex>
 
index c8e077e2122562a33c4a7a849357ce17eeaaa6f7..07a0d042811cadea7f297df9360fbedf74808ad9 100644 (file)
@@ -5,11 +5,11 @@
        <DataSources>
                <DataSource name="dataSource">
                        <param name="driver" value="org.postgresql.Driver" />
-                       <param name="url" value="${argeo.node.repo.dburl}" />
-                       <param name="user" value="${argeo.node.repo.dbuser}" />
-                       <param name="password" value="${argeo.node.repo.dbpassword}" />
+                       <param name="url" value="${dburl}" />
+                       <param name="user" value="${dbuser}" />
+                       <param name="password" value="${dbpassword}" />
                        <param name="databaseType" value="postgresql" />
-                       <param name="maxPoolSize" value="${argeo.node.repo.maxPoolSize}" />
+                       <param name="maxPoolSize" value="${maxPoolSize}" />
                </DataSource>
        </DataSources>
 
@@ -25,7 +25,7 @@
 
        <!-- Workspace templates -->
        <Workspaces rootPath="${rep.home}/workspaces"
-               defaultWorkspace="${argeo.node.repo.defaultWorkspace}" />
+               defaultWorkspace="${defaultWorkspace}" />
        <Workspace name="${wsp.name}">
                <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem">
                        <param name="dataSourceName" value="dataSource" />
                        class="org.apache.jackrabbit.core.persistence.pool.PostgreSQLPersistenceManager">
                        <param name="dataSourceName" value="dataSource" />
                        <param name="schemaObjectPrefix" value="${wsp.name}_pm_" />
-                       <param name="bundleCacheSize" value="${argeo.node.repo.bundleCacheMB}" />
+                       <param name="bundleCacheSize" value="${bundleCacheMB}" />
                </PersistenceManager>
                <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
                        <param name="path" value="${wsp.home}/index" />
-                       <param name="extractorPoolSize" value="${argeo.node.repo.extractorPoolSize}" />
-                       <param name="cacheSize" value="${argeo.node.repo.searchCacheSize}" />
-                       <param name="maxVolatileIndexSize" value="${argeo.node.repo.maxVolatileIndexSize}" />
+                       <param name="extractorPoolSize" value="${extractorPoolSize}" />
+                       <param name="cacheSize" value="${searchCacheSize}" />
+                       <param name="maxVolatileIndexSize" value="${maxVolatileIndexSize}" />
                </SearchIndex>
                <WorkspaceSecurity>
                        <AccessControlProvider
                        class="org.apache.jackrabbit.core.persistence.pool.PostgreSQLPersistenceManager">
                        <param name="dataSourceName" value="dataSource" />
                        <param name="schemaObjectPrefix" value="pm_ver_" />
-                       <param name="bundleCacheSize" value="${argeo.node.repo.bundleCacheMB}" />
+                       <param name="bundleCacheSize" value="${bundleCacheMB}" />
                </PersistenceManager>
        </Versioning>
 
        <!-- Indexing -->
        <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
                <param name="path" value="${rep.home}/index" />
-               <param name="extractorPoolSize" value="${argeo.node.repo.extractorPoolSize}" />
-               <param name="cacheSize" value="${argeo.node.repo.searchCacheSize}" />
-               <param name="maxVolatileIndexSize" value="${argeo.node.repo.maxVolatileIndexSize}" />
+               <param name="extractorPoolSize" value="${extractorPoolSize}" />
+               <param name="cacheSize" value="${searchCacheSize}" />
+               <param name="maxVolatileIndexSize" value="${maxVolatileIndexSize}" />
        </SearchIndex>
 
        <!-- Security -->
index 5d4b60fba034b090e20a184480880fdd67b14aaf..96778282039c2b2281e1bd7ce517601629f587bd 100644 (file)
@@ -5,11 +5,11 @@
        <DataSources>
                <DataSource name="dataSource">
                        <param name="driver" value="org.postgresql.Driver" />
-                       <param name="url" value="${argeo.node.repo.dburl}" />
-                       <param name="user" value="${argeo.node.repo.dbuser}" />
-                       <param name="password" value="${argeo.node.repo.dbpassword}" />
+                       <param name="url" value="${dburl}" />
+                       <param name="user" value="${dbuser}" />
+                       <param name="password" value="${dbpassword}" />
                        <param name="databaseType" value="postgresql" />
-                       <param name="maxPoolSize" value="${argeo.node.repo.maxPoolSize}" />
+                       <param name="maxPoolSize" value="${maxPoolSize}" />
                </DataSource>
        </DataSources>
 
@@ -22,7 +22,7 @@
 
        <!-- Workspace templates -->
        <Workspaces rootPath="${rep.home}/workspaces"
-               defaultWorkspace="${argeo.node.repo.defaultWorkspace}" />
+               defaultWorkspace="${defaultWorkspace}" />
        <Workspace name="${wsp.name}">
                <FileSystem class="org.apache.jackrabbit.core.fs.db.DbFileSystem">
                        <param name="dataSourceName" value="dataSource" />
                        class="org.apache.jackrabbit.core.persistence.pool.PostgreSQLPersistenceManager">
                        <param name="dataSourceName" value="dataSource" />
                        <param name="schemaObjectPrefix" value="${wsp.name}_pm_" />
-                       <param name="bundleCacheSize" value="${argeo.node.repo.bundleCacheMB}" />
+                       <param name="bundleCacheSize" value="${bundleCacheMB}" />
                </PersistenceManager>
                <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
                        <param name="path" value="${wsp.home}/index" />
-                       <param name="extractorPoolSize" value="${argeo.node.repo.extractorPoolSize}" />
-                       <param name="cacheSize" value="${argeo.node.repo.searchCacheSize}" />
-                       <param name="maxVolatileIndexSize" value="${argeo.node.repo.maxVolatileIndexSize}" />
+                       <param name="extractorPoolSize" value="${extractorPoolSize}" />
+                       <param name="cacheSize" value="${searchCacheSize}" />
+                       <param name="maxVolatileIndexSize" value="${maxVolatileIndexSize}" />
                </SearchIndex>
                <WorkspaceSecurity>
                        <AccessControlProvider
                        class="org.apache.jackrabbit.core.persistence.pool.PostgreSQLPersistenceManager">
                        <param name="dataSourceName" value="dataSource" />
                        <param name="schemaObjectPrefix" value="pm_ver_" />
-                       <param name="bundleCacheSize" value="${argeo.node.repo.bundleCacheMB}" />
+                       <param name="bundleCacheSize" value="${bundleCacheMB}" />
                </PersistenceManager>
        </Versioning>
 
        <!-- Indexing -->
        <SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
                <param name="path" value="${rep.home}/index" />
-               <param name="extractorPoolSize" value="${argeo.node.repo.extractorPoolSize}" />
-               <param name="cacheSize" value="${argeo.node.repo.searchCacheSize}" />
-               <param name="maxVolatileIndexSize" value="${argeo.node.repo.maxVolatileIndexSize}" />
+               <param name="extractorPoolSize" value="${extractorPoolSize}" />
+               <param name="cacheSize" value="${searchCacheSize}" />
+               <param name="maxVolatileIndexSize" value="${maxVolatileIndexSize}" />
        </SearchIndex>
 
        <!-- Security -->
diff --git a/org.argeo.cms/src/org/argeo/cms/maintenance/AbstractOsgiComposite.java b/org.argeo.cms/src/org/argeo/cms/maintenance/AbstractOsgiComposite.java
new file mode 100644 (file)
index 0000000..2494d90
--- /dev/null
@@ -0,0 +1,43 @@
+package org.argeo.cms.maintenance;
+
+import java.util.Collection;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.cms.util.CmsUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+abstract class AbstractOsgiComposite extends Composite {
+       private static final long serialVersionUID = -4097415973477517137L;
+       protected final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
+       protected final Log log = LogFactory.getLog(getClass());
+
+       public AbstractOsgiComposite(Composite parent, int style) {
+               super(parent, style);
+               parent.setLayout(CmsUtils.noSpaceGridLayout());
+               setLayout(CmsUtils.noSpaceGridLayout());
+               setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+               initUi(style);
+       }
+
+       protected abstract void initUi(int style);
+
+       protected <T> T getService(Class<? extends T> clazz) {
+               return bc.getService(bc.getServiceReference(clazz));
+       }
+
+       protected <T> Collection<ServiceReference<T>> getServiceReferences(Class<T> clazz, String filter) {
+               try {
+                       return bc.getServiceReferences(clazz, filter);
+               } catch (InvalidSyntaxException e) {
+                       throw new IllegalArgumentException("Filter " + filter + " is invalid", e);
+               }
+       }
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/maintenance/ConnectivityDeploymentUi.java b/org.argeo.cms/src/org/argeo/cms/maintenance/ConnectivityDeploymentUi.java
new file mode 100644 (file)
index 0000000..f4f3079
--- /dev/null
@@ -0,0 +1,48 @@
+package org.argeo.cms.maintenance;
+
+import org.argeo.cms.util.CmsUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.useradmin.UserAdmin;
+
+class ConnectivityDeploymentUi extends AbstractOsgiComposite {
+       private static final long serialVersionUID = 590221539553514693L;
+
+       public ConnectivityDeploymentUi(Composite parent, int style) {
+               super(parent, style);
+       }
+
+       @Override
+       protected void initUi(int style) {
+               StringBuffer text = new StringBuffer();
+               text.append("<span style='font-variant: small-caps;'>Provided Servers</span><br/>");
+
+               ServiceReference<HttpService> userAdminRef = bc.getServiceReference(HttpService.class);
+               if (userAdminRef != null) {
+                       // FIXME use constants
+                       Object httpPort = userAdminRef.getProperty("http.port");
+                       Object httpsPort = userAdminRef.getProperty("https.port");
+                       if (httpPort != null)
+                               text.append("<b>http</b> ").append(httpPort).append("<br/>");
+                       if (httpsPort != null)
+                               text.append("<b>https</b> ").append(httpsPort).append("<br/>");
+
+               }
+
+               text.append("<br/>");
+               text.append("<span style='font-variant: small-caps;'>Referenced Servers</span><br/>");
+
+               Label label = new Label(this, SWT.NONE);
+               label.setData(new GridData(SWT.FILL, SWT.FILL, false, false));
+               CmsUtils.markup(label);
+               label.setText(text.toString());
+       }
+
+       protected boolean isDeployed() {
+               return bc.getServiceReference(UserAdmin.class) != null;
+       }
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/maintenance/DataDeploymentUi.java b/org.argeo.cms/src/org/argeo/cms/maintenance/DataDeploymentUi.java
new file mode 100644 (file)
index 0000000..8e0c564
--- /dev/null
@@ -0,0 +1,149 @@
+package org.argeo.cms.maintenance;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileStore;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collection;
+
+import org.apache.jackrabbit.core.RepositoryContext;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.argeo.cms.CmsException;
+import org.argeo.cms.internal.kernel.JackrabbitType;
+import org.argeo.cms.util.CmsUtils;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.node.NodeConstants;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+class DataDeploymentUi extends AbstractOsgiComposite {
+       private static final long serialVersionUID = 590221539553514693L;
+
+       public DataDeploymentUi(Composite parent, int style) {
+               super(parent, style);
+       }
+
+       @Override
+       protected void initUi(int style) {
+               if (isDeployed()) {
+                       initCurrentUi(this);
+               } else {
+                       initNewUi(this);
+               }
+       }
+
+       private void initNewUi(Composite parent) {
+               try {
+                       ConfigurationAdmin confAdmin = bc.getService(bc.getServiceReference(ConfigurationAdmin.class));
+                       Configuration[] confs = confAdmin.listConfigurations(
+                                       "(" + ConfigurationAdmin.SERVICE_FACTORYPID + "=" + NodeConstants.JACKRABBIT_FACTORY_PID + ")");
+                       if (confs == null || confs.length == 0) {
+                               Group buttonGroup = new Group(parent, SWT.NONE);
+                               buttonGroup.setText("Repository Type");
+                               buttonGroup.setLayout(new GridLayout(2, true));
+                               buttonGroup.setLayoutData(new GridData(GridData.FILL_VERTICAL));
+
+                               SelectionListener selectionListener = new SelectionAdapter() {
+                                       private static final long serialVersionUID = 6247064348421088092L;
+
+                                       public void widgetSelected(SelectionEvent event) {
+                                               Button radio = (Button) event.widget;
+                                               if (!radio.getSelection())
+                                                       return;
+                                               log.debug(event);
+                                               JackrabbitType nodeType = (JackrabbitType) radio.getData();
+                                               if (log.isDebugEnabled())
+                                                       log.debug(" selected = " + nodeType.name());
+                                       };
+                               };
+
+                               for (JackrabbitType nodeType : JackrabbitType.values()) {
+                                       Button radio = new Button(buttonGroup, SWT.RADIO);
+                                       radio.setText(nodeType.name());
+                                       radio.setData(nodeType);
+                                       if (nodeType.equals(JackrabbitType.localfs))
+                                               radio.setSelection(true);
+                                       radio.addSelectionListener(selectionListener);
+                               }
+
+                       } else if (confs.length == 1) {
+
+                       } else {
+                               throw new CmsException("Multiple repos not yet supported");
+                       }
+               } catch (Exception e) {
+                       throw new CmsException("Cannot initialize UI", e);
+               }
+
+       }
+
+       private void initCurrentUi(Composite parent) {
+               parent.setLayout(new GridLayout());
+               Collection<ServiceReference<RepositoryContext>> contexts = getServiceReferences(RepositoryContext.class,
+                               "(" + ArgeoJcrConstants.JCR_REPOSITORY_ALIAS + "=*)");
+               StringBuffer text = new StringBuffer();
+               text.append("<span style='font-variant: small-caps;'>Jackrabbit Repositories</span><br/>");
+               for (ServiceReference<RepositoryContext> sr : contexts) {
+                       RepositoryContext repositoryContext = bc.getService(sr);
+                       String alias = sr.getProperty(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS).toString();
+                       String rootNodeId = repositoryContext.getRootNodeId().toString();
+                       RepositoryConfig repositoryConfig = repositoryContext.getRepositoryConfig();
+                       Path repoHomePath = new File(repositoryConfig.getHomeDir()).toPath().toAbsolutePath();
+                       // TODO check data store
+
+                       text.append("<b>" + alias + "</b><br/>");
+                       text.append("rootNodeId: " + rootNodeId + "<br/>");
+                       try {
+                               FileStore fileStore = Files.getFileStore(repoHomePath);
+                               text.append("partition: " + fileStore.toString() + "<br/>");
+                               text.append(
+                                               percentUsed(fileStore) + " used (" + humanReadable(fileStore.getUsableSpace()) + " free)<br/>");
+                       } catch (IOException e) {
+                               log.error("Cannot check fileStore for " + repoHomePath, e);
+                       }
+               }
+               Label label = new Label(parent, SWT.NONE);
+               label.setData(new GridData(SWT.FILL, SWT.FILL, false, false));
+               CmsUtils.markup(label);
+               label.setText("<span style=''>" + text.toString() + "</span>");
+       }
+
+       private String humanReadable(long bytes) {
+               long mb = bytes / (1024 * 1024);
+               return mb >= 2048 ? Long.toString(mb / 1024) + " GB" : Long.toString(mb) + " MB";
+       }
+
+       private String percentUsed(FileStore fs) throws IOException {
+               long used = fs.getTotalSpace() - fs.getUnallocatedSpace();
+               long percent = used * 100 / fs.getTotalSpace();
+               if (log.isTraceEnabled()) {
+                       // output identical to `df -B 1`)
+                       log.trace(fs.getTotalSpace() + "," + used + "," + fs.getUsableSpace());
+               }
+               String span;
+               if (percent < 80)
+                       span = "<span style='color:green;font-weight:bold'>";
+               else if (percent < 95)
+                       span = "<span style='color:orange;font-weight:bold'>";
+               else
+                       span = "<span style='color:red;font-weight:bold'>";
+               return span + percent + "%</span>";
+       }
+
+       protected boolean isDeployed() {
+               return bc.getServiceReference(RepositoryContext.class) != null;
+       }
+
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/maintenance/DeploymentEntryPoint.java b/org.argeo.cms/src/org/argeo/cms/maintenance/DeploymentEntryPoint.java
new file mode 100644 (file)
index 0000000..e21974c
--- /dev/null
@@ -0,0 +1,94 @@
+package org.argeo.cms.maintenance;
+
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+import org.argeo.cms.util.CmsUtils;
+import org.argeo.node.NodeConstants;
+import org.argeo.node.NodeDeployment;
+import org.argeo.node.NodeState;
+import org.eclipse.rap.rwt.application.AbstractEntryPoint;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+
+class DeploymentEntryPoint extends AbstractEntryPoint {
+       private static final long serialVersionUID = -881152502968982437L;
+       private final BundleContext bc = FrameworkUtil.getBundle(getClass()).getBundleContext();
+
+       @Override
+       protected void createContents(Composite parent) {
+               // parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               if (isDesktop()) {
+                       parent.setLayout(new GridLayout(2, true));
+               } else {
+                       // TODO add scrolling
+                       parent.setLayout(new GridLayout(1, true));
+               }
+
+               initHighLevelSummary(parent);
+
+               Group securityGroup = createHighLevelGroup(parent, "Security");
+               securityGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+               new SecurityDeploymentUi(securityGroup, SWT.NONE);
+
+               Group dataGroup = createHighLevelGroup(parent, "Data");
+               dataGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
+               new DataDeploymentUi(dataGroup, SWT.NONE);
+
+               Group logGroup = createHighLevelGroup(parent, "Notifications");
+               logGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
+               new LogDeploymentUi(logGroup, SWT.NONE);
+
+               Group connectivityGroup = createHighLevelGroup(parent, "Connectivity");
+               new ConnectivityDeploymentUi(connectivityGroup, SWT.NONE);
+               connectivityGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, true));
+
+       }
+
+       private void initHighLevelSummary(Composite parent) {
+               Composite composite = new Composite(parent, SWT.NONE);
+               GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
+               if (isDesktop())
+                       gridData.horizontalSpan = 3;
+               composite.setLayoutData(gridData);
+               composite.setLayout(new FillLayout());
+
+               ServiceReference<NodeState> nodeStateRef = bc.getServiceReference(NodeState.class);
+               if (nodeStateRef == null)
+                       throw new IllegalStateException("No CMS state available");
+               NodeState nodeState = bc.getService(nodeStateRef);
+               ServiceReference<NodeDeployment> nodeDeploymentRef = bc.getServiceReference(NodeDeployment.class);
+               Label label = new Label(composite, SWT.WRAP);
+               CmsUtils.markup(label);
+               if (nodeDeploymentRef == null) {
+                       label.setText("Not yet deployed on <br>" + nodeState.getHostname() + "</br>, please configure below.");
+               } else {
+                       Object stateUuid = nodeStateRef.getProperty(NodeConstants.CN);
+                       NodeDeployment nodeDeployment = bc.getService(nodeDeploymentRef);
+                       GregorianCalendar calendar = new GregorianCalendar();
+                       calendar.setTimeInMillis(nodeDeployment.getAvailableSince());
+                       calendar.setTimeZone(TimeZone.getDefault());
+                       label.setText("[" + "<b>" + nodeState.getHostname() + "</b>]# " + "Deployment state " + stateUuid
+                                       + ", available since <b>" + calendar.getTime() + "</b>");
+               }
+       }
+
+       private static Group createHighLevelGroup(Composite parent, String text) {
+               Group group = new Group(parent, SWT.NONE);
+               group.setText(text);
+               CmsUtils.markup(group);
+               return group;
+       }
+
+       private boolean isDesktop() {
+               return true;
+       }
+}
diff --git a/org.argeo.cms/src/org/argeo/cms/maintenance/LogDeploymentUi.java b/org.argeo.cms/src/org/argeo/cms/maintenance/LogDeploymentUi.java
new file mode 100644 (file)
index 0000000..8fb9643
--- /dev/null
@@ -0,0 +1,74 @@
+package org.argeo.cms.maintenance;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Enumeration;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+import org.argeo.cms.util.CmsUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Text;
+import org.osgi.service.log.LogEntry;
+import org.osgi.service.log.LogListener;
+import org.osgi.service.log.LogReaderService;
+
+class LogDeploymentUi extends AbstractOsgiComposite implements LogListener {
+       private static final long serialVersionUID = 590221539553514693L;
+
+       private DateFormat dateFormat = new SimpleDateFormat("MMdd HH:mm");
+
+       private Display display;
+       private Text logDisplay;
+
+       public LogDeploymentUi(Composite parent, int style) {
+               super(parent, style);
+       }
+
+       @Override
+       protected void initUi(int style) {
+               LogReaderService logReader = getService(LogReaderService.class);
+               // FIXME use server push
+               // logReader.addLogListener(this);
+               this.display = getDisplay();
+               this.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               logDisplay = new Text(this, SWT.WRAP | SWT.MULTI | SWT.READ_ONLY);
+               logDisplay.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               CmsUtils.markup(logDisplay);
+               @SuppressWarnings("unchecked")
+               Enumeration<LogEntry> logEntries = (Enumeration<LogEntry>) logReader.getLog();
+               while (logEntries.hasMoreElements())
+                       logDisplay.append(printEntry(logEntries.nextElement()));
+       }
+
+       private String printEntry(LogEntry entry) {
+               StringBuilder sb = new StringBuilder();
+               GregorianCalendar calendar = new GregorianCalendar(TimeZone.getDefault());
+               calendar.setTimeInMillis(entry.getTime());
+               sb.append(dateFormat.format(calendar.getTime())).append(' ');
+               sb.append(entry.getMessage());
+               sb.append('\n');
+               return sb.toString();
+       }
+
+       @Override
+       public void logged(LogEntry entry) {
+               if (display.isDisposed())
+                       return;
+               display.asyncExec(() -> {
+                       if (logDisplay.isDisposed())
+                               return;
+                       logDisplay.append(printEntry(entry));
+               });
+               display.wake();
+       }
+
+       // @Override
+       // public void dispose() {
+       // super.dispose();
+       // getService(LogReaderService.class).removeLogListener(this);
+       // }
+}
index 49556bc99db4c9a9605a7ea2575f58c966684df8..538379f06451d7bcb7010e869e992e261eace049 100644 (file)
@@ -7,7 +7,7 @@ public class MaintenanceUi implements ApplicationConfiguration {
 
        @Override
        public void configure(Application application) {
-               application.addEntryPoint("/migration", MigrationEntryPoint.class, null);
+               application.addEntryPoint("/status", DeploymentEntryPoint.class, null);
        }
 
 }
diff --git a/org.argeo.cms/src/org/argeo/cms/maintenance/MigrationEntryPoint.java b/org.argeo.cms/src/org/argeo/cms/maintenance/MigrationEntryPoint.java
deleted file mode 100644 (file)
index e6bae8f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.argeo.cms.maintenance;
-
-import org.eclipse.rap.rwt.application.AbstractEntryPoint;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Label;
-
-public class MigrationEntryPoint extends AbstractEntryPoint {
-
-       @Override
-       protected void createContents(Composite parent) {
-               new Label(parent, SWT.NONE).setText("Migration");
-       }
-
-       
-
-}
diff --git a/org.argeo.cms/src/org/argeo/cms/maintenance/SecurityDeploymentUi.java b/org.argeo.cms/src/org/argeo/cms/maintenance/SecurityDeploymentUi.java
new file mode 100644 (file)
index 0000000..9fcdaf9
--- /dev/null
@@ -0,0 +1,85 @@
+package org.argeo.cms.maintenance;
+
+import java.net.URI;
+
+import org.argeo.cms.util.CmsUtils;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.useradmin.Role;
+import org.osgi.service.useradmin.UserAdmin;
+
+class SecurityDeploymentUi extends AbstractOsgiComposite {
+       private static final long serialVersionUID = 590221539553514693L;
+
+       public SecurityDeploymentUi(Composite parent, int style) {
+               super(parent, style);
+       }
+
+       @Override
+       protected void initUi(int style) {
+               if (isDeployed()) {
+                       initCurrentUi(this);
+               } else {
+                       initNewUi(this);
+               }
+       }
+
+       private void initNewUi(Composite parent) {
+               new Label(parent, SWT.NONE).setText("Security is not configured");
+       }
+
+       private void initCurrentUi(Composite parent) {
+               ServiceReference<UserAdmin> userAdminRef = bc.getServiceReference(UserAdmin.class);
+               UserAdmin userAdmin = bc.getService(userAdminRef);
+               StringBuffer text = new StringBuffer();
+               text.append("<span style='font-variant: small-caps;'>Domains</span><br/>");
+               domains: for (String key : userAdminRef.getPropertyKeys()) {
+                       if (!key.startsWith("/"))
+                               continue domains;
+                       URI uri;
+                       try {
+                               uri = new URI(key);
+                       } catch (Exception e) {
+                               // ignore non URI keys
+                               continue domains;
+                       }
+
+                       String rootDn = uri.getPath().substring(1, uri.getPath().length());
+                       // FIXME make reading query options more robust, using utils
+                       boolean readOnly = uri.getQuery().equals("readOnly=true");
+                       if (readOnly)
+                               text.append("<span style='font-weight:bold;font-style: italic'>");
+                       else
+                               text.append("<span style='font-weight:bold'>");
+
+                       text.append(rootDn);
+                       text.append("</span><br/>");
+                       try {
+                               Role[] roles = userAdmin.getRoles("(dn=*," + rootDn + ")");
+                               long userCount = 0;
+                               long groupCount = 0;
+                               for (Role role : roles) {
+                                       if (role.getType() == Role.USER)
+                                               userCount++;
+                                       else
+                                               groupCount++;
+                               }
+                               text.append(" " + userCount + " users, " + groupCount +" groups.<br/>");
+                       } catch (InvalidSyntaxException e) {
+                               log.error("Invalid syntax", e);
+                       }
+               }
+               Label label = new Label(parent, SWT.NONE);
+               label.setData(new GridData(SWT.FILL, SWT.FILL, false, false));
+               CmsUtils.markup(label);
+               label.setText(text.toString());
+       }
+
+       protected boolean isDeployed() {
+               return bc.getServiceReference(UserAdmin.class) != null;
+       }
+}
index 845c231113e71f751047eb89a3ce1b7f9bf6641b..92cd0b1b538c5c7a5aa41080c766ab37f53ab08c 100644 (file)
@@ -2,23 +2,20 @@ package org.argeo.eclipse.ui.workbench.internal.jcr.model;
 
 import javax.jcr.Repository;
 
-import org.argeo.ArgeoException;
 import org.argeo.eclipse.ui.TreeParent;
-import org.argeo.jcr.MaintainedRepository;
 
-/** Wrap a {@link MaintainedRepository} */
+/** Wrap a MaintainedRepository */
 public class MaintainedRepositoryElem extends RepositoryElem {
 
-       public MaintainedRepositoryElem(String alias, Repository repository,
-                       TreeParent parent) {
+       public MaintainedRepositoryElem(String alias, Repository repository, TreeParent parent) {
                super(alias, repository, parent);
-               if (!(repository instanceof MaintainedRepository)) {
-                       throw new ArgeoException("Repository " + alias
-                                       + " is not amiantained repository");
-               }
+               // if (!(repository instanceof MaintainedRepository)) {
+               // throw new ArgeoException("Repository " + alias
+               // + " is not amiantained repository");
+               // }
        }
 
-       protected MaintainedRepository getMaintainedRepository() {
-               return (MaintainedRepository) getRepository();
-       }
+       // protected MaintainedRepository getMaintainedRepository() {
+       // return (MaintainedRepository) getRepository();
+       // }
 }
index 984d01b5ff60044a50d9a14bfca1343dc9911dcd..0737544873b4e1d39657f72c665844dade9a1407 100644 (file)
@@ -28,7 +28,6 @@ import org.argeo.ArgeoException;
 import org.argeo.eclipse.ui.TreeParent;
 import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
 import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.MaintainedRepository;
 import org.argeo.jcr.RepositoryRegister;
 import org.argeo.jcr.UserJcrUtils;
 import org.argeo.util.security.Keyring;
@@ -55,9 +54,8 @@ public class RepositoriesElem extends TreeParent implements ArgeoNames {
        private final Session userSession;
        private final Keyring keyring;
 
-       public RepositoriesElem(String name, RepositoryRegister repositoryRegister,
-                       RepositoryFactory repositoryFactory, TreeParent parent,
-                       Session userSession, Keyring keyring) {
+       public RepositoriesElem(String name, RepositoryRegister repositoryRegister, RepositoryFactory repositoryFactory,
+                       TreeParent parent, Session userSession, Keyring keyring) {
                super(name);
                this.repositoryRegister = repositoryRegister;
                this.repositoryFactory = repositoryFactory;
@@ -75,15 +73,14 @@ public class RepositoriesElem extends TreeParent implements ArgeoNames {
                        return super.getChildren();
                } else {
                        // initialize current object
-                       Map<String, Repository> refRepos = repositoryRegister
-                                       .getRepositories();
+                       Map<String, Repository> refRepos = repositoryRegister.getRepositories();
                        for (String name : refRepos.keySet()) {
                                Repository repository = refRepos.get(name);
-                               if (repository instanceof MaintainedRepository)
-                                       super.addChild(new MaintainedRepositoryElem(name,
-                                                       repository, this));
-                               else
-                                       super.addChild(new RepositoryElem(name, repository, this));
+                               // if (repository instanceof MaintainedRepository)
+                               // super.addChild(new MaintainedRepositoryElem(name,
+                               // repository, this));
+                               // else
+                               super.addChild(new RepositoryElem(name, repository, this));
                        }
 
                        // remote
@@ -91,16 +88,14 @@ public class RepositoriesElem extends TreeParent implements ArgeoNames {
                                try {
                                        addRemoteRepositories(keyring);
                                } catch (RepositoryException e) {
-                                       throw new ArgeoException(
-                                                       "Cannot browse remote repositories", e);
+                                       throw new ArgeoException("Cannot browse remote repositories", e);
                                }
                        }
                        return super.getChildren();
                }
        }
 
-       protected void addRemoteRepositories(Keyring jcrKeyring)
-                       throws RepositoryException {
+       protected void addRemoteRepositories(Keyring jcrKeyring) throws RepositoryException {
                Node userHome = UserJcrUtils.getUserHome(userSession);
                if (userHome != null && userHome.hasNode(ARGEO_REMOTE)) {
                        NodeIterator it = userHome.getNode(ARGEO_REMOTE).getNodes();
@@ -108,13 +103,11 @@ public class RepositoriesElem extends TreeParent implements ArgeoNames {
                                Node remoteNode = it.nextNode();
                                String uri = remoteNode.getProperty(ARGEO_URI).getString();
                                try {
-                                       RemoteRepositoryElem remoteRepositoryNode = new RemoteRepositoryElem(
-                                                       remoteNode.getName(), repositoryFactory, uri, this,
-                                                       userSession, jcrKeyring, remoteNode.getPath());
+                                       RemoteRepositoryElem remoteRepositoryNode = new RemoteRepositoryElem(remoteNode.getName(),
+                                                       repositoryFactory, uri, this, userSession, jcrKeyring, remoteNode.getPath());
                                        super.addChild(remoteRepositoryNode);
                                } catch (Exception e) {
-                                       ErrorFeedback.show("Cannot add remote repository "
-                                                       + remoteNode, e);
+                                       ErrorFeedback.show("Cannot add remote repository " + remoteNode, e);
                                }
                        }
                }
diff --git a/org.argeo.server.jcr/ext/test/org/argeo/jcr/spring/CollectionsObject.java b/org.argeo.server.jcr/ext/test/org/argeo/jcr/spring/CollectionsObject.java
deleted file mode 100644 (file)
index eadabfd..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.spring;
-
-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/org.argeo.server.jcr/ext/test/org/argeo/jcr/spring/MapperTest.java b/org.argeo.server.jcr/ext/test/org/argeo/jcr/spring/MapperTest.java
deleted file mode 100644 (file)
index e4bccd9..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.spring;
-
-import javax.jcr.Node;
-
-import org.argeo.jackrabbit.unit.AbstractJackrabbitTestCase;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.spring.BeanNodeMapper;
-
-@Deprecated
-public class MapperTest extends AbstractJackrabbitTestCase {
-       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/org.argeo.server.jcr/ext/test/org/argeo/jcr/spring/OtherObject.java b/org.argeo.server.jcr/ext/test/org/argeo/jcr/spring/OtherObject.java
deleted file mode 100644 (file)
index d6fb699..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.spring;
-
-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/org.argeo.server.jcr/ext/test/org/argeo/jcr/spring/SimpleObject.java b/org.argeo.server.jcr/ext/test/org/argeo/jcr/spring/SimpleObject.java
deleted file mode 100644 (file)
index d18dd04..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.spring;
-
-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/org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitAuthorizations.java b/org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitAuthorizations.java
deleted file mode 100644 (file)
index 84e0799..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit;
-
-import java.security.Principal;
-import java.util.List;
-
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.jcr.security.JcrAuthorizations;
-
-/** Apply authorizations to a Jackrabbit repository. */
-@Deprecated
-public class JackrabbitAuthorizations extends JcrAuthorizations {
-       private final static Log log = LogFactory.getLog(JackrabbitAuthorizations.class);
-
-       // private List<String> groupPrefixes = Arrays.asList(new String[] { "ROLE_"
-       // });// new
-       // ArrayList<String>();
-
-       @Override
-       protected Principal getOrCreatePrincipal(Session session, String principalName) throws RepositoryException {
-               String msg = "Use org.argeo.jcr.security.JcrAuthorizations instead of org.argeo.jackrabbit.JackrabbitAuthorizations";
-               log.error(msg);
-               throw new UnsupportedOperationException(msg);
-               // UserManager um = ((JackrabbitSession) session).getUserManager();
-               // synchronized (um) {
-               // Authorizable authorizable = um.getAuthorizable(principalName);
-               // if (authorizable == null) {
-               // groupPrefixes: for (String groupPrefix : groupPrefixes) {
-               // if (principalName.startsWith(groupPrefix)) {
-               // authorizable = um.createGroup(principalName);
-               // log.info("Created group " + principalName);
-               // break groupPrefixes;
-               // }
-               // }
-               // if (authorizable == null)
-               // throw new ArgeoException("Authorizable " + principalName
-               // + " not found");
-               // }
-               // return authorizable.getPrincipal();
-               // }
-       }
-
-       public void setGroupPrefixes(List<String> groupsToCreate) {
-               // this.groupPrefixes = groupsToCreate;
-       }
-}
index 85e9e203f96e6613746e7f38461b8425fffc144c..547db9b0d1ec5ff04a54b653f539807476a98f22 100644 (file)
@@ -41,7 +41,6 @@ import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
 import org.argeo.ArgeoException;
 import org.argeo.jcr.ArgeoNames;
 import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.MaintainedRepository;
 import org.springframework.core.io.Resource;
 import org.springframework.util.SystemPropertyUtils;
 import org.xml.sax.InputSource;
@@ -50,8 +49,8 @@ import org.xml.sax.InputSource;
  * Wrapper around a Jackrabbit repository which allows to configure it in Spring
  * and expose it as a {@link Repository}.
  */
-public class JackrabbitContainer extends JackrabbitWrapper implements
-               MaintainedRepository {
+@Deprecated
+public class JackrabbitContainer extends JackrabbitWrapper {
        private final static Log log = LogFactory.getLog(JackrabbitContainer.class);
 
        // local
@@ -81,8 +80,7 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
                // long begin = System.currentTimeMillis();
 
                if (getRepository() != null)
-                       throw new ArgeoException(
-                                       "Cannot be used to wrap another repository");
+                       throw new ArgeoException("Cannot be used to wrap another repository");
                Repository repository = createJackrabbitRepository();
                super.setRepository(repository);
 
@@ -108,14 +106,12 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
                        // temporary
                        if (inMemory && getHomeDirectory().exists()) {
                                FileUtils.deleteDirectory(getHomeDirectory());
-                               log.warn("Deleted Jackrabbit home directory "
-                                               + getHomeDirectory());
+                               log.warn("Deleted Jackrabbit home directory " + getHomeDirectory());
                        }
 
                        // process configuration file
                        Properties vars = getConfigurationProperties();
-                       vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
-                                       getHomeDirectory().getCanonicalPath());
+                       vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, getHomeDirectory().getCanonicalPath());
                        InputSource is;
                        if (configurationXml != null)
                                is = configurationXml;
@@ -132,13 +128,11 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
 
                        double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
                        if (log.isTraceEnabled())
-                               log.trace("Created Jackrabbit repository in " + duration
-                                               + " s, home: " + getHomeDirectory());
+                               log.trace("Created Jackrabbit repository in " + duration + " s, home: " + getHomeDirectory());
 
                        return repository;
                } catch (Exception e) {
-                       throw new ArgeoException("Cannot create Jackrabbit repository "
-                                       + getHomeDirectory(), e);
+                       throw new ArgeoException("Cannot create Jackrabbit repository " + getHomeDirectory(), e);
                } finally {
                        IOUtils.closeQuietly(configurationIn);
                }
@@ -149,12 +143,8 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
                try {
                        if (homeDirectory == null) {
                                if (inMemory) {
-                                       homeDirectory = new File(
-                                                       System.getProperty("java.io.tmpdir")
-                                                                       + File.separator
-                                                                       + System.getProperty("user.name")
-                                                                       + File.separator + "jackrabbit-"
-                                                                       + UUID.randomUUID());
+                                       homeDirectory = new File(System.getProperty("java.io.tmpdir") + File.separator
+                                                       + System.getProperty("user.name") + File.separator + "jackrabbit-" + UUID.randomUUID());
                                        homeDirectory.mkdirs();
                                        // will it work if directory is not empty??
                                        homeDirectory.deleteOnExit();
@@ -163,8 +153,7 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
 
                        return homeDirectory.getCanonicalFile();
                } catch (IOException e) {
-                       throw new ArgeoException("Cannot get canonical file for "
-                                       + homeDirectory, e);
+                       throw new ArgeoException("Cannot get canonical file for " + homeDirectory, e);
                }
        }
 
@@ -198,9 +187,7 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
                if (restartAndClearCaches) {
                        Repository repository = getRepository();
                        if (repository instanceof RepositoryImpl) {
-                               JackrabbitDataModelMigration
-                                               .clearRepositoryCaches(((RepositoryImpl) repository)
-                                                               .getConfig());
+                               JackrabbitDataModelMigration.clearRepositoryCaches(((RepositoryImpl) repository).getConfig());
                        }
                        ((JackrabbitRepository) repository).shutdown();
                        createJackrabbitRepository();
@@ -216,12 +203,9 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
                for (JackrabbitDataModelMigration dataModelMigration : new TreeSet<JackrabbitDataModelMigration>(
                                dataModelMigrations)) {
                        try {
-                               if (session.itemExists(dataModelMigration
-                                               .getDataModelNodePath())) {
-                                       Node dataModelNode = session.getNode(dataModelMigration
-                                                       .getDataModelNodePath());
-                                       dataModelNode.setProperty(
-                                                       ArgeoNames.ARGEO_DATA_MODEL_VERSION,
+                               if (session.itemExists(dataModelMigration.getDataModelNodePath())) {
+                                       Node dataModelNode = session.getNode(dataModelMigration.getDataModelNodePath());
+                                       dataModelNode.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION,
                                                        dataModelMigration.getTargetVersion());
                                        session.save();
                                }
@@ -243,20 +227,17 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
                                if (getHomeDirectory().exists()) {
                                        FileUtils.deleteDirectory(getHomeDirectory());
                                        if (log.isDebugEnabled())
-                                               log.debug("Deleted Jackrabbit home directory "
-                                                               + getHomeDirectory());
+                                               log.debug("Deleted Jackrabbit home directory " + getHomeDirectory());
                                }
                        double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
                        if (log.isTraceEnabled())
-                               log.trace("Destroyed Jackrabbit repository in " + duration
-                                               + " s, home: " + getHomeDirectory());
+                               log.trace("Destroyed Jackrabbit repository in " + duration + " s, home: " + getHomeDirectory());
                }
                repository = null;
        }
 
        public void dispose() {
-               throw new IllegalArgumentException(
-                               "Call destroy() method instead of dispose()");
+               throw new IllegalArgumentException("Call destroy() method instead of dispose()");
        }
 
        /*
@@ -267,11 +248,9 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
         */
        protected InputStream readConfiguration() {
                try {
-                       return configuration != null ? configuration.getInputStream()
-                                       : null;
+                       return configuration != null ? configuration.getInputStream() : null;
                } catch (IOException e) {
-                       throw new ArgeoException("Cannot read Jackrabbit configuration "
-                                       + configuration, e);
+                       throw new ArgeoException("Cannot read Jackrabbit configuration " + configuration, e);
                }
        }
 
@@ -285,8 +264,7 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
                try {
                        return variables != null ? variables.getInputStream() : null;
                } catch (IOException e) {
-                       throw new ArgeoException("Cannot read Jackrabbit variables "
-                                       + variables, e);
+                       throw new ArgeoException("Cannot read Jackrabbit variables " + variables, e);
                }
        }
 
@@ -294,8 +272,7 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
         * Resolves ${} placeholders in the provided string. Based on system
         * properties if no map is provided.
         */
-       protected String resolvePlaceholders(String string,
-                       Map<String, String> variables) {
+       protected String resolvePlaceholders(String string, Map<String, String> variables) {
                return SystemPropertyUtils.resolvePlaceholders(string);
        }
 
@@ -315,8 +292,7 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
                        // resolve system properties
                        for (Object key : vars.keySet()) {
                                // TODO: implement a smarter mechanism to resolve nested ${}
-                               String newValue = resolvePlaceholders(
-                                               vars.getProperty(key.toString()), null);
+                               String newValue = resolvePlaceholders(vars.getProperty(key.toString()), null);
                                vars.put(key, newValue);
                        }
                        // override with system properties
@@ -352,8 +328,7 @@ public class JackrabbitContainer extends JackrabbitWrapper implements
                throw new ArgeoException("Cannot be used to wrap another repository");
        }
 
-       public void setDataModelMigrations(
-                       Set<JackrabbitDataModelMigration> dataModelMigrations) {
+       public void setDataModelMigrations(Set<JackrabbitDataModelMigration> dataModelMigrations) {
                this.dataModelMigrations = dataModelMigrations;
        }
 
diff --git a/org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitDataModel.java b/org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitDataModel.java
deleted file mode 100644 (file)
index b342d18..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-package org.argeo.jackrabbit;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.Repository;
-import javax.jcr.Session;
-import javax.jcr.nodetype.NodeType;
-
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.jackrabbit.commons.NamespaceHelper;
-import org.apache.jackrabbit.commons.cnd.CndImporter;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.jcr.ArgeoNames;
-import org.argeo.jcr.ArgeoTypes;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.util.security.DigestUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.packageadmin.ExportedPackage;
-import org.osgi.service.packageadmin.PackageAdmin;
-
-public class JackrabbitDataModel {
-       private final static Log log = LogFactory.getLog(JackrabbitDataModel.class);
-       private final static String DIGEST_ALGORITHM = "MD5";
-       final static String[] DEFAULT_CNDS = { "/org/argeo/jcr/argeo.cnd", "/org/argeo/cms/cms.cnd" };
-
-       // data model
-       /** Node type definitions in CND format */
-       private List<String> cndFiles = new ArrayList<String>();
-       /**
-        * Always import CNDs. Useful during development of new data models. In
-        * production, explicit migration processes should be used.
-        */
-       private Boolean forceCndImport = true;
-
-       /** Namespaces to register: key is prefix, value namespace */
-       private Map<String, String> namespaces = new HashMap<String, String>();
-
-       private final BundleContext bc;
-
-       public JackrabbitDataModel(BundleContext bc) {
-               this.bc = bc;
-       }
-
-       /**
-        * Import declared node type definitions and register namespaces. Tries to
-        * update the node definitions if they have changed. In case of failures an
-        * error will be logged but no exception will be thrown.
-        */
-       public void prepareDataModel(Repository repository) {
-               cndFiles = Arrays.asList(DEFAULT_CNDS);
-               if ((cndFiles == null || cndFiles.size() == 0) && (namespaces == null || namespaces.size() == 0))
-                       return;
-
-               Session session = null;
-               try {
-                       session = repository.login();
-                       // register namespaces
-                       if (namespaces.size() > 0) {
-                               NamespaceHelper namespaceHelper = new NamespaceHelper(session);
-                               namespaceHelper.registerNamespaces(namespaces);
-                       }
-
-                       // load CND files from classpath or as URL
-                       for (String resUrl : cndFiles) {
-                               processCndFile(session, resUrl);
-                       }
-               } catch (Exception e) {
-                       JcrUtils.discardQuietly(session);
-                       throw new ArgeoException("Cannot import node type definitions " + cndFiles, e);
-               } finally {
-                       JcrUtils.logoutQuietly(session);
-               }
-
-       }
-
-       protected void processCndFile(Session session, String resUrl) {
-               Reader reader = null;
-               try {
-                       // check existing data model nodes
-                       new NamespaceHelper(session).registerNamespace(ArgeoNames.ARGEO, ArgeoNames.ARGEO_NAMESPACE);
-                       if (!session.itemExists(ArgeoJcrConstants.DATA_MODELS_BASE_PATH))
-                               JcrUtils.mkdirs(session, ArgeoJcrConstants.DATA_MODELS_BASE_PATH);
-                       Node dataModels = session.getNode(ArgeoJcrConstants.DATA_MODELS_BASE_PATH);
-                       NodeIterator it = dataModels.getNodes();
-                       Node dataModel = null;
-                       while (it.hasNext()) {
-                               Node node = it.nextNode();
-                               if (node.getProperty(ArgeoNames.ARGEO_URI).getString().equals(resUrl)) {
-                                       dataModel = node;
-                                       break;
-                               }
-                       }
-
-                       Bundle bundle = findDataModelBundle(resUrl);
-
-                       byte[] cndContent = readCndContent(resUrl);
-                       String newDigest = DigestUtils.digest(DIGEST_ALGORITHM, cndContent);
-
-                       String currentVersion = null;
-                       if (dataModel != null) {
-                               currentVersion = dataModel.getProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION).getString();
-                               if (dataModel.hasNode(Node.JCR_CONTENT)) {
-                                       String oldDigest = JcrUtils.checksumFile(dataModel, DIGEST_ALGORITHM);
-                                       if (oldDigest.equals(newDigest)) {
-                                               if (log.isTraceEnabled())
-                                                       log.trace("Data model " + resUrl + " hasn't changed, keeping version " + currentVersion);
-                                               return;
-                                       }
-                               }
-                       }
-
-                       if (dataModel != null && !forceCndImport) {
-                               log.info(
-                                               "Data model " + resUrl + " has changed since version " + currentVersion
-                                                               + (bundle != null
-                                                                               ? ": version " + bundle.getVersion() + ", bundle " + bundle.getSymbolicName()
-                                                                               : ""));
-                               return;
-                       }
-
-                       reader = new InputStreamReader(new ByteArrayInputStream(cndContent));
-                       // actually imports the CND
-                       try {
-                               CndImporter.registerNodeTypes(reader, session, true);
-                       } catch (Exception e) {
-                               log.error("Cannot import data model " + resUrl, e);
-                               return;
-                       }
-
-                       if (dataModel != null && !dataModel.isNodeType(NodeType.NT_FILE)) {
-                               dataModel.remove();
-                               dataModel = null;
-                       }
-
-                       // FIXME: what if argeo.cnd would not be the first called on
-                       // a new repo? argeo:dataModel would not be found
-                       String fileName = FilenameUtils.getName(resUrl);
-                       if (dataModel == null) {
-                               dataModel = dataModels.addNode(fileName, NodeType.NT_FILE);
-                               dataModel.addNode(Node.JCR_CONTENT, NodeType.NT_RESOURCE);
-                               dataModel.addMixin(ArgeoTypes.ARGEO_DATA_MODEL);
-                               dataModel.setProperty(ArgeoNames.ARGEO_URI, resUrl);
-                       } else {
-                               session.getWorkspace().getVersionManager().checkout(dataModel.getPath());
-                       }
-                       if (bundle != null)
-                               dataModel.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION, bundle.getVersion().toString());
-                       else
-                               dataModel.setProperty(ArgeoNames.ARGEO_DATA_MODEL_VERSION, "0.0.0");
-                       JcrUtils.copyBytesAsFile(dataModel.getParent(), fileName, cndContent);
-                       JcrUtils.updateLastModified(dataModel);
-                       session.save();
-                       session.getWorkspace().getVersionManager().checkin(dataModel.getPath());
-
-                       if (currentVersion == null)
-                               log.info(
-                                               "Data model " + resUrl
-                                                               + (bundle != null
-                                                                               ? ", version " + bundle.getVersion() + ", bundle " + bundle.getSymbolicName()
-                                                                               : ""));
-                       else
-                               log.info(
-                                               "Data model " + resUrl + " updated from version " + currentVersion
-                                                               + (bundle != null
-                                                                               ? ", version " + bundle.getVersion() + ", bundle " + bundle.getSymbolicName()
-                                                                               : ""));
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot process data model " + resUrl, e);
-               } finally {
-                       IOUtils.closeQuietly(reader);
-               }
-       }
-
-       protected byte[] readCndContent(String resUrl) {
-               BundleContext bundleContext = bc;
-               InputStream in = null;
-               try {
-                       boolean classpath;
-                       // normalize URL
-                       if (bundleContext != null && resUrl.startsWith("classpath:")) {
-                               resUrl = resUrl.substring("classpath:".length());
-                               classpath = true;
-                       } else if (resUrl.indexOf(':') < 0) {
-                               if (!resUrl.startsWith("/")) {
-                                       resUrl = "/" + resUrl;
-                                       log.warn("Classpath should start with '/'");
-                               }
-                               classpath = true;
-                       } else {
-                               classpath = false;
-                       }
-
-                       URL url = null;
-                       if (classpath) {
-                               // if (bundleContext != null) {
-                               Bundle currentBundle = bundleContext.getBundle();
-                               url = currentBundle.getResource(resUrl);
-                               // } else {
-                               // resUrl = "classpath:" + resUrl;
-                               // url = null;
-                               // }
-                       } else if (!resUrl.startsWith("classpath:")) {
-                               url = new URL(resUrl);
-                       }
-
-                       if (url != null) {
-                               in = url.openStream();
-                               // } else if (resourceLoader != null) {
-                               // Resource res = resourceLoader.getResource(resUrl);
-                               // in = res.getInputStream();
-                               // url = res.getURL();
-                       } else {
-                               throw new ArgeoException(
-                                               "No " + resUrl + " in the classpath," + " make sure the containing" + " package is visible.");
-                       }
-
-                       return IOUtils.toByteArray(in);
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot read CND from " + resUrl, e);
-               } finally {
-                       IOUtils.closeQuietly(in);
-               }
-       }
-
-       /*
-        * UTILITIES
-        */
-       /** Find which OSGi bundle provided the data model resource */
-       protected Bundle findDataModelBundle(String resUrl) {
-               BundleContext bundleContext = bc;
-               if (bundleContext == null)
-                       return null;
-
-               if (resUrl.startsWith("/"))
-                       resUrl = resUrl.substring(1);
-               String pkg = resUrl.substring(0, resUrl.lastIndexOf('/')).replace('/', '.');
-               ServiceReference<PackageAdmin> paSr = bundleContext.getServiceReference(PackageAdmin.class);
-               PackageAdmin packageAdmin = (PackageAdmin) bundleContext.getService(paSr);
-
-               // find exported package
-               ExportedPackage exportedPackage = null;
-               ExportedPackage[] exportedPackages = packageAdmin.getExportedPackages(pkg);
-               if (exportedPackages == null)
-                       throw new ArgeoException("No exported package found for " + pkg);
-               for (ExportedPackage ep : exportedPackages) {
-                       for (Bundle b : ep.getImportingBundles()) {
-                               if (b.getBundleId() == bundleContext.getBundle().getBundleId()) {
-                                       exportedPackage = ep;
-                                       break;
-                               }
-                       }
-               }
-
-               Bundle exportingBundle = null;
-               if (exportedPackage != null) {
-                       exportingBundle = exportedPackage.getExportingBundle();
-               } else {
-                       // assume this is in the same bundle
-                       exportingBundle = bundleContext.getBundle();
-                       // throw new ArgeoException("No OSGi exporting package found for "
-                       // + resUrl);
-               }
-               return exportingBundle;
-       }
-
-}
diff --git a/org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitNodeType.java b/org.argeo.server.jcr/src/org/argeo/jackrabbit/JackrabbitNodeType.java
deleted file mode 100644 (file)
index 5d78514..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-package org.argeo.jackrabbit;
-
-/** The available Jackrabbit node types */
-public enum JackrabbitNodeType {
-       NOT_CONFIGURED, h2, postgresql, memory, localfs;
-}
index e5bb3bce0e3d00d2901febc697e4bd127989497e..3502abd592d71dec2a4deb98f5fd56a0e3d91c78 100644 (file)
@@ -48,12 +48,11 @@ import org.xml.sax.InputSource;
  * Jackrabbit repositories
  */
 public class JackrabbitRepositoryFactory implements RepositoryFactory, ArgeoJcrConstants {
-
        private final static Log log = LogFactory.getLog(JackrabbitRepositoryFactory.class);
 
        private Resource fileRepositoryConfiguration = new ClassPathResource("/org/argeo/jackrabbit/repository-h2.xml");
 
-       @SuppressWarnings({ "rawtypes", "unchecked" })
+       @SuppressWarnings({ "rawtypes" })
        public Repository getRepository(Map parameters) throws RepositoryException {
                // // check if can be found by alias
                // Repository repository = super.getRepository(parameters);
@@ -73,13 +72,10 @@ public class JackrabbitRepositoryFactory implements RepositoryFactory, ArgeoJcrC
                                repository = createRemoteRepository(uri);
                        else if (uri.startsWith("file"))// http, https
                                repository = createFileRepository(uri, parameters);
-                        else if (uri.startsWith("vm")) {
-                        log.warn("URI "
-                        + uri
-                        + " should have been managed by generic JCR repository factory");
-                        repository = getRepositoryByAlias(getAliasFromURI(uri));
-                        }
-                       else
+                       else if (uri.startsWith("vm")) {
+                               log.warn("URI " + uri + " should have been managed by generic JCR repository factory");
+                               repository = getRepositoryByAlias(getAliasFromURI(uri));
+                       } else
                                throw new ArgeoJcrException("Unrecognized URI format " + uri);
 
                }
index 7288cdf4bbea30908e1f813210fe443442f4ff36..89a39496dbdba655ffe567e450f934112a4a2d9b 100644 (file)
@@ -61,7 +61,7 @@ import org.springframework.core.io.ResourceLoader;
  * Wrapper around a Jackrabbit repository which allows to simplify configuration
  * and intercept some actions. It exposes itself as a {@link Repository}.
  */
-@SuppressWarnings("deprecation")
+@Deprecated
 public class JackrabbitWrapper extends JcrRepositoryWrapper implements
                JackrabbitRepository, ResourceLoaderAware {
        private final static Log log = LogFactory.getLog(JackrabbitWrapper.class);
diff --git a/org.argeo.server.jcr/src/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java b/org.argeo.server.jcr/src/org/argeo/jackrabbit/OsgiJackrabbitRepositoryFactory.java
deleted file mode 100644 (file)
index a617ec6..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jackrabbit;
-
-import java.util.Collection;
-import java.util.Hashtable;
-import java.util.Properties;
-
-import javax.jcr.Repository;
-
-import org.argeo.jcr.ArgeoJcrException;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceReference;
-
-/**
- * OSGi-aware Jackrabbit repository factory which can retrieve/publish
- * {@link Repository} as OSGi services.
- */
-public class OsgiJackrabbitRepositoryFactory extends JackrabbitRepositoryFactory {
-       private BundleContext bundleContext;
-
-       @Override
-       protected Repository getRepositoryByAlias(String alias) {
-               try {
-                       Collection<ServiceReference<Repository>> srs = bundleContext.getServiceReferences(Repository.class,
-                                       "(" + JCR_REPOSITORY_ALIAS + "=" + alias + ")");
-                       if (srs.size() == 0)
-                               throw new ArgeoJcrException("No repository with alias " + alias + " found in OSGi registry");
-                       else if (srs.size() > 1)
-                               throw new ArgeoJcrException(
-                                               srs.size() + " repositories with alias " + alias + " found in OSGi registry");
-                       return bundleContext.getService(srs.iterator().next());
-               } catch (InvalidSyntaxException e) {
-                       throw new ArgeoJcrException("Cannot find repository with alias " + alias, e);
-               }
-       }
-
-       protected void publish(String alias, Repository repository, Properties properties) {
-               if (bundleContext != null) {
-                       // do not modify reference
-                       Hashtable<String, String> props = new Hashtable<String, String>();
-                       props.putAll(props);
-                       props.put(JCR_REPOSITORY_ALIAS, alias);
-                       bundleContext.registerService(Repository.class.getName(), repository, props);
-               }
-       }
-
-       public void setBundleContext(BundleContext bundleContext) {
-               this.bundleContext = bundleContext;
-       }
-
-}
diff --git a/org.argeo.server.jcr/src/org/argeo/jcr/MaintainedRepository.java b/org.argeo.server.jcr/src/org/argeo/jcr/MaintainedRepository.java
deleted file mode 100644 (file)
index 702d47a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-package org.argeo.jcr;
-
-import javax.jcr.Repository;
-
-/** Abstracts maintenance operations on a {@link Repository} */
-public interface MaintainedRepository extends Repository {
-
-}
diff --git a/org.argeo.server.jcr/src/org/argeo/jcr/NodeMapper.java b/org.argeo.server.jcr/src/org/argeo/jcr/NodeMapper.java
deleted file mode 100644 (file)
index af792c3..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.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/org.argeo.server.jcr/src/org/argeo/jcr/NodeMapperProvider.java b/org.argeo.server.jcr/src/org/argeo/jcr/NodeMapperProvider.java
deleted file mode 100644 (file)
index 07e623b..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.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);
-}
index 722215701b00f4544f58df0e264e568986349251..56caab0a399ac3c9e0fe769493c8b49b8bb77197 100644 (file)
@@ -126,6 +126,7 @@ public abstract class ThreadBoundJcrSessionFactory {
        }
 
        public void init() throws Exception {
+               log.error("SHOULD NOT BE USED ANYMORE");
                monitoringThread = new MonitoringThread();
                monitoringThread.start();
        }
diff --git a/org.argeo.server.jcr/src/org/argeo/jcr/spring/BeanNodeMapper.java b/org.argeo.server.jcr/src/org/argeo/jcr/spring/BeanNodeMapper.java
deleted file mode 100644 (file)
index e78cee4..0000000
+++ /dev/null
@@ -1,650 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.jcr.spring;
-
-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.Binary;
-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.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.NodeMapper;
-import org.argeo.jcr.NodeMapperProvider;
-import org.springframework.beans.BeanWrapper;
-import org.springframework.beans.BeanWrapperImpl;
-
-@Deprecated
-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, 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 {
-               if (log.isTraceEnabled())
-                       log.trace("Load     " + node);
-
-               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();
-
-                               if (log.isTraceEnabled())
-                                       log.trace("Load " + prop + ", propClass=" + propClass
-                                                       + ", property descriptor=" + pd);
-
-                               // 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>();
-                                       }
-
-                                       if (childNode.hasNodes()) {
-                                               // Look for children nodes
-                                               NodeIterator valuesIt = childNode.getNodes();
-                                               while (valuesIt.hasNext()) {
-                                                       Node lstValueNode = valuesIt.nextNode();
-                                                       Object lstValue = nodeToBean(lstValueNode);
-                                                       lst.add(lstValue);
-                                               }
-                                       } else {
-                                               // look for a property with the same name which will
-                                               // provide
-                                               // primitives
-                                               Property childProp = childNode.getProperty(childNode
-                                                               .getName());
-                                               Class<?> valuesClass = classFromProperty(childProp);
-                                               if (valuesClass != null)
-                                                       if (childProp.getDefinition().isMultiple())
-                                                               for (Value value : childProp.getValues()) {
-                                                                       lst.add(asObject(value, valuesClass));
-                                                               }
-                                                       else
-                                                               lst.add(asObject(childProp.getValue(),
-                                                                               valuesClass));
-                                       }
-                                       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) {
-                       Binary binary = session.getValueFactory().createBinary(
-                                       (InputStream) value);
-                       return valueFactory.createValue(binary);
-               } 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.getBinary().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.getNodeByIdentifier(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;
-       }
-}