import java.io.ByteArrayInputStream;
import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.io.Reader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
+import java.util.concurrent.Executor;
import javax.jcr.Credentials;
import javax.jcr.LoginException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.jackrabbit.api.JackrabbitRepository;
-import org.apache.jackrabbit.commons.JcrUtils;
import org.apache.jackrabbit.commons.NamespaceHelper;
import org.apache.jackrabbit.commons.cnd.CndImporter;
-import org.apache.jackrabbit.core.RepositoryFactoryImpl;
import org.apache.jackrabbit.core.RepositoryImpl;
import org.apache.jackrabbit.core.TransientRepository;
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.JcrUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
+import org.springframework.util.SystemPropertyUtils;
import org.xml.sax.InputSource;
/**
private ResourceLoader resourceLoader;
/** Node type definitions in CND format */
- private List<byte[]> cnds = new ArrayList<byte[]>();
private List<String> cndFiles = new ArrayList<String>();
/** Namespaces to register: key is prefix, value namespace */
private Boolean autocreateWorkspaces = false;
- public void afterPropertiesSet() throws Exception {
- // Load cnds as resources
- for (String resUrl : cndFiles) {
- Resource res = resourceLoader.getResource(resUrl);
- byte[] arr = IOUtils.toByteArray(res.getInputStream());
- cnds.add(arr);
- }
+ private Executor systemExecutor;
+ private Credentials adminCredentials;
+ public void afterPropertiesSet() throws Exception {
+ // remote repository
if (uri != null && !uri.trim().equals("")) {
Map<String, String> params = new HashMap<String, String>();
- params.put(JcrUtils.REPOSITORY_URI, uri);
+ params.put(org.apache.jackrabbit.commons.JcrUtils.REPOSITORY_URI,
+ uri);
repository = new Jcr2davRepositoryFactory().getRepository(params);
if (repository == null)
throw new ArgeoException("Remote Davex repository " + uri
+ " not found");
log.info("Initialized Jackrabbit repository " + repository
- + " from uri " + uri);
- } else {
- if (inMemory && homeDirectory.exists()) {
- FileUtils.deleteDirectory(homeDirectory);
- log.warn("Deleted Jackrabbit home directory " + homeDirectory);
+ + " from URI " + uri);
+ // do not perform further initialization since we assume that the
+ // remote repository has been properly configured
+ return;
+ }
+
+ // local repository
+ if (inMemory && homeDirectory.exists()) {
+ FileUtils.deleteDirectory(homeDirectory);
+ log.warn("Deleted Jackrabbit home directory " + homeDirectory);
+ }
+
+ RepositoryConfig config;
+ Properties vars = getConfigurationProperties();
+ InputStream in = configuration.getInputStream();
+ try {
+ vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
+ homeDirectory.getCanonicalPath());
+ config = RepositoryConfig.create(new InputSource(in), vars);
+ } catch (Exception e) {
+ throw new RuntimeException("Cannot read configuration", e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+
+ if (inMemory)
+ repository = new TransientRepository(config);
+ else
+ repository = RepositoryImpl.create(config);
+
+ if (cndFiles != null && cndFiles.size() > 0)
+ importNodeTypeDefinitions(repository);
+
+ log.info("Initialized Jackrabbit repository " + repository + " in "
+ + homeDirectory + " with config " + configuration);
+ }
+
+ protected Properties getConfigurationProperties() {
+ InputStream propsIn = null;
+ Properties vars;
+ try {
+ vars = new Properties();
+ if (variables != null) {
+ propsIn = variables.getInputStream();
+ vars.load(propsIn);
+ }
+ // resolve system properties
+ for (Object key : vars.keySet()) {
+ // TODO: implement a smarter mechanism to resolve nested ${}
+ String newValue = SystemPropertyUtils.resolvePlaceholders(vars
+ .getProperty(key.toString()));
+ vars.put(key, newValue);
}
+ // override with system properties
+ vars.putAll(System.getProperties());
+ } catch (IOException e) {
+ throw new ArgeoException("Cannot read configuration properties", e);
+ } finally {
+ IOUtils.closeQuietly(propsIn);
+ }
+ return vars;
+ }
+
+ /**
+ * Import declared node type definitions, trying to update them if they have
+ * changed. In case of failures an error will be logged but no exception
+ * will be thrown.
+ */
+ protected void importNodeTypeDefinitions(final Repository repository) {
+ final Credentials credentialsToUse;
+ if (systemExecutor == null) {
+ if (adminCredentials == null)
+ throw new ArgeoException(
+ "No system executor or admin credentials found");
+ credentialsToUse = adminCredentials;
+ } else {
+ credentialsToUse = null;
+ }
- RepositoryConfig config;
- InputStream in = configuration.getInputStream();
- InputStream propsIn = null;
- try {
- Properties vars = new Properties();
- if (variables != null) {
- propsIn = variables.getInputStream();
- vars.load(propsIn);
+ Runnable action = new Runnable() {
+ public void run() {
+ Reader reader = null;
+ Session session = null;
+ try {
+ session = repository.login(credentialsToUse);
+ processNewSession(session);
+ // Load cnds as resources
+ for (String resUrl : cndFiles) {
+ Resource res = resourceLoader.getResource(resUrl);
+ byte[] arr = IOUtils.toByteArray(res.getInputStream());
+ reader = new InputStreamReader(
+ new ByteArrayInputStream(arr));
+ CndImporter.registerNodeTypes(reader, session, true);
+ }
+ session.save();
+ } catch (Exception e) {
+ log.error(
+ "Cannot import node type definitions " + cndFiles,
+ e);
+ JcrUtils.discardQuietly(session);
+ } finally {
+ IOUtils.closeQuietly(reader);
+ JcrUtils.logoutQuietly(session);
}
- // override with system properties
- vars.putAll(System.getProperties());
- vars.put(
- RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
- homeDirectory.getCanonicalPath());
- config = RepositoryConfig.create(new InputSource(in), vars);
- } catch (Exception e) {
- throw new RuntimeException("Cannot read configuration", e);
- } finally {
- IOUtils.closeQuietly(in);
- IOUtils.closeQuietly(propsIn);
}
+ };
- if (inMemory)
- repository = new TransientRepository(config);
- else
- repository = RepositoryImpl.create(config);
-
- log.info("Initialized Jackrabbit repository " + repository + " in "
- + homeDirectory + " with config " + configuration);
- }
+ if (systemExecutor != null)
+ systemExecutor.execute(action);
+ else
+ action.run();
}
public void destroy() throws Exception {
+ homeDirectory);
}
- if (uri != null)
+ if (uri != null && !uri.trim().equals(""))
log.info("Destroyed Jackrabbit repository with uri " + uri);
else
log.info("Destroyed Jackrabbit repository " + repository + " in "
NamespaceHelper namespaceHelper = new NamespaceHelper(session);
namespaceHelper.registerNamespaces(namespaces);
- for (byte[] arr : cnds)
- CndImporter.registerNodeTypes(new InputStreamReader(
- new ByteArrayInputStream(arr)), session, true);
} catch (Exception e) {
throw new ArgeoException("Cannot process new session", e);
}
this.uri = uri;
}
+ public void setSystemExecutor(Executor systemExecutor) {
+ this.systemExecutor = systemExecutor;
+ }
+
+ public void setAdminCredentials(Credentials adminCredentials) {
+ this.adminCredentials = adminCredentials;
+ }
+
}