KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > info > magnolia > jackrabbit > ProviderImpl


1 /**
2  *
3  * Magnolia and its source-code is licensed under the LGPL.
4  * You may copy, adapt, and redistribute this file for commercial or non-commercial use.
5  * When copying, adapting, or redistributing this document in keeping with the guidelines above,
6  * you are required to provide proper attribution to obinary.
7  * If you reproduce or distribute the document without making any substantive modifications to its content,
8  * please use the following attribution line:
9  *
10  * Copyright 1993-2006 obinary Ltd. (http://www.obinary.com) All rights reserved.
11  *
12  */

13 package info.magnolia.jackrabbit;
14
15 import info.magnolia.cms.beans.config.ContentRepository;
16 import info.magnolia.cms.beans.config.ShutdownManager;
17 import info.magnolia.cms.beans.config.ShutdownTask;
18 import info.magnolia.cms.core.Path;
19 import info.magnolia.repository.Provider;
20 import info.magnolia.repository.RepositoryMapping;
21 import info.magnolia.repository.RepositoryNotInitializedException;
22
23 import java.io.File JavaDoc;
24 import java.io.FileInputStream JavaDoc;
25 import java.io.FileNotFoundException JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.io.InputStream JavaDoc;
28 import java.text.MessageFormat JavaDoc;
29 import java.util.Hashtable JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.Map JavaDoc;
32
33 import javax.jcr.NamespaceException;
34 import javax.jcr.Repository;
35 import javax.jcr.RepositoryException;
36 import javax.jcr.Session;
37 import javax.jcr.SimpleCredentials;
38 import javax.jcr.Workspace;
39 import javax.jcr.nodetype.NoSuchNodeTypeException;
40 import javax.jcr.nodetype.NodeTypeManager;
41 import javax.naming.Context JavaDoc;
42 import javax.naming.InitialContext JavaDoc;
43 import javax.naming.NameNotFoundException JavaDoc;
44 import javax.naming.NamingException JavaDoc;
45 import javax.xml.transform.TransformerFactoryConfigurationError JavaDoc;
46
47 import org.apache.commons.io.IOUtils;
48 import org.apache.commons.lang.ArrayUtils;
49 import org.apache.commons.lang.StringUtils;
50 import org.apache.commons.lang.SystemUtils;
51 import org.apache.jackrabbit.core.WorkspaceImpl;
52 import org.apache.jackrabbit.core.jndi.RegistryHelper;
53 import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException;
54 import org.apache.jackrabbit.core.nodetype.NodeTypeDef;
55 import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl;
56 import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry;
57 import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader;
58 import org.slf4j.Logger;
59 import org.slf4j.LoggerFactory;
60
61
62 /**
63  * @author Sameer Charles
64  * @author Fabrizio Giustina
65  * @version $Id: ProviderImpl.java 6617 2006-10-06 13:22:12Z scharles $
66  */

67 public class ProviderImpl implements Provider {
68
69     protected static Logger log = LoggerFactory.getLogger(ProviderImpl.class);
70
71     private static final String JavaDoc CONFIG_FILENAME_KEY = "configFile"; //$NON-NLS-1$
72

73     private static final String JavaDoc REPOSITORY_HOME_KEY = "repositoryHome"; //$NON-NLS-1$
74

75     private static final String JavaDoc CONTEXT_FACTORY_CLASS_KEY = "contextFactoryClass"; //$NON-NLS-1$
76

77     private static final String JavaDoc PROVIDER_URL_KEY = "providerURL"; //$NON-NLS-1$
78

79     private static final String JavaDoc BIND_NAME_KEY = "bindName"; //$NON-NLS-1$
80

81     private static final String JavaDoc MGNL_NODETYPES = "/mgnl-nodetypes/magnolia-nodetypes.xml"; //$NON-NLS-1$
82

83     private static final String JavaDoc CUSTOM_NODETYPES = "customNodeTypes"; //$NON-NLS-1$
84

85     private RepositoryMapping repositoryMapping;
86
87     private Repository repository;
88
89     private static final String JavaDoc REPO_HOME_PREFIX = "${repository.home}";
90
91     private static final int REPO_HOME_SUFIX_LEN = REPO_HOME_PREFIX.length();
92
93     private static final String JavaDoc sysRepositoryHome = System.getProperty("repository.home");
94
95     private static final String JavaDoc sysRepositoryHomes = System.getProperty("repository.homes");
96
97     /**
98      * Find the physical path to the repository folder
99      * @param repositoryHome the property set in the repository.xml file
100      * @return the full path resolved to the repository dir
101      */

102     private String JavaDoc getRepositoryHome(final String JavaDoc repositoryHome) {
103         boolean relocate = false;
104         String JavaDoc tmp = repositoryHome;
105         if (repositoryHome.startsWith(REPOSITORY_HOME_KEY)) {
106             tmp = repositoryHome.substring(REPO_HOME_SUFIX_LEN);
107             relocate = true;
108         }
109         /*
110          * Resolve if the path started with the suffix
111          */

112         if (sysRepositoryHome != null && relocate) {
113             return sysRepositoryHome + File.separator + tmp;
114         }
115
116         /*
117          * This is apply to all repositories if the java property is set
118          */

119         if (sysRepositoryHomes != null) {
120             return sysRepositoryHomes + File.separator + tmp;
121         }
122
123         /*
124          * Return the same value as before if neither of the above applied
125          */

126         return Path.getAbsoluteFileSystemPath(tmp);
127     }
128
129     /**
130      * @see info.magnolia.repository.Provider#init(info.magnolia.repository.RepositoryMapping)
131      */

132     public void init(RepositoryMapping repositoryMapping) throws RepositoryNotInitializedException {
133         checkXmlSettings();
134
135         this.repositoryMapping = repositoryMapping;
136         /* connect to repository */
137         Map JavaDoc params = this.repositoryMapping.getParameters();
138         String JavaDoc configFile = (String JavaDoc) params.get(CONFIG_FILENAME_KEY);
139         configFile = Path.getAbsoluteFileSystemPath(configFile);
140         String JavaDoc repositoryHome = (String JavaDoc) params.get(REPOSITORY_HOME_KEY);
141         repositoryHome = getRepositoryHome(repositoryHome);
142         if (log.isInfoEnabled()) {
143             log.info("Loading repository at {} (config file: {})", repositoryHome, configFile); //$NON-NLS-1$
144
}
145         String JavaDoc contextFactoryClass = (String JavaDoc) params.get(CONTEXT_FACTORY_CLASS_KEY);
146         String JavaDoc providerURL = (String JavaDoc) params.get(PROVIDER_URL_KEY);
147         boolean addShutdownTask = false;
148         final String JavaDoc bindName = (String JavaDoc) params.get(BIND_NAME_KEY);
149         final Hashtable JavaDoc env = new Hashtable JavaDoc();
150         env.put(Context.INITIAL_CONTEXT_FACTORY, contextFactoryClass);
151         env.put(Context.PROVIDER_URL, providerURL);
152
153         try {
154             InitialContext JavaDoc ctx = new InitialContext JavaDoc(env);
155             // first try to find the existing object if any
156
try {
157                 this.repository = (Repository) ctx.lookup(bindName);
158             }
159             catch (NameNotFoundException JavaDoc ne) {
160                 if (log.isDebugEnabled()) {
161                     log.debug(
162                         "No JNDI bound Repository found with name {} , trying to initialize a new Repository",
163                         bindName);
164                 }
165                 RegistryHelper.registerRepository(ctx, bindName, configFile, repositoryHome, true);
166                 this.repository = (Repository) ctx.lookup(bindName);
167                 addShutdownTask = true;
168             }
169             this.validateWorkspaces();
170         }
171         catch (NamingException JavaDoc e) {
172             log.error("Unable to initialize repository: " + e.getMessage(), e);
173             throw new RepositoryNotInitializedException(e);
174         }
175         catch (RepositoryException e) {
176             log.error("Unable to initialize repository: " + e.getMessage(), e);
177             throw new RepositoryNotInitializedException(e);
178         }
179         catch (TransformerFactoryConfigurationError JavaDoc e) {
180             log.error("Unable to initialize repository: " + e.getMessage(), e);
181             throw new RepositoryNotInitializedException(e);
182         }
183
184         if (addShutdownTask) {
185             ShutdownManager.addShutdownTask(new ShutdownTask() {
186
187                 public boolean execute(info.magnolia.context.Context context) {
188                     log.info("Shutting down repository bound to '{}'", bindName);
189
190                     try {
191                         Context JavaDoc ctx = new InitialContext JavaDoc(env);
192                         RegistryHelper.unregisterRepository(ctx, bindName);
193                     }
194                     catch (NamingException JavaDoc ne) {
195                         log.warn(MessageFormat.format("Unable to shutdown repository {0}: {1} {2}", new Object JavaDoc[]{
196                             bindName,
197                             ne.getClass().getName(),
198                             ne.getMessage()}), ne);
199                     }
200                     catch (Throwable JavaDoc e) {
201                         log.warn(MessageFormat.format("Failed to shutdown repository {0}: {1} {2}", new Object JavaDoc[]{
202                             bindName,
203                             e.getClass().getName(),
204                             e.getMessage()}), e);
205                     }
206                     return true;
207                 }
208             });
209         }
210     }
211
212     /**
213      * @see info.magnolia.repository.Provider#getUnderlineRepository()
214      */

215     public Repository getUnderlineRepository() throws RepositoryNotInitializedException {
216         if (this.repository == null) {
217             throw new RepositoryNotInitializedException("Null repository"); //$NON-NLS-1$
218
}
219         return this.repository;
220     }
221
222     /**
223      * @see info.magnolia.repository.Provider#registerNamespace(java.lang.String, java.lang.String, javax.jcr.Workspace)
224      */

225     public void registerNamespace(String JavaDoc namespacePrefix, String JavaDoc uri, Workspace workspace) throws RepositoryException {
226         try {
227             workspace.getNamespaceRegistry().getURI(namespacePrefix);
228         }
229         catch (NamespaceException e) {
230             if (log.isDebugEnabled()) {
231                 log.debug(e.getMessage());
232             }
233             log.info("registering prefix [{}] with uri {}", namespacePrefix, uri); //$NON-NLS-1$
234
workspace.getNamespaceRegistry().registerNamespace(namespacePrefix, uri);
235         }
236     }
237
238     /**
239      * @see info.magnolia.repository.Provider#unregisterNamespace(java.lang.String, javax.jcr.Workspace)
240      */

241     public void unregisterNamespace(String JavaDoc prefix, Workspace workspace) throws RepositoryException {
242         workspace.getNamespaceRegistry().unregisterNamespace(prefix);
243     }
244
245     /**
246      * @see info.magnolia.repository.Provider#registerNodeTypes(String)
247      */

248     public void registerNodeTypes() throws RepositoryException {
249         registerNodeTypes(StringUtils.EMPTY);
250     }
251
252     /**
253      * @see info.magnolia.repository.Provider#registerNodeTypes(java.lang.String)
254      */

255     public void registerNodeTypes(String JavaDoc configuration) throws RepositoryException {
256         if (StringUtils.isEmpty(configuration)) {
257             configuration = (String JavaDoc) this.repositoryMapping.getParameters().get(CUSTOM_NODETYPES);
258         }
259
260         InputStream JavaDoc xml = getNodeTypeDefinition(configuration);
261         this.registerNodeTypes(xml);
262     }
263
264     /**
265      * @see info.magnolia.repository.Provider#registerNodeTypes(java.io.InputStream)
266      */

267     public void registerNodeTypes(InputStream JavaDoc xmlStream) throws RepositoryException {
268         SimpleCredentials credentials = new SimpleCredentials(
269             ContentRepository.REPOSITORY_USER,
270             ContentRepository.REPOSITORY_PSWD.toCharArray());
271         Session jcrSession = this.repository.login(credentials);
272         Workspace workspace = jcrSession.getWorkspace();
273
274         // should never happen
275
if (xmlStream == null) {
276             throw new MissingNodetypesException();
277         }
278
279         NodeTypeDef[] types;
280         try {
281             types = NodeTypeReader.read(xmlStream);
282         }
283         catch (InvalidNodeTypeDefException e) {
284             throw new RepositoryException(e.getMessage(), e);
285         }
286         catch (IOException JavaDoc e) {
287             throw new RepositoryException(e.getMessage(), e);
288         }
289         finally {
290             IOUtils.closeQuietly(xmlStream);
291         }
292
293         NodeTypeManager ntMgr = workspace.getNodeTypeManager();
294         NodeTypeRegistry ntReg;
295         try {
296             ntReg = ((NodeTypeManagerImpl) ntMgr).getNodeTypeRegistry();
297         } catch (ClassCastException JavaDoc e) {
298             // this could happen if the repository provider does not have proper Shared API for the
299
// application server like at the moment in Jackrabbit
300
log.debug("Failed to get NodeTypeRegistry",e);
301             return;
302         }
303
304         for (int j = 0; j < types.length; j++) {
305             NodeTypeDef def = types[j];
306
307             try {
308                 ntReg.getNodeTypeDef(def.getName());
309             }
310             catch (NoSuchNodeTypeException nsne) {
311                 log.info("registering nodetype {}", def.getName()); //$NON-NLS-1$
312

313                 try {
314                     ntReg.registerNodeType(def);
315                 }
316                 catch (InvalidNodeTypeDefException e) {
317                     throw new RepositoryException(e.getMessage(), e);
318                 }
319                 catch (RepositoryException e) {
320                     throw new RepositoryException(e.getMessage(), e);
321                 }
322             }
323
324         }
325     }
326
327     /**
328      * @param configuration
329      * @return InputStream of node type definition file
330      */

331     private InputStream JavaDoc getNodeTypeDefinition(String JavaDoc configuration) {
332
333         InputStream JavaDoc xml;
334
335         if (StringUtils.isNotEmpty(configuration)) {
336
337             // 1: try to load the configured file from the classpath
338
xml = getClass().getResourceAsStream(configuration);
339             if (xml != null) {
340                 log.info("Custom node types registered using {}", configuration);
341                 return xml;
342             }
343
344             // 2: try to load it from the file system
345
File JavaDoc nodeTypeDefinition = new File JavaDoc(Path.getAbsoluteFileSystemPath(configuration));
346             if (nodeTypeDefinition.exists()) {
347                 try {
348                     return new FileInputStream JavaDoc(nodeTypeDefinition);
349                 }
350                 catch (FileNotFoundException JavaDoc e) {
351                     // should never happen
352
log.error("File not found: {}", xml);
353                 }
354             }
355
356             // 3: defaults to standard nodetypes
357
log.error(
358                 "Unable to find node type definition: {} for repository {}",
359                 configuration,
360                 this.repositoryMapping.getName());
361         }
362
363         // initialize default magnolia nodetypes
364
xml = getClass().getResourceAsStream(MGNL_NODETYPES);
365
366         return xml;
367     }
368
369     /**
370      * WORKAROUND for tomcat 5.0/jdk 1.5 problem tomcat\common\endorsed contains an xml-apis.jar needed by tomcat and
371      * loaded before all xmsl stuff present in the jdk (1.4 naming problem). In the xml-apis.jar file the
372      * TransformerFactoryImpl is set to "org.apache.xalan.processor.TransformerFactoryImpl" instead of
373      * "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl". solution: remove the file xml-apis.jar
374      * from the directory OR manually change the javax.xml.transform.TransformerFactory system property
375      */

376     protected void checkXmlSettings() {
377         if (SystemUtils.isJavaVersionAtLeast(1.5f)
378             && "org.apache.xalan.processor.TransformerFactoryImpl".equals(System
379                 .getProperty("javax.xml.transform.TransformerFactory"))) {
380
381             log.info("Java 1.5 detected, setting system property \"javax.xml.transform.TransformerFactory\" to "
382                 + "\"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl\"");
383
384             System.setProperty(
385                 "javax.xml.transform.TransformerFactory",
386                 "com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
387         }
388     }
389
390     /**
391      * checks if all workspaces are present according to the repository mapping, creates any missing workspace
392      */

393     private void validateWorkspaces() throws RepositoryException {
394         Iterator JavaDoc configuredNames = repositoryMapping.getWorkspaces().iterator();
395         while (configuredNames.hasNext()) {
396             registerWorkspace((String JavaDoc) configuredNames.next());
397         }
398     }
399
400     /**
401      * @see info.magnolia.repository.Provider#registerWorkspace(java.lang.String)
402      */

403     public boolean registerWorkspace(String JavaDoc workspaceName) throws RepositoryException {
404         // check if workspace already exists
405
SimpleCredentials credentials = new SimpleCredentials(
406             ContentRepository.REPOSITORY_USER,
407             ContentRepository.REPOSITORY_PSWD.toCharArray());
408         Session jcrSession = this.repository.login(credentials);
409         try {
410             WorkspaceImpl defaultWorkspace = (WorkspaceImpl) jcrSession.getWorkspace();
411             String JavaDoc[] workspaceNames = defaultWorkspace.getAccessibleWorkspaceNames();
412
413             boolean alreadyExists = ArrayUtils.contains(workspaceNames, workspaceName);
414             if (!alreadyExists) {
415                 defaultWorkspace.createWorkspace(workspaceName);
416             }
417             jcrSession.logout();
418
419             return !alreadyExists;
420         } catch (ClassCastException JavaDoc e) {
421             // this could happen if the repository provider does not have proper Shared API for the
422
// application server like at the moment in Jackrabbit
423
log.debug("Unable to register workspace, will continue", e);
424         } catch (Throwable JavaDoc t) {
425             log.error("Unable to register workspace, will continue", t);
426         }
427         return false;
428     }
429
430 }
431
Popular Tags