Source Code Cross Referenced for XMLFileModule.java in  » Content-Management-System » apache-lenya-2.0 » org » apache » cocoon » components » modules » input » 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.components.modules.input 
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.components.modules.input;
018:
019:        import org.apache.avalon.framework.component.Component;
020:        import org.apache.avalon.framework.component.ComponentException;
021:        import org.apache.avalon.framework.component.ComponentManager;
022:        import org.apache.avalon.framework.component.Composable;
023:        import org.apache.avalon.framework.configuration.Configuration;
024:        import org.apache.avalon.framework.configuration.ConfigurationException;
025:        import org.apache.avalon.framework.logger.Logger;
026:        import org.apache.avalon.framework.thread.ThreadSafe;
027:        import org.apache.cocoon.components.source.SourceUtil;
028:        import org.apache.commons.collections.map.AbstractReferenceMap;
029:        import org.apache.commons.collections.map.ReferenceMap;
030:        import org.apache.excalibur.source.Source;
031:        import org.apache.excalibur.source.SourceResolver;
032:        import org.apache.excalibur.source.SourceValidity;
033:        import org.w3c.dom.Document;
034:
035:        import java.util.Collections;
036:        import java.util.HashMap;
037:        import java.util.Map;
038:
039:        /**
040:
041:         <grammar>
042:         <define name="input.module.config.contents" combine="choice">
043:         <optional><element name="reloadable"><data type="boolean"/></element></optional>
044:         <optional><element name="cacheable"><data type="boolean"/></element></optional>
045:         <optional>
046:         <ref name="org.apache.cocoon.components.modules.input.XMLFileModule:file">
047:         </optional>
048:         </define>
049:
050:         <define name="input.module.runtime.contents" combine="choice">
051:         <optional>
052:         <ref name="org.apache.cocoon.components.modules.input.XMLFileModule:file">
053:         </optional>
054:         </define>
055:
056:         <define name="org.apache.cocoon.components.modules.input.XMLFileModule:file">
057:         <element name="file">
058:         <attribute name="src"><data type="anyURI"/></attribute>
059:         <optional><attribute name="reloadable"><data type="boolean"/></attribute></optional>
060:         <optional><attribute name="cacheable"><data type="boolean"/></attribute></optional>
061:         </element>
062:         </define>
063:         </grammar>
064:
065:         * This module provides an Input Module interface to any XML document, by using
066:         * XPath expressions as attribute keys.
067:         * The XML can be obtained from any Cocoon <code>Source</code> (e.g.,
068:         * <code>cocoon:/...</code>, <code>context://..</code>, and regular URLs).
069:         * Sources can be held in memory for better performance and reloaded if
070:         * changed.
071:         *
072:         * <p>Caching and reloading can be turned on / off (default: caching on,
073:         * reloading off) through <code>&lt;reloadable&gt;false&lt;/reloadable&gt;</code>
074:         * and <code>&lt;cacheable&gt;false&lt;/cacheable&gt;</code>. The file
075:         * (source) to use is specified through <code>&lt;file
076:         * src="protocol:path/to/file.xml" reloadable="true"
077:         * cacheable="true"/&gt;</code> optionally overriding defaults for
078:         * caching and/or reloading.</p>
079:         *
080:         * <p>In addition, xpath expressions are cached for higher performance.
081:         * Thus, if an expression has been evaluated for a file, the result
082:         * is cached and will be reused, the expression is not evaluated
083:         * a second time. This can be turned off using the <code>cache-expressions</code>
084:         * configuration option.</p>
085:         *
086:         * @author <a href="mailto:jefft@apache.org">Jeff Turner</a>
087:         * @author <a href="mailto:haul@apache.org">Christian Haul</a>
088:         * @version $Id: XMLFileModule.java 540711 2007-05-22 19:36:07Z cziegeler $
089:         */
090:        public class XMLFileModule extends AbstractJXPathModule implements 
091:                Composable, ThreadSafe {
092:
093:            /** Static (cocoon.xconf) configuration location, for error reporting */
094:            String staticConfLocation;
095:
096:            /** Cached documents */
097:            Map documents;
098:
099:            /** Default value for reloadability of sources. Defaults to false. */
100:            boolean reloadAll;
101:
102:            /** Default value for cacheability of sources. Defaults to true. */
103:            boolean cacheAll;
104:
105:            /** Default value for cacheability of xpath expressions. Defaults to true. */
106:            boolean cacheExpressions;
107:
108:            /** Default src */
109:            String src;
110:
111:            SourceResolver resolver;
112:            ComponentManager manager;
113:
114:            //
115:            // need two caches for Object and Object[]
116:            //
117:
118:            /** XPath expression cache for single attribute values. */
119:            private Map expressionCache;
120:
121:            /** XPath expression cache for multiple attribute values. */
122:            private Map expressionValuesCache;
123:
124:            /**
125:             * Takes care of (re-)loading and caching of sources.
126:             */
127:            protected static class DocumentHelper {
128:                private boolean reloadable;
129:                private boolean cacheable;
130:
131:                /** Source location */
132:                private String uri;
133:
134:                /** Source validity */
135:                private SourceValidity validity;
136:
137:                /** Source content cached as DOM Document */
138:                private Document document;
139:
140:                /** Remember who created us (and who's caching us) */
141:                private XMLFileModule instance;
142:
143:                /**
144:                 * Creates a new <code>DocumentHelper</code> instance.
145:                 *
146:                 * @param reload a <code>boolean</code> value, whether this source should be reloaded if changed.
147:                 * @param cache a <code>boolean</code> value, whether this source should be kept in memory.
148:                 * @param src a <code>String</code> value containing the URI
149:                 */
150:                public DocumentHelper(boolean reload, boolean cache,
151:                        String src, XMLFileModule instance) {
152:                    this .reloadable = reload;
153:                    this .cacheable = cache;
154:                    this .uri = src;
155:                    this .instance = instance;
156:                    // defer loading of the document
157:                }
158:
159:                /**
160:                 * Returns the Document belonging to the configured
161:                 * source. Transparently handles reloading and caching.
162:                 *
163:                 * @param manager a <code>ComponentManager</code> value
164:                 * @param resolver a <code>SourceResolver</code> value
165:                 * @return a <code>Document</code> value
166:                 * @exception Exception if an error occurs
167:                 */
168:                public synchronized Document getDocument(
169:                        ComponentManager manager, SourceResolver resolver,
170:                        Logger logger) throws Exception {
171:                    Source src = null;
172:                    Document dom = null;
173:                    try {
174:                        if (this .document == null) {
175:                            if (logger.isDebugEnabled()) {
176:                                logger
177:                                        .debug("Document not cached... Loading uri "
178:                                                + this .uri);
179:                            }
180:                            src = resolver.resolveURI(this .uri);
181:                            this .validity = src.getValidity();
182:                            this .document = SourceUtil.toDOM(src);
183:                        } else if (this .reloadable) {
184:                            if (logger.isDebugEnabled()) {
185:                                logger
186:                                        .debug("Document cached... checking validity of uri "
187:                                                + this .uri);
188:                            }
189:
190:                            int valid = this .validity == null ? SourceValidity.INVALID
191:                                    : this .validity.isValid();
192:                            if (valid != SourceValidity.VALID) {
193:                                // Get new source and validity
194:                                src = resolver.resolveURI(this .uri);
195:                                SourceValidity newValidity = src.getValidity();
196:                                // If already invalid, or invalid after validities comparison, reload
197:                                if (valid == SourceValidity.INVALID
198:                                        || this .validity.isValid(newValidity) != SourceValidity.VALID) {
199:                                    if (logger.isDebugEnabled()) {
200:                                        logger
201:                                                .debug("Reloading document... uri "
202:                                                        + this .uri);
203:                                    }
204:                                    this .validity = newValidity;
205:                                    this .document = SourceUtil.toDOM(src);
206:
207:                                    /*
208:                                     * Clear the cache, otherwise reloads won't do much.
209:                                     *
210:                                     * FIXME (pf): caches should be held in the DocumentHelper
211:                                     *             instance itself, clearing global cache will
212:                                     *             clear everything for each configured document.
213:                                     *             (this is a quick fix, no time to do the whole)
214:                                     */
215:                                    this .instance.flushCache();
216:                                }
217:                            }
218:                        }
219:                        dom = this .document;
220:                    } finally {
221:                        if (src != null) {
222:                            resolver.release(src);
223:                        }
224:                        if (!this .cacheable) {
225:                            if (logger.isDebugEnabled()) {
226:                                logger
227:                                        .debug("Not caching document cached... uri "
228:                                                + this .uri);
229:                            }
230:                            this .validity = null;
231:                            this .document = null;
232:                        }
233:                    }
234:                    if (logger.isDebugEnabled()) {
235:                        logger.debug("Done with document... uri " + this .uri);
236:                    }
237:                    return dom;
238:                }
239:            }
240:
241:            /**
242:             * Set the current <code>ComponentManager</code> instance used by this
243:             * <code>Composable</code>.
244:             */
245:            public void compose(ComponentManager manager)
246:                    throws ComponentException {
247:                this .manager = manager;
248:                this .resolver = (SourceResolver) manager
249:                        .lookup(SourceResolver.ROLE);
250:            }
251:
252:            /**
253:             * Static (cocoon.xconf) configuration.
254:             * Configuration is expected to be of the form:
255:             * &lt;...&gt;
256:             *   &lt;reloadable&gt;true|<b>false</b>&lt;/reloadable&gt;
257:             *   &lt;cacheable&gt;<b>true</b>|false&lt;/cacheable&gt;
258:             *   &lt;file src="<i>src1</i>" reloadable="true|<b>false</b>" cacheable="<b>true</b>|false"/&gt;
259:             *   &lt;file src="<i>src2</i>" reloadable="true|<b>false</b>" cacheable="<b>true</b>|false"/&gt;
260:             *   ...
261:             * &lt;/...&gt;
262:             *
263:             * Each &lt;file/&gt; element pre-loads an XML DOM for querying. Typically only one
264:             * &lt;file&gt; is specified, and its <i>src</i> is used as a default if not
265:             * overridden in the {@link #getContextObject(Configuration, Map)}
266:             *
267:             * @param config a <code>Configuration</code> value, as described above.
268:             * @exception ConfigurationException if an error occurs
269:             */
270:            public void configure(Configuration config)
271:                    throws ConfigurationException {
272:                super .configure(config);
273:                this .staticConfLocation = config.getLocation();
274:                this .reloadAll = config.getChild("reloadable")
275:                        .getValueAsBoolean(false);
276:
277:                if (config.getChild("cachable", false) != null) {
278:                    throw new ConfigurationException("Bzzt! Wrong spelling at "
279:                            + config.getChild("cachable").getLocation()
280:                            + ": please use 'cacheable', not 'cachable'");
281:                }
282:                this .cacheAll = config.getChild("cacheable").getValueAsBoolean(
283:                        true);
284:
285:                this .documents = Collections
286:                        .synchronizedMap(new ReferenceMap());
287:                Configuration[] files = config.getChildren("file");
288:                for (int i = 0; i < files.length; i++) {
289:                    boolean reload = files[i].getAttributeAsBoolean(
290:                            "reloadable", this .reloadAll);
291:                    boolean cache = files[i].getAttributeAsBoolean("cacheable",
292:                            this .cacheAll);
293:                    this .src = files[i].getAttribute("src");
294:                    // by assigning the source uri to this.src the last one will be the default
295:                    // OTOH caching / reload parameters can be specified in one central place
296:                    // if multiple file tags are used.
297:                    this .documents.put(this .src, new DocumentHelper(reload,
298:                            cache, this .src, this ));
299:                }
300:
301:                // init caches
302:                this .cacheExpressions = config.getChild("cache-expressions")
303:                        .getValueAsBoolean(true);
304:                if (this .cacheExpressions) {
305:                    this .expressionCache = new ReferenceMap(
306:                            AbstractReferenceMap.SOFT,
307:                            AbstractReferenceMap.SOFT);
308:                    this .expressionValuesCache = new ReferenceMap(
309:                            AbstractReferenceMap.SOFT,
310:                            AbstractReferenceMap.SOFT);
311:                }
312:            }
313:
314:            /**
315:             * Dispose this component
316:             */
317:            public void dispose() {
318:                super .dispose();
319:                if (this .manager != null) {
320:                    this .manager.release((Component) this .resolver);
321:                    this .resolver = null;
322:                    this .manager = null;
323:                }
324:
325:                this .documents = null;
326:                this .expressionCache = null;
327:                this .expressionValuesCache = null;
328:            }
329:
330:            /**
331:             * Retrieve document helper
332:             */
333:            private DocumentHelper getDocumentHelper(Configuration modeConf)
334:                    throws ConfigurationException {
335:                boolean hasDynamicConf = false; // whether we have a <file src="..."> dynamic configuration
336:                Configuration fileConf = null; // the nested <file>, if any
337:
338:                if (modeConf != null && modeConf.getChildren().length > 0) {
339:                    fileConf = modeConf.getChild("file", false);
340:                    if (fileConf == null) {
341:                        if (this .getLogger().isDebugEnabled()) {
342:                            this .getLogger().debug(
343:                                    "Missing 'file' child element at "
344:                                            + modeConf.getLocation());
345:                        }
346:                    } else {
347:                        hasDynamicConf = true;
348:                    }
349:                }
350:
351:                String src = this .src;
352:                if (hasDynamicConf) {
353:                    src = fileConf.getAttribute("src");
354:                }
355:
356:                if (src == null) {
357:                    throw new ConfigurationException("No source specified"
358:                            + (modeConf != null ? ", either dynamically in "
359:                                    + modeConf.getLocation() + ", or " : "")
360:                            + " statically in " + this .staticConfLocation);
361:                }
362:                if (!this .documents.containsKey(src)) {
363:                    boolean reload = this .reloadAll;
364:                    boolean cache = this .cacheAll;
365:                    if (hasDynamicConf) {
366:                        reload = fileConf.getAttributeAsBoolean("reloadable",
367:                                reload);
368:                        cache = fileConf.getAttributeAsBoolean("cacheable",
369:                                cache);
370:                        if (fileConf.getAttribute("cachable", null) != null) {
371:                            throw new ConfigurationException(
372:                                    "Bzzt! Wrong spelling at "
373:                                            + fileConf.getLocation()
374:                                            + ": please use 'cacheable', not 'cachable'");
375:                        }
376:                    }
377:                    this .documents.put(src, new DocumentHelper(reload, cache,
378:                            src, this ));
379:                }
380:                return (DocumentHelper) this .documents.get(src);
381:            }
382:
383:            /**
384:             * Get the DOM object that JXPath will operate on when evaluating
385:             * attributes.  This DOM is loaded from a Source, specified in the
386:             * modeConf, or (if modeConf is null) from the
387:             * {@link #configure(Configuration)}.
388:             * @param modeConf The dynamic configuration for the current operation. May
389:             * be <code>null</code>, in which case static (cocoon.xconf) configuration
390:             * is used.  Configuration is expected to have a &lt;file> child node, and
391:             * be of the form:
392:             * &lt;...&gt;
393:             *   &lt;file src="..." reloadable="true|false"/&gt;
394:             * &lt;/...&gt;
395:             * @param objectModel Object Model for the current module operation.
396:             */
397:            protected Object getContextObject(Configuration modeConf,
398:                    Map objectModel) throws ConfigurationException {
399:                DocumentHelper helper = this .getDocumentHelper(modeConf);
400:
401:                try {
402:                    return helper.getDocument(this .manager, this .resolver, this 
403:                            .getLogger());
404:                } catch (Exception e) {
405:                    if (this .getLogger().isDebugEnabled()) {
406:                        this .getLogger().debug(
407:                                "Error using source " + this .src + "\n"
408:                                        + e.getMessage(), e);
409:                    }
410:                    throw new ConfigurationException("Error using source "
411:                            + this .src, e);
412:                }
413:            }
414:
415:            public Object getAttribute(String name, Configuration modeConf,
416:                    Map objectModel) throws ConfigurationException {
417:                return this .getAttribute(name, modeConf, objectModel, false);
418:            }
419:
420:            public Object[] getAttributeValues(String name,
421:                    Configuration modeConf, Map objectModel)
422:                    throws ConfigurationException {
423:                Object result = this .getAttribute(name, modeConf, objectModel,
424:                        true);
425:                return (result != null ? (Object[]) result : null);
426:            }
427:
428:            private Object getAttribute(String name, Configuration modeConf,
429:                    Map objectModel, boolean getValues)
430:                    throws ConfigurationException {
431:                Object contextObj = this 
432:                        .getContextObject(modeConf, objectModel);
433:                if (modeConf != null) {
434:                    name = modeConf.getChild("parameter").getValue(
435:                            this .parameter != null ? this .parameter : name);
436:                }
437:
438:                Object result = null;
439:                Map cache = null;
440:                boolean hasBeenCached = false;
441:                if (this .cacheExpressions) {
442:                    cache = this .getExpressionCache(
443:                            getValues ? this .expressionValuesCache
444:                                    : this .expressionCache, contextObj);
445:                    hasBeenCached = cache.containsKey(name);
446:                    if (hasBeenCached) {
447:                        result = cache.get(name);
448:                    }
449:                }
450:
451:                if (!hasBeenCached) {
452:                    if (getValues) {
453:                        result = JXPathHelper.getAttributeValues(name,
454:                                modeConf, this .configuration, contextObj);
455:                    } else {
456:                        result = JXPathHelper.getAttribute(name, modeConf,
457:                                this .configuration, contextObj);
458:                    }
459:                    if (this .cacheExpressions) {
460:                        cache.put(name, result);
461:                        if (this .getLogger().isDebugEnabled()) {
462:                            this .getLogger().debug(
463:                                    "for " + name + " newly caching result "
464:                                            + result);
465:                        }
466:                    } else {
467:                        if (this .getLogger().isDebugEnabled()) {
468:                            this .getLogger().debug(
469:                                    "for " + name + " result is " + result);
470:                        }
471:                    }
472:                } else {
473:                    if (this .getLogger().isDebugEnabled()) {
474:                        this .getLogger().debug(
475:                                "for " + name + " using cached result "
476:                                        + result);
477:                    }
478:                }
479:
480:                return result;
481:            }
482:
483:            protected void flushCache() {
484:                if (this .cacheExpressions) {
485:                    synchronized (this .expressionCache) {
486:                        this .expressionCache.clear();
487:                    }
488:                    synchronized (this .expressionValuesCache) {
489:                        this .expressionValuesCache.clear();
490:                    }
491:                }
492:            }
493:
494:            private Map getExpressionCache(Map cache, Object key) {
495:                synchronized (cache) {
496:                    Map map = (Map) cache.get(key);
497:                    if (map == null) {
498:                        map = Collections.synchronizedMap(new HashMap());
499:                        cache.put(key, map);
500:                    }
501:                    return map;
502:                }
503:            }
504:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.