svn commit: r1413895 - in /cocoon/branches/BRANCH_2_1_X/src: java/org/apache/cocoon/components/modules/input/XPathXMLFileModule.java test/org/apache/cocoon/components/source/impl/ZipSourceTestCase.xtest

[email protected]
Newsgroups gmane.text.xml.cocoon.cvs
Message-ID <[email protected]>
Author: crossley
Date: Mon Nov 26 22:15:10 2012
New Revision: 1413895

URL: http://svn.apache.org/viewvc?rev=1413895&view=rev
Log:
Fix line endings and set svn:eol-style property.

Modified:
    cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/modules/input/XPathXMLFileModule.java   (contents, props changed)
    cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/components/source/impl/ZipSourceTestCase.xtest   (contents, props changed)

Modified: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/modules/input/XPathXMLFileModule.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/modules/input/XPathXMLFileModule.java?rev=1413895&r1=1413894&r2=1413895&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/modules/input/XPathXMLFileModule.java (original)
+++ cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/modules/input/XPathXMLFileModule.java Mon Nov 26 22:15:10 2012
@@ -1,515 +1,515 @@
-package org.apache.cocoon.components.modules.input;
-
-import org.apache.avalon.framework.service.ServiceException;
-import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.Serviceable;
-import org.apache.avalon.framework.thread.ThreadSafe;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.excalibur.source.SourceResolver;
-import org.apache.excalibur.source.SourceValidity;
-import org.apache.excalibur.source.Source;
-import org.apache.excalibur.store.Store;
-import org.apache.cocoon.components.source.SourceUtil;
-import org.apache.cocoon.components.treeprocessor.variables.VariableResolverFactory;
-import org.apache.cocoon.components.treeprocessor.variables.VariableResolver;
-
-import org.apache.cocoon.sitemap.PatternException;
-import org.apache.cocoon.ProcessingException;
-import org.apache.commons.collections.map.ReferenceMap;
-import org.apache.commons.collections.map.AbstractReferenceMap;
-import org.w3c.dom.Document;
-import org.xml.sax.SAXException;
-
-import java.util.Map;
-import java.net.MalformedURLException;
-import java.io.IOException;
-
-/**
- * <grammar>
- *   <define name="input.module.config.contents" combine="choice">
- *     <optional><element name="cacheable"><data type="boolean"/></element></optional>
- *     <optional><element name="reloadable"><data type="boolean"/></element></optional>
- *     <optional>
- *       <ref name="org.apache.cocoon.components.modules.input.XPathXMLFileModule:file">
- *     </optional>
- *     <optional><element name="cache-role"><data type="String"/></element></optional>
- *   </define>
- * <p/>
- *   <define name="input.module.runtime.contents" combine="choice">
- *     <optional>
- *       <ref name="org.apache.cocoon.components.modules.input.XPathXMLFileModule:file">
- *     </optional>
- *   </define>
- * <p/>
- *   <define name="org.apache.cocoon.components.modules.input.XPathXMLFileModule:file">
- *     <element name="file">
- *       <attribute name="src"><data type="anyURI"/></attribute>
- *       <optional><attribute name="cacheable"><data type="boolean"/></attribute></optional>
- *       <optional><attribute name="reloadable"><data type="boolean"/></attribute></optional>
- *     </element>
- *   </define>
- * </grammar>
- * <p/>
- * This module provides an Input Module interface to any XML document, by using
- * XPath expressions as attribute keys.
- * The XML can be obtained from any Cocoon <code>Source</code> (e.g.,
- * <code>cocoon:/...</code>, <code>context://..</code>, and regular URLs).
- * Sources can be cached in memory for better performance and reloaded if
- * changed. The source can also contain references to other input modules to allow the source
- * file name to be determined dynamically.
- * <p/>
- * Caching and reloading can be turned on / off (default: caching on,
- * reloading off) through <code>&lt;reloadable&gt;false&lt;/reloadable&gt;</code>
- * and <code>&lt;cacheable&gt;false&lt;/cacheable&gt;</code>. The file
- * (source) to use is specified through <code>&lt;file
- * src="protocol:path/to/file.xml" reloadable="true" cacheable="true"/&gt;</code>
- * optionally overriding the defaults for caching and/or reloading. When specfied as attributes
- * to the file element the values for cacheable and reloadable may be input module references which
- * will be resolved on every call. These must resolve to 'true' or 'false'.
- * </>
- * The XML documents will be cached using the Store configured via the cache-role configuration
- * element. If not specified the default Store as specified in this classes ROLE attribute will
- * be used.
- * <p/>
- * In addition, xpath expressions can be cached for higher performance.
- * Thus, if an expression has been evaluated for a file, the result
- * is cached and will be reused, the expression is not evaluated
- * a second time. This can be turned off using the <code>cache-expressions</code>
- * configuration option.
- *
- * @version $Id: $
- */
-public class XPathXMLFileModule extends AbstractInputModule
-    implements Serviceable, ThreadSafe
-{
-    public static final String ROLE = Store.ROLE + "/XPathXMLFileTransientStore";
-    /**
-     * Contains all globally registered extension classes and
-     * packages. Thus the lookup and loading of globally registered
-     * extensions is done only once.
-     */
-    protected JXPathHelperConfiguration configuration;
-
-    /**
-     * Static (cocoon.xconf) configuration location, for error reporting
-     */
-    String staticConfLocation;
-
-    /**
-     * Cached documents
-     */
-    private Store cache;
-
-    /**
-     * Determines whether the configured source document should be cached.
-     */
-    private String  cacheParm;
-    private Boolean cacheSource;
-
-    /**
-     * Determines whether the configured source document should be reloaded.
-     */
-    private String  reloadParm;
-    private Boolean reloadSource;
-
-    /**
-     * Default value for reloadability of sources. Defaults to false.
-     */
-    boolean reloadAll;
-    /**
-     * Default value for cacheability of xpath expressions. Defaults to true.
-     */
-    private boolean cacheExpressions;
-
-    /**
-     *  Whether the source needs to be resolved.
-     */
-    private boolean needsResolve;
-
-    /**
-     * Overrides attribute name
-     */
-    protected String parameter;
-
-    /**
-     * Default src
-     */
-    private String src;
-
-    protected SourceResolver resolver;
-    protected ServiceManager manager;
-
-
-    /* (non-Javadoc)
-    * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
-    */
-    public void service(ServiceManager manager) throws ServiceException {
-        this.manager = manager;
-        this.resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
-    }
-
-    /**
-     * Static (cocoon.xconf) configuration.
-     * Configuration is expected to be of the form:
-     * &lt;...&gt;
-     * &lt;reloadable&gt;<b>true</b>|false&lt;/reloadable&gt;
-     * &lt;cacheable&gt;<b>true</b>|false&lt;/cacheable&gt;
-     * &lt;cache-role&gt;org.apache.excalibur.store.Store/TransientStore&lt;/cache-role&gt;
-     * &lt;file src="<i>src</i>"/&gt;
-     * ...
-     * &lt;/...&gt;
-     * <p/>
-     * The &lt;file/&gt; element specifies a file pattern. Only one
-     * &lt;file&gt; can be specified, however it can contain references to input modules which will be resolved
-     * each time the module is used. The configured <i>src</i> is used if not
-     * overridden via a file parameter in the sitemap.
-     *
-     * @param config a <code>Configuration</code> value, as described above.
-     * @throws org.apache.avalon.framework.configuration.ConfigurationException
-     *          if an error occurs
-     */
-    public void configure(Configuration config) throws ConfigurationException {
-        this.configuration = JXPathHelper.setup(config);
-        this.staticConfLocation = config.getLocation();
-        Configuration roleConfig = config.getChild("cache-role", true);
-        boolean cacheAll = config.getChild("cacheable").getValueAsBoolean(true);
-        this.reloadAll = config.getChild("reloadable").getValueAsBoolean(true);
-        String cacheRole = roleConfig.getValue(ROLE);
-
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Using cache " + cacheRole);
-        }
-
-        try {
-            this.cache = (Store) this.manager.lookup(cacheRole);
-        } catch (ServiceException ce) {
-            throw new ConfigurationException("Unable to lookup cache: " + cacheRole, ce);
-        }
-
-        Configuration fileConfig = config.getChild("file");
-
-        this.src = fileConfig.getAttribute("src");
-        this.cacheParm = fileConfig.getAttribute("cacheable", null);
-        this.reloadParm = fileConfig.getAttribute("reloadable", null);
-        if (this.cacheParm == null) {
-            this.cacheSource = Boolean.valueOf(cacheAll);
-        } else if (VariableResolverFactory.needsResolve(this.cacheParm)) {
-            this.cacheSource = null;
-        } else {
-            this.cacheSource = Boolean.valueOf(this.cacheParm);
-        }
-        if (this.reloadParm == null) {
-            this.reloadSource = Boolean.valueOf(this.reloadAll);
-        } else if (VariableResolverFactory.needsResolve(this.reloadParm)) {
-            this.reloadSource = null;
-        } else {
-            this.reloadSource = Boolean.valueOf(this.reloadParm);
-        }
-
-        // init caches
-        this.cacheExpressions = config.getChild("cache-expressions").getValueAsBoolean(true);
-        this.needsResolve = VariableResolverFactory.needsResolve(this.src);
-    }
-
-    /**
-     * Dispose this component
-     */
-    public void dispose() {
-        super.dispose();
-        if (this.manager != null) {
-            this.manager.release(this.resolver);
-            this.manager.release(this.cache);
-            this.resolver = null;
-            this.cache = null;
-            this.manager = null;
-        }
-    }
-
-    public Object getAttribute(String name, Configuration modeConf, Map objectModel)
-        throws ConfigurationException {
-        return getAttribute(name, modeConf, objectModel, false);
-    }
-
-    public Object[] getAttributeValues(String name, Configuration modeConf, Map objectModel)
-        throws ConfigurationException {
-        Object result = getAttribute(name, modeConf, objectModel, true);
-        return (result != null ? (Object[]) result : null);
-    }
-    /**
-     * Get the DocumentInfo for the DOM object that JXPath will operate on when evaluating
-     * attributes.  This DOM is loaded from a Source, specified in the
-     * modeConf, or (if modeConf is null) from the
-     * {@link #configure(org.apache.avalon.framework.configuration.Configuration)}.
-     *
-     * @param name The JXPath to retrieve
-     * @param modeConf    The dynamic configuration for the current operation. May
-     *                    be <code>null</code>, in which case static (cocoon.xconf) configuration
-     *                    is used.  Configuration is expected to have a &lt;file> child node, and
-     *                    be of the form:
-     *                    &lt;...&gt;
-     *                    &lt;file src="..." reloadable="true|false"/&gt;
-     *                    &lt;/...&gt;
-     * @param objectModel Object Model for the current module operation.
-     * @param getValues true if multiple values should be retrieve, false otherwise
-     * @return the result of the XPath query into the XML document
-     * @throws ConfigurationException if an error occurs.
-     */
-    private Object getAttribute(String name, Configuration modeConf, Map objectModel, boolean getValues)
-        throws ConfigurationException {
-
-        if (modeConf != null) {
-            name = modeConf.getChild("parameter").getValue(this.parameter != null ? this.parameter : name);
-        }
-
-        boolean hasDynamicConf = false; // whether we have a <file src="..."> dynamic configuration
-        Configuration fileConf = null;  // the nested <file>, if any
-
-        if (modeConf != null && modeConf.getChildren().length > 0) {
-            fileConf = modeConf.getChild("file", false);
-            if (fileConf == null) {
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("Missing 'file' child element at " + modeConf.getLocation());
-                }
-            } else {
-                hasDynamicConf = true;
-            }
-        }
-
-        String src = this.src;
-        Boolean cacheSource = this.cacheSource;
-        Boolean reloadSource = this.cacheSource;
-        boolean needsResolve = this.needsResolve;
-        String cacheParm = this.cacheParm;
-        String reloadParm = this.reloadParm;
-
-        if (hasDynamicConf) {
-            src = fileConf.getAttribute("src");
-            cacheParm = fileConf.getAttribute("cacheable", this.cacheParm);
-            reloadParm = fileConf.getAttribute("reloadable", this.reloadParm);
-            if (cacheParm == null) {
-                cacheSource = this.cacheSource;
-            } else if (VariableResolverFactory.needsResolve(cacheParm)) {
-                cacheSource = null;
-                if (cacheSource == null) {
-                    try {
-                        VariableResolver varResolver = VariableResolverFactory.getResolver(cacheParm, this.manager);
-                        cacheSource = Boolean.valueOf(varResolver.resolve(objectModel));
-                    } catch (PatternException pe) {
-                        throw new ConfigurationException("Error resolving " + cacheParm, pe);
-                    }
-                }
-            } else {
-                cacheSource = Boolean.valueOf(cacheParm);
-            }
-            if (reloadParm == null) {
-                reloadSource = this.reloadSource;
-            } else if (VariableResolverFactory.needsResolve(reloadParm)) {
-                reloadSource = null;
-            } else {
-                reloadSource = Boolean.valueOf(reloadParm);
-            }
-            needsResolve = true;
-        }
-        if (cacheSource == null) {
-            try {
-                VariableResolver varResolver = VariableResolverFactory.getResolver(cacheParm, this.manager);
-                cacheSource = Boolean.valueOf(varResolver.resolve(objectModel));
-            } catch (PatternException pe) {
-                throw new ConfigurationException("Error resolving " + cacheParm, pe);
-            }
-        }
-        if (reloadSource == null) {
-            try {
-                VariableResolver varResolver =
-                    VariableResolverFactory.getResolver(reloadParm, this.manager);
-                reloadSource = Boolean.valueOf(varResolver.resolve(objectModel));
-            } catch (PatternException pe) {
-                throw new ConfigurationException("Error resolving " + reloadParm, pe);
-            }
-        }
-
-        if (src == null) {
-            throw new ConfigurationException(
-                "No source specified"
-                    + (modeConf != null ? ", either dynamically in " + modeConf.getLocation() + ", or " : "")
-                    + " statically in "
-                    + staticConfLocation);
-        }
-
-        if (needsResolve) {
-            try {
-                VariableResolver varResolver = VariableResolverFactory.getResolver(src, this.manager);
-                src = varResolver.resolve(objectModel);
-            } catch (PatternException pe) {
-                throw new ConfigurationException("Error resolving variables for " + src, pe);
-            }
-        }
-
-        Object result;
-
-        if (cacheSource.booleanValue()) {
-            DocumentInfo info = (DocumentInfo) this.cache.get(src);
-            if (info == null || (reloadSource.booleanValue() && !info.isValid())) {
-                Source docSource = null;
-                try {
-                    docSource = resolver.resolveURI(src);
-                    DocumentInfo newInfo =  new DocumentInfo(src, SourceUtil.toDOM(docSource),
-                        docSource.getValidity(), this.cacheExpressions, this.resolver);
-                    synchronized(this.cache) {
-                        DocumentInfo cachedInfo = (DocumentInfo)this.cache.get(src);
-                        if (cachedInfo == null || cachedInfo == info) {
-                            this.cache.store(src, newInfo);
-                            info = newInfo;
-                        } else {
-                            info = cachedInfo;
-                        }
-                    }
-                } catch (MalformedURLException mue) {
-                    throw new ConfigurationException("Unable to resolve " + src, mue);
-                } catch (IOException ioe) {
-                    throw new ConfigurationException("Unable to access" + src, ioe);
-                } catch (ProcessingException pe) {
-                    throw new ConfigurationException("Unable to process " + src, pe);
-                } catch (SAXException se) {
-                    throw new ConfigurationException("Error processing XML document " + src, se);
-                } finally {
-                    if (docSource != null) {
-                        resolver.release(docSource);
-                    }
-                }
-            }
-            if (info.cacheExpressions) {
-                Map cache = getValues ? info.expressionValuesCache : info.expressionCache;
-                synchronized (cache) {
-                    if (cache.containsKey(name)) {
-                        result = cache.get(name);
-                        if (getLogger().isDebugEnabled()) {
-                            getLogger().debug("for " + name + " using cached result " + result);
-                        }
-                    } else {
-                        result = getResult(name, info.document, modeConf, getValues);
-                        if (result != null) {
-                            cache.put(name, result);
-                            if (getLogger().isDebugEnabled()) {
-                                getLogger().debug("for " + name + " newly caching result " + result);
-                            }
-                        } else {
-                            if (getLogger().isDebugEnabled()) {
-                                getLogger().debug("for " + name + " result is null");
-                            }
-                        }
-                    }
-                }
-            } else {
-                result = getResult(name, info.document, modeConf, getValues);
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("for " + name + " result is " + result);
-                }
-            }
-        } else {
-            Source docSource = null;
-            try {
-                docSource = resolver.resolveURI(src);
-                result = getResult(name, SourceUtil.toDOM(docSource), modeConf, getValues);
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("for " + name + " result is " + result);
-                }
-            } catch (MalformedURLException mue) {
-                throw new ConfigurationException("Unable to resolve " + src, mue);
-            } catch (IOException ioe) {
-                throw new ConfigurationException("Unable to access" + src, ioe);
-            } catch (ProcessingException pe) {
-                throw new ConfigurationException("Unable to process " + src, pe);
-            } catch (SAXException se) {
-                throw new ConfigurationException("Error processing XML document " + src, se);
-            } finally {
-                if (docSource != null) {
-                    resolver.release(docSource);
-                }
-            }
-        }
-
-        return result;
-    }
-
-    private Object getResult(String name, Document document, Configuration modeConf, boolean getValues)
-        throws ConfigurationException {
-        Object result;
-
-        if (getValues) {
-            result = JXPathHelper.getAttributeValues(name, modeConf, this.configuration, document);
-        } else {
-            result = JXPathHelper.getAttributeValue(name, modeConf, this.configuration, document);
-        }
-        return result;
-    }
-
-    /**
-     * Used to keep track of the Document, its validity and any cached expressions.
-     */
-    private static class DocumentInfo
-    {
-        public DocumentInfo(String uri, Document doc, SourceValidity validity, boolean cacheExpressions,
-                            SourceResolver resolver) {
-            this.cacheExpressions = cacheExpressions;
-            if (cacheExpressions) {
-                expressionCache = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.SOFT);
-                expressionValuesCache = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.SOFT);
-            }
-            this.resolver = resolver;
-            this.uri = uri;
-            this.document = doc;
-            this.validity = validity;
-        }
-
-        private boolean cacheExpressions;
-
-        private final String uri;
-
-        private final SourceValidity validity;
-
-        private final SourceResolver resolver;
-
-        /**
-         * Source content cached as DOM Document
-         */
-        private final Document document;
-
-        private Map expressionCache;
-        private Map expressionValuesCache;
-
-        /**
-         * Returns true if the document is valid, false otherwise.
-         * <p/>
-         *
-         * @return returns true if the document is valid, false otherwise.
-         */
-        private boolean isValid() {
-            Source src = null;
-            boolean result = true;
-
-            try {
-                int valid = validity == null ? SourceValidity.INVALID : validity.isValid();
-                if (valid == SourceValidity.UNKNOWN) {
-                    // Get new source and validity
-                    src = resolver.resolveURI(this.uri);
-                    SourceValidity newValidity = src.getValidity();
-                    valid = validity.isValid(newValidity);
-                }
-                if (valid != SourceValidity.VALID) {
-                    result = false;
-                }
-            }
-            catch (Exception ex) {
-                result = false;
-            }
-            finally {
-                if (src != null) {
-                    resolver.release(src);
-                }
-            }
-            return result;
-        }
-    }
+package org.apache.cocoon.components.modules.input;
+
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.excalibur.source.SourceResolver;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.store.Store;
+import org.apache.cocoon.components.source.SourceUtil;
+import org.apache.cocoon.components.treeprocessor.variables.VariableResolverFactory;
+import org.apache.cocoon.components.treeprocessor.variables.VariableResolver;
+
+import org.apache.cocoon.sitemap.PatternException;
+import org.apache.cocoon.ProcessingException;
+import org.apache.commons.collections.map.ReferenceMap;
+import org.apache.commons.collections.map.AbstractReferenceMap;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import java.util.Map;
+import java.net.MalformedURLException;
+import java.io.IOException;
+
+/**
+ * <grammar>
+ *   <define name="input.module.config.contents" combine="choice">
+ *     <optional><element name="cacheable"><data type="boolean"/></element></optional>
+ *     <optional><element name="reloadable"><data type="boolean"/></element></optional>
+ *     <optional>
+ *       <ref name="org.apache.cocoon.components.modules.input.XPathXMLFileModule:file">
+ *     </optional>
+ *     <optional><element name="cache-role"><data type="String"/></element></optional>
+ *   </define>
+ * <p/>
+ *   <define name="input.module.runtime.contents" combine="choice">
+ *     <optional>
+ *       <ref name="org.apache.cocoon.components.modules.input.XPathXMLFileModule:file">
+ *     </optional>
+ *   </define>
+ * <p/>
+ *   <define name="org.apache.cocoon.components.modules.input.XPathXMLFileModule:file">
+ *     <element name="file">
+ *       <attribute name="src"><data type="anyURI"/></attribute>
+ *       <optional><attribute name="cacheable"><data type="boolean"/></attribute></optional>
+ *       <optional><attribute name="reloadable"><data type="boolean"/></attribute></optional>
+ *     </element>
+ *   </define>
+ * </grammar>
+ * <p/>
+ * This module provides an Input Module interface to any XML document, by using
+ * XPath expressions as attribute keys.
+ * The XML can be obtained from any Cocoon <code>Source</code> (e.g.,
+ * <code>cocoon:/...</code>, <code>context://..</code>, and regular URLs).
+ * Sources can be cached in memory for better performance and reloaded if
+ * changed. The source can also contain references to other input modules to allow the source
+ * file name to be determined dynamically.
+ * <p/>
+ * Caching and reloading can be turned on / off (default: caching on,
+ * reloading off) through <code>&lt;reloadable&gt;false&lt;/reloadable&gt;</code>
+ * and <code>&lt;cacheable&gt;false&lt;/cacheable&gt;</code>. The file
+ * (source) to use is specified through <code>&lt;file
+ * src="protocol:path/to/file.xml" reloadable="true" cacheable="true"/&gt;</code>
+ * optionally overriding the defaults for caching and/or reloading. When specfied as attributes
+ * to the file element the values for cacheable and reloadable may be input module references which
+ * will be resolved on every call. These must resolve to 'true' or 'false'.
+ * </>
+ * The XML documents will be cached using the Store configured via the cache-role configuration
+ * element. If not specified the default Store as specified in this classes ROLE attribute will
+ * be used.
+ * <p/>
+ * In addition, xpath expressions can be cached for higher performance.
+ * Thus, if an expression has been evaluated for a file, the result
+ * is cached and will be reused, the expression is not evaluated
+ * a second time. This can be turned off using the <code>cache-expressions</code>
+ * configuration option.
+ *
+ * @version $Id: $
+ */
+public class XPathXMLFileModule extends AbstractInputModule
+    implements Serviceable, ThreadSafe
+{
+    public static final String ROLE = Store.ROLE + "/XPathXMLFileTransientStore";
+    /**
+     * Contains all globally registered extension classes and
+     * packages. Thus the lookup and loading of globally registered
+     * extensions is done only once.
+     */
+    protected JXPathHelperConfiguration configuration;
+
+    /**
+     * Static (cocoon.xconf) configuration location, for error reporting
+     */
+    String staticConfLocation;
+
+    /**
+     * Cached documents
+     */
+    private Store cache;
+
+    /**
+     * Determines whether the configured source document should be cached.
+     */
+    private String  cacheParm;
+    private Boolean cacheSource;
+
+    /**
+     * Determines whether the configured source document should be reloaded.
+     */
+    private String  reloadParm;
+    private Boolean reloadSource;
+
+    /**
+     * Default value for reloadability of sources. Defaults to false.
+     */
+    boolean reloadAll;
+    /**
+     * Default value for cacheability of xpath expressions. Defaults to true.
+     */
+    private boolean cacheExpressions;
+
+    /**
+     *  Whether the source needs to be resolved.
+     */
+    private boolean needsResolve;
+
+    /**
+     * Overrides attribute name
+     */
+    protected String parameter;
+
+    /**
+     * Default src
+     */
+    private String src;
+
+    protected SourceResolver resolver;
+    protected ServiceManager manager;
+
+
+    /* (non-Javadoc)
+    * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+    */
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+        this.resolver = (SourceResolver) manager.lookup(SourceResolver.ROLE);
+    }
+
+    /**
+     * Static (cocoon.xconf) configuration.
+     * Configuration is expected to be of the form:
+     * &lt;...&gt;
+     * &lt;reloadable&gt;<b>true</b>|false&lt;/reloadable&gt;
+     * &lt;cacheable&gt;<b>true</b>|false&lt;/cacheable&gt;
+     * &lt;cache-role&gt;org.apache.excalibur.store.Store/TransientStore&lt;/cache-role&gt;
+     * &lt;file src="<i>src</i>"/&gt;
+     * ...
+     * &lt;/...&gt;
+     * <p/>
+     * The &lt;file/&gt; element specifies a file pattern. Only one
+     * &lt;file&gt; can be specified, however it can contain references to input modules which will be resolved
+     * each time the module is used. The configured <i>src</i> is used if not
+     * overridden via a file parameter in the sitemap.
+     *
+     * @param config a <code>Configuration</code> value, as described above.
+     * @throws org.apache.avalon.framework.configuration.ConfigurationException
+     *          if an error occurs
+     */
+    public void configure(Configuration config) throws ConfigurationException {
+        this.configuration = JXPathHelper.setup(config);
+        this.staticConfLocation = config.getLocation();
+        Configuration roleConfig = config.getChild("cache-role", true);
+        boolean cacheAll = config.getChild("cacheable").getValueAsBoolean(true);
+        this.reloadAll = config.getChild("reloadable").getValueAsBoolean(true);
+        String cacheRole = roleConfig.getValue(ROLE);
+
+        if (getLogger().isDebugEnabled()) {
+            getLogger().debug("Using cache " + cacheRole);
+        }
+
+        try {
+            this.cache = (Store) this.manager.lookup(cacheRole);
+        } catch (ServiceException ce) {
+            throw new ConfigurationException("Unable to lookup cache: " + cacheRole, ce);
+        }
+
+        Configuration fileConfig = config.getChild("file");
+
+        this.src = fileConfig.getAttribute("src");
+        this.cacheParm = fileConfig.getAttribute("cacheable", null);
+        this.reloadParm = fileConfig.getAttribute("reloadable", null);
+        if (this.cacheParm == null) {
+            this.cacheSource = Boolean.valueOf(cacheAll);
+        } else if (VariableResolverFactory.needsResolve(this.cacheParm)) {
+            this.cacheSource = null;
+        } else {
+            this.cacheSource = Boolean.valueOf(this.cacheParm);
+        }
+        if (this.reloadParm == null) {
+            this.reloadSource = Boolean.valueOf(this.reloadAll);
+        } else if (VariableResolverFactory.needsResolve(this.reloadParm)) {
+            this.reloadSource = null;
+        } else {
+            this.reloadSource = Boolean.valueOf(this.reloadParm);
+        }
+
+        // init caches
+        this.cacheExpressions = config.getChild("cache-expressions").getValueAsBoolean(true);
+        this.needsResolve = VariableResolverFactory.needsResolve(this.src);
+    }
+
+    /**
+     * Dispose this component
+     */
+    public void dispose() {
+        super.dispose();
+        if (this.manager != null) {
+            this.manager.release(this.resolver);
+            this.manager.release(this.cache);
+            this.resolver = null;
+            this.cache = null;
+            this.manager = null;
+        }
+    }
+
+    public Object getAttribute(String name, Configuration modeConf, Map objectModel)
+        throws ConfigurationException {
+        return getAttribute(name, modeConf, objectModel, false);
+    }
+
+    public Object[] getAttributeValues(String name, Configuration modeConf, Map objectModel)
+        throws ConfigurationException {
+        Object result = getAttribute(name, modeConf, objectModel, true);
+        return (result != null ? (Object[]) result : null);
+    }
+    /**
+     * Get the DocumentInfo for the DOM object that JXPath will operate on when evaluating
+     * attributes.  This DOM is loaded from a Source, specified in the
+     * modeConf, or (if modeConf is null) from the
+     * {@link #configure(org.apache.avalon.framework.configuration.Configuration)}.
+     *
+     * @param name The JXPath to retrieve
+     * @param modeConf    The dynamic configuration for the current operation. May
+     *                    be <code>null</code>, in which case static (cocoon.xconf) configuration
+     *                    is used.  Configuration is expected to have a &lt;file> child node, and
+     *                    be of the form:
+     *                    &lt;...&gt;
+     *                    &lt;file src="..." reloadable="true|false"/&gt;
+     *                    &lt;/...&gt;
+     * @param objectModel Object Model for the current module operation.
+     * @param getValues true if multiple values should be retrieve, false otherwise
+     * @return the result of the XPath query into the XML document
+     * @throws ConfigurationException if an error occurs.
+     */
+    private Object getAttribute(String name, Configuration modeConf, Map objectModel, boolean getValues)
+        throws ConfigurationException {
+
+        if (modeConf != null) {
+            name = modeConf.getChild("parameter").getValue(this.parameter != null ? this.parameter : name);
+        }
+
+        boolean hasDynamicConf = false; // whether we have a <file src="..."> dynamic configuration
+        Configuration fileConf = null;  // the nested <file>, if any
+
+        if (modeConf != null && modeConf.getChildren().length > 0) {
+            fileConf = modeConf.getChild("file", false);
+            if (fileConf == null) {
+                if (getLogger().isDebugEnabled()) {
+                    getLogger().debug("Missing 'file' child element at " + modeConf.getLocation());
+                }
+            } else {
+                hasDynamicConf = true;
+            }
+        }
+
+        String src = this.src;
+        Boolean cacheSource = this.cacheSource;
+        Boolean reloadSource = this.cacheSource;
+        boolean needsResolve = this.needsResolve;
+        String cacheParm = this.cacheParm;
+        String reloadParm = this.reloadParm;
+
+        if (hasDynamicConf) {
+            src = fileConf.getAttribute("src");
+            cacheParm = fileConf.getAttribute("cacheable", this.cacheParm);
+            reloadParm = fileConf.getAttribute("reloadable", this.reloadParm);
+            if (cacheParm == null) {
+                cacheSource = this.cacheSource;
+            } else if (VariableResolverFactory.needsResolve(cacheParm)) {
+                cacheSource = null;
+                if (cacheSource == null) {
+                    try {
+                        VariableResolver varResolver = VariableResolverFactory.getResolver(cacheParm, this.manager);
+                        cacheSource = Boolean.valueOf(varResolver.resolve(objectModel));
+                    } catch (PatternException pe) {
+                        throw new ConfigurationException("Error resolving " + cacheParm, pe);
+                    }
+                }
+            } else {
+                cacheSource = Boolean.valueOf(cacheParm);
+            }
+            if (reloadParm == null) {
+                reloadSource = this.reloadSource;
+            } else if (VariableResolverFactory.needsResolve(reloadParm)) {
+                reloadSource = null;
+            } else {
+                reloadSource = Boolean.valueOf(reloadParm);
+            }
+            needsResolve = true;
+        }
+        if (cacheSource == null) {
+            try {
+                VariableResolver varResolver = VariableResolverFactory.getResolver(cacheParm, this.manager);
+                cacheSource = Boolean.valueOf(varResolver.resolve(objectModel));
+            } catch (PatternException pe) {
+                throw new ConfigurationException("Error resolving " + cacheParm, pe);
+            }
+        }
+        if (reloadSource == null) {
+            try {
+                VariableResolver varResolver =
+                    VariableResolverFactory.getResolver(reloadParm, this.manager);
+                reloadSource = Boolean.valueOf(varResolver.resolve(objectModel));
+            } catch (PatternException pe) {
+                throw new ConfigurationException("Error resolving " + reloadParm, pe);
+            }
+        }
+
+        if (src == null) {
+            throw new ConfigurationException(
+                "No source specified"
+                    + (modeConf != null ? ", either dynamically in " + modeConf.getLocation() + ", or " : "")
+                    + " statically in "
+                    + staticConfLocation);
+        }
+
+        if (needsResolve) {
+            try {
+                VariableResolver varResolver = VariableResolverFactory.getResolver(src, this.manager);
+                src = varResolver.resolve(objectModel);
+            } catch (PatternException pe) {
+                throw new ConfigurationException("Error resolving variables for " + src, pe);
+            }
+        }
+
+        Object result;
+
+        if (cacheSource.booleanValue()) {
+            DocumentInfo info = (DocumentInfo) this.cache.get(src);
+            if (info == null || (reloadSource.booleanValue() && !info.isValid())) {
+                Source docSource = null;
+                try {
+                    docSource = resolver.resolveURI(src);
+                    DocumentInfo newInfo =  new DocumentInfo(src, SourceUtil.toDOM(docSource),
+                        docSource.getValidity(), this.cacheExpressions, this.resolver);
+                    synchronized(this.cache) {
+                        DocumentInfo cachedInfo = (DocumentInfo)this.cache.get(src);
+                        if (cachedInfo == null || cachedInfo == info) {
+                            this.cache.store(src, newInfo);
+                            info = newInfo;
+                        } else {
+                            info = cachedInfo;
+                        }
+                    }
+                } catch (MalformedURLException mue) {
+                    throw new ConfigurationException("Unable to resolve " + src, mue);
+                } catch (IOException ioe) {
+                    throw new ConfigurationException("Unable to access" + src, ioe);
+                } catch (ProcessingException pe) {
+                    throw new ConfigurationException("Unable to process " + src, pe);
+                } catch (SAXException se) {
+                    throw new ConfigurationException("Error processing XML document " + src, se);
+                } finally {
+                    if (docSource != null) {
+                        resolver.release(docSource);
+                    }
+                }
+            }
+            if (info.cacheExpressions) {
+                Map cache = getValues ? info.expressionValuesCache : info.expressionCache;
+                synchronized (cache) {
+                    if (cache.containsKey(name)) {
+                        result = cache.get(name);
+                        if (getLogger().isDebugEnabled()) {
+                            getLogger().debug("for " + name + " using cached result " + result);
+                        }
+                    } else {
+                        result = getResult(name, info.document, modeConf, getValues);
+                        if (result != null) {
+                            cache.put(name, result);
+                            if (getLogger().isDebugEnabled()) {
+                                getLogger().debug("for " + name + " newly caching result " + result);
+                            }
+                        } else {
+                            if (getLogger().isDebugEnabled()) {
+                                getLogger().debug("for " + name + " result is null");
+                            }
+                        }
+                    }
+                }
+            } else {
+                result = getResult(name, info.document, modeConf, getValues);
+                if (getLogger().isDebugEnabled()) {
+                    getLogger().debug("for " + name + " result is " + result);
+                }
+            }
+        } else {
+            Source docSource = null;
+            try {
+                docSource = resolver.resolveURI(src);
+                result = getResult(name, SourceUtil.toDOM(docSource), modeConf, getValues);
+                if (getLogger().isDebugEnabled()) {
+                    getLogger().debug("for " + name + " result is " + result);
+                }
+            } catch (MalformedURLException mue) {
+                throw new ConfigurationException("Unable to resolve " + src, mue);
+            } catch (IOException ioe) {
+                throw new ConfigurationException("Unable to access" + src, ioe);
+            } catch (ProcessingException pe) {
+                throw new ConfigurationException("Unable to process " + src, pe);
+            } catch (SAXException se) {
+                throw new ConfigurationException("Error processing XML document " + src, se);
+            } finally {
+                if (docSource != null) {
+                    resolver.release(docSource);
+                }
+            }
+        }
+
+        return result;
+    }
+
+    private Object getResult(String name, Document document, Configuration modeConf, boolean getValues)
+        throws ConfigurationException {
+        Object result;
+
+        if (getValues) {
+            result = JXPathHelper.getAttributeValues(name, modeConf, this.configuration, document);
+        } else {
+            result = JXPathHelper.getAttributeValue(name, modeConf, this.configuration, document);
+        }
+        return result;
+    }
+
+    /**
+     * Used to keep track of the Document, its validity and any cached expressions.
+     */
+    private static class DocumentInfo
+    {
+        public DocumentInfo(String uri, Document doc, SourceValidity validity, boolean cacheExpressions,
+                            SourceResolver resolver) {
+            this.cacheExpressions = cacheExpressions;
+            if (cacheExpressions) {
+                expressionCache = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.SOFT);
+                expressionValuesCache = new ReferenceMap(AbstractReferenceMap.SOFT, AbstractReferenceMap.SOFT);
+            }
+            this.resolver = resolver;
+            this.uri = uri;
+            this.document = doc;
+            this.validity = validity;
+        }
+
+        private boolean cacheExpressions;
+
+        private final String uri;
+
+        private final SourceValidity validity;
+
+        private final SourceResolver resolver;
+
+        /**
+         * Source content cached as DOM Document
+         */
+        private final Document document;
+
+        private Map expressionCache;
+        private Map expressionValuesCache;
+
+        /**
+         * Returns true if the document is valid, false otherwise.
+         * <p/>
+         *
+         * @return returns true if the document is valid, false otherwise.
+         */
+        private boolean isValid() {
+            Source src = null;
+            boolean result = true;
+
+            try {
+                int valid = validity == null ? SourceValidity.INVALID : validity.isValid();
+                if (valid == SourceValidity.UNKNOWN) {
+                    // Get new source and validity
+                    src = resolver.resolveURI(this.uri);
+                    SourceValidity newValidity = src.getValidity();
+                    valid = validity.isValid(newValidity);
+                }
+                if (valid != SourceValidity.VALID) {
+                    result = false;
+                }
+            }
+            catch (Exception ex) {
+                result = false;
+            }
+            finally {
+                if (src != null) {
+                    resolver.release(src);
+                }
+            }
+            return result;
+        }
+    }
 }
\ No newline at end of file

Propchange: cocoon/branches/BRANCH_2_1_X/src/java/org/apache/cocoon/components/modules/input/XPathXMLFileModule.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/components/source/impl/ZipSourceTestCase.xtest
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/components/source/impl/ZipSourceTestCase.xtest?rev=1413895&r1=1413894&r2=1413895&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/components/source/impl/ZipSourceTestCase.xtest (original)
+++ cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/components/source/impl/ZipSourceTestCase.xtest Mon Nov 26 22:15:10 2012
@@ -1,39 +1,39 @@
-<?xml version="1.0" ?>
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one or more
-  contributor license agreements.  See the NOTICE file distributed with
-  this work for additional information regarding copyright ownership.
-  The ASF licenses this file to You under the Apache License, Version 2.0
-  (the "License"); you may not use this file except in compliance with
-  the License.  You may obtain a copy of the License at
-
-      http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
-<testcase>
- <roles>
-  <role name="org.apache.excalibur.source.SourceFactorySelector"
-        shorthand="source-factories"
-        default-class="org.apache.avalon.excalibur.component.ExcaliburComponentSelector"/>
-
-  <role name="org.apache.excalibur.source.SourceResolver"
-        shorthand="source-resolver"
-        default-class="org.apache.excalibur.source.impl.SourceResolverImpl"/>
- </roles>
-
- <components>
-  <source-factories>
-   <component-instance class="org.apache.excalibur.source.impl.ResourceSourceFactory" name="resource"/>
-   <component-instance class="org.apache.cocoon.components.source.impl.ZipSourceFactory" name="zip"/>
-   <component-instance class="org.apache.excalibur.source.impl.URLSourceFactory" name="*"/>
-  </source-factories>
-
-  <source-resolver class="org.apache.excalibur.source.impl.SourceResolverImpl"/>
- </components>
-
-</testcase>
+<?xml version="1.0" ?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<testcase>
+ <roles>
+  <role name="org.apache.excalibur.source.SourceFactorySelector"
+        shorthand="source-factories"
+        default-class="org.apache.avalon.excalibur.component.ExcaliburComponentSelector"/>
+
+  <role name="org.apache.excalibur.source.SourceResolver"
+        shorthand="source-resolver"
+        default-class="org.apache.excalibur.source.impl.SourceResolverImpl"/>
+ </roles>
+
+ <components>
+  <source-factories>
+   <component-instance class="org.apache.excalibur.source.impl.ResourceSourceFactory" name="resource"/>
+   <component-instance class="org.apache.cocoon.components.source.impl.ZipSourceFactory" name="zip"/>
+   <component-instance class="org.apache.excalibur.source.impl.URLSourceFactory" name="*"/>
+  </source-factories>
+
+  <source-resolver class="org.apache.excalibur.source.impl.SourceResolverImpl"/>
+ </components>
+
+</testcase>

Propchange: cocoon/branches/BRANCH_2_1_X/src/test/org/apache/cocoon/components/source/impl/ZipSourceTestCase.xtest
------------------------------------------------------------------------------
    svn:eol-style = native
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.