Use internal classloader for reading Jackrabbit configurations.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / internal / jcr / RepositoryBuilder.java
index ca5dfccb836924e33013c6913fe235cbcda2132d..fbb1e4f7a03f1a380f549b07da5fc952498ba84a 100644 (file)
@@ -1,6 +1,5 @@
 package org.argeo.cms.internal.jcr;
 
-import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
@@ -15,7 +14,6 @@ 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;
@@ -23,17 +21,16 @@ 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.api.NodeConstants;
 import org.argeo.cms.internal.kernel.CmsPaths;
-import org.argeo.jcr.ArgeoJcrException;
-import org.argeo.node.NodeConstants;
 import org.xml.sax.InputSource;
 
 /** Can interpret properties in order to create an actual JCR repository. */
 public class RepositoryBuilder {
        private final static Log log = LogFactory.getLog(RepositoryBuilder.class);
 
-       public RepositoryContext createRepositoryContext(Dictionary<String, ?> properties) throws RepositoryException {
+       public RepositoryContext createRepositoryContext(Dictionary<String, ?> properties)
+                       throws RepositoryException, IOException {
                RepositoryConfig repositoryConfig = createRepositoryConfig(properties);
                RepositoryContext repositoryContext = createJackrabbitRepository(repositoryConfig);
                RepositoryImpl repository = repositoryContext.getRepository();
@@ -50,22 +47,31 @@ public class RepositoryBuilder {
                return repositoryContext;
        }
 
-       RepositoryConfig createRepositoryConfig(Dictionary<String, ?> properties) throws RepositoryException {
+       RepositoryConfig createRepositoryConfig(Dictionary<String, ?> properties) throws RepositoryException, IOException {
                JackrabbitType type = JackrabbitType.valueOf(prop(properties, RepoConf.type).toString());
                ClassLoader cl = getClass().getClassLoader();
-               InputStream in = null;
-               try {
-                       final String base = "/org/argeo/cms/internal/jcr";
-                       in = cl.getResourceAsStream(base + "/repository-" + type.name() + ".xml");
-
+               final String base = "/org/argeo/cms/internal/jcr";
+               try (InputStream in = cl.getResourceAsStream(base + "/repository-" + type.name() + ".xml")) {
                        if (in == null)
-                               throw new ArgeoJcrException("Repository configuration not found");
+                               throw new IllegalArgumentException("Repository configuration not found");
                        InputSource config = new InputSource(in);
                        Properties jackrabbitVars = getConfigurationProperties(type, properties);
-                       RepositoryConfig repositoryConfig = RepositoryConfig.create(config, jackrabbitVars);
+                       // RepositoryConfig repositoryConfig = RepositoryConfig.create(config,
+                       // jackrabbitVars);
+
+                       // custom configuration parser
+                       CustomRepositoryConfigurationParser parser = new CustomRepositoryConfigurationParser(jackrabbitVars);
+                       parser.setClassLoader(cl);
+                       RepositoryConfig repositoryConfig = parser.parseRepositoryConfig(config);
+                       repositoryConfig.init();
+
+                       // set the proper classloaders
+                       repositoryConfig.getSecurityConfig().getSecurityManagerConfig().setClassLoader(cl);
+                       repositoryConfig.getSecurityConfig().getAccessManagerConfig().setClassLoader(cl);
+//                     for (WorkspaceConfig workspaceConfig : repositoryConfig.getWorkspaceConfigs()) {
+//                             workspaceConfig.getSecurityConfig().getAccessControlProviderConfig().setClassLoader(cl);
+//                     }
                        return repositoryConfig;
-               } finally {
-                       IOUtils.closeQuietly(in);
                }
        }
 
@@ -76,31 +82,56 @@ public class RepositoryBuilder {
                        props.put(key, properties.get(key));
                }
 
+               // cluster id
+               // cf. https://wiki.apache.org/jackrabbit/Clustering
+               // TODO deal with multiple repos
+               String clusterId = System.getProperty("org.apache.jackrabbit.core.cluster.node_id");
+               String clusterIdProp = props.getProperty(RepoConf.clusterId.name());
+               if (clusterId != null) {
+                       if (clusterIdProp != null)
+                               throw new IllegalArgumentException("Cluster id defined as System properties and in deploy config");
+                       props.put(RepoConf.clusterId.name(), clusterId);
+               } else {
+                       clusterId = clusterIdProp;
+               }
+
                // home
                String homeUri = props.getProperty(RepoConf.labeledUri.name());
                Path homePath;
                if (homeUri == null) {
                        String cn = props.getProperty(NodeConstants.CN);
                        assert cn != null;
-                       homePath = CmsPaths.getRepoDirPath(cn);
+                       if (clusterId != null) {
+                               homePath = CmsPaths.getRepoDirPath(cn + '/' + clusterId);
+                       } else {
+                               homePath = CmsPaths.getRepoDirPath(cn);
+                       }
                } else {
                        try {
-                               homePath = Paths.get(new URI(homeUri)).toAbsolutePath();
+                               URI uri = new URI(homeUri);
+                               String host = uri.getHost();
+                               if (host == null || host.trim().equals("")) {
+                                       homePath = Paths.get(uri).toAbsolutePath();
+                               } else {
+                                       // TODO remote at this stage?
+                                       throw new IllegalArgumentException("Cannot manage repository path for host " + host);
+                               }
                        } catch (URISyntaxException e) {
-                               throw new CmsException("Invalid repository home URI", e);
+                               throw new IllegalArgumentException("Invalid repository home URI", e);
                        }
                }
+               // TODO use Jackrabbit API (?)
                Path rootUuidPath = homePath.resolve("repository/meta/rootUUID");
-               if (!Files.exists(rootUuidPath)) {
-                       try {
+               try {
+                       if (!Files.exists(rootUuidPath)) {
                                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();
+               } catch (IOException e) {
+                       throw new RuntimeException("Cannot set up repository  home " + homePath, e);
                }
-               File homeDir = homePath.toFile();
-               homeDir.mkdirs();
                // home cannot be overridden
                props.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, homePath.toString());
 
@@ -119,7 +150,13 @@ public class RepositoryBuilder {
                String dburl;
                switch (type) {
                case h2:
-                       dburl = "jdbc:h2:" + homeDir.getPath() + "/h2/repository";
+                       dburl = "jdbc:h2:" + homePath.toAbsolutePath() + "/h2/repository";
+                       setProp(props, RepoConf.dburl, dburl);
+                       setProp(props, RepoConf.dbuser, "sa");
+                       setProp(props, RepoConf.dbpassword, "");
+                       break;
+               case h2_postgresql:
+                       dburl = "jdbc:h2:" + homePath.toAbsolutePath() + "/h2/repository;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE";
                        setProp(props, RepoConf.dburl, dburl);
                        setProp(props, RepoConf.dbuser, "sa");
                        setProp(props, RepoConf.dbpassword, "");
@@ -127,6 +164,7 @@ public class RepositoryBuilder {
                case postgresql:
                case postgresql_ds:
                case postgresql_cluster:
+               case postgresql_cluster_ds:
                        dburl = "jdbc:postgresql://localhost/demo";
                        setProp(props, RepoConf.dburl, dburl);
                        setProp(props, RepoConf.dbuser, "argeo");
@@ -137,7 +175,7 @@ public class RepositoryBuilder {
                case localfs:
                        break;
                default:
-                       throw new ArgeoJcrException("Unsupported node type " + type);
+                       throw new IllegalArgumentException("Unsupported node type " + type);
                }
                return props;
        }
@@ -175,8 +213,8 @@ public class RepositoryBuilder {
                        RepositoryContext repositoryContext = RepositoryContext.create(repositoryConfig);
 
                        double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
-                       if (log.isTraceEnabled())
-                               log.trace(
+                       if (log.isDebugEnabled())
+                               log.debug(
                                                "Created Jackrabbit repository in " + duration + " s, home: " + repositoryConfig.getHomeDir());
 
                        return repositoryContext;