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