]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - org.argeo.server.jcr/src/org/argeo/jackrabbit/ManagedJackrabbitRepository.java
Use OSGi Configuration Manager for node's Jackrabbit repository
[lgpl/argeo-commons.git] / org.argeo.server.jcr / src / org / argeo / jackrabbit / ManagedJackrabbitRepository.java
diff --git a/org.argeo.server.jcr/src/org/argeo/jackrabbit/ManagedJackrabbitRepository.java b/org.argeo.server.jcr/src/org/argeo/jackrabbit/ManagedJackrabbitRepository.java
new file mode 100644 (file)
index 0000000..2ec8693
--- /dev/null
@@ -0,0 +1,263 @@
+package org.argeo.jackrabbit;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.jcr.Credentials;
+import javax.jcr.LoginException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.api.JackrabbitRepository;
+import org.apache.jackrabbit.core.RepositoryContext;
+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.apache.jackrabbit.stats.RepositoryStatisticsImpl;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.ArgeoJcrException;
+import org.argeo.jcr.JcrRepositoryWrapper;
+import org.argeo.jcr.RepoConf;
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.cm.ManagedService;
+import org.xml.sax.InputSource;
+
+public class ManagedJackrabbitRepository extends JcrRepositoryWrapper implements ManagedService, JackrabbitRepository {
+       private final static Log log = LogFactory.getLog(ManagedJackrabbitRepository.class);
+
+       // Node
+       final static String REPO_TYPE = "repoType";
+       // final static String REPO_CONFIGURATION = "argeo.node.repo.configuration";
+       // final static String REPO_DEFAULT_WORKSPACE = "defaultWorkspace";
+       // final static String REPO_DBURL = "dburl";
+       // final static String REPO_DBUSER = "dbuser";
+       // final static String REPO_DBPASSWORD = "dbpassword";
+       // final static String REPO_MAX_POOL_SIZE = "maxPoolSize";
+       // final static String REPO_MAX_CACHE_MB = "maxCacheMB";
+       // final static String REPO_BUNDLE_CACHE_MB = "bundleCacheMB";
+       // final static String REPO_EXTRACTOR_POOL_SIZE = "extractorPoolSize";
+       // final static String REPO_SEARCH_CACHE_SIZE = "searchCacheSize";
+       // final static String REPO_MAX_VOLATILE_INDEX_SIZE =
+       // "maxVolatileIndexSize";
+
+       private Dictionary<String, ?> properties;
+
+       @Override
+       public void updated(Dictionary<String, ?> properties) throws ConfigurationException {
+               this.properties = properties;
+               if (properties == null)
+                       return;
+
+               JackrabbitNodeType type = JackrabbitNodeType.valueOf(prop(RepoConf.type).toString());
+               try {
+                       repositoryContext = createNode(type);
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       throw new ArgeoException("Cannot create Jackrabbit repository of type " + type, e);
+               }
+       }
+
+       private RepositoryContext repositoryContext;
+
+       public ManagedJackrabbitRepository() {
+               // setBundleContext(Activator.getBundleContext());
+               // JackrabbitNodeType type = JackrabbitNodeType.valueOf(prop(REPO_TYPE,
+               // JackrabbitNodeType.h2.name()));
+               // try {
+               // repositoryContext = createNode(type);
+               // cndFiles = Arrays.asList(DEFAULT_CNDS);
+               // prepareDataModel();
+               // } catch (Exception e) {
+               // throw new ArgeoException("Cannot create Jackrabbit repository of type
+               // " + type, e);
+               // }
+       }
+
+       public void destroy() {
+               ((RepositoryImpl) getRepository()).shutdown();
+       }
+
+       RepositoryStatisticsImpl getRepositoryStatistics() {
+               return repositoryContext.getRepositoryStatistics();
+       }
+
+       private RepositoryConfig getConfiguration(JackrabbitNodeType type, Hashtable<String, Object> props)
+                       throws RepositoryException {
+               ClassLoader cl = getClass().getClassLoader();
+               InputStream in = null;
+               try {
+                       final String base = "/org/argeo/jackrabbit";
+                       switch (type) {
+                       case h2:
+                               in = cl.getResourceAsStream(base + "/repository-h2.xml");
+                               break;
+                       case postgresql:
+                               in = cl.getResourceAsStream(base + "/repository-postgresql.xml");
+                               break;
+                       case memory:
+                               in = cl.getResourceAsStream(base + "/repository-memory.xml");
+                               break;
+                       case localfs:
+                               in = cl.getResourceAsStream(base + "/repository-localfs.xml");
+                               break;
+                       default:
+                               throw new ArgeoJcrException("Unsupported node type " + type);
+                       }
+
+                       if (in == null)
+                               throw new ArgeoJcrException("Repository configuration not found");
+                       InputSource config = new InputSource(in);
+                       Properties jackrabbitVars = new Properties();
+                       // convert values to Strings, otherwise they are skipped
+                       for (String key : props.keySet())
+                               jackrabbitVars.setProperty(key, props.get(key).toString());
+                       RepositoryConfig repositoryConfig = RepositoryConfig.create(config, jackrabbitVars);
+                       return repositoryConfig;
+               } finally {
+                       IOUtils.closeQuietly(in);
+               }
+       }
+
+       private Hashtable<String, Object> getConfigurationProperties(JackrabbitNodeType type) {
+               Hashtable<String, Object> props = new Hashtable<String, Object>();
+
+               // home
+               File osgiInstanceDir = getOsgiInstanceDir();
+               File homeDir = new File(osgiInstanceDir, "repos/node");
+               homeDir.mkdirs();
+               // home cannot be overridden
+               props.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, homeDir.getAbsolutePath());
+
+               // common
+               setProp(props, RepoConf.defaultWorkspace);
+               setProp(props, RepoConf.maxPoolSize);
+               // Jackrabbit defaults
+               setProp(props, RepoConf.bundleCacheMB);
+               // See http://wiki.apache.org/jackrabbit/Search
+               setProp(props, RepoConf.extractorPoolSize);
+               setProp(props, RepoConf.searchCacheSize);
+               setProp(props, RepoConf.maxVolatileIndexSize);
+
+               // specific
+               String dburl;
+               switch (type) {
+               case h2:
+                       dburl = "jdbc:h2:" + homeDir.getPath() + "/h2/repository";
+                       setProp(props, RepoConf.dburl, dburl);
+                       setProp(props, RepoConf.dbuser, "sa");
+                       setProp(props, RepoConf.dbpassword, "");
+                       break;
+               case postgresql:
+                       dburl = "jdbc:postgresql://localhost/demo";
+                       setProp(props, RepoConf.dburl, dburl);
+                       setProp(props, RepoConf.dbuser, "argeo");
+                       setProp(props, RepoConf.dbpassword, "argeo");
+                       break;
+               case memory:
+                       break;
+               case localfs:
+                       break;
+               default:
+                       throw new ArgeoJcrException("Unsupported node type " + type);
+               }
+               return props;
+       }
+
+       private void setProp(Dictionary<String, Object> props, RepoConf key, String def) {
+               Object value = prop(key);
+               if (value == null)
+                       value = def;
+               props.put(key.name(), value);
+       }
+
+       private void setProp(Dictionary<String, Object> props, RepoConf key) {
+               setProp(props, key, null);
+       }
+
+       private Object prop(RepoConf key) {
+               if (properties == null)
+                       throw new ArgeoJcrException("Properties are not set");
+               Object value = properties.get(key.name());
+               if (value == null)
+                       return key.getDefault();
+               else
+                       return value;
+       }
+
+       private RepositoryContext createNode(JackrabbitNodeType type) throws RepositoryException {
+               Hashtable<String, Object> props = getConfigurationProperties(type);
+               RepositoryConfig repositoryConfig = getConfiguration(type, props);
+               RepositoryContext repositoryContext = createJackrabbitRepository(repositoryConfig);
+               RepositoryImpl repository = repositoryContext.getRepository();
+
+               // cache
+               Object maxCacheMbStr = prop(RepoConf.maxCacheMB);
+               if (maxCacheMbStr != null) {
+                       Integer maxCacheMB = Integer.parseInt(maxCacheMbStr.toString());
+                       CacheManager cacheManager = repository.getCacheManager();
+                       cacheManager.setMaxMemory(maxCacheMB * 1024l * 1024l);
+                       cacheManager.setMaxMemoryPerCache((maxCacheMB / 4) * 1024l * 1024l);
+               }
+
+               // wrap the repository
+               setRepository(repository);
+               return repositoryContext;
+       }
+
+       private RepositoryContext createJackrabbitRepository(RepositoryConfig repositoryConfig) throws RepositoryException {
+               long begin = System.currentTimeMillis();
+               //
+               // Actual repository creation
+               //
+               RepositoryContext repositoryContext = RepositoryContext.create(repositoryConfig);
+
+               double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
+               if (log.isTraceEnabled())
+                       log.trace("Created Jackrabbit repository in " + duration + " s, home: " + repositoryConfig.getHomeDir());
+
+               return repositoryContext;
+       }
+
+       /*
+        * DATA MODEL
+        */
+
+       public synchronized void waitForInit() {
+               while (repositoryContext == null)
+                       try {
+                               wait(100);
+                       } catch (InterruptedException e) {
+                               return;
+                       }
+       }
+
+       private final static String OSGI_INSTANCE_AREA = "osgi.instance.area";
+
+       private File getOsgiInstanceDir() {
+               String instanceArea = System.getProperty(OSGI_INSTANCE_AREA);
+               return new File(instanceArea.substring("file:".length())).getAbsoluteFile();
+       }
+
+       @Override
+       public Session login(Credentials credentials, String workspaceName, Map<String, Object> attributes)
+                       throws LoginException, NoSuchWorkspaceException, RepositoryException {
+               // TODO Auto-generated method stub
+               return null;
+       }
+
+       @Override
+       public void shutdown() {
+               destroy();
+
+       }
+
+}