From: Mathieu Baudier Date: Thu, 9 Feb 2012 14:13:56 +0000 (+0000) Subject: Make CND import smarter X-Git-Tag: argeo-commons-2.1.30~1030 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=562975c6208f47789e4d6d4e062a70dfb77e0cf2;p=lgpl%2Fargeo-commons.git Make CND import smarter git-svn-id: https://svn.argeo.org/commons/trunk@5030 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java index 82648998b..9f3fdf186 100644 --- a/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java +++ b/server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java @@ -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 cndFiles = new ArrayList(); + /** + * 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 dataModelMigrations = new HashSet(); @@ -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; + } + } diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java index 5d5983c40..366a1ef63 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoJcrConstants.java @@ -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"; diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoTypes.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoTypes.java index f59c97749..284485fa2 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoTypes.java +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/ArgeoTypes.java @@ -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"; diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryFactory.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryFactory.java index 25c355467..a2a0a3df1 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryFactory.java +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/DefaultRepositoryFactory.java @@ -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); + } + } diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java index cf6b666a5..3a65de567 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/JcrUtils.java @@ -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); diff --git a/server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/argeo.cnd b/server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/argeo.cnd index 2bd38ca5a..e46aec737 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/argeo.cnd +++ b/server/runtime/org.argeo.server.jcr/src/main/resources/org/argeo/jcr/argeo.cnd @@ -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