svn commit: r1573205 [4/5] - in /cocoon/branches/BRANCH_2_1_X-dojo1_1: ./ legal/ lib/ lib/core/ lib/endorsed/ lib/optional/ misc/notes/ src/blocks/auth/java/org/apache/cocoon/auth/ src/blocks/batik/java/org/apache/cocoon/serialization/ src/blocks/batik...

[email protected]
Newsgroups gmane.text.xml.cocoon.cvs
Message-ID <[email protected]>
Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/flow/ContinuationsManagerImpl.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/flow/ContinuationsManagerImpl.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/flow/ContinuationsManagerImpl.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/flow/ContinuationsManagerImpl.java Sat Mar  1 18:02:14 2014
@@ -72,7 +72,7 @@ import org.apache.excalibur.instrument.V
  * this setting for web applications. Set "session-bound-continuations"
  * configuration option to true to activate this mode.</li>
  * </ul>
- * 
+ *
  * @author <a href="mailto:[email protected]">Ovidiu Predescu </a>
  * @author <a href="mailto:[email protected]">Michael Melhem </a>
  * @since March 19, 2002
@@ -83,7 +83,7 @@ public class ContinuationsManagerImpl
         extends AbstractLogEnabled
         implements ContinuationsManager, Component, Configurable,
                    ThreadSafe, Instrumentable, Serviceable, Contextualizable {
-    
+
     private static final int CONTINUATION_ID_LENGTH = 20;
 
     /**
@@ -141,7 +141,7 @@ public class ContinuationsManagerImpl
     }
 
     public void contextualize(Context context) throws ContextException {
-        this.context = context;        
+        this.context = context;
     }
 
     public void service(ServiceManager manager) throws ServiceException {
@@ -152,12 +152,12 @@ public class ContinuationsManagerImpl
         this.defaultTimeToLive = config.getAttributeAsInteger("time-to-live", (3600 * 1000));
         this.isContinuationSharingBugCompatible = config.getAttributeAsBoolean("continuation-sharing-bug-compatible", false);
         this.bindContinuationsToSession = config.getAttributeAsBoolean( "session-bound-continuations", false );
-        
+
         // create a global ContinuationsHolder if this the "session-bound-continuations" parameter is set to false
         if (!this.bindContinuationsToSession) {
             this.continuationsHolder = new WebContinuationsHolder();
         }
-        
+
         // create a thread that invalidates the continuations
         final Configuration expireConf = config.getChild("expirations-check");
         final long initialDelay = expireConf.getChild("offset", true).getValueAsLong(180000);
@@ -200,7 +200,7 @@ public class ContinuationsManagerImpl
     public WebContinuation createWebContinuation(Object kont,
                                                  WebContinuation parent,
                                                  int timeToLive,
-                                                 String interpreterId, 
+                                                 String interpreterId,
                                                  ContinuationsDisposer disposer) {
         int ttl = timeToLive == 0 ? defaultTimeToLive : timeToLive;
 
@@ -226,22 +226,22 @@ public class ContinuationsManagerImpl
         if (continuationsHolder == null) {
             return null;
         }
-        
+
         WebContinuation kont = continuationsHolder.get(id);
         if (kont == null) {
-            return null;            
+            return null;
         }
-        
+
         if (kont.hasExpired()) {
             removeContinuation(continuationsHolder, kont);
             return null;
         }
-            
+
         if (!kont.interpreterMatches(interpreterId)) {
             if (getLogger().isWarnEnabled()) {
-                getLogger().warn("WK: Continuation (" + kont.getId() 
-                                 + ") lookup for wrong interpreter. Bound to: " 
-                                 + kont.getInterpreterId() + ", looked up for: " 
+                getLogger().warn("WK: Continuation (" + kont.getId()
+                                 + ") lookup for wrong interpreter. Bound to: "
+                                 + kont.getInterpreterId() + ", looked up for: "
                                  + interpreterId);
             }
 
@@ -449,17 +449,21 @@ public class ContinuationsManagerImpl
      * continuationsHolder.
      */
     protected void invalidateContinuations(WebContinuationsHolder continuationsHolder) {
+        // It's not possible to just iterate over continuationsHolder.holder since _invalidate(..)
+        // calls remove(..) on the map leading to ConcurrentModification at the end.
+        WebContinuation[] continuations;
         synchronized (continuationsHolder.holder) {
-            for (Iterator iter = continuationsHolder.holder.values().iterator(); iter.hasNext();) {
-                WebContinuation wk = (WebContinuation) iter.next();
-                _detach(wk);
-                _invalidate(continuationsHolder, wk);
-            }
+            continuations = new WebContinuation[continuationsHolder.holder.size()];
+            continuations = (WebContinuation[]) continuationsHolder.holder.values().toArray(continuations);
+        }
+        for (int i = 0; i < continuations.length; i++) {
+            _detach(continuations[i]);
+            _invalidate(continuationsHolder, continuations[i]);
         }
     }
 
     /**
-     * Lookup a proper web continuations holder. 
+     * Lookup a proper web continuations holder.
      * @param createNew
      *            should the manager create a continuations holder in session
      *            when none found?
@@ -468,7 +472,7 @@ public class ContinuationsManagerImpl
         //there is only one holder if continuations are not bound to session
         if (!this.bindContinuationsToSession)
             return this.continuationsHolder;
-        
+
         //if continuations bound to session lookup a proper holder in the session
         Map objectModel = ContextHelper.getObjectModel(this.context);
         Request request = ObjectModelHelper.getRequest(objectModel);
@@ -477,7 +481,7 @@ public class ContinuationsManagerImpl
             return null;
 
         Session session = request.getSession(true);
-        WebContinuationsHolder holder = 
+        WebContinuationsHolder holder =
             (WebContinuationsHolder) session.getAttribute(
                     WebContinuationsHolder.CONTINUATIONS_HOLDER);
         if (!createNew)
@@ -503,7 +507,7 @@ public class ContinuationsManagerImpl
                 rootWebContinuations.add(webContinuation);
             }
         }
-        
+
         Set clonedRootWebContinuations = new HashSet();
         for (Iterator iter = rootWebContinuations.iterator(); iter.hasNext();) {
             WebContinuation rootContinuation = (WebContinuation) iter.next();
@@ -514,7 +518,7 @@ public class ContinuationsManagerImpl
 
     /**
      * Get a list of all web continuations (data only)
-     * 
+     *
      * @deprecated
      */
     public List getWebContinuationsDataBeanList() {
@@ -535,7 +539,7 @@ public class ContinuationsManagerImpl
      */
     protected void displayExpireSet() {
         StringBuffer wkSet = new StringBuffer("\nWK; Expire set size: ");
-        
+
         synchronized (this.expirations) {
             wkSet.append(this.expirations.size());
             for (Iterator i = this.expirations.iterator(); i.hasNext();) {
@@ -555,7 +559,7 @@ public class ContinuationsManagerImpl
     /**
      * Dump to Log file all <code>WebContinuation</code>s
      * in the system.
-     * 
+     *
      * This method will be changed to be an internal method solely for debugging
      * purposes just like {@link #displayExpireSet()}.
      */
@@ -572,11 +576,11 @@ public class ContinuationsManagerImpl
     /**
      * A holder for WebContinuations. When bound to session notifies the
      * continuations manager of session invalidation.
-     * 
+     *
      * For thread-safe access you have to synchronize on the Map {@link #holder}!
      */
     protected class WebContinuationsHolder implements HttpSessionBindingListener {
-        
+
         private final static String CONTINUATIONS_HOLDER = "o.a.c.c.f.SCMI.WebContinuationsHolder";
 
         private Map holder = Collections.synchronizedMap(new HashMap());
@@ -593,14 +597,10 @@ public class ContinuationsManagerImpl
             this.holder.remove(wk.getId());
         }
 
-        public Set getContinuationIds() {
-            return holder.keySet();
-        }
-        
         public boolean contains(String continuationId) {
             return this.holder.containsKey(continuationId);
         }
-        
+
         public boolean contains(WebContinuation wk) {
             return contains(wk.getId());
         }

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/modules/input/XPathXMLFileModule.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/modules/input/XPathXMLFileModule.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/modules/input/XPathXMLFileModule.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/modules/input/XPathXMLFileModule.java Sat Mar  1 18:02:14 2014
@@ -1,515 +1,531 @@
-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;
-        }
-    }
+/*
+ * 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.
+ */
+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-dojo1_1/src/java/org/apache/cocoon/components/modules/input/XPathXMLFileModule.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/pipeline/impl/AbstractCachingProcessingPipeline.java Sat Mar  1 18:02:14 2014
@@ -36,6 +36,8 @@ import org.apache.cocoon.caching.Caching
 import org.apache.cocoon.caching.ComponentCacheKey;
 import org.apache.cocoon.caching.PipelineCacheKey;
 import org.apache.cocoon.environment.Environment;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.commandline.AbstractCommandLineEnvironment;
 import org.apache.cocoon.environment.http.HttpEnvironment;
 import org.apache.cocoon.transformation.Transformer;
 import org.apache.cocoon.util.HashUtil;
@@ -193,6 +195,9 @@ public abstract class AbstractCachingPro
 
             // Avoid deadlock with self (see JIRA COCOON-1985).
             Object current = env.getObjectModel().get(HttpEnvironment.HTTP_REQUEST_OBJECT);
+            if (current==null){
+              current = env.getObjectModel().get(AbstractCommandLineEnvironment.CLI_REQUEST_ID);
+            }
             if (lock != null && lock != current) {
                 if (getLogger().isDebugEnabled()) {
                     getLogger().debug("Waiting on Lock '" + lockKey + "'");
@@ -243,6 +248,9 @@ public abstract class AbstractCachingPro
                     }
                 } else {
                     Object lock = env.getObjectModel().get(HttpEnvironment.HTTP_REQUEST_OBJECT);
+                    if (lock == null){
+                      lock = env.getObjectModel().get(AbstractCommandLineEnvironment.CLI_REQUEST_ID);
+                    }
                     try {
                         transientStore.store(lockKey, lock);
                     } catch (IOException e) {

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java Sat Mar  1 18:02:14 2014
@@ -35,6 +35,7 @@ import org.apache.cocoon.components.Coco
 import org.apache.cocoon.components.pipeline.ProcessingPipeline;
 import org.apache.cocoon.environment.Environment;
 import org.apache.cocoon.environment.ForwardRedirector;
+import org.apache.cocoon.environment.PermanentRedirector;
 import org.apache.cocoon.environment.Redirector;
 import org.apache.cocoon.environment.wrapper.EnvironmentWrapper;
 import org.apache.cocoon.environment.wrapper.MutableEnvironmentFacade;
@@ -287,8 +288,10 @@ public class ConcreteTreeProcessor exten
         // Get the processor that should process this request
         // (see https://issues.apache.org/jira/browse/COCOON-1990).
         ConcreteTreeProcessor processor = this;
-        if (uri.startsWith("cocoon://"))
+        if (uri.startsWith("cocoon://")) {
             processor = ((TreeProcessor)getRootProcessor()).concreteProcessor;
+            newEnv.changeContext("", ((TreeProcessor)getRootProcessor()).source.getURI());
+        }
 
         // Process the redirect
         // No more reset since with TreeProcessorRedirector, we need to pop values from the redirect location
@@ -298,8 +301,15 @@ public class ConcreteTreeProcessor exten
         if ( facade != null ) {
             newEnv = facade.getDelegate();
         }
-        if ( ((ForwardEnvironmentWrapper)newEnv).getRedirectURL() != null ) {
-            environment.redirect( false, ((ForwardEnvironmentWrapper)newEnv).getRedirectURL() );
+        
+        ForwardEnvironmentWrapper forwardEnv = (ForwardEnvironmentWrapper) newEnv;
+        if (forwardEnv.hasRedirected()) {
+            if (forwardEnv.isPermanentRedirection() && environment instanceof PermanentRedirector) {
+                ((PermanentRedirector )environment).permanentRedirect(false, forwardEnv.getRedirectURL());
+            }
+            else {
+                environment.redirect( false, forwardEnv.getRedirectURL() );
+            }
         }
         return result;
     }

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/commandline/AbstractCommandLineEnvironment.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/commandline/AbstractCommandLineEnvironment.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/commandline/AbstractCommandLineEnvironment.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/commandline/AbstractCommandLineEnvironment.java Sat Mar  1 18:02:14 2014
@@ -22,6 +22,7 @@ import org.apache.cocoon.Constants;
 import org.apache.cocoon.ProcessingException;
 import org.apache.cocoon.components.source.SourceUtil;
 import org.apache.cocoon.environment.AbstractEnvironment;
+import org.apache.cocoon.environment.ObjectModelHelper;
 import org.apache.cocoon.environment.Redirector;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceException;
@@ -32,6 +33,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.MalformedURLException;
+import java.util.Map;
 
 /**
  * This environment is used to save the requested file to disk.
@@ -43,6 +45,8 @@ import java.net.MalformedURLException;
 public abstract class AbstractCommandLineEnvironment
 extends AbstractEnvironment
 implements Redirector {
+  
+    public static final String CLI_REQUEST_ID = "clirequest-id";
 
     protected String contentType;
     protected int contentLength;
@@ -56,11 +60,36 @@ implements Redirector {
                                           Logger log)
     throws MalformedURLException {
         super(uri, view, context);
-        this.enableLogging(log);
-        this.outputStream = stream;
-        this.statusCode = 0;
+        initCliEnvironment(stream, log);
+        
     }
+    private void initCliEnvironment(OutputStream stream, Logger log) {
+      this.enableLogging(log);
+      this.outputStream = stream;
+      this.statusCode = 0;
+    }
+    public AbstractCommandLineEnvironment(String uri,
+        Map attributes,
+        Map parameters,
+        Map headers,
+        String view,
+        File context,
+        CommandLineContext cliContext,
+        OutputStream stream,
+        Logger log)
+    throws MalformedURLException {
+      super(uri, view, context);
+      initCliEnvironment(stream, log);
+      CommandLineRequest request = new CommandLineRequest(this, null, uri, null, attributes, parameters, headers);
+      this.objectModel.put(ObjectModelHelper.REQUEST_OBJECT,
+          request);
+      this.objectModel.put(ObjectModelHelper.RESPONSE_OBJECT,
+          new CommandLineResponse());
+      this.objectModel.put(ObjectModelHelper.CONTEXT_OBJECT,
+          cliContext);
+      this.objectModel.put(CLI_REQUEST_ID, new String(uri));
 
+    }
     /**
      * Redirect the client to a new URL
      */

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/commandline/FileSavingEnvironment.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/commandline/FileSavingEnvironment.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/commandline/FileSavingEnvironment.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/commandline/FileSavingEnvironment.java Sat Mar  1 18:02:14 2014
@@ -19,7 +19,6 @@ package org.apache.cocoon.environment.co
 import org.apache.avalon.framework.logger.Logger;
 
 import org.apache.cocoon.Constants;
-import org.apache.cocoon.environment.ObjectModelHelper;
 
 import java.io.File;
 import java.io.OutputStream;
@@ -51,13 +50,7 @@ public class FileSavingEnvironment exten
                                  OutputStream stream,
                                  Logger log)
     throws MalformedURLException {
-        super(uri, null, context, stream, log);
-        this.objectModel.put(ObjectModelHelper.REQUEST_OBJECT,
-                             new CommandLineRequest(this, null, uri, null, attributes, parameters, headers));
-        this.objectModel.put(ObjectModelHelper.RESPONSE_OBJECT,
-                             new CommandLineResponse());
-        this.objectModel.put(ObjectModelHelper.CONTEXT_OBJECT,
-                             cliContext);
+        super(uri, attributes, parameters, headers, null, context, cliContext, stream, log);
         this.sourceLastModified = lastModified;
         if (links != null) {
             this.objectModel.put(Constants.LINK_OBJECT, links);

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/commandline/LinkSamplingEnvironment.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/commandline/LinkSamplingEnvironment.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/commandline/LinkSamplingEnvironment.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/commandline/LinkSamplingEnvironment.java Sat Mar  1 18:02:14 2014
@@ -29,7 +29,6 @@ import java.util.Map;
 
 import org.apache.avalon.framework.logger.Logger;
 import org.apache.cocoon.Constants;
-import org.apache.cocoon.environment.ObjectModelHelper;
 
 /**
  * This environment is sample the links of the resource.
@@ -50,16 +49,10 @@ public class LinkSamplingEnvironment ext
                                    CommandLineContext cliContext,
                                    Logger log)
     throws MalformedURLException, IOException {
-        super(uri, Constants.LINK_VIEW, contextFile, new ByteArrayOutputStream(), log);
+        super(uri, attributes, parameters, headers, Constants.LINK_VIEW, contextFile, cliContext, new ByteArrayOutputStream(), log);
         if (getLogger().isDebugEnabled()) {
             getLogger().debug("uri = " + uri);
         }
-        this.objectModel.put(ObjectModelHelper.REQUEST_OBJECT,
-                             new CommandLineRequest(this, null, uri, null, attributes, parameters, headers));
-        this.objectModel.put(ObjectModelHelper.RESPONSE_OBJECT,
-                             new CommandLineResponse());
-        this.objectModel.put(ObjectModelHelper.CONTEXT_OBJECT,
-                             cliContext);
     }
 
     /**

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/http/HttpEnvironment.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/http/HttpEnvironment.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/http/HttpEnvironment.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/http/HttpEnvironment.java Sat Mar  1 18:02:14 2014
@@ -75,8 +75,14 @@ public class HttpEnvironment extends Abs
         super(uri, null, root, null);
 
         this.request = new HttpRequest(req, this);
-        this.request.setCharacterEncoding(defaultFormEncoding);
-        this.request.setContainerEncoding(containerEncoding);
+
+        if (req.getCharacterEncoding() == null) { // use the value from web.xml
+            this.request.setContainerEncoding(containerEncoding != null ? containerEncoding : "ISO-8859-1");
+        } else { // use what we have been given
+            this.request.setContainerEncoding(req.getCharacterEncoding());
+        }
+        this.request.setCharacterEncoding(defaultFormEncoding != null ? defaultFormEncoding : "UTF-8");
+        
         this.response = new HttpResponse(res);
         this.webcontext = context;
 

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/http/HttpRequest.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/http/HttpRequest.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/http/HttpRequest.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/http/HttpRequest.java Sat Mar  1 18:02:14 2014
@@ -324,23 +324,17 @@ public final class HttpRequest implement
 
     public String getParameter(String name) {
         String value = this.req.getParameter(name);
-        if (this.form_encoding == null || this.container_encoding == null || value == null) {
-            return value;
+        if (!this.container_encoding.equals(this.form_encoding)) {
+            value = decode(value);
         }
-        // Form and container encoding are equal, skip expensive value decoding
-        if (this.container_encoding.equals(this.form_encoding)) {
-            return value;
-        }
-        return decode(value);
+        return value;
     }
 
     private String decode(String str) {
         if (str == null) return null;
         try {
-            if (this.container_encoding == null)
-                this.container_encoding = "ISO-8859-1";
             byte[] bytes = str.getBytes(this.container_encoding);
-            return new String(bytes, form_encoding);
+            return new String(bytes, this.form_encoding);
         } catch (UnsupportedEncodingException uee) {
             throw new CascadingRuntimeException("Unsupported Encoding Exception", uee);
         }
@@ -353,7 +347,7 @@ public final class HttpRequest implement
     public String[] getParameterValues(String name) {
         String[] values = this.req.getParameterValues(name);
         if (values == null) return null;
-        if (this.form_encoding == null) {
+        if (this.container_encoding.equals(this.form_encoding)) {
             return values;
         }
         String[] decoded_values = new String[values.length];

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/wrapper/EnvironmentWrapper.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/wrapper/EnvironmentWrapper.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/wrapper/EnvironmentWrapper.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/environment/wrapper/EnvironmentWrapper.java Sat Mar  1 18:02:14 2014
@@ -29,6 +29,8 @@ import org.apache.cocoon.Constants;
 import org.apache.cocoon.environment.AbstractEnvironment;
 import org.apache.cocoon.environment.Environment;
 import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.PermanentRedirector;
+import org.apache.cocoon.environment.Redirector;
 import org.apache.cocoon.environment.Request;
 import org.apache.cocoon.environment.Response;
 import org.apache.cocoon.util.BufferedOutputStream;
@@ -42,7 +44,7 @@ import org.apache.cocoon.util.BufferedOu
  * @author <a href="mailto:[email protected]">Carsten Ziegeler</a>
  * @version $Id$
  */
-public class EnvironmentWrapper extends AbstractEnvironment {
+public class EnvironmentWrapper extends AbstractEnvironment implements Redirector, PermanentRedirector {
 
     /** The wrapped environment */
     protected Environment environment;
@@ -52,7 +54,7 @@ public class EnvironmentWrapper extends 
 
     /** The redirect url */
     protected String redirectURL;
-
+    
     /** The request object */
     protected Request request;
 
@@ -63,6 +65,10 @@ public class EnvironmentWrapper extends 
 
     protected boolean internalRedirect = false;
 
+    protected boolean hasRedirected;
+
+    protected boolean permanentRedirection;
+
     /**
      * Constructs an EnvironmentWrapper object from a Request
      * and Response objects
@@ -267,6 +273,7 @@ public class EnvironmentWrapper extends 
     public void redirect(boolean sessionmode, String newURL)
     throws IOException {
         this.redirectURL = newURL;
+        this.hasRedirected = true;
 
         // check if session mode shall be activated
         if (sessionmode) {
@@ -276,6 +283,31 @@ public class EnvironmentWrapper extends 
     }
 
     /**
+     * Permanentlty redirect the client to a new URL is not allowed
+     */
+    public void permanentRedirect(boolean sessionmode, String newURL)
+    throws IOException {
+        this.redirect(sessionmode, newURL);
+        this.permanentRedirection = true;
+    }
+    
+    public boolean hasRedirected() {
+        return this.hasRedirected;
+    }
+    
+    /**
+     * Has a permanent redirection been asked
+     */
+    public boolean isPermanentRedirection() {
+        return this.permanentRedirection;
+    }
+    
+    public void sendStatus(int sc) {
+        this.setStatus(sc);
+        this.hasRedirected = true;
+    }
+
+    /**
      * Redirect in the first non-wrapped environment
      */
     public void globalRedirect(boolean sessionmode, String newURL)

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/reading/ImageReader.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/reading/ImageReader.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/reading/ImageReader.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/reading/ImageReader.java Sat Mar  1 18:02:14 2014
@@ -27,20 +27,20 @@ import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.Serializable;
+import java.util.Iterator;
 import java.util.Map;
+
+import javax.imageio.ImageIO;
+import javax.imageio.ImageWriteParam;
+import javax.imageio.ImageWriter;
+import javax.imageio.stream.ImageOutputStream;
 import javax.swing.ImageIcon;
 
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.cocoon.ProcessingException;
 import org.apache.cocoon.environment.SourceResolver;
-import org.apache.commons.lang.SystemUtils;
 import org.xml.sax.SAXException;
 
-import com.sun.image.codec.jpeg.ImageFormatException;
-import com.sun.image.codec.jpeg.JPEGCodec;
-import com.sun.image.codec.jpeg.JPEGEncodeParam;
-import com.sun.image.codec.jpeg.JPEGImageEncoder;
-
 /**
  * The <code>ImageReader</code> component is used to serve binary image data
  * in a sitemap pipeline. It makes use of HTTP Headers to determine if
@@ -97,9 +97,6 @@ final public class ImageReader extends R
     private static final boolean ENLARGE_DEFAULT = true;
     private static final boolean FIT_DEFAULT = false;
 
-    /* See http://developer.java.sun.com/developer/bugParade/bugs/4502892.html */
-    private static final boolean JVMBugFixed = SystemUtils.isJavaVersionAtLeast(1.4f);
-
     private int width;
     private int height;
     private float[] scaleColor = new float[3];
@@ -263,28 +260,6 @@ final public class ImageReader extends R
                                   + " expires: " + expires);
             }
 
-            /*
-             * NOTE (SM):
-             * Due to Bug Id 4502892 (which is found in *all* JVM implementations from
-             * 1.2.x and 1.3.x on all OS!), we must buffer the JPEG generation to avoid
-             * that connection resetting by the peer (user pressing the stop button,
-             * for example) crashes the entire JVM (yes, dude, the bug is *that* nasty
-             * since it happens in JPEG routines which are native!)
-             * I'm perfectly aware of the huge memory problems that this causes (almost
-             * doubling memory consumption for each image and making the GC work twice
-             * as hard) but it's *far* better than restarting the JVM every 2 minutes
-             * (since this is the average experience for image-intensive web application
-             * such as an image gallery).
-             * Please, go to the <a href="http://developer.java.sun.com/developer/bugParade/bugs/4502892.html">Sun Developers Connection</a>
-             * and vote this BUG as the one you would like fixed sooner rather than
-             * later and all this hack will automagically go away.
-             * Many deep thanks to Michael Hartle <[email protected]> for tracking
-             * this down and suggesting the workaround.
-             *
-             * UPDATE (SM):
-             * This appears to be fixed on JDK 1.4
-             */
-
             try {
                 byte content[] = readFully(inputStream);
                 ImageIcon icon = new ImageIcon(content);
@@ -321,25 +296,17 @@ final public class ImageReader extends R
                     colorFilter.filter(currentImage, currentImage);
                 }
 
-                // JVM Bug handling
-                if (JVMBugFixed) {
-                    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
-                    JPEGEncodeParam p = encoder.getDefaultJPEGEncodeParam(currentImage);
-                    p.setQuality(this.quality[0], true);
-                    encoder.setJPEGEncodeParam(p);
-                    encoder.encode(currentImage);
-                } else {
-                    ByteArrayOutputStream bstream = new ByteArrayOutputStream();
-                    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bstream);
-                    JPEGEncodeParam p = encoder.getDefaultJPEGEncodeParam(currentImage);
-                    p.setQuality(this.quality[0], true);
-                    encoder.setJPEGEncodeParam(p);
-                    encoder.encode(currentImage);
-                    out.write(bstream.toByteArray());
-                }
+                Iterator writers = ImageIO.getImageWritersByFormatName("jpeg");
+                ImageOutputStream ios = ImageIO.createImageOutputStream(out);
+                ImageWriter writer = (ImageWriter) writers.next();
+                writer.setOutput(ios);
+                ImageWriteParam p = writer.getDefaultWriteParam();
+                p.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
+                p.setCompressionQuality(this.quality[0]);
+                writer.write(currentImage);
 
-                out.flush();
-            } catch (ImageFormatException e) {
+                ios.flush();
+            } catch (IOException e) {
                 throw new ProcessingException("Error reading the image. " +
                                               "Note that only JPEG images are currently supported.");
             } finally {

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/reading/ResourceReader.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/reading/ResourceReader.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/reading/ResourceReader.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/reading/ResourceReader.java Sat Mar  1 18:02:14 2014
@@ -342,7 +342,9 @@ public class ResourceReader extends Abst
                 documents.put(request.getRequestURI(), inputSource.getURI());
             }
         } catch (IOException e) {
+            // COCOON-2307: if the client severed the connection, no matter for it that we rethrow the exception as it will never receive it
             getLogger().debug("Received an IOException, assuming client severed connection on purpose");
+            throw e;
         }
     }
 

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/selection/HostSelector.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/selection/HostSelector.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/selection/HostSelector.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/selection/HostSelector.java Sat Mar  1 18:02:14 2014
@@ -16,12 +16,13 @@
  */
 package org.apache.cocoon.selection;
 
+import java.util.Map;
+
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.parameters.Parameters;
-import org.apache.cocoon.environment.ObjectModelHelper;
 
-import java.util.Map;
+import org.apache.cocoon.environment.ObjectModelHelper;
 
 /**
  * A <code>Selector</code> that matches a string from within the host parameter
@@ -67,6 +68,6 @@ public class HostSelector extends NamedP
             return false;
         }
 
-        return checkPatterns(expression, host);
+        return checkPatterns(expression, host, false);
     }
 }

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/selection/NamedPatternsSelector.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/selection/NamedPatternsSelector.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/selection/NamedPatternsSelector.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/selection/NamedPatternsSelector.java Sat Mar  1 18:02:14 2014
@@ -16,18 +16,18 @@
  */
 package org.apache.cocoon.selection;
 
-import org.apache.avalon.framework.configuration.Configurable;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
-import org.apache.avalon.framework.thread.ThreadSafe;
-
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.thread.ThreadSafe;
+
 /**
  * Abstract class for selectors that select a value when it matches
  * some patterns associated to the select expression.
@@ -39,7 +39,7 @@ import java.util.Map;
  */
 
 public abstract class NamedPatternsSelector extends AbstractLogEnabled
-  implements Configurable, ThreadSafe, Selector {
+                                            implements Configurable, ThreadSafe, Selector {
 
     /**
      * Association of names to String[] of values.
@@ -95,7 +95,7 @@ public abstract class NamedPatternsSelec
     }
 
     /**
-     * Checks if <code>value</code> is a substring of one of the patterns associated
+     * Checks if <code>value</code> is a (case-sensitive) substring of one of the patterns associated
      * to <code>expression</code>
      *
      * @param expression the expression that is selected
@@ -103,6 +103,19 @@ public abstract class NamedPatternsSelec
      * @return true if <code>value</code> matches one of the patterns
      */
     protected boolean checkPatterns(String expression, String value) {
+        return checkPatterns(expression, value, true);
+    }
+
+    /**
+     * Checks if <code>value</code> is a substring of one of the patterns associated
+     * to <code>expression</code>
+     *
+     * @param expression the expression that is selected
+     * @param value the value to check
+     * @param caseSensitive boolean switch whether comparison is done case-sensitive  
+     * @return true if <code>value</code> matches one of the patterns
+     */
+    protected boolean checkPatterns(String expression, String value, boolean caseSensitive) {
         if (value == null) {
             getLogger().debug("No value given -- failing.");
             return false;
@@ -114,9 +127,14 @@ public abstract class NamedPatternsSelec
             return false;
         }
 
+        if (!caseSensitive) {
+            value = value.toLowerCase();
+        }
+
         // Does a pattern match 'value' ?
         for (int i = 0; i < patterns.length; i++) {
-            if (value.indexOf(patterns[i]) != -1) {
+            if ((caseSensitive && value.indexOf(patterns[i]) != -1)
+                || (!caseSensitive && value.indexOf(patterns[i].toLowerCase()) != -1)) {
                 getLogger().debug(expression + " selected value " + value);
                 return true;
             }

Modified: cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/servlet/CocoonServlet.java
URL: http://svn.apache.org/viewvc/cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/servlet/CocoonServlet.java?rev=1573205&r1=1573204&r2=1573205&view=diff
==============================================================================
--- cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/servlet/CocoonServlet.java (original)
+++ cocoon/branches/BRANCH_2_1_X-dojo1_1/src/java/org/apache/cocoon/servlet/CocoonServlet.java Sat Mar  1 18:02:14 2014
@@ -177,17 +177,17 @@ public class CocoonServlet extends HttpS
     /**
      * Allow processing of upload requests (mime/multipart)
      */
-    private boolean enableUploads;
-    private boolean autoSaveUploads;
-    private boolean allowOverwrite;
-    private boolean silentlyRename;
-    private int maxUploadSize;
-
-    private File uploadDir;
-    private File workDir;
-    private File cacheDir;
-    private String containerEncoding;
-    private String defaultFormEncoding;
+    protected boolean enableUploads;
+    protected boolean autoSaveUploads;
+    protected boolean allowOverwrite;
+    protected boolean silentlyRename;
+    protected int maxUploadSize;
+
+    protected File uploadDir;
+    protected File workDir;
+    protected File cacheDir;
+    protected String containerEncoding;
+    protected String defaultFormEncoding;
 
     protected ServletContext servletContext;
 
@@ -488,18 +488,26 @@ public class CocoonServlet extends HttpS
 
         this.enableInstrumentation = getInitParameterAsBoolean("enable-instrumentation", false);
 
-        this.requestFactory = new RequestFactory(this.autoSaveUploads,
-                                                 this.uploadDir,
-                                                 this.allowOverwrite,
-                                                 this.silentlyRename,
-                                                 this.maxUploadSize,
-                                                 this.containerEncoding);
+        createRequestFactory();
+
         // Add the servlet configuration
         this.appContext.put(CONTEXT_SERVLET_CONFIG, conf);
         this.createCocoon();
     }
 
     /**
+     * Creates the {@link RequestFactory}.
+     */
+    protected void createRequestFactory(){
+        this.requestFactory = new RequestFactory(this.autoSaveUploads,
+                this.uploadDir,
+                this.allowOverwrite,
+                this.silentlyRename,
+                this.maxUploadSize,
+                this.containerEncoding);
+    }
+
+    /**
      * Dispose Cocoon when servlet is destroyed
      */
     public void destroy() {
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.