Source Code Cross Referenced for JCRSourceFactory.java in  » Content-Management-System » apache-lenya-2.0 » org » apache » cocoon » jcr » source » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Content Management System » apache lenya 2.0 » org.apache.cocoon.jcr.source 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Licensed to the Apache Software Foundation (ASF) under one or more
003:         * contributor license agreements.  See the NOTICE file distributed with
004:         * this work for additional information regarding copyright ownership.
005:         * The ASF licenses this file to You under the Apache License, Version 2.0
006:         * (the "License"); you may not use this file except in compliance with
007:         * the License.  You may obtain a copy of the License at
008:         *
009:         *      http://www.apache.org/licenses/LICENSE-2.0
010:         *
011:         * Unless required by applicable law or agreed to in writing, software
012:         * distributed under the License is distributed on an "AS IS" BASIS,
013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014:         * See the License for the specific language governing permissions and
015:         * limitations under the License.
016:         */
017:        package org.apache.cocoon.jcr.source;
018:
019:        import java.io.IOException;
020:        import java.net.MalformedURLException;
021:        import java.util.HashMap;
022:        import java.util.Map;
023:
024:        import javax.jcr.LoginException;
025:        import javax.jcr.Node;
026:        import javax.jcr.Property;
027:        import javax.jcr.Repository;
028:        import javax.jcr.RepositoryException;
029:        import javax.jcr.Session;
030:
031:        import org.apache.avalon.framework.CascadingRuntimeException;
032:        import org.apache.avalon.framework.configuration.Configurable;
033:        import org.apache.avalon.framework.configuration.Configuration;
034:        import org.apache.avalon.framework.configuration.ConfigurationException;
035:        import org.apache.avalon.framework.service.ServiceException;
036:        import org.apache.avalon.framework.service.ServiceManager;
037:        import org.apache.avalon.framework.service.Serviceable;
038:        import org.apache.avalon.framework.thread.ThreadSafe;
039:        import org.apache.excalibur.source.Source;
040:        import org.apache.excalibur.source.SourceException;
041:        import org.apache.excalibur.source.SourceFactory;
042:        import org.apache.excalibur.source.SourceUtil;
043:
044:        /**
045:         * JCRSourceFactory is an implementation of
046:         * <code>ModifiableTraversableSource</code> on top of a JCR (aka <a
047:         * href="http://www.jcp.org/en/jsr/detail?id=170">JSR-170</a>) repository.
048:         * <p>
049:         * Since JCR allows a repository to define its own node types, it is necessary
050:         * to configure this source factory with a description of what node types map to
051:         * "files" and "folders" and the properties used to store source-related data.
052:         * <p>
053:         * A typical configuration for a naked Jackrabbit repository is as follows:
054:         *
055:         * <pre>
056:         *
057:         *    &lt;source-factories&gt;
058:         *      &lt;component-instance class=&quot;org.apache.cocoon.jcr.source.JCRSourceFactory&quot; name=&quot;jcr&quot;&gt;
059:         *        &lt;folder-node type=&quot;rep:root&quot;  new-file=&quot;nt:file&quot; new-folder=&quot;nt:folder&quot;/&gt;
060:         *        &lt;folder-node type=&quot;nt:folder&quot; new-file=&quot;nt:file&quot;/&gt;
061:         *        &lt;file-node type=&quot;nt:file&quot; content-path=&quot;jcr:content&quot; content-type=&quot;nt:resource&quot;/&gt;
062:         *        &lt;file-node type=&quot;nt:linkedFile&quot; content-ref=&quot;jcr:content&quot;/&gt;
063:         *        &lt;content-node type=&quot;nt:resource&quot;
064:         *                      content-prop=&quot;jcr:data&quot;
065:         *                      mimetype-prop=&quot;jcr:mimeType&quot;
066:         *                      lastmodified-prop=&quot;jcr:lastModified&quot;
067:         *                      validity-prop=&quot;jcr:lastModified&quot;/&gt;
068:         *      &lt;/component-instance&gt;
069:         *    &lt;/source-factories&gt;
070:         *
071:         * </pre>
072:         *
073:         * A <code>&lt;folder-node&gt;</code> defines a node type that is mapped to a
074:         * non-terminal source (i.e. that can have children). The <code>new-file</code>
075:         * and <code>new-folder</code> attributes respectively define what node types
076:         * should be used to create a new terminal and non-terminal source.
077:         * <p>
078:         * A <code>&lt;file-node&gt;</code> defines a note type that is mapped to a
079:         * terminal source (i.e. that can have some content). The
080:         * <code>content-path</code> attribute defines the path to the node's child
081:         * that actually holds the content, and <code>content-type</code> defines the
082:         * type of this content node.
083:         * <p>
084:         * The <code>content-ref</code> attribute is used to comply with JCR's
085:         * <code>nt:linkedFile</code> definition where the content node is not a
086:         * direct child of the file node, but is referenced by a property of this file
087:         * node. Such node types are read-only as there's no way to indicate where the
088:         * referenced content node should be created.
089:         * <p>
090:         * A <code>&lt;content-node&gt;</code> defines a node type that actually holds
091:         * the content of a <code>file-node</code>. The <code>content-prop</code>
092:         * attribute must be present and gives the name of the node's binary property
093:         * that will hold the actual content. Other attributes are optional:
094:         * <ul>
095:         * <li><code>mimetype-prop</code> defines a string property holding the
096:         * content's MIME type, </li>
097:         * <li><code>lastmodified-prop</code> defines a date property holding the
098:         * node's last modification date. It is automatically updated when content is
099:         * written to the <code>content-node</code>. </li>
100:         * <li><code>validity-prop</code> defines a property that gives the validity
101:         * of the content, used by Cocoon's cache. If not specified,
102:         * <code>lastmodified-prop</code> is used, if present. Otherwise the source
103:         * has no validity and won't be cacheable. </li>
104:         * </ul>
105:         * <p>
106:         * The format of URIs for this source is a path in the repository, and it is
107:         * therefore currently limited to repository traversal. Further work will add
108:         * the ability to specify query strings.
109:         *
110:         * @version $Id: JCRSourceFactory.java 449153 2006-09-23 04:27:50Z crossley $
111:         */
112:        public class JCRSourceFactory implements  ThreadSafe, SourceFactory,
113:                Configurable, Serviceable {
114:
115:            protected static class NodeTypeInfo {
116:                // Empty base class
117:            }
118:
119:            protected static class FolderTypeInfo extends NodeTypeInfo {
120:                public String newFileType;
121:
122:                public String newFolderType;
123:            }
124:
125:            protected static class FileTypeInfo extends NodeTypeInfo {
126:                public String contentPath;
127:
128:                public String contentType;
129:
130:                public String contentRef;
131:            }
132:
133:            protected static class ContentTypeInfo extends NodeTypeInfo {
134:                public String contentProp;
135:
136:                public String mimeTypeProp;
137:
138:                public String lastModifiedProp;
139:
140:                public String validityProp;
141:            }
142:
143:            /**
144:             * The repository we use
145:             */
146:            protected Repository repo;
147:
148:            /**
149:             * Scheme, lazily computed at the first call to getSource()
150:             */
151:            protected String scheme;
152:
153:            /**
154:             * The NodeTypeInfo for each of the types described in the configuration
155:             */
156:            protected Map typeInfos;
157:
158:            protected ServiceManager manager;
159:
160:            public void service(ServiceManager manager) throws ServiceException {
161:                this .manager = manager;
162:                // this.repo is lazily initialized to avoid a circular dependency between SourceResolver
163:                // and JackrabbitRepository that leads to a StackOverflowError at initialization time
164:            }
165:
166:            public void configure(Configuration config)
167:                    throws ConfigurationException {
168:                this .typeInfos = new HashMap();
169:
170:                Configuration[] children = config.getChildren();
171:
172:                for (int i = 0; i < children.length; i++) {
173:                    Configuration child = children[i];
174:                    String name = child.getName();
175:
176:                    if ("folder-node".equals(name)) {
177:                        FolderTypeInfo info = new FolderTypeInfo();
178:                        String type = child.getAttribute("type");
179:                        info.newFileType = child.getAttribute("new-file");
180:                        info.newFolderType = child.getAttribute("new-folder",
181:                                type);
182:
183:                        this .typeInfos.put(type, info);
184:
185:                    } else if ("file-node".equals(name)) {
186:                        FileTypeInfo info = new FileTypeInfo();
187:                        info.contentPath = child.getAttribute("content-path",
188:                                null);
189:                        info.contentType = child.getAttribute("content-type",
190:                                null);
191:                        info.contentRef = child.getAttribute("content-ref",
192:                                null);
193:                        if (info.contentPath == null && info.contentRef == null) {
194:                            throw new ConfigurationException(
195:                                    "One of content-path or content-ref is required at "
196:                                            + child.getLocation());
197:                        }
198:                        if (info.contentPath != null
199:                                && info.contentType == null) {
200:                            throw new ConfigurationException(
201:                                    "content-type must be present with content-path at "
202:                                            + child.getLocation());
203:                        }
204:                        this .typeInfos.put(child.getAttribute("type"), info);
205:
206:                    } else if ("content-node".equals(name)) {
207:                        ContentTypeInfo info = new ContentTypeInfo();
208:                        info.contentProp = child.getAttribute("content-prop");
209:                        info.lastModifiedProp = child.getAttribute(
210:                                "lastmodified-prop", null);
211:                        info.mimeTypeProp = child.getAttribute("mimetype-prop",
212:                                null);
213:                        info.validityProp = child.getAttribute("validity-prop",
214:                                info.lastModifiedProp);
215:                        this .typeInfos.put(child.getAttribute("type"), info);
216:
217:                    } else {
218:                        throw new ConfigurationException(
219:                                "Unknown configuration " + name + " at "
220:                                        + child.getLocation());
221:                    }
222:                }
223:
224:            }
225:
226:            protected void lazyInit() {
227:                if (this .repo == null) {
228:                    try {
229:                        this .repo = (Repository) manager
230:                                .lookup(Repository.class.getName());
231:                    } catch (Exception e) {
232:                        throw new CascadingRuntimeException(
233:                                "Cannot lookup repository", e);
234:                    }
235:                }
236:            }
237:
238:            /*
239:             * (non-Javadoc)
240:             *
241:             * @see org.apache.excalibur.source.SourceFactory#getSource(java.lang.String,
242:             *      java.util.Map)
243:             */
244:            public Source getSource(String uri, Map parameters)
245:                    throws IOException, MalformedURLException {
246:                lazyInit();
247:
248:                if (this .scheme == null) {
249:                    this .scheme = SourceUtil.getScheme(uri);
250:                }
251:
252:                Session session;
253:                try {
254:                    // TODO: accept a different workspace?
255:                    session = repo.login();
256:                } catch (LoginException e) {
257:                    throw new SourceException("Login to repository failed", e);
258:                } catch (RepositoryException e) {
259:                    throw new SourceException("Cannot access repository", e);
260:                }
261:
262:                // Compute the path
263:                String path = SourceUtil.getSpecificPart(uri);
264:                if (!path.startsWith("//")) {
265:                    throw new MalformedURLException("Expecting " + this .scheme
266:                            + "://path and got " + uri);
267:                }
268:                // Remove first '/'
269:                path = path.substring(1);
270:                int pathLen = path.length();
271:                if (pathLen > 1) {
272:                    // Not root: ensure there's no trailing '/'
273:                    if (path.charAt(pathLen - 1) == '/') {
274:                        path = path.substring(0, pathLen - 1);
275:                    }
276:                }
277:
278:                return createSource(session, path);
279:            }
280:
281:            /*
282:             * (non-Javadoc)
283:             *
284:             * @see org.apache.excalibur.source.SourceFactory#release(org.apache.excalibur.source.Source)
285:             */
286:            public void release(Source source) {
287:                // nothing
288:            }
289:
290:            public String getScheme() {
291:                return this .scheme;
292:            }
293:
294:            /**
295:             * Get the type info for a node.
296:             *
297:             * @param node the node
298:             * @return the type info
299:             * @throws RepositoryException if node type couldn't be accessed or if no type info is found
300:             */
301:            public NodeTypeInfo getTypeInfo(Node node)
302:                    throws RepositoryException {
303:                String typeName = node.getPrimaryNodeType().getName();
304:                NodeTypeInfo result = (NodeTypeInfo) this .typeInfos
305:                        .get(typeName);
306:                if (result == null) {
307:                    // TODO: build a NodeTypeInfo using introspection
308:                    throw new RepositoryException(
309:                            "No type info found for node type '" + typeName
310:                                    + "' at " + node.getPath());
311:                }
312:
313:                return result;
314:            }
315:
316:            /**
317:             * Get the type info for a given node type name.
318:             * @param typeName the type name
319:             * @return the type info
320:             * @throws RepositoryException if no type info is found
321:             */
322:            public NodeTypeInfo getTypeInfo(String typeName)
323:                    throws RepositoryException {
324:                NodeTypeInfo result = (NodeTypeInfo) this .typeInfos
325:                        .get(typeName);
326:                if (result == null) {
327:                    // TODO: build a NodeTypeInfo using introspection
328:                    throw new RepositoryException(
329:                            "No type info found for node type '" + typeName
330:                                    + "'");
331:                }
332:
333:                return result;
334:            }
335:
336:            /**
337:             * Get the content node for a given node
338:             *
339:             * @param node the node for which we want the content node
340:             * @return the content node
341:             * @throws RepositoryException if some error occurs, or if the given node isn't a file node or a content node
342:             */
343:            public Node getContentNode(Node node) throws RepositoryException {
344:                NodeTypeInfo info = getTypeInfo(node);
345:
346:                if (info instanceof  ContentTypeInfo) {
347:                    return node;
348:
349:                } else if (info instanceof  FileTypeInfo) {
350:                    FileTypeInfo finfo = (FileTypeInfo) info;
351:                    if (".".equals(finfo.contentPath)) {
352:                        return node;
353:                    } else if (finfo.contentPath != null) {
354:                        return node.getNode(finfo.contentPath);
355:                    } else {
356:                        Property ref = node.getProperty(finfo.contentRef);
357:                        return getContentNode(ref.getNode());
358:                    }
359:                } else {
360:                    // A folder
361:                    throw new RepositoryException(
362:                            "Can't get content node for folder node at "
363:                                    + node.getPath());
364:                }
365:            }
366:
367:            /**
368:             * Creates a new source given its parent and its node
369:             *
370:             * @param parent the parent
371:             * @param node the node
372:             * @return a new source
373:             * @throws SourceException
374:             */
375:            public JCRNodeSource createSource(JCRNodeSource parent, Node node)
376:                    throws SourceException {
377:                return new JCRNodeSource(parent, node);
378:            }
379:
380:            /**
381:             * Creates a new source given a session and a path
382:             *
383:             * @param session the session
384:             * @param path the absolute path
385:             * @return a new source
386:             * @throws SourceException
387:             */
388:            public JCRNodeSource createSource(Session session, String path)
389:                    throws SourceException {
390:                return new JCRNodeSource(this , session, path);
391:            }
392:
393:            /**
394:             * Create a child file node in a folder node.
395:             *
396:             * @param folderNode the folder node
397:             * @param name the child's name
398:             * @return the newly created child node
399:             * @throws RepositoryException if some error occurs
400:             */
401:            public Node createFileNode(Node folderNode, String name)
402:                    throws RepositoryException {
403:                NodeTypeInfo info = getTypeInfo(folderNode);
404:                if (!(info instanceof  FolderTypeInfo)) {
405:                    throw new RepositoryException("Node type "
406:                            + folderNode.getPrimaryNodeType().getName()
407:                            + " is not a folder type");
408:                }
409:
410:                FolderTypeInfo folderInfo = (FolderTypeInfo) info;
411:                return folderNode.addNode(name, folderInfo.newFileType);
412:            }
413:
414:            /**
415:             * Create the content node for a file node.
416:             *
417:             * @param fileNode the file node
418:             * @return the content node for this file node
419:             * @throws RepositoryException if some error occurs
420:             */
421:            public Node createContentNode(Node fileNode)
422:                    throws RepositoryException {
423:
424:                NodeTypeInfo info = getTypeInfo(fileNode);
425:                if (!(info instanceof  FileTypeInfo)) {
426:                    throw new RepositoryException("Node type "
427:                            + fileNode.getPrimaryNodeType().getName()
428:                            + " is not a file type");
429:                }
430:
431:                FileTypeInfo fileInfo = (FileTypeInfo) info;
432:                Node contentNode = fileNode.addNode(fileInfo.contentPath,
433:                        fileInfo.contentType);
434:
435:                return contentNode;
436:            }
437:
438:            /**
439:             * Get the content property for a given node
440:             *
441:             * @param node a file or content node
442:             * @return the content property
443:             * @throws RepositoryException if some error occurs
444:             */
445:            public Property getContentProperty(Node node)
446:                    throws RepositoryException {
447:                Node contentNode = getContentNode(node);
448:                ContentTypeInfo info = (ContentTypeInfo) getTypeInfo(contentNode);
449:                return contentNode.getProperty(info.contentProp);
450:            }
451:
452:            /**
453:             * Get the mime-type property for a given node
454:             *
455:             * @param node a file or content node
456:             * @return the mime-type property, or <code>null</code> if no such property exists
457:             * @throws RepositoryException if some error occurs
458:             */
459:            public Property getMimeTypeProperty(Node node)
460:                    throws RepositoryException {
461:                Node contentNode = getContentNode(node);
462:                ContentTypeInfo info = (ContentTypeInfo) getTypeInfo(contentNode);
463:
464:                String propName = info.mimeTypeProp;
465:                if (propName != null && contentNode.hasProperty(propName)) {
466:                    return contentNode.getProperty(propName);
467:                } else {
468:                    return null;
469:                }
470:            }
471:
472:            /**
473:             * Get the lastmodified property for a given node
474:             *
475:             * @param node a file or content node
476:             * @return the lastmodified property, or <code>null</code> if no such property exists
477:             * @throws RepositoryException if some error occurs
478:             */
479:            public Property getLastModifiedDateProperty(Node node)
480:                    throws RepositoryException {
481:                Node contentNode = getContentNode(node);
482:                ContentTypeInfo info = (ContentTypeInfo) getTypeInfo(contentNode);
483:
484:                String propName = info.lastModifiedProp;
485:                if (propName != null && contentNode.hasProperty(propName)) {
486:                    return contentNode.getProperty(propName);
487:                } else {
488:                    return null;
489:                }
490:            }
491:
492:            /**
493:             * Get the validity property for a given node
494:             *
495:             * @param node a file or content node
496:             * @return the validity property, or <code>null</code> if no such property exists
497:             * @throws RepositoryException if some error occurs
498:             */
499:            public Property getValidityProperty(Node node)
500:                    throws RepositoryException {
501:                Node contentNode = getContentNode(node);
502:                ContentTypeInfo info = (ContentTypeInfo) getTypeInfo(contentNode);
503:
504:                String propName = info.validityProp;
505:                if (propName != null && contentNode.hasProperty(propName)) {
506:                    return contentNode.getProperty(propName);
507:                } else {
508:                    return null;
509:                }
510:            }
511:
512:            /**
513:             * Does a node represent a collection (i.e. folder-node)?
514:             *
515:             * @param node the node
516:             * @return <code>true</code> if it's a collection
517:             * @throws RepositoryException if some error occurs
518:             */
519:            public boolean isCollection(Node node) throws RepositoryException {
520:                return getTypeInfo(node) instanceof  FolderTypeInfo;
521:            }
522:
523:            /**
524:             * Get the node type to create a new subfolder of a given folder node.
525:             *
526:             * @param folderNode
527:             * @return the child folder node type
528:             * @throws RepositoryException if some error occurs
529:             */
530:            public String getFolderNodeType(Node folderNode)
531:                    throws RepositoryException {
532:                FolderTypeInfo info = (FolderTypeInfo) getTypeInfo(folderNode);
533:                return info.newFolderType;
534:            }
535:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.