2 * Copyright (C) 2010 Mathieu Baudier <mbaudier@argeo.org>
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package org
.argeo
.server
.jackrabbit
;
19 import java
.io
.ByteArrayInputStream
;
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
;
27 import java
.util
.Properties
;
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
;
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
;
56 * Wrapper around a Jackrabbit repository which allows to configure it in Spring
57 * and expose it as a {@link Repository}.
59 public class JackrabbitContainer
implements InitializingBean
, DisposableBean
,
60 Repository
, ResourceLoaderAware
{
61 private Log log
= LogFactory
.getLog(JackrabbitContainer
.class);
63 private Resource configuration
;
64 private File homeDirectory
;
65 private Resource variables
;
67 private Boolean inMemory
= false;
69 private Repository repository
;
71 private ResourceLoader resourceLoader
;
73 /** Node type definitions in CND format */
74 private List
<byte[]> cnds
= new ArrayList
<byte[]>();
75 private List
<String
> cndFiles
= new ArrayList
<String
>();
77 /** Namespaces to register: key is prefix, value namespace */
78 private Map
<String
, String
> namespaces
= new HashMap
<String
, String
>();
80 public void afterPropertiesSet() throws Exception
{
81 // Load cnds as resources
82 for (String resUrl
: cndFiles
) {
84 Resource res
= resourceLoader
.getResource(resUrl
);
85 byte[] arr
= IOUtils
.toByteArray(res
.getInputStream());
89 if (inMemory
&& homeDirectory
.exists()) {
90 FileUtils
.deleteDirectory(homeDirectory
);
91 log
.warn("Deleted Jackrabbit home directory " + homeDirectory
);
94 RepositoryConfig config
;
95 InputStream in
= configuration
.getInputStream();
96 InputStream propsIn
= null;
98 Properties vars
= new Properties();
99 if (variables
!= null) {
100 propsIn
= variables
.getInputStream();
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
);
111 IOUtils
.closeQuietly(in
);
112 IOUtils
.closeQuietly(propsIn
);
116 repository
= new TransientRepository(config
);
118 repository
= RepositoryImpl
.create(config
);
120 log
.info("Initialized Jackrabbit repository " + repository
+ " in "
121 + homeDirectory
+ " with config " + configuration
);
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();
133 if (homeDirectory
.exists()) {
134 FileUtils
.deleteDirectory(homeDirectory
);
135 if (log
.isDebugEnabled())
136 log
.debug("Deleted Jackrabbit home directory "
139 log
.info("Destroyed Jackrabbit repository " + repository
+ " in "
140 + homeDirectory
+ " with config " + configuration
);
143 // JCR REPOSITORY (delegated)
144 public String
getDescriptor(String key
) {
145 return repository
.getDescriptor(key
);
148 public String
[] getDescriptorKeys() {
149 return repository
.getDescriptorKeys();
152 public Session
login() throws LoginException
, RepositoryException
{
153 Session session
= repository
.login();
154 processNewSession(session
);
158 public Session
login(Credentials credentials
, String workspaceName
)
159 throws LoginException
, NoSuchWorkspaceException
,
160 RepositoryException
{
163 session
= repository
.login(credentials
, workspaceName
);
164 } catch (NoSuchWorkspaceException e
) {
165 session
= createWorkspaceAndLogsIn(credentials
, workspaceName
);
167 processNewSession(session
);
171 public Session
login(Credentials credentials
) throws LoginException
,
172 RepositoryException
{
173 Session session
= repository
.login(credentials
);
174 processNewSession(session
);
178 public Session
login(String workspaceName
) throws LoginException
,
179 NoSuchWorkspaceException
, RepositoryException
{
182 session
= repository
.login(workspaceName
);
183 } catch (NoSuchWorkspaceException e
) {
184 session
= createWorkspaceAndLogsIn(null, workspaceName
);
186 processNewSession(session
);
190 protected synchronized void processNewSession(Session session
) {
192 NamespaceHelper namespaceHelper
= new NamespaceHelper(session
);
193 namespaceHelper
.registerNamespaces(namespaces
);
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
);
204 * Logs in to the default workspace, creates the required workspace, logs
205 * out, logs in to the required workspace.
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
);
214 return repository
.login(credentials
, workspaceName
);
217 public void setResourceLoader(ResourceLoader resourceLoader
) {
218 this.resourceLoader
= resourceLoader
;
221 public boolean isStandardDescriptor(String key
) {
222 return repository
.isStandardDescriptor(key
);
225 public boolean isSingleValueDescriptor(String key
) {
226 return repository
.isSingleValueDescriptor(key
);
229 public Value
getDescriptorValue(String key
) {
230 return repository
.getDescriptorValue(key
);
233 public Value
[] getDescriptorValues(String key
) {
234 return repository
.getDescriptorValues(key
);
238 public void setHomeDirectory(File homeDirectory
) {
239 this.homeDirectory
= homeDirectory
;
242 public void setConfiguration(Resource configuration
) {
243 this.configuration
= configuration
;
246 public void setInMemory(Boolean inMemory
) {
247 this.inMemory
= inMemory
;
250 public void setNamespaces(Map
<String
, String
> namespaces
) {
251 this.namespaces
= namespaces
;
254 public void setCndFiles(List
<String
> cndFiles
) {
255 this.cndFiles
= cndFiles
;
258 public void setVariables(Resource variables
) {
259 this.variables
= variables
;