]> git.argeo.org Git - lgpl/argeo-commons.git/blob - internal/jcr/RepositoryBuilder.java
Prepare next development cycle
[lgpl/argeo-commons.git] / internal / jcr / 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.logging.Log;
18 import org.apache.commons.logging.LogFactory;
19 import org.apache.jackrabbit.core.RepositoryContext;
20 import org.apache.jackrabbit.core.RepositoryImpl;
21 import org.apache.jackrabbit.core.cache.CacheManager;
22 import org.apache.jackrabbit.core.config.RepositoryConfig;
23 import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
24 import org.argeo.api.NodeConstants;
25 import org.argeo.cms.CmsException;
26 import org.argeo.cms.internal.kernel.CmsPaths;
27 import org.argeo.jcr.ArgeoJcrException;
28 import org.xml.sax.InputSource;
29
30 /** Can interpret properties in order to create an actual JCR repository. */
31 public class RepositoryBuilder {
32 private final static Log log = LogFactory.getLog(RepositoryBuilder.class);
33
34 public RepositoryContext createRepositoryContext(Dictionary<String, ?> properties)
35 throws RepositoryException, IOException {
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, IOException {
53 JackrabbitType type = JackrabbitType.valueOf(prop(properties, RepoConf.type).toString());
54 ClassLoader cl = getClass().getClassLoader();
55 final String base = "/org/argeo/cms/internal/jcr";
56 try (InputStream in = cl.getResourceAsStream(base + "/repository-" + type.name() + ".xml")) {
57 if (in == null)
58 throw new ArgeoJcrException("Repository configuration not found");
59 InputSource config = new InputSource(in);
60 Properties jackrabbitVars = getConfigurationProperties(type, properties);
61 // RepositoryConfig repositoryConfig = RepositoryConfig.create(config,
62 // jackrabbitVars);
63
64 // custom configuration parser
65 CustomRepositoryConfigurationParser parser = new CustomRepositoryConfigurationParser(jackrabbitVars);
66 parser.setAccessControlProviderClassLoader(cl);
67 RepositoryConfig repositoryConfig = parser.parseRepositoryConfig(config);
68 repositoryConfig.init();
69
70 // set the proper classloaders
71 repositoryConfig.getSecurityConfig().getSecurityManagerConfig().setClassLoader(cl);
72 repositoryConfig.getSecurityConfig().getAccessManagerConfig().setClassLoader(cl);
73 // for (WorkspaceConfig workspaceConfig : repositoryConfig.getWorkspaceConfigs()) {
74 // workspaceConfig.getSecurityConfig().getAccessControlProviderConfig().setClassLoader(cl);
75 // }
76 return repositoryConfig;
77 }
78 }
79
80 private Properties getConfigurationProperties(JackrabbitType type, Dictionary<String, ?> properties) {
81 Properties props = new Properties();
82 for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements();) {
83 String key = keys.nextElement();
84 props.put(key, properties.get(key));
85 }
86
87 // cluster id
88 // cf. https://wiki.apache.org/jackrabbit/Clustering
89 // TODO deal with multiple repos
90 String clusterId = System.getProperty("org.apache.jackrabbit.core.cluster.node_id");
91 String clusterIdProp = props.getProperty(RepoConf.clusterId.name());
92 if (clusterId != null) {
93 if (clusterIdProp != null)
94 throw new CmsException("Cluster id defined as System properties and in deploy config");
95 props.put(RepoConf.clusterId.name(), clusterId);
96 } else {
97 clusterId = clusterIdProp;
98 }
99
100 // home
101 String homeUri = props.getProperty(RepoConf.labeledUri.name());
102 Path homePath;
103 if (homeUri == null) {
104 String cn = props.getProperty(NodeConstants.CN);
105 assert cn != null;
106 if (clusterId != null) {
107 homePath = CmsPaths.getRepoDirPath(cn + '/' + clusterId);
108 } else {
109 homePath = CmsPaths.getRepoDirPath(cn);
110 }
111 } else {
112 try {
113 URI uri = new URI(homeUri);
114 String host = uri.getHost();
115 if (host == null || host.trim().equals("")) {
116 homePath = Paths.get(uri).toAbsolutePath();
117 } else {
118 // TODO remote at this stage?
119 throw new IllegalArgumentException("Cannot manage repository path for host " + host);
120 }
121 } catch (URISyntaxException e) {
122 throw new CmsException("Invalid repository home URI", e);
123 }
124 }
125 // TODO use Jackrabbit API (?)
126 Path rootUuidPath = homePath.resolve("repository/meta/rootUUID");
127 try {
128 if (!Files.exists(rootUuidPath)) {
129 Files.createDirectories(rootUuidPath.getParent());
130 Files.write(rootUuidPath, UUID.randomUUID().toString().getBytes());
131 }
132 // File homeDir = homePath.toFile();
133 // homeDir.mkdirs();
134 } catch (IOException e) {
135 throw new CmsException("Cannot set up repository home " + homePath, e);
136 }
137 // home cannot be overridden
138 props.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, homePath.toString());
139
140 setProp(props, RepoConf.indexesBase, CmsPaths.getRepoIndexesBase().toString());
141 // common
142 setProp(props, RepoConf.defaultWorkspace);
143 setProp(props, RepoConf.maxPoolSize);
144 // Jackrabbit defaults
145 setProp(props, RepoConf.bundleCacheMB);
146 // See http://wiki.apache.org/jackrabbit/Search
147 setProp(props, RepoConf.extractorPoolSize);
148 setProp(props, RepoConf.searchCacheSize);
149 setProp(props, RepoConf.maxVolatileIndexSize);
150
151 // specific
152 String dburl;
153 switch (type) {
154 case h2:
155 dburl = "jdbc:h2:" + homePath.toAbsolutePath() + "/h2/repository";
156 setProp(props, RepoConf.dburl, dburl);
157 setProp(props, RepoConf.dbuser, "sa");
158 setProp(props, RepoConf.dbpassword, "");
159 break;
160 case postgresql:
161 case postgresql_ds:
162 case postgresql_cluster:
163 case postgresql_cluster_ds:
164 dburl = "jdbc:postgresql://localhost/demo";
165 setProp(props, RepoConf.dburl, dburl);
166 setProp(props, RepoConf.dbuser, "argeo");
167 setProp(props, RepoConf.dbpassword, "argeo");
168 break;
169 case memory:
170 break;
171 case localfs:
172 break;
173 default:
174 throw new ArgeoJcrException("Unsupported node type " + type);
175 }
176 return props;
177 }
178
179 private void setProp(Properties props, RepoConf key, String def) {
180 Object value = props.get(key.name());
181 if (value == null)
182 value = def;
183 if (value == null)
184 value = key.getDefault();
185 if (value != null)
186 props.put(key.name(), value.toString());
187 }
188
189 private void setProp(Properties props, RepoConf key) {
190 setProp(props, key, null);
191 }
192
193 private String prop(Dictionary<String, ?> properties, RepoConf key) {
194 Object value = properties.get(key.name());
195 if (value == null)
196 return key.getDefault() != null ? key.getDefault().toString() : null;
197 else
198 return value.toString();
199 }
200
201 private RepositoryContext createJackrabbitRepository(RepositoryConfig repositoryConfig) throws RepositoryException {
202 ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
203 Thread.currentThread().setContextClassLoader(RepositoryBuilder.class.getClassLoader());
204 try {
205 long begin = System.currentTimeMillis();
206 //
207 // Actual repository creation
208 //
209 RepositoryContext repositoryContext = RepositoryContext.create(repositoryConfig);
210
211 double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
212 if (log.isDebugEnabled())
213 log.debug(
214 "Created Jackrabbit repository in " + duration + " s, home: " + repositoryConfig.getHomeDir());
215
216 return repositoryContext;
217 } finally {
218 Thread.currentThread().setContextClassLoader(currentContextCl);
219 }
220 }
221
222 }