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