]> git.argeo.org Git - lgpl/argeo-commons.git/blob - server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/JackrabbitContainer.java
Add web dav support
[lgpl/argeo-commons.git] / server / runtime / org.argeo.server.jackrabbit / src / main / java / org / argeo / jackrabbit / JackrabbitContainer.java
1 /*
2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.argeo.jackrabbit;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.File;
21 import java.io.InputStream;
22 import java.io.InputStreamReader;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Properties;
28
29 import javax.jcr.Credentials;
30 import javax.jcr.LoginException;
31 import javax.jcr.NoSuchWorkspaceException;
32 import javax.jcr.Repository;
33 import javax.jcr.RepositoryException;
34 import javax.jcr.Session;
35 import javax.jcr.Value;
36
37 import org.apache.commons.io.FileUtils;
38 import org.apache.commons.io.IOUtils;
39 import org.apache.commons.logging.Log;
40 import org.apache.commons.logging.LogFactory;
41 import org.apache.jackrabbit.api.JackrabbitRepository;
42 import org.apache.jackrabbit.commons.JcrUtils;
43 import org.apache.jackrabbit.commons.NamespaceHelper;
44 import org.apache.jackrabbit.commons.cnd.CndImporter;
45 import org.apache.jackrabbit.core.RepositoryFactoryImpl;
46 import org.apache.jackrabbit.core.RepositoryImpl;
47 import org.apache.jackrabbit.core.TransientRepository;
48 import org.apache.jackrabbit.core.config.RepositoryConfig;
49 import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
50 import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory;
51 import org.argeo.ArgeoException;
52 import org.springframework.beans.factory.DisposableBean;
53 import org.springframework.beans.factory.InitializingBean;
54 import org.springframework.context.ResourceLoaderAware;
55 import org.springframework.core.io.Resource;
56 import org.springframework.core.io.ResourceLoader;
57 import org.xml.sax.InputSource;
58
59 /**
60 * Wrapper around a Jackrabbit repository which allows to configure it in Spring
61 * and expose it as a {@link Repository}.
62 */
63 public class JackrabbitContainer implements InitializingBean, DisposableBean,
64 Repository, ResourceLoaderAware {
65 private Log log = LogFactory.getLog(JackrabbitContainer.class);
66
67 private Resource configuration;
68 private File homeDirectory;
69 private Resource variables;
70
71 private Boolean inMemory = false;
72 private String uri = null;
73
74 private Repository repository;
75
76 private ResourceLoader resourceLoader;
77
78 /** Node type definitions in CND format */
79 private List<byte[]> cnds = new ArrayList<byte[]>();
80 private List<String> cndFiles = new ArrayList<String>();
81
82 /** Namespaces to register: key is prefix, value namespace */
83 private Map<String, String> namespaces = new HashMap<String, String>();
84
85 private Boolean autocreateWorkspaces = false;
86
87 public void afterPropertiesSet() throws Exception {
88 // Load cnds as resources
89 for (String resUrl : cndFiles) {
90 Resource res = resourceLoader.getResource(resUrl);
91 byte[] arr = IOUtils.toByteArray(res.getInputStream());
92 cnds.add(arr);
93 }
94
95 if (uri != null && !uri.trim().equals("")) {
96 Map<String, String> params = new HashMap<String, String>();
97 params.put(JcrUtils.REPOSITORY_URI, uri);
98 repository = new Jcr2davRepositoryFactory().getRepository(params);
99 if (repository == null)
100 throw new ArgeoException("Remote Davex repository " + uri
101 + " not found");
102 log.info("Initialized Jackrabbit repository " + repository
103 + " from uri " + uri);
104 } else {
105 if (inMemory && homeDirectory.exists()) {
106 FileUtils.deleteDirectory(homeDirectory);
107 log.warn("Deleted Jackrabbit home directory " + homeDirectory);
108 }
109
110 RepositoryConfig config;
111 InputStream in = configuration.getInputStream();
112 InputStream propsIn = null;
113 try {
114 Properties vars = new Properties();
115 if (variables != null) {
116 propsIn = variables.getInputStream();
117 vars.load(propsIn);
118 }
119 // override with system properties
120 vars.putAll(System.getProperties());
121 vars.put(
122 RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
123 homeDirectory.getCanonicalPath());
124 config = RepositoryConfig.create(new InputSource(in), vars);
125 } catch (Exception e) {
126 throw new RuntimeException("Cannot read configuration", e);
127 } finally {
128 IOUtils.closeQuietly(in);
129 IOUtils.closeQuietly(propsIn);
130 }
131
132 if (inMemory)
133 repository = new TransientRepository(config);
134 else
135 repository = RepositoryImpl.create(config);
136
137 log.info("Initialized Jackrabbit repository " + repository + " in "
138 + homeDirectory + " with config " + configuration);
139 }
140 }
141
142 public void destroy() throws Exception {
143 if (repository != null) {
144 if (repository instanceof JackrabbitRepository)
145 ((JackrabbitRepository) repository).shutdown();
146 else if (repository instanceof RepositoryImpl)
147 ((RepositoryImpl) repository).shutdown();
148 else if (repository instanceof TransientRepository)
149 ((TransientRepository) repository).shutdown();
150 }
151
152 if (inMemory)
153 if (homeDirectory.exists()) {
154 FileUtils.deleteDirectory(homeDirectory);
155 if (log.isDebugEnabled())
156 log.debug("Deleted Jackrabbit home directory "
157 + homeDirectory);
158 }
159
160 if (uri != null)
161 log.info("Destroyed Jackrabbit repository with uri " + uri);
162 else
163 log.info("Destroyed Jackrabbit repository " + repository + " in "
164 + homeDirectory + " with config " + configuration);
165 }
166
167 // JCR REPOSITORY (delegated)
168 public String getDescriptor(String key) {
169 return repository.getDescriptor(key);
170 }
171
172 public String[] getDescriptorKeys() {
173 return repository.getDescriptorKeys();
174 }
175
176 public Session login() throws LoginException, RepositoryException {
177 Session session = repository.login();
178 processNewSession(session);
179 return session;
180 }
181
182 public Session login(Credentials credentials, String workspaceName)
183 throws LoginException, NoSuchWorkspaceException,
184 RepositoryException {
185 Session session;
186 try {
187 session = repository.login(credentials, workspaceName);
188 } catch (NoSuchWorkspaceException e) {
189 if (autocreateWorkspaces)
190 session = createWorkspaceAndLogsIn(credentials, workspaceName);
191 else
192 throw e;
193 }
194 processNewSession(session);
195 return session;
196 }
197
198 public Session login(Credentials credentials) throws LoginException,
199 RepositoryException {
200 Session session = repository.login(credentials);
201 processNewSession(session);
202 return session;
203 }
204
205 public Session login(String workspaceName) throws LoginException,
206 NoSuchWorkspaceException, RepositoryException {
207 Session session;
208 try {
209 session = repository.login(workspaceName);
210 } catch (NoSuchWorkspaceException e) {
211 if (autocreateWorkspaces)
212 session = createWorkspaceAndLogsIn(null, workspaceName);
213 else
214 throw e;
215 }
216 processNewSession(session);
217 return session;
218 }
219
220 protected synchronized void processNewSession(Session session) {
221 try {
222 NamespaceHelper namespaceHelper = new NamespaceHelper(session);
223 namespaceHelper.registerNamespaces(namespaces);
224
225 for (byte[] arr : cnds)
226 CndImporter.registerNodeTypes(new InputStreamReader(
227 new ByteArrayInputStream(arr)), session, true);
228 } catch (Exception e) {
229 throw new ArgeoException("Cannot process new session", e);
230 }
231 }
232
233 /**
234 * Logs in to the default workspace, creates the required workspace, logs
235 * out, logs in to the required workspace.
236 */
237 protected Session createWorkspaceAndLogsIn(Credentials credentials,
238 String workspaceName) throws RepositoryException {
239 if (workspaceName == null)
240 throw new ArgeoException("No workspace specified.");
241 Session session = repository.login(credentials);
242 session.getWorkspace().createWorkspace(workspaceName);
243 session.logout();
244 return repository.login(credentials, workspaceName);
245 }
246
247 public void setResourceLoader(ResourceLoader resourceLoader) {
248 this.resourceLoader = resourceLoader;
249 }
250
251 public boolean isStandardDescriptor(String key) {
252 return repository.isStandardDescriptor(key);
253 }
254
255 public boolean isSingleValueDescriptor(String key) {
256 return repository.isSingleValueDescriptor(key);
257 }
258
259 public Value getDescriptorValue(String key) {
260 return repository.getDescriptorValue(key);
261 }
262
263 public Value[] getDescriptorValues(String key) {
264 return repository.getDescriptorValues(key);
265 }
266
267 // BEANS METHODS
268 public void setHomeDirectory(File homeDirectory) {
269 this.homeDirectory = homeDirectory;
270 }
271
272 public void setConfiguration(Resource configuration) {
273 this.configuration = configuration;
274 }
275
276 public void setInMemory(Boolean inMemory) {
277 this.inMemory = inMemory;
278 }
279
280 public void setNamespaces(Map<String, String> namespaces) {
281 this.namespaces = namespaces;
282 }
283
284 public void setCndFiles(List<String> cndFiles) {
285 this.cndFiles = cndFiles;
286 }
287
288 public void setVariables(Resource variables) {
289 this.variables = variables;
290 }
291
292 public void setUri(String uri) {
293 this.uri = uri;
294 }
295
296 }