]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java
Improve JCR remoting
[lgpl/argeo-commons.git] / server / runtime / org.argeo.server.jackrabbit / src / main / java / org / argeo / jackrabbit / JackrabbitContainer.java
index e27a473b5e041cf6bd2baa99ec2df943707e2973..a708aadd1d67a6eada7401b8bcf94d3cf95ff8ad 100644 (file)
@@ -30,11 +30,13 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.UUID;
 import java.util.concurrent.Executor;
 
 import javax.jcr.Credentials;
 import javax.jcr.LoginException;
 import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Node;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -53,6 +55,7 @@ import org.apache.jackrabbit.core.config.RepositoryConfig;
 import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
 import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory;
 import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoNames;
 import org.argeo.jcr.JcrUtils;
 import org.springframework.context.ResourceLoaderAware;
 import org.springframework.core.io.Resource;
@@ -68,16 +71,17 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
        private Log log = LogFactory.getLog(JackrabbitContainer.class);
 
        private Resource configuration;
-       private String homeDirectory;
+       private File homeDirectory;
        private Resource variables;
-       /** cache home */
-       private File home;
 
        private Boolean inMemory = false;
        private String uri = null;
 
+       // wrapped repository
        private Repository repository;
+       private RepositoryConfig repositoryConfig;
 
+       // CND
        private ResourceLoader resourceLoader;
 
        /** Node type definitions in CND format */
@@ -100,7 +104,7 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
                        return;
                }
 
-               repository = createJackrabbitRepository();
+               createJackrabbitRepository();
 
                // migrate if needed
                migrate();
@@ -111,8 +115,8 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
        }
 
        /** Actually creates a new repository. */
-       protected JackrabbitRepository createJackrabbitRepository() {
-               JackrabbitRepository repository;
+       protected void createJackrabbitRepository() {
+               long begin = System.currentTimeMillis();
                try {
                        // remote repository
                        if (uri != null && !uri.trim().equals("")) {
@@ -120,7 +124,7 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
                                params.put(
                                                org.apache.jackrabbit.commons.JcrUtils.REPOSITORY_URI,
                                                uri);
-                               repository = (JackrabbitRepository) new Jcr2davRepositoryFactory()
+                               repository = new Jcr2davRepositoryFactory()
                                                .getRepository(params);
                                if (repository == null)
                                        throw new ArgeoException("Remote Davex repository " + uri
@@ -130,23 +134,24 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
                                // do not perform further initialization since we assume that
                                // the
                                // remote repository has been properly configured
-                               return repository;
+                               return;
                        }
 
                        // local repository
-                       if (inMemory && getHome().exists()) {
-                               FileUtils.deleteDirectory(getHome());
-                               log.warn("Deleted Jackrabbit home directory " + getHome());
+                       if (inMemory && getHomeDirectory().exists()) {
+                               FileUtils.deleteDirectory(getHomeDirectory());
+                               log.warn("Deleted Jackrabbit home directory "
+                                               + getHomeDirectory());
                        }
 
-                       RepositoryConfig config;
                        Properties vars = getConfigurationProperties();
                        InputStream in = configuration.getInputStream();
                        try {
                                vars.put(
                                                RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
-                                               getHome().getCanonicalPath());
-                               config = RepositoryConfig.create(new InputSource(in), vars);
+                                               getHomeDirectory().getCanonicalPath());
+                               repositoryConfig = RepositoryConfig.create(new InputSource(in),
+                                               vars);
                        } catch (Exception e) {
                                throw new RuntimeException("Cannot read configuration", e);
                        } finally {
@@ -154,22 +159,26 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
                        }
 
                        if (inMemory)
-                               repository = new TransientRepository(config);
+                               repository = new TransientRepository(repositoryConfig);
                        else
-                               repository = RepositoryImpl.create(config);
+                               repository = RepositoryImpl.create(repositoryConfig);
 
-                       log.info("Initialized Jackrabbit repository " + repository + " in "
-                                       + getHome() + " with config " + configuration);
-
-                       return repository;
+                       double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
+                       log.info("Initialized Jackrabbit repository in " + duration
+                                       + " s, home: " + getHomeDirectory() + ", config: "
+                                       + configuration);
                } catch (Exception e) {
                        throw new ArgeoException("Cannot create Jackrabbit repository "
-                                       + getHome(), e);
+                                       + getHomeDirectory(), e);
                }
        }
 
        /** Executes migrations, if needed. */
        protected void migrate() {
+               // No migration to perform
+               if (dataModelMigrations.size() == 0)
+                       return;
+
                Boolean restartAndClearCaches = false;
 
                // migrate data
@@ -192,38 +201,65 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
 
                // restart repository
                if (restartAndClearCaches) {
+                       JackrabbitDataModelMigration
+                                       .clearRepositoryCaches(repositoryConfig);
                        ((JackrabbitRepository) repository).shutdown();
-                       JackrabbitDataModelMigration.clearRepositoryCaches(getHome());
-                       repository = createJackrabbitRepository();
+                       createJackrabbitRepository();
+               }
+
+               // set data model version
+               try {
+                       session = login();
+               } catch (RepositoryException e) {
+                       throw new ArgeoException("Cannot login to migrated repository", e);
+               }
+
+               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,
+                                                       dataModelMigration.getTargetVersion());
+                                       session.save();
+                               }
+                       } catch (Exception e) {
+                               log.error("Cannot set model version", e);
+                       }
                }
+               JcrUtils.logoutQuietly(session);
+
        }
 
        /** Lazy init. */
-       protected File getHome() {
-               if (home != null)
-                       return home;
-
+       protected File getHomeDirectory() {
                try {
-                       String osgiData = System.getProperty("osgi.instance.area");
-                       if (osgiData != null)
-                               osgiData = osgiData.substring("file:".length());
-                       String path;
-                       if (homeDirectory == null)
-                               path = "./jackrabbit";
-                       else
-                               path = homeDirectory;
-                       if (path.startsWith(".") && osgiData != null) {
-                               home = new File(osgiData + '/' + path).getCanonicalFile();
-                       } else
-                               home = new File(path).getCanonicalFile();
-                       return home;
-               } catch (Exception e) {
-                       throw new ArgeoException("Cannot define Jackrabbit home based on "
+                       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.mkdirs();
+                                       // will it work if directory is not empty?
+                                       homeDirectory.deleteOnExit();
+                               }
+                       }
+
+                       return homeDirectory.getCanonicalFile();
+               } catch (IOException e) {
+                       throw new ArgeoException("Cannot get canonical file for "
                                        + homeDirectory, e);
                }
        }
 
        public void dispose() throws Exception {
+               long begin = System.currentTimeMillis();
                if (repository != null) {
                        if (repository instanceof JackrabbitRepository)
                                ((JackrabbitRepository) repository).shutdown();
@@ -234,17 +270,20 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
                }
 
                if (inMemory)
-                       if (getHome().exists()) {
-                               FileUtils.deleteDirectory(getHome());
+                       if (getHomeDirectory().exists()) {
+                               FileUtils.deleteDirectory(getHomeDirectory());
                                if (log.isDebugEnabled())
-                                       log.debug("Deleted Jackrabbit home directory " + getHome());
+                                       log.debug("Deleted Jackrabbit home directory "
+                                                       + getHomeDirectory());
                        }
 
+               double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
                if (uri != null && !uri.trim().equals(""))
                        log.info("Destroyed Jackrabbit repository with uri " + uri);
                else
-                       log.info("Destroyed Jackrabbit repository " + repository + " in "
-                                       + getHome() + " with config " + configuration);
+                       log.info("Destroyed Jackrabbit repository in " + duration
+                                       + " s, home: " + getHomeDirectory() + ", config "
+                                       + configuration);
        }
 
        /**
@@ -278,6 +317,13 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
                        }
                        // override with system properties
                        vars.putAll(System.getProperties());
+
+                       if (log.isTraceEnabled()) {
+                               log.trace("Jackrabbit config variables:");
+                               for (Object key : new TreeSet<Object>(vars.keySet()))
+                                       log.trace(key + "=" + vars.getProperty(key.toString()));
+                       }
+
                } catch (IOException e) {
                        throw new ArgeoException("Cannot read configuration properties", e);
                } finally {
@@ -328,15 +374,15 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
 
        // JCR REPOSITORY (delegated)
        public String getDescriptor(String key) {
-               return repository.getDescriptor(key);
+               return getRepository().getDescriptor(key);
        }
 
        public String[] getDescriptorKeys() {
-               return repository.getDescriptorKeys();
+               return getRepository().getDescriptorKeys();
        }
 
        public Session login() throws LoginException, RepositoryException {
-               Session session = repository.login();
+               Session session = getRepository().login();
                processNewSession(session);
                return session;
        }
@@ -346,7 +392,7 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
                        RepositoryException {
                Session session;
                try {
-                       session = repository.login(credentials, workspaceName);
+                       session = getRepository().login(credentials, workspaceName);
                } catch (NoSuchWorkspaceException e) {
                        if (autocreateWorkspaces)
                                session = createWorkspaceAndLogsIn(credentials, workspaceName);
@@ -359,7 +405,7 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
 
        public Session login(Credentials credentials) throws LoginException,
                        RepositoryException {
-               Session session = repository.login(credentials);
+               Session session = getRepository().login(credentials);
                processNewSession(session);
                return session;
        }
@@ -368,7 +414,7 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
                        NoSuchWorkspaceException, RepositoryException {
                Session session;
                try {
-                       session = repository.login(workspaceName);
+                       session = getRepository().login(workspaceName);
                } catch (NoSuchWorkspaceException e) {
                        if (autocreateWorkspaces)
                                session = createWorkspaceAndLogsIn(null, workspaceName);
@@ -379,6 +425,17 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
                return session;
        }
 
+       /** Wraps access to the repository, making sure it is available. */
+       protected Repository getRepository() {
+               if (repository == null) {
+                       throw new ArgeoException(
+                                       "No repository initialized."
+                                                       + " Was the init() method called?"
+                                                       + " The dispose() method should also be called on shutdown.");
+               }
+               return repository;
+       }
+
        protected synchronized void processNewSession(Session session) {
                try {
                        NamespaceHelper namespaceHelper = new NamespaceHelper(session);
@@ -396,10 +453,10 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
                        String workspaceName) throws RepositoryException {
                if (workspaceName == null)
                        throw new ArgeoException("No workspace specified.");
-               Session session = repository.login(credentials);
+               Session session = getRepository().login(credentials);
                session.getWorkspace().createWorkspace(workspaceName);
                session.logout();
-               return repository.login(credentials, workspaceName);
+               return getRepository().login(credentials, workspaceName);
        }
 
        public void setResourceLoader(ResourceLoader resourceLoader) {
@@ -407,23 +464,23 @@ public class JackrabbitContainer implements Repository, ResourceLoaderAware {
        }
 
        public boolean isStandardDescriptor(String key) {
-               return repository.isStandardDescriptor(key);
+               return getRepository().isStandardDescriptor(key);
        }
 
        public boolean isSingleValueDescriptor(String key) {
-               return repository.isSingleValueDescriptor(key);
+               return getRepository().isSingleValueDescriptor(key);
        }
 
        public Value getDescriptorValue(String key) {
-               return repository.getDescriptorValue(key);
+               return getRepository().getDescriptorValue(key);
        }
 
        public Value[] getDescriptorValues(String key) {
-               return repository.getDescriptorValues(key);
+               return getRepository().getDescriptorValues(key);
        }
 
        // BEANS METHODS
-       public void setHomeDirectory(String homeDirectory) {
+       public void setHomeDirectory(File homeDirectory) {
                this.homeDirectory = homeDirectory;
        }