]> git.argeo.org Git - lgpl/argeo-commons.git/blob - RepositoryBuilder.java
622600d3ce6ba6fe5f34198247ed850eb349e30c
[lgpl/argeo-commons.git] / RepositoryBuilder.java
1 package org.argeo.cms.internal.jcr;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.net.URI;
6 import java.net.URISyntaxException;
7 import java.nio.file.Files;
8 import java.nio.file.Path;
9 import java.nio.file.Paths;
10 import java.util.Dictionary;
11 import java.util.Enumeration;
12 import java.util.Properties;
13 import java.util.UUID;
14
15 import javax.jcr.RepositoryException;
16
17 import org.apache.commons.io.IOUtils;
18 import org.apache.commons.logging.Log;
19 import org.apache.commons.logging.LogFactory;
20 import org.apache.jackrabbit.core.RepositoryContext;
21 import org.apache.jackrabbit.core.RepositoryImpl;
22 import org.apache.jackrabbit.core.cache.CacheManager;
23 import org.apache.jackrabbit.core.config.RepositoryConfig;
24 import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
25 import org.argeo.cms.CmsException;
26 import org.argeo.cms.internal.kernel.CmsPaths;
27 import org.argeo.jcr.ArgeoJcrException;
28 import org.argeo.node.NodeConstants;
29 import org.xml.sax.InputSource;
30
31 /** Can interpret properties in order to create an actual JCR repository. */
32 public class RepositoryBuilder {
33 private final static Log log = LogFactory.getLog(RepositoryBuilder.class);
34
35 public RepositoryContext createRepositoryContext(Dictionary<String, ?> properties) throws RepositoryException {
36 RepositoryConfig repositoryConfig = createRepositoryConfig(properties);
37 RepositoryContext repositoryContext = createJackrabbitRepository(repositoryConfig);
38 RepositoryImpl repository = repositoryContext.getRepository();
39
40 // cache
41 Object maxCacheMbStr = prop(properties, RepoConf.maxCacheMB);
42 if (maxCacheMbStr != null) {
43 Integer maxCacheMB = Integer.parseInt(maxCacheMbStr.toString());
44 CacheManager cacheManager = repository.getCacheManager();
45 cacheManager.setMaxMemory(maxCacheMB * 1024l * 1024l);
46 cacheManager.setMaxMemoryPerCache((maxCacheMB / 4) * 1024l * 1024l);
47 }
48
49 return repositoryContext;
50 }
51
52 RepositoryConfig createRepositoryConfig(Dictionary<String, ?> properties) throws RepositoryException {
53 JackrabbitType type = JackrabbitType.valueOf(prop(properties, RepoConf.type).toString());
54 ClassLoader cl = getClass().getClassLoader();
55 InputStream in = null;
56 try {
57 final String base = "/org/argeo/cms/internal/jcr";
58 in = cl.getResourceAsStream(base + "/repository-" + type.name() + ".xml");
59
60 if (in == null)
61 throw new ArgeoJcrException("Repository configuration not found");
62 InputSource config = new InputSource(in);
63 Properties jackrabbitVars = getConfigurationProperties(type, properties);
64 RepositoryConfig repositoryConfig = RepositoryConfig.create(config, jackrabbitVars);
65 return repositoryConfig;
66 } finally {
67 IOUtils.closeQuietly(in);
68 }
69 }
70
71 private Properties getConfigurationProperties(JackrabbitType type, Dictionary<String, ?> properties) {
72 Properties props = new Properties();
73 for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements();) {
74 String key = keys.nextElement();
75 props.put(key, properties.get(key));
76 }
77
78 // cluster id
79 // cf. https://wiki.apache.org/jackrabbit/Clustering
80 // TODO deal with multiple repos
81 String clusterId = System.getProperty("org.apache.jackrabbit.core.cluster.node_id");
82 String clusterIdProp = props.getProperty(RepoConf.clusterId.name());
83 if (clusterId != null) {
84 if (clusterIdProp != null)
85 throw new CmsException("Cluster id defined as System properties and in deploy config");
86 props.put(RepoConf.clusterId.name(), clusterId);
87 } else {
88 clusterId = clusterIdProp;
89 }
90
91 // home
92 String homeUri = props.getProperty(RepoConf.labeledUri.name());
93 Path homePath;
94 if (homeUri == null) {
95 String cn = props.getProperty(NodeConstants.CN);
96 assert cn != null;
97 if (clusterId != null) {
98 homePath = CmsPaths.getRepoDirPath(cn + '/' + clusterId);
99 } else {
100 homePath = CmsPaths.getRepoDirPath(cn);
101 }
102 } else {
103 try {
104 homePath = Paths.get(new URI(homeUri)).toAbsolutePath();
105 } catch (URISyntaxException e) {
106 throw new CmsException("Invalid repository home URI", e);
107 }
108 }
109 // TODO use Jackrabbit API (?)
110 Path rootUuidPath = homePath.resolve("repository/meta/rootUUID");
111 try {
112 if (!Files.exists(rootUuidPath)) {
113 Files.createDirectories(rootUuidPath.getParent());
114 Files.write(rootUuidPath, UUID.randomUUID().toString().getBytes());
115 }
116 // File homeDir = homePath.toFile();
117 // homeDir.mkdirs();
118 } catch (IOException e) {
119 throw new CmsException("Cannot set up repository home " + homePath, e);
120 }
121 // home cannot be overridden
122 props.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, homePath.toString());
123
124 setProp(props, RepoConf.indexesBase, CmsPaths.getRepoIndexesBase().toString());
125 // common
126 setProp(props, RepoConf.defaultWorkspace);
127 setProp(props, RepoConf.maxPoolSize);
128 // Jackrabbit defaults
129 setProp(props, RepoConf.bundleCacheMB);
130 // See http://wiki.apache.org/jackrabbit/Search
131 setProp(props, RepoConf.extractorPoolSize);
132 setProp(props, RepoConf.searchCacheSize);
133 setProp(props, RepoConf.maxVolatileIndexSize);
134
135 // specific
136 String dburl;
137 switch (type) {
138 case h2:
139 dburl = "jdbc:h2:" + homePath.toAbsolutePath() + "/h2/repository";
140 setProp(props, RepoConf.dburl, dburl);
141 setProp(props, RepoConf.dbuser, "sa");
142 setProp(props, RepoConf.dbpassword, "");
143 break;
144 case postgresql:
145 case postgresql_ds:
146 case postgresql_cluster:
147 case postgresql_cluster_ds:
148 dburl = "jdbc:postgresql://localhost/demo";
149 setProp(props, RepoConf.dburl, dburl);
150 setProp(props, RepoConf.dbuser, "argeo");
151 setProp(props, RepoConf.dbpassword, "argeo");
152 break;
153 case memory:
154 break;
155 case localfs:
156 break;
157 default:
158 throw new ArgeoJcrException("Unsupported node type " + type);
159 }
160 return props;
161 }
162
163 private void setProp(Properties props, RepoConf key, String def) {
164 Object value = props.get(key.name());
165 if (value == null)
166 value = def;
167 if (value == null)
168 value = key.getDefault();
169 if (value != null)
170 props.put(key.name(), value.toString());
171 }
172
173 private void setProp(Properties props, RepoConf key) {
174 setProp(props, key, null);
175 }
176
177 private String prop(Dictionary<String, ?> properties, RepoConf key) {
178 Object value = properties.get(key.name());
179 if (value == null)
180 return key.getDefault() != null ? key.getDefault().toString() : null;
181 else
182 return value.toString();
183 }
184
185 private RepositoryContext createJackrabbitRepository(RepositoryConfig repositoryConfig) throws RepositoryException {
186 ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
187 Thread.currentThread().setContextClassLoader(RepositoryBuilder.class.getClassLoader());
188 try {
189 long begin = System.currentTimeMillis();
190 //
191 // Actual repository creation
192 //
193 RepositoryContext repositoryContext = RepositoryContext.create(repositoryConfig);
194
195 double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
196 if (log.isTraceEnabled())
197 log.trace(
198 "Created Jackrabbit repository in " + duration + " s, home: " + repositoryConfig.getHomeDir());
199
200 return repositoryContext;
201 } finally {
202 Thread.currentThread().setContextClassLoader(currentContextCl);
203 }
204 }
205
206 }