]> git.argeo.org Git - lgpl/argeo-commons.git/blob - ManagedJackrabbitRepository.java
85eff49e8b9653cd5af8280da3ad92d4395ed11e
[lgpl/argeo-commons.git] / ManagedJackrabbitRepository.java
1 package org.argeo.jackrabbit;
2
3 import java.io.File;
4 import java.io.InputStream;
5 import java.util.Dictionary;
6 import java.util.Hashtable;
7 import java.util.Map;
8 import java.util.Properties;
9
10 import javax.jcr.Credentials;
11 import javax.jcr.LoginException;
12 import javax.jcr.NoSuchWorkspaceException;
13 import javax.jcr.RepositoryException;
14 import javax.jcr.Session;
15
16 import org.apache.commons.io.IOUtils;
17 import org.apache.commons.logging.Log;
18 import org.apache.commons.logging.LogFactory;
19 import org.apache.jackrabbit.api.JackrabbitRepository;
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.apache.jackrabbit.stats.RepositoryStatisticsImpl;
26 import org.argeo.ArgeoException;
27 import org.argeo.jcr.ArgeoJcrException;
28 import org.argeo.jcr.JcrRepositoryWrapper;
29 import org.argeo.jcr.RepoConf;
30 import org.osgi.service.cm.ConfigurationException;
31 import org.osgi.service.cm.ManagedService;
32 import org.xml.sax.InputSource;
33
34 public class ManagedJackrabbitRepository extends JcrRepositoryWrapper implements ManagedService, JackrabbitRepository {
35 private final static Log log = LogFactory.getLog(ManagedJackrabbitRepository.class);
36
37 // Node
38 final static String REPO_TYPE = "repoType";
39 // final static String REPO_CONFIGURATION = "argeo.node.repo.configuration";
40 // final static String REPO_DEFAULT_WORKSPACE = "defaultWorkspace";
41 // final static String REPO_DBURL = "dburl";
42 // final static String REPO_DBUSER = "dbuser";
43 // final static String REPO_DBPASSWORD = "dbpassword";
44 // final static String REPO_MAX_POOL_SIZE = "maxPoolSize";
45 // final static String REPO_MAX_CACHE_MB = "maxCacheMB";
46 // final static String REPO_BUNDLE_CACHE_MB = "bundleCacheMB";
47 // final static String REPO_EXTRACTOR_POOL_SIZE = "extractorPoolSize";
48 // final static String REPO_SEARCH_CACHE_SIZE = "searchCacheSize";
49 // final static String REPO_MAX_VOLATILE_INDEX_SIZE =
50 // "maxVolatileIndexSize";
51
52 private Dictionary<String, ?> properties;
53
54 @Override
55 public void updated(Dictionary<String, ?> properties) throws ConfigurationException {
56 this.properties = properties;
57 if (properties == null)
58 return;
59
60 JackrabbitNodeType type = JackrabbitNodeType.valueOf(prop(RepoConf.type).toString());
61 try {
62 repositoryContext = createNode(type);
63 } catch (Exception e) {
64 e.printStackTrace();
65 throw new ArgeoException("Cannot create Jackrabbit repository of type " + type, e);
66 }
67 }
68
69 private RepositoryContext repositoryContext;
70
71 public ManagedJackrabbitRepository() {
72 // setBundleContext(Activator.getBundleContext());
73 // JackrabbitNodeType type = JackrabbitNodeType.valueOf(prop(REPO_TYPE,
74 // JackrabbitNodeType.h2.name()));
75 // try {
76 // repositoryContext = createNode(type);
77 // cndFiles = Arrays.asList(DEFAULT_CNDS);
78 // prepareDataModel();
79 // } catch (Exception e) {
80 // throw new ArgeoException("Cannot create Jackrabbit repository of type
81 // " + type, e);
82 // }
83 }
84
85 public void destroy() {
86 ((RepositoryImpl) getRepository()).shutdown();
87 }
88
89 RepositoryStatisticsImpl getRepositoryStatistics() {
90 return repositoryContext.getRepositoryStatistics();
91 }
92
93 private RepositoryConfig getConfiguration(JackrabbitNodeType type, Hashtable<String, Object> props)
94 throws RepositoryException {
95 ClassLoader cl = getClass().getClassLoader();
96 InputStream in = null;
97 try {
98 final String base = "/org/argeo/jackrabbit";
99 switch (type) {
100 case h2:
101 in = cl.getResourceAsStream(base + "/repository-h2.xml");
102 break;
103 case postgresql:
104 in = cl.getResourceAsStream(base + "/repository-postgresql.xml");
105 break;
106 case memory:
107 in = cl.getResourceAsStream(base + "/repository-memory.xml");
108 break;
109 case localfs:
110 in = cl.getResourceAsStream(base + "/repository-localfs.xml");
111 break;
112 default:
113 throw new ArgeoJcrException("Unsupported node type " + type);
114 }
115
116 if (in == null)
117 throw new ArgeoJcrException("Repository configuration not found");
118 InputSource config = new InputSource(in);
119 Properties jackrabbitVars = new Properties();
120 // convert values to Strings, otherwise they are skipped
121 for (String key : props.keySet())
122 jackrabbitVars.setProperty(key, props.get(key).toString());
123 RepositoryConfig repositoryConfig = RepositoryConfig.create(config, jackrabbitVars);
124 return repositoryConfig;
125 } finally {
126 IOUtils.closeQuietly(in);
127 }
128 }
129
130 private Hashtable<String, Object> getConfigurationProperties(JackrabbitNodeType type) {
131 Hashtable<String, Object> props = new Hashtable<String, Object>();
132
133 // home
134 File osgiInstanceDir = getOsgiInstanceDir();
135 File homeDir = new File(osgiInstanceDir, "repos/node");
136 homeDir.mkdirs();
137 // home cannot be overridden
138 props.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE, homeDir.getAbsolutePath());
139
140 // common
141 setProp(props, RepoConf.defaultWorkspace);
142 setProp(props, RepoConf.maxPoolSize);
143 // Jackrabbit defaults
144 setProp(props, RepoConf.bundleCacheMB);
145 // See http://wiki.apache.org/jackrabbit/Search
146 setProp(props, RepoConf.extractorPoolSize);
147 setProp(props, RepoConf.searchCacheSize);
148 setProp(props, RepoConf.maxVolatileIndexSize);
149
150 // specific
151 String dburl;
152 switch (type) {
153 case h2:
154 dburl = "jdbc:h2:" + homeDir.getPath() + "/h2/repository";
155 setProp(props, RepoConf.dburl, dburl);
156 setProp(props, RepoConf.dbuser, "sa");
157 setProp(props, RepoConf.dbpassword, "");
158 break;
159 case postgresql:
160 dburl = "jdbc:postgresql://localhost/demo";
161 setProp(props, RepoConf.dburl, dburl);
162 setProp(props, RepoConf.dbuser, "argeo");
163 setProp(props, RepoConf.dbpassword, "argeo");
164 break;
165 case memory:
166 break;
167 case localfs:
168 break;
169 default:
170 throw new ArgeoJcrException("Unsupported node type " + type);
171 }
172 return props;
173 }
174
175 private void setProp(Dictionary<String, Object> props, RepoConf key, String def) {
176 Object value = prop(key);
177 if (value == null)
178 value = def;
179 props.put(key.name(), value);
180 }
181
182 private void setProp(Dictionary<String, Object> props, RepoConf key) {
183 setProp(props, key, null);
184 }
185
186 private Object prop(RepoConf key) {
187 if (properties == null)
188 throw new ArgeoJcrException("Properties are not set");
189 Object value = properties.get(key.name());
190 if (value == null)
191 return key.getDefault();
192 else
193 return value;
194 }
195
196 private RepositoryContext createNode(JackrabbitNodeType type) throws RepositoryException {
197 Hashtable<String, Object> props = getConfigurationProperties(type);
198 RepositoryConfig repositoryConfig = getConfiguration(type, props);
199 RepositoryContext repositoryContext = createJackrabbitRepository(repositoryConfig);
200 RepositoryImpl repository = repositoryContext.getRepository();
201
202 // cache
203 Object maxCacheMbStr = prop(RepoConf.maxCacheMB);
204 if (maxCacheMbStr != null) {
205 Integer maxCacheMB = Integer.parseInt(maxCacheMbStr.toString());
206 CacheManager cacheManager = repository.getCacheManager();
207 cacheManager.setMaxMemory(maxCacheMB * 1024l * 1024l);
208 cacheManager.setMaxMemoryPerCache((maxCacheMB / 4) * 1024l * 1024l);
209 }
210
211 // wrap the repository
212 setRepository(repository);
213 return repositoryContext;
214 }
215
216 private RepositoryContext createJackrabbitRepository(RepositoryConfig repositoryConfig) throws RepositoryException {
217 ClassLoader currentContextCl = Thread.currentThread().getContextClassLoader();
218 Thread.currentThread().setContextClassLoader(ManagedJackrabbitRepository.class.getClassLoader());
219 try {
220 long begin = System.currentTimeMillis();
221 //
222 // Actual repository creation
223 //
224 RepositoryContext repositoryContext = RepositoryContext.create(repositoryConfig);
225
226 double duration = ((double) (System.currentTimeMillis() - begin)) / 1000;
227 if (log.isTraceEnabled())
228 log.trace(
229 "Created Jackrabbit repository in " + duration + " s, home: " + repositoryConfig.getHomeDir());
230
231 return repositoryContext;
232 } finally {
233 Thread.currentThread().setContextClassLoader(currentContextCl);
234 }
235 }
236
237 /*
238 * DATA MODEL
239 */
240
241 public synchronized void waitForInit() {
242 while (repositoryContext == null)
243 try {
244 wait(100);
245 } catch (InterruptedException e) {
246 return;
247 }
248 }
249
250 private final static String OSGI_INSTANCE_AREA = "osgi.instance.area";
251
252 private File getOsgiInstanceDir() {
253 String instanceArea = System.getProperty(OSGI_INSTANCE_AREA);
254 return new File(instanceArea.substring("file:".length())).getAbsoluteFile();
255 }
256
257 @Override
258 public Session login(Credentials credentials, String workspaceName, Map<String, Object> attributes)
259 throws LoginException, NoSuchWorkspaceException, RepositoryException {
260 // TODO Auto-generated method stub
261 return null;
262 }
263
264 @Override
265 public void shutdown() {
266 destroy();
267
268 }
269
270 }