]> git.argeo.org Git - lgpl/argeo-commons.git/blob - RepositoryBuilder.java
f866c2b99a346c7884a72193d2eeaa5dd17db349
[lgpl/argeo-commons.git] / 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.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 class RepositoryBuilder {
33 private final static Log log = LogFactory.getLog(RepositoryBuilder.class);
34
35 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/kernel";
58 // switch (type) {
59 // case h2:
60 // in = cl.getResourceAsStream(base + "/repository-h2.xml");
61 // break;
62 // case postgresql:
63 // in = cl.getResourceAsStream(base + "/repository-postgresql.xml");
64 // break;
65 // case postgresql_ds:
66 // in = cl.getResourceAsStream(base + "/repository-postgresql-ds.xml");
67 // break;
68 // case memory:
69 // in = cl.getResourceAsStream(base + "/repository-memory.xml");
70 // break;
71 // case localfs:
72 // in = cl.getResourceAsStream(base + "/repository-localfs.xml");
73 // break;
74 // default:
75 // throw new ArgeoJcrException("Unsupported node type " + type);
76 // }
77 in = cl.getResourceAsStream(base + "/repository-"+type.name()+".xml");
78
79 if (in == null)
80 throw new ArgeoJcrException("Repository configuration not found");
81 InputSource config = new InputSource(in);
82 Properties jackrabbitVars = getConfigurationProperties(type, properties);
83 RepositoryConfig repositoryConfig = RepositoryConfig.create(config, jackrabbitVars);
84 return repositoryConfig;
85 } finally {
86 IOUtils.closeQuietly(in);
87 }
88 }
89
90 private Properties getConfigurationProperties(JackrabbitType type, Dictionary<String, ?> properties) {
91 Properties props = new Properties();
92 for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements();) {
93 String key = keys.nextElement();
94 // if (key.equals(ConfigurationAdmin.SERVICE_FACTORYPID) ||
95 // key.equals(Constants.SERVICE_PID)
96 // || key.equals(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS))
97 // continue keys;
98 // try {
99 // String value = prop(properties, RepoConf.valueOf(key));
100 // if (value != null)
101 props.put(key, properties.get(key));
102 // } catch (IllegalArgumentException e) {
103 // // ignore non RepoConf
104 // // FIXME make it more flexible/extensible
105 // }
106 }
107
108 // home
109 String homeUri = props.getProperty(RepoConf.labeledUri.name());
110 Path homePath;
111 if (homeUri == null) {
112 String cn = props.getProperty(NodeConstants.CN);
113 assert cn != null;
114 homePath = KernelUtils.getOsgiInstancePath(KernelConstants.DIR_REPOS + '/' + cn);
115 } else {
116 try {
117 homePath = Paths.get(new URI(homeUri)).toAbsolutePath();
118 } catch (URISyntaxException e) {
119 throw new CmsException("Invalid repository home URI", e);
120 }
121 }
122 Path rootUuidPath = homePath.resolve("repository/meta/rootUUID");
123 if (!Files.exists(rootUuidPath)) {
124 try {
125 Files.createDirectories(rootUuidPath.getParent());
126 Files.write(rootUuidPath, UUID.randomUUID().toString().getBytes());
127 } catch (IOException e) {
128 log.error("Could not set rootUUID", e);
129 }
130 }
131 File homeDir = homePath.toFile();
132 homeDir.mkdirs();
133 // home cannot be overridden
134 props.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, homePath.toString());
135
136 // common
137 setProp(props, RepoConf.defaultWorkspace);
138 setProp(props, RepoConf.maxPoolSize);
139 // Jackrabbit defaults
140 setProp(props, RepoConf.bundleCacheMB);
141 // See http://wiki.apache.org/jackrabbit/Search
142 setProp(props, RepoConf.extractorPoolSize);
143 setProp(props, RepoConf.searchCacheSize);
144 setProp(props, RepoConf.maxVolatileIndexSize);
145
146 // specific
147 String dburl;
148 switch (type) {
149 case h2:
150 dburl = "jdbc:h2:" + homeDir.getPath() + "/h2/repository";
151 setProp(props, RepoConf.dburl, dburl);
152 setProp(props, RepoConf.dbuser, "sa");
153 setProp(props, RepoConf.dbpassword, "");
154 break;
155 case postgresql:
156 case postgresql_ds:
157 case postgresql_cluster:
158 dburl = "jdbc:postgresql://localhost/demo";
159 setProp(props, RepoConf.dburl, dburl);
160 setProp(props, RepoConf.dbuser, "argeo");
161 setProp(props, RepoConf.dbpassword, "argeo");
162 break;
163 case memory:
164 break;
165 case localfs:
166 break;
167 default:
168 throw new ArgeoJcrException("Unsupported node type " + type);
169 }
170 return props;
171 }
172
173 private void setProp(Properties props, RepoConf key, String def) {
174 Object value = props.get(key.name());
175 if (value == null)
176 value = def;
177 if (value == null)
178 value = key.getDefault();
179 if (value != null)
180 props.put(key.name(), value.toString());
181 }
182
183 private void setProp(Properties props, RepoConf key) {
184 setProp(props, key, null);
185 }
186
187 private String prop(Dictionary<String, ?> properties, RepoConf key) {
188 Object value = properties.get(key.name());
189 if (value == null)
190 return key.getDefault() != null ? key.getDefault().toString() : null;
191 else
192 return value.toString();
193 }
194
195 private RepositoryContext createJackrabbitRepository(RepositoryConfig repositoryConfig) throws RepositoryException {
196 ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
197 Thread.currentThread().setContextClassLoader(RepositoryBuilder.class.getClassLoader());
198 try {
199 long begin = System.currentTimeMillis();
200 //
201 // Actual repository creation
202 //
203 RepositoryContext repositoryContext = RepositoryContext.create(repositoryConfig);
204
205 double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
206 if (log.isTraceEnabled())
207 log.trace(
208 "Created Jackrabbit repository in " + duration + " s, home: " + repositoryConfig.getHomeDir());
209
210 return repositoryContext;
211 } finally {
212 Thread.currentThread().setContextClassLoader(currentContextCl);
213 }
214 }
215
216 }