Make CND import smarter
authorMathieu Baudier <mbaudier@argeo.org>
Thu, 9 Feb 2012 14:13:56 +0000 (14:13 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Thu, 9 Feb 2012 14:13:56 +0000 (14:13 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@5030 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoTypes.java
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryFactory.java
server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java
server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/argeo.cnd

index 82648998b7c1b5c8c5720abdc88b092f87e85b26..9f3fdf1867cafe4442e890abeb3adb2fe2f5ab6f 100644 (file)
@@ -33,11 +33,13 @@ import javax.jcr.Credentials;
 import javax.jcr.LoginException;
 import javax.jcr.NoSuchWorkspaceException;
 import javax.jcr.Node;
+import javax.jcr.NodeIterator;
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
 
+import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -46,7 +48,9 @@ import org.apache.jackrabbit.commons.NamespaceHelper;
 import org.apache.jackrabbit.commons.cnd.CndImporter;
 import org.apache.jackrabbit.core.RepositoryImpl;
 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.security.SystemAuthentication;
 import org.osgi.framework.Bundle;
@@ -77,6 +81,11 @@ public class JackrabbitContainer extends JackrabbitWrapper {
        // 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 = false;
 
        /** Migrations to execute (if not already done) */
        private Set<JackrabbitDataModelMigration> dataModelMigrations = new HashSet<JackrabbitDataModelMigration>();
@@ -143,20 +152,7 @@ public class JackrabbitContainer extends JackrabbitWrapper {
                        // load CND files from classpath or as URL
                        for (String resUrl : cndFiles) {
                                boolean classpath;
-                               // if (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 '/'");
-                               // }
-                               // resUrl = "classpath:" + resUrl;
-                               // classpath = true;
-                               // } else {
-                               // classpath = false;
-                               // }
-
+                               // normalize URL
                                if (resUrl.startsWith("classpath:")) {
                                        resUrl = resUrl.substring("classpath:".length());
                                        classpath = true;
@@ -171,12 +167,6 @@ public class JackrabbitContainer extends JackrabbitWrapper {
                                        classpath = false;
                                }
 
-                               // Resource resource =
-                               // resourceLoader.getResource(resUrl);
-
-                               // = classpath ? new ClassPathResource(resUrl) : new
-                               // UrlResource(resUrl);
-
                                URL url;
                                Bundle dataModelBundle = null;
                                if (classpath) {
@@ -199,10 +189,71 @@ public class JackrabbitContainer extends JackrabbitWrapper {
                                        url = new URL(resUrl);
                                }
 
+                               // check existing data model nodes
+                               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;
+                                       }
+                               }
+
+                               // does nothing if data model already registered
+                               if (dataModel != null && !forceCndImport) {
+                                       if (dataModelBundle != null) {
+                                               String version = dataModel.getProperty(
+                                                               ArgeoNames.ARGEO_DATA_MODEL_VERSION)
+                                                               .getString();
+                                               String dataModelBundleVersion = dataModelBundle
+                                                               .getVersion().toString();
+                                               if (!version.equals(dataModelBundleVersion)) {
+                                                       log.warn("Data model with version "
+                                                                       + dataModelBundleVersion
+                                                                       + " available, current version is "
+                                                                       + version);
+                                               }
+                                       }
+                                       // do not implicitly update
+                                       return;
+                               }
+
                                Reader reader = null;
                                try {
                                        reader = new InputStreamReader(url.openStream());
+                                       // actually imports the CND
                                        CndImporter.registerNodeTypes(reader, session, true);
+
+                                       // 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(url.getPath());
+                                       if (dataModel == null) {
+                                               dataModel = dataModels.addNode(fileName);
+                                               dataModel.addMixin(ArgeoTypes.ARGEO_DATA_MODEL);
+                                               dataModel.setProperty(ArgeoNames.ARGEO_URI, resUrl);
+                                       } else {
+                                               session.getWorkspace().getVersionManager()
+                                                               .checkout(dataModel.getPath());
+                                       }
+                                       if (dataModelBundle != null)
+                                               dataModel.setProperty(
+                                                               ArgeoNames.ARGEO_DATA_MODEL_VERSION,
+                                                               dataModelBundle.getVersion().toString());
+                                       else
+                                               dataModel.setProperty(
+                                                               ArgeoNames.ARGEO_DATA_MODEL_VERSION, "0.0.0");
+                                       JcrUtils.updateLastModified(dataModel);
+                                       session.save();
+                                       session.getWorkspace().getVersionManager()
+                                                       .checkin(dataModel.getPath());
                                } finally {
                                        IOUtils.closeQuietly(reader);
                                }
@@ -419,4 +470,9 @@ public class JackrabbitContainer extends JackrabbitWrapper {
        public void setBundleContext(BundleContext bundleContext) {
                this.bundleContext = bundleContext;
        }
+
+       public void setForceCndImport(Boolean forceCndUpdate) {
+               this.forceCndImport = forceCndUpdate;
+       }
+
 }
index 5d5983c40e4051f505546dd8465f3b44b2641b82..366a1ef6339d714b12a33db18dc71db20f187c15 100644 (file)
@@ -2,6 +2,11 @@ package org.argeo.jcr;
 
 /** JCR related constants */
 public interface ArgeoJcrConstants {
+       public final static String ARGEO_BASE_PATH = "/argeo";
+       public final static String DATA_MODELS_BASE_PATH = ARGEO_BASE_PATH
+                       + "/dataModels";
+       /** The home base path. Not yet configurable */
+       public final static String DEFAULT_HOME_BASE_PATH = "/home";
 
        // parameters (typically for call to a RepositoryFactory)
        public final static String JCR_REPOSITORY_ALIAS = "argeo.jcr.repository.alias";
index f59c97749adc209a99ee9c8432a4beac0ac64c6a..284485fa296c36830b2d643358e8e5c293f3f2d1 100644 (file)
@@ -8,6 +8,9 @@ public interface ArgeoTypes {
        public final static String ARGEO_REMOTE_REPOSITORY = "argeo:remoteRepository";
        public final static String ARGEO_PREFERENCE_NODE = "argeo:preferenceNode";
 
+       // data model
+       public final static String ARGEO_DATA_MODEL = "argeo:dataModel";
+       
        // tabular
        public final static String ARGEO_TABLE = "argeo:table";
        public final static String ARGEO_COLUMN = "argeo:column";
index 25c355467792c1f78bf723838b3437d289f0349a..a2a0a3df1d2d7ce399a334485ec3955e70c9efbf 100644 (file)
@@ -1,6 +1,7 @@
 package org.argeo.jcr;
 
 import java.util.Map;
+import java.util.Properties;
 
 import javax.jcr.Repository;
 import javax.jcr.RepositoryException;
@@ -8,17 +9,33 @@ import javax.jcr.RepositoryFactory;
 
 public class DefaultRepositoryFactory extends DefaultRepositoryRegister
                implements RepositoryFactory, ArgeoJcrConstants {
-//     private final static Log log = LogFactory
-//                     .getLog(DefaultRepositoryFactory.class);
+       // private final static Log log = LogFactory
+       // .getLog(DefaultRepositoryFactory.class);
 
        @SuppressWarnings("rawtypes")
        public Repository getRepository(Map parameters) throws RepositoryException {
                if (parameters.containsKey(JCR_REPOSITORY_ALIAS)) {
                        String alias = parameters.get(JCR_REPOSITORY_ALIAS).toString();
-                       if (getRepositories().containsKey(alias))
-                               return getRepositories().get(alias);
+                       return getRepositoryByAlias(alias);
                }
                return null;
        }
 
+       /**
+        * Retrieve a repository by alias
+        * 
+        * @return the repository registered with alias or null if none
+        */
+       protected Repository getRepositoryByAlias(String alias) {
+               if (getRepositories().containsKey(alias))
+                       return getRepositories().get(alias);
+               else
+                       return null;
+       }
+
+       protected void publish(String alias, Repository repository,
+                       Properties properties) {
+               register(repository, properties);
+       }
+
 }
index cf6b666a5cc5a70ff64c3f14be7192685a887e6d..3a65de567d4316e888adacf8d47e5ae60bd0655e 100644 (file)
@@ -60,8 +60,6 @@ import org.argeo.ArgeoException;
 
 /** Utility methods to simplify common JCR operations. */
 public class JcrUtils implements ArgeoJcrConstants {
-       /** The home base path. Not yet configurable */
-       public final static String DEFAULT_HOME_BASE_PATH = "/home";
 
        private final static Log log = LogFactory.getLog(JcrUtils.class);
 
index 2bd38ca5a6afa7d51c2a7547e4b45b29fcb3f14f..e46aec737c16ef5a2e0f9ac7e259e3f0a7748055 100644 (file)
@@ -9,6 +9,12 @@ mixin
 [argeo:references] > nt:unstructured
 - * (REFERENCE) *
 
+// DATA MODEL
+[argeo:dataModel] > mix:created, mix:lastModified, mix:versionable
+mixin
+- argeo:uri (STRING) m
+- argeo:dataModelVersion (STRING) m
+
 // USER NODES
 // user should be lower case, between 3 and 15 characters long
 [argeo:userHome] > mix:created, mix:lastModified