cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ilgro...@apache.org
Subject 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...
Date Sat, 01 Mar 2014 18:02:20 GMT
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:ovidiu@cup.hp.com">Ovidiu Predescu </a>
  * @author <a href="mailto:Michael.Melhem@managesoft.com">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:cziegeler@apache.org">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 <mhartle@hartle-klug.com> 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() {



Mime
View raw message