]> git.argeo.org Git - lgpl/argeo-commons.git/blob - server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/server/jackrabbit/JackrabbitContainer.java
Improve JCR
[lgpl/argeo-commons.git] / server / runtime / org.argeo.server.jackrabbit / src / main / java / org / argeo / server / 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.server.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.commons.NamespaceHelper;
42 import org.apache.jackrabbit.commons.cnd.CndImporter;
43 import org.apache.jackrabbit.core.RepositoryImpl;
44 import org.apache.jackrabbit.core.TransientRepository;
45 import org.apache.jackrabbit.core.config.RepositoryConfig;
46 import org.apache.jackrabbit.core.config.RepositoryConfigurationParser;
47 import org.argeo.ArgeoException;
48 import org.springframework.beans.factory.DisposableBean;
49 import org.springframework.beans.factory.InitializingBean;
50 import org.springframework.context.ResourceLoaderAware;
51 import org.springframework.core.io.Resource;
52 import org.springframework.core.io.ResourceLoader;
53 import org.xml.sax.InputSource;
54
55 /**
56 * Wrapper around a Jackrabbit repository which allows to configure it in Spring
57 * and expose it as a {@link Repository}.
58 */
59 public class JackrabbitContainer implements InitializingBean, DisposableBean,
60 Repository, ResourceLoaderAware {
61 private Log log = LogFactory.getLog(JackrabbitContainer.class);
62
63 private Resource configuration;
64 private File homeDirectory;
65 private Resource variables;
66
67 private Boolean inMemory = false;
68
69 private Repository repository;
70
71 private ResourceLoader resourceLoader;
72
73 /** Node type definitions in CND format */
74 private List<byte[]> cnds = new ArrayList<byte[]>();
75 private List<String> cndFiles = new ArrayList<String>();
76
77 /** Namespaces to register: key is prefix, value namespace */
78 private Map<String, String> namespaces = new HashMap<String, String>();
79
80 public void afterPropertiesSet() throws Exception {
81 // Load cnds as resources
82 for (String resUrl : cndFiles) {
83
84 Resource res = resourceLoader.getResource(resUrl);
85 byte[] arr = IOUtils.toByteArray(res.getInputStream());
86 cnds.add(arr);
87 }
88
89 if (inMemory && homeDirectory.exists()) {
90 FileUtils.deleteDirectory(homeDirectory);
91 log.warn("Deleted Jackrabbit home directory " + homeDirectory);
92 }
93
94 RepositoryConfig config;
95 InputStream in = configuration.getInputStream();
96 InputStream propsIn = null;
97 try {
98 Properties vars = new Properties();
99 if (variables != null) {
100 propsIn = variables.getInputStream();
101 vars.load(propsIn);
102 }
103 // override with system properties
104 vars.putAll(System.getProperties());
105 vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
106 homeDirectory.getCanonicalPath());
107 config = RepositoryConfig.create(new InputSource(in), vars);
108 } catch (Exception e) {
109 throw new RuntimeException("Cannot read configuration", e);
110 } finally {
111 IOUtils.closeQuietly(in);
112 IOUtils.closeQuietly(propsIn);
113 }
114
115 if (inMemory)
116 repository = new TransientRepository(config);
117 else
118 repository = RepositoryImpl.create(config);
119
120 log.info("Initialized Jackrabbit repository " + repository + " in "
121 + homeDirectory + " with config " + configuration);
122 }
123
124 public void destroy() throws Exception {
125 if (repository != null) {
126 if (repository instanceof RepositoryImpl)
127 ((RepositoryImpl) repository).shutdown();
128 else if (repository instanceof TransientRepository)
129 ((TransientRepository) repository).shutdown();
130 }
131
132 if (inMemory)
133 if (homeDirectory.exists()) {
134 FileUtils.deleteDirectory(homeDirectory);
135 if (log.isDebugEnabled())
136 log.debug("Deleted Jackrabbit home directory "
137 + homeDirectory);
138 }
139 log.info("Destroyed Jackrabbit repository " + repository + " in "
140 + homeDirectory + " with config " + configuration);
141 }
142
143 // JCR REPOSITORY (delegated)
144 public String getDescriptor(String key) {
145 return repository.getDescriptor(key);
146 }
147
148 public String[] getDescriptorKeys() {
149 return repository.getDescriptorKeys();
150 }
151
152 public Session login() throws LoginException, RepositoryException {
153 Session session = repository.login();
154 processNewSession(session);
155 return session;
156 }
157
158 public Session login(Credentials credentials, String workspaceName)
159 throws LoginException, NoSuchWorkspaceException,
160 RepositoryException {
161 Session session;
162 try {
163 session = repository.login(credentials, workspaceName);
164 } catch (NoSuchWorkspaceException e) {
165 session = createWorkspaceAndLogsIn(credentials, workspaceName);
166 }
167 processNewSession(session);
168 return session;
169 }
170
171 public Session login(Credentials credentials) throws LoginException,
172 RepositoryException {
173 Session session = repository.login(credentials);
174 processNewSession(session);
175 return session;
176 }
177
178 public Session login(String workspaceName) throws LoginException,
179 NoSuchWorkspaceException, RepositoryException {
180 Session session;
181 try {
182 session = repository.login(workspaceName);
183 } catch (NoSuchWorkspaceException e) {
184 session = createWorkspaceAndLogsIn(null, workspaceName);
185 }
186 processNewSession(session);
187 return session;
188 }
189
190 protected synchronized void processNewSession(Session session) {
191 try {
192 NamespaceHelper namespaceHelper = new NamespaceHelper(session);
193 namespaceHelper.registerNamespaces(namespaces);
194
195 for (byte[] arr : cnds)
196 CndImporter.registerNodeTypes(new InputStreamReader(
197 new ByteArrayInputStream(arr)), session, true);
198 } catch (Exception e) {
199 throw new ArgeoException("Cannot process new session", e);
200 }
201 }
202
203 /**
204 * Logs in to the default workspace, creates the required workspace, logs
205 * out, logs in to the required workspace.
206 */
207 protected Session createWorkspaceAndLogsIn(Credentials credentials,
208 String workspaceName) throws RepositoryException {
209 if (workspaceName == null)
210 throw new ArgeoException("No workspace specified.");
211 Session session = repository.login(credentials);
212 session.getWorkspace().createWorkspace(workspaceName);
213 session.logout();
214 return repository.login(credentials, workspaceName);
215 }
216
217 public void setResourceLoader(ResourceLoader resourceLoader) {
218 this.resourceLoader = resourceLoader;
219 }
220
221 public boolean isStandardDescriptor(String key) {
222 return repository.isStandardDescriptor(key);
223 }
224
225 public boolean isSingleValueDescriptor(String key) {
226 return repository.isSingleValueDescriptor(key);
227 }
228
229 public Value getDescriptorValue(String key) {
230 return repository.getDescriptorValue(key);
231 }
232
233 public Value[] getDescriptorValues(String key) {
234 return repository.getDescriptorValues(key);
235 }
236
237 // BEANS METHODS
238 public void setHomeDirectory(File homeDirectory) {
239 this.homeDirectory = homeDirectory;
240 }
241
242 public void setConfiguration(Resource configuration) {
243 this.configuration = configuration;
244 }
245
246 public void setInMemory(Boolean inMemory) {
247 this.inMemory = inMemory;
248 }
249
250 public void setNamespaces(Map<String, String> namespaces) {
251 this.namespaces = namespaces;
252 }
253
254 public void setCndFiles(List<String> cndFiles) {
255 this.cndFiles = cndFiles;
256 }
257
258 public void setVariables(Resource variables) {
259 this.variables = variables;
260 }
261
262 }