cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jheym...@apache.org
Subject svn commit: r330548 [50/132] - in /cocoon/whiteboard/maven2/cocoon-flat-layout: ./ cocoon-ajax-block/ cocoon-ajax-block/api/ cocoon-ajax-block/api/src/ cocoon-ajax-block/api/src/main/ cocoon-ajax-block/api/src/main/java/ cocoon-ajax-block/api/src/main/...
Date Thu, 03 Nov 2005 14:00:48 GMT
Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/WildcardURIMatcher.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/WildcardURIMatcher.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/WildcardURIMatcher.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/WildcardURIMatcher.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,43 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.matching;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.environment.ObjectModelHelper;
+
+import java.util.Map;
+
+/**
+ * Match the request URI against a wildcard expression.
+ *
+ * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
+ * @version CVS $Id: WildcardURIMatcher.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+public class WildcardURIMatcher extends AbstractWildcardMatcher
+{
+    /**
+     * Return the request URI.
+     */
+    protected String getMatchString(Map objectModel, Parameters parameters) {
+        String uri = ObjectModelHelper.getRequest(objectModel).getSitemapURI();
+
+        if (uri.startsWith("/")) {
+            uri = uri.substring(1);
+        }
+
+        return uri;
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/WildcardURIMatcher.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/helpers/WildcardHelper.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/helpers/WildcardHelper.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/helpers/WildcardHelper.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/helpers/WildcardHelper.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,385 @@
+/*
+ * Copyright 1999-2005 The Apache Software Foundation.
+ * 
+ * Licensed 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.matching.helpers;
+
+import java.util.HashMap;
+
+/**
+ * This class is an utility class that perform wilcard-patterns matching and
+ * isolation.
+ *
+ * @author <a href="mailto:pier@apache.org">Pierpaolo Fumagalli</a>
+ *         (Apache Software Foundation)
+ * @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a>
+ * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
+ * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a>
+ * @version CVS $Id: WildcardHelper.java 160568 2005-04-08 17:33:05Z sylvain $
+ */
+public class WildcardHelper {
+
+    /** The int representing '*' in the pattern <code>int []</code>. */
+    protected static final int MATCH_FILE = -1;
+    /** The int representing '**' in the pattern <code>int []</code>. */
+    protected static final int MATCH_PATH = -2;
+    /** The int representing begin in the pattern <code>int []</code>. */
+    protected static final int MATCH_BEGIN = -4;
+    /** The int representing end in pattern <code>int []</code>. */
+    protected static final int MATCH_THEEND = -5;
+    /** The int value that terminates the pattern <code>int []</code>. */
+    protected static final int MATCH_END = -3;
+
+
+    /**
+     * Translate the given <code>String</code> into a <code>int []</code>
+     * representing the pattern matchable by this class.
+     * <br>
+     * This function translates a <code>String</code> into an int array
+     * converting the special '*' and '\' characters.
+     * <br>
+     * Here is how the conversion algorithm works:
+     * <ul>
+     *   <li>The '*' character is converted to MATCH_FILE, meaning that zero
+     *        or more characters (excluding the path separator '/') are to
+     *        be matched.</li>
+     *   <li>The '**' sequence is converted to MATCH_PATH, meaning that zero
+     *       or more characters (including the path separator '/') are to
+     *        be matched.</li>
+     *   <li>The '\' character is used as an escape sequence ('\*' is
+     *       translated in '*', not in MATCH_FILE). If an exact '\' character
+     *       is to be matched the source string must contain a '\\'.
+     *       sequence.</li>
+     * </ul>
+     * When more than two '*' characters, not separated by another character,
+     * are found their value is considered as '**' (MATCH_PATH).
+     * <br>
+     * The array is always terminated by a special value (MATCH_END).
+     * <br>
+     * All MATCH* values are less than zero, while normal characters are equal
+     * or greater.
+     *
+     * @param data The string to translate.
+     * @return The encoded string as an int array, terminated by the MATCH_END
+     *         value (don't consider the array length).
+     * @exception NullPointerException If data is null.
+     */
+    public static int[] compilePattern(String data)
+    throws NullPointerException {
+
+        // Prepare the arrays
+        int expr[] = new int[data.length() + 2];
+        char buff[] = data.toCharArray();
+
+        // Prepare variables for the translation loop
+        int y = 0;
+        boolean slash = false;
+
+        // Must start from beginning
+        expr[y++] = MATCH_BEGIN;
+
+        if (buff.length > 0) {
+            if (buff[0]=='\\') {
+                slash = true;
+            } else if (buff[0] == '*') {
+                expr[y++] = MATCH_FILE;
+            }  else {
+                expr[y++] = buff[0];
+            }
+
+            // Main translation loop
+            for (int x = 1; x < buff.length; x++) {
+                // If the previous char was '\' simply copy this char.
+                if (slash) {
+                    expr[y++] = buff[x];
+                    slash = false;
+                // If the previous char was not '\' we have to do a bunch of checks
+                } else {
+                    // If this char is '\' declare that and continue
+                    if (buff[x] == '\\') {
+                        slash = true;
+                    // If this char is '*' check the previous one
+                    } else if (buff[x] == '*') {
+                        // If the previous character als was '*' match a path
+                        if (expr[y-1] <= MATCH_FILE) {
+                            expr[y-1] = MATCH_PATH;
+                        } else {
+                            expr[y++] = MATCH_FILE;
+                        }
+                    } else {
+                        expr[y++]=buff[x];
+                    }
+                }
+            }
+        }
+
+        // Must match end at the end
+        expr[y] = MATCH_THEEND;
+        return expr;
+    }
+
+    /**
+     * match a pattern agains a string and isolates wildcard replacement into a
+     * <code>Stack</code>.
+     */
+    public static boolean match (HashMap map, String data, int[] expr) 
+    throws NullPointerException {
+        if (data == null) {
+            throw new NullPointerException ("No data provided");
+        }
+        if (expr == null) {
+            throw new NullPointerException ("No pattern expression provided");
+        }
+
+
+        char buff[] = data.toCharArray();
+        // Allocate the result buffer
+        char rslt[] = new char[expr.length + buff.length];
+
+
+        // The previous and current position of the expression character
+        // (MATCH_*)
+        int charpos = 0;
+
+        // The position in the expression, input, translation and result arrays
+        int exprpos = 0;
+        int buffpos = 0;
+        int rsltpos = 0;
+        int offset = -1;
+
+        // The matching count
+        int mcount = 0;
+
+        if ( map != null ) {
+            // We want the complete data be in {0}
+            map.put(Integer.toString(mcount),data);
+        }
+
+        // First check for MATCH_BEGIN
+        boolean matchBegin = false;
+        if (expr[charpos] == MATCH_BEGIN) {
+            matchBegin = true;
+            exprpos = ++charpos;
+        }
+
+        // Search the fist expression character (except MATCH_BEGIN - already skipped)
+        while (expr[charpos] >= 0)
+            charpos++;
+
+        // The expression charater (MATCH_*)
+        int exprchr = expr[charpos];
+
+        while (true) {
+            // Check if the data in the expression array before the current
+            // expression character matches the data in the input buffer
+            if (matchBegin) {
+                if (!matchArray(expr, exprpos, charpos, buff, buffpos))
+                    return (false);
+                matchBegin = false;
+            } else {
+                offset = indexOfArray (expr, exprpos, charpos, buff,
+                        buffpos);
+                if (offset < 0)
+                    return (false);
+            }
+
+            // Check for MATCH_BEGIN
+            if (matchBegin) {
+                if (offset != 0)
+                    return (false);
+                matchBegin = false;
+            }
+
+            // Advance buffpos
+            buffpos += (charpos - exprpos);
+
+            // Check for END's
+            if (exprchr == MATCH_END) {
+                if (rsltpos > 0 && map != null) {
+                    map.put(Integer.toString(++mcount),new String(rslt, 0, rsltpos));
+                }
+                // Don't care about rest of input buffer
+                return (true);
+            } else if (exprchr == MATCH_THEEND) {
+                if (rsltpos > 0 && map != null ) {
+                    map.put (Integer.toString(++mcount),new String(rslt, 0, rsltpos));
+                }
+                // Check that we reach buffer's end
+                return (buffpos == buff.length);
+            }
+
+            // Search the next expression character
+            exprpos = ++charpos;
+            while (expr[charpos] >= 0)
+                charpos++;
+            int prevchr = exprchr;
+            exprchr = expr[charpos];
+
+            // We have here prevchr == * or **.
+            offset = (prevchr == MATCH_FILE) ?
+                    indexOfArray (expr, exprpos, charpos, buff, buffpos) :
+                    lastIndexOfArray (expr, exprpos, charpos, buff,
+                    buffpos);
+
+            if (offset < 0)
+                return (false);
+
+            // Copy the data from the source buffer into the result buffer
+            // to substitute the expression character
+            if (prevchr == MATCH_PATH) {
+                while (buffpos < offset)
+                    rslt[rsltpos++] = buff[buffpos++];
+            } else {
+                // Matching file, don't copy '/'
+                while (buffpos < offset) {
+                    if (buff[buffpos] == '/')
+                        return (false);
+                    rslt[rsltpos++] = buff[buffpos++];
+                }
+            }
+
+            if ( map != null ) {
+                map.put(Integer.toString(++mcount),new String (rslt, 0, rsltpos));
+            }
+            rsltpos = 0;
+        }
+    }
+
+    /**
+      * Get the offset of a part of an int array within a char array.
+      * <br>
+      * This method return the index in d of the first occurrence after dpos of
+      * that part of array specified by r, starting at rpos and terminating at
+      * rend.
+      *
+      * @param r The array containing the data that need to be matched in d.
+      * @param rpos The index of the first character in r to look for.
+      * @param rend The index of the last character in r to look for plus 1.
+      * @param d The array of char that should contain a part of r.
+      * @param dpos The starting offset in d for the matching.
+      * @return The offset in d of the part of r matched in d or -1 if that was
+      *         not found.
+      */
+    protected static int indexOfArray (int r[], int rpos, int rend,
+            char d[], int dpos) {
+        // Check if pos and len are legal
+        if (rend < rpos)
+            throw new IllegalArgumentException ("rend < rpos");
+        // If we need to match a zero length string return current dpos
+        if (rend == rpos)
+            return (d.length); //?? dpos?
+        // If we need to match a 1 char length string do it simply
+        if ((rend - rpos) == 1) {
+            // Search for the specified character
+            for (int x = dpos; x < d.length; x++)
+                if (r[rpos] == d[x])
+                    return (x);
+        }
+        // Main string matching loop. It gets executed if the characters to
+        // match are less then the characters left in the d buffer
+        while ((dpos + rend - rpos) <= d.length) {
+            // Set current startpoint in d
+            int y = dpos;
+            // Check every character in d for equity. If the string is matched
+            // return dpos
+            for (int x = rpos; x <= rend; x++) {
+                if (x == rend)
+                    return (dpos);
+                if (r[x] != d[y++])
+                    break;
+            }
+            // Increase dpos to search for the same string at next offset
+            dpos++;
+        }
+        // The remaining chars in d buffer were not enough or the string
+        // wasn't matched
+        return (-1);
+    }
+
+    /**
+      * Get the offset of a last occurance of an int array within a char array.
+      * <br>
+      * This method return the index in d of the last occurrence after dpos of
+      * that part of array specified by r, starting at rpos and terminating at
+      * rend.
+      *
+      * @param r The array containing the data that need to be matched in d.
+      * @param rpos The index of the first character in r to look for.
+      * @param rend The index of the last character in r to look for plus 1.
+      * @param d The array of char that should contain a part of r.
+      * @param dpos The starting offset in d for the matching.
+      * @return The offset in d of the last part of r matched in d or -1 if that was
+      *         not found.
+      */
+    protected static int lastIndexOfArray (int r[], int rpos, int rend,
+            char d[], int dpos) {
+        // Check if pos and len are legal
+        if (rend < rpos)
+            throw new IllegalArgumentException ("rend < rpos");
+        // If we need to match a zero length string return current dpos
+        if (rend == rpos)
+            return (d.length); //?? dpos?
+
+        // If we need to match a 1 char length string do it simply
+        if ((rend - rpos) == 1) {
+            // Search for the specified character
+            for (int x = d.length - 1; x > dpos; x--)
+                if (r[rpos] == d[x])
+                    return (x);
+        }
+
+        // Main string matching loop. It gets executed if the characters to
+        // match are less then the characters left in the d buffer
+        int l = d.length - (rend - rpos);
+        while (l >= dpos) {
+            // Set current startpoint in d
+            int y = l;
+            // Check every character in d for equity. If the string is matched
+            // return dpos
+            for (int x = rpos; x <= rend; x++) {
+                if (x == rend)
+                    return (l);
+                if (r[x] != d[y++])
+                    break;
+            }
+            // Decrease l to search for the same string at next offset
+            l--;
+        }
+        // The remaining chars in d buffer were not enough or the string
+        // wasn't matched
+        return (-1);
+    }
+
+    /**
+      * Matches elements of array r from rpos to rend with array d, starting from dpos.
+      * <br>
+      * This method return true if elements of array r from rpos to rend
+      * equals elements of array d starting from dpos to dpos+(rend-rpos).
+      *
+      * @param r The array containing the data that need to be matched in d.
+      * @param rpos The index of the first character in r to look for.
+      * @param d The array of char that should start from a part of r.
+      * @param dpos The starting offset in d for the matching.
+      * @return true if array d starts from portion of array r.
+      */
+    protected static boolean matchArray (int r[], int rpos, int rend,
+            char d[], int dpos) {
+        if (d.length - dpos < rend - rpos)
+            return (false);
+        for (int i = rpos; i < rend; i++)
+            if (r[i] != d[dpos++])
+                return (false);
+        return (true);
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/helpers/WildcardHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/CachingRegexpMatcher.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/CachingRegexpMatcher.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/CachingRegexpMatcher.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/CachingRegexpMatcher.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,203 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.matching.modular;
+
+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.parameters.Parameters;
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.ServiceSelector;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.thread.ThreadSafe;
+
+import org.apache.cocoon.components.modules.input.InputModule;
+
+import org.apache.cocoon.matching.AbstractRegexpMatcher;
+
+import java.util.Map;
+
+/**
+ * Matches against a regular expression. Needs an input module to
+ * obtain value to match against.
+ *
+ * <p><b>Global and local configuration</b></p>
+ * <table border="1">
+ * <tr><td><code>input-module</code></td><td>Name of the input module used to obtain the value</td></tr>
+ * <tr><td><code>parameter-name</code></td><td>Name of the parameter to match * against</td></tr>
+ * </table>
+ *
+ * @author <a href="mailto:haul@apache.org">Christian Haul</a>
+ * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
+ * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
+ * @version CVS $Id: CachingRegexpMatcher.java 55054 2004-10-19 08:21:39Z cziegeler $
+ */
+public class CachingRegexpMatcher extends AbstractRegexpMatcher
+    implements Configurable,  Initializable, Serviceable, Disposable
+{
+
+    /** The service manager instance */
+    protected ServiceManager manager;
+
+    private String defaultParam;
+    private String defaultInput = "request-param"; // default to request parameters
+    private Configuration inputConf = null; // will become an empty configuration object
+                                            // during configure() so why bother here...
+    String INPUT_MODULE_ROLE = InputModule.ROLE;
+    String INPUT_MODULE_SELECTOR = INPUT_MODULE_ROLE+"Selector";
+
+    private boolean initialized = false;
+    private InputModule input;
+    private ServiceSelector inputSelector;
+
+    /* (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;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
+     */
+    public void configure(Configuration config) throws ConfigurationException {
+
+        this.defaultParam = config.getChild("parameter-name").getValue(null);
+        this.inputConf = config.getChild("input-module");
+        this.defaultInput = this.inputConf.getAttribute("name",this.defaultInput);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.activity.Initializable#initialize()
+     */
+    public void initialize() {
+        try {
+            // obtain input module
+            this.inputSelector=(ServiceSelector) this.manager.lookup(INPUT_MODULE_SELECTOR); 
+            if (this.defaultInput != null && 
+                this.inputSelector != null && 
+                this.inputSelector.isSelectable(this.defaultInput)
+                ){
+                this.input = (InputModule) this.inputSelector.select(this.defaultInput);
+                if (!(this.input instanceof ThreadSafe && this.inputSelector instanceof ThreadSafe) ) {
+                    this.inputSelector.release(this.input);
+                    this.manager.release(this.inputSelector);
+                    this.input = null;
+                    this.inputSelector = null;
+                }
+                this.initialized = true;
+            } else {
+                if (getLogger().isErrorEnabled())
+                    getLogger().error("A problem occurred setting up '" + this.defaultInput 
+                                      + "': Selector is "+(this.inputSelector!=null?"not ":"")
+                                      +"null, Component is "
+                                      +(this.inputSelector!=null&&this.inputSelector.isSelectable(this.defaultInput)?"known":"unknown"));
+            }
+        } catch (Exception e) {
+            if (getLogger().isWarnEnabled()) 
+                getLogger().warn("A problem occurred setting up '" + this.defaultInput + "': " + e.getMessage());
+        }
+    }
+
+
+
+    public void dispose() {
+
+        if (!this.initialized) 
+            if (getLogger().isErrorEnabled()) 
+                getLogger().error("Uninitialized Component! FAILING");
+        else 
+            if (this.inputSelector != null) {
+                if (this.input != null)
+                    this.inputSelector.release(this.input);
+                this.manager.release(this.inputSelector);
+            }
+    }
+
+
+
+    protected String getMatchString(Map objectModel, Parameters parameters) {
+
+        String paramName = parameters.getParameter("parameter-name", this.defaultParam);
+        String inputName = parameters.getParameter("input-module", this.defaultInput);
+
+        if (!this.initialized) {
+            if (getLogger().isErrorEnabled()) 
+                getLogger().error("Uninitialized Component! FAILING");
+            return null;
+        }
+        if (paramName == null) {
+            if (getLogger().isWarnEnabled()) 
+                getLogger().warn("No parameter name given. Trying to Continue");
+        }
+        if (inputName == null) {
+            if (getLogger().isWarnEnabled()) 
+                getLogger().warn("No input module given. FAILING");
+            return null;
+        }
+
+        Object result = null;
+
+        if (this.input != null && inputName.equals(this.defaultInput)) {
+            // input module is thread safe
+            // thus we still have a reference to it
+            try {
+                if (this.input != null) {
+                    result = this.input.getAttribute(paramName, this.inputConf, objectModel);
+                }
+            } catch (Exception e) {
+                if (getLogger().isWarnEnabled()) 
+                    getLogger().warn("A problem occurred acquiring Parameter '" + paramName 
+                                      + "' from '" + inputName + "': " + e.getMessage());
+            }
+        } else {
+            // input was not thread safe
+            // so acquire it again
+            ServiceSelector iputSelector = null;
+            InputModule iput = null;
+            try {
+                // obtain input module
+                iputSelector=(ServiceSelector) this.manager.lookup(INPUT_MODULE_SELECTOR); 
+                if (inputName != null && iputSelector != null && iputSelector.isSelectable(inputName)){
+                    iput = (InputModule) iputSelector.select(inputName);
+                }
+                if (iput != null) {
+                    result = iput.getAttribute(paramName, this.inputConf, objectModel);
+                }
+            } catch (Exception e) {
+                if (getLogger().isWarnEnabled()) 
+                    getLogger().warn("A problem occurred acquiring Parameter '" + paramName 
+                                     + "' from '" + inputName + "': " + e.getMessage());
+            } finally {
+                // release components
+                if (iputSelector != null) {
+                    if (iput != null)
+                        iputSelector.release(iput);
+                    this.manager.release(iputSelector);
+                }
+            }
+        }
+
+        if (result instanceof String) {
+            return (String) result;
+        } else {
+            return result.toString();
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/CachingRegexpMatcher.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/CachingWildcardMatcher.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/CachingWildcardMatcher.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/CachingWildcardMatcher.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/CachingWildcardMatcher.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,200 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.matching.modular;
+
+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.parameters.Parameters;
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.ServiceSelector;
+import org.apache.avalon.framework.service.Serviceable;
+import org.apache.avalon.framework.thread.ThreadSafe;
+
+import org.apache.cocoon.components.modules.input.InputModule;
+import org.apache.cocoon.matching.AbstractWildcardMatcher;
+
+import java.util.Map;
+
+/**
+ * Matches against a wildcard expression. Needs an input module to
+ * obtain value to match against.
+ *
+ * <p><b>Global and local configuration</b></p>
+ * <table border="1">
+ * <tr><td><code>input-module</code></td><td>Name of the input module used to obtain the value</td></tr>
+ * <tr><td><code>parameter-name</code></td><td>Name of the parameter to match * against</td></tr>
+ * </table>
+ *
+ * @author <a href="mailto:haul@apache.org">Christian Haul</a>
+ * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
+ * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
+ * @version CVS $Id: CachingWildcardMatcher.java 55054 2004-10-19 08:21:39Z cziegeler $
+ */
+public class CachingWildcardMatcher extends AbstractWildcardMatcher
+    implements Configurable,  Initializable, Serviceable, Disposable
+{
+
+    /** The service manager instance */
+    protected ServiceManager manager;
+
+    private String defaultParam;
+    private String defaultInput = "request-param"; // default to request parameters
+    private Configuration inputConf = null; // will become an empty configuration object
+                                            // during configure() so why bother here...
+    String INPUT_MODULE_ROLE = InputModule.ROLE;
+    String INPUT_MODULE_SELECTOR = INPUT_MODULE_ROLE+"Selector";
+
+    private boolean initialized = false;
+    private InputModule input;
+    private ServiceSelector inputSelector;
+
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
+     */
+    public void configure(Configuration config) throws ConfigurationException {
+        this.defaultParam = config.getChild("parameter-name").getValue(null);
+        this.inputConf = config.getChild("input-module");
+        this.defaultInput = this.inputConf.getAttribute("name",this.defaultInput);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.activity.Initializable#initialize()
+     */
+    public void initialize() {
+        try {
+            // obtain input module
+            this.inputSelector=(ServiceSelector) this.manager.lookup(INPUT_MODULE_SELECTOR); 
+            if (this.defaultInput != null && 
+                this.inputSelector != null && 
+                this.inputSelector.isSelectable(this.defaultInput)
+                ){
+                this.input = (InputModule) this.inputSelector.select(this.defaultInput);
+                if (!(this.input instanceof ThreadSafe && this.inputSelector instanceof ThreadSafe) ) {
+                    this.inputSelector.release(this.input);
+                    this.manager.release(this.inputSelector);
+                    this.input = null;
+                    this.inputSelector = null;
+                }
+                this.initialized = true;
+            } else {
+                if (getLogger().isErrorEnabled())
+                    getLogger().error("A problem occurred setting up '" + this.defaultInput 
+                                      + "': Selector is "+(this.inputSelector!=null?"not ":"")
+                                      +"null, Component is "
+                                      +(this.inputSelector!=null&&this.inputSelector.isSelectable(this.defaultInput)?"known":"unknown"));
+            }
+        } catch (Exception e) {
+            if (getLogger().isWarnEnabled()) 
+                getLogger().warn("A problem occurred setting up '" + this.defaultInput + "': " + e.getMessage());
+        }
+    }
+
+
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.activity.Disposable#dispose()
+     */
+    public void dispose() {
+        if (!this.initialized) 
+            if (getLogger().isErrorEnabled()) 
+                getLogger().error("Uninitialized Component! FAILING");
+        else 
+            if (this.inputSelector != null) {
+                if (this.input != null)
+                    this.inputSelector.release(this.input);
+                this.manager.release(this.inputSelector);
+            }
+    }
+
+
+
+    protected String getMatchString(Map objectModel, Parameters parameters) {
+
+        String paramName = parameters.getParameter("parameter-name", this.defaultParam);
+        String inputName = parameters.getParameter("input-module", this.defaultInput);
+
+        if (!this.initialized) {
+            if (getLogger().isErrorEnabled()) 
+                getLogger().error("Uninitialized Component! FAILING");
+            return null;
+        }
+        if (paramName == null) {
+            if (getLogger().isWarnEnabled()) 
+                getLogger().warn("No parameter name given. Trying to Continue");
+        }
+        if (inputName == null) {
+            if (getLogger().isWarnEnabled()) 
+                getLogger().warn("No input module given. FAILING");
+            return null;
+        }
+
+        Object result = null;
+
+        if (this.input != null && inputName.equals(this.defaultInput)) {
+            // input module is thread safe
+            // thus we still have a reference to it
+            try {
+                if (this.input != null) {
+                    result = this.input.getAttribute(paramName, this.inputConf, objectModel);
+                }
+            } catch (Exception e) {
+                if (getLogger().isWarnEnabled()) 
+                    getLogger().warn("A problem occurred acquiring Parameter '" + paramName 
+                                      + "' from '" + inputName + "': " + e.getMessage());
+            }
+        } else {
+            // input was not thread safe
+            // so acquire it again
+            ServiceSelector iputSelector = null;
+            InputModule iput = null;
+            try {
+                // obtain input module
+                iputSelector=(ServiceSelector) this.manager.lookup(INPUT_MODULE_SELECTOR); 
+                if (inputName != null && iputSelector != null && iputSelector.isSelectable(inputName)){
+                    iput = (InputModule) iputSelector.select(inputName);
+                }
+                if (iput != null) {
+                    result = iput.getAttribute(paramName, this.inputConf, objectModel);
+                }
+            } catch (Exception e) {
+                if (getLogger().isWarnEnabled()) 
+                    getLogger().warn("A problem occurred acquiring Parameter '" + paramName 
+                                     + "' from '" + inputName + "': " + e.getMessage());
+            } finally {
+                // release components
+                if (iputSelector != null) {
+                    if (iput != null)
+                        iputSelector.release(iput);
+                    this.manager.release(iputSelector);
+                }
+            }
+        }
+
+        if (result instanceof String) {
+            return (String) result;
+        } else {
+            return result.toString();
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/CachingWildcardMatcher.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/WildcardMatcher.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/WildcardMatcher.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/WildcardMatcher.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/WildcardMatcher.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,131 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.matching.modular;
+
+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.parameters.Parameters;
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.ServiceSelector;
+import org.apache.avalon.framework.service.Serviceable;
+
+import org.apache.cocoon.components.modules.input.InputModule;
+import org.apache.cocoon.matching.AbstractWildcardMatcher;
+
+import java.util.Map;
+
+/**
+ * Matches against a wildcard expression. Needs an input module to
+ * obtain value to match against.
+ *
+ * <p><b>Global and local configuration</b></p>
+ * <table border="1">
+ * <tr><td><code>input-module</code></td><td>Name of the input module used to obtain the value</td></tr>
+ * <tr><td><code>parameter-name</code></td><td>Name of the parameter to match * against</td></tr>
+ * </table>
+ *
+ * @author <a href="mailto:haul@apache.org">Christian Haul</a>
+ * @author <a href="mailto:sylvain@apache.org">Sylvain Wallez</a>
+ * @author <a href="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
+ * @version CVS $Id: WildcardMatcher.java 55054 2004-10-19 08:21:39Z cziegeler $
+ */
+public class WildcardMatcher extends AbstractWildcardMatcher
+    implements Configurable, Serviceable
+{
+
+    /** The service manager instance */
+    protected ServiceManager manager;
+
+    private String defaultParam;
+    private String defaultInput = "request-param"; // default to request parameters
+    private Configuration inputConf = null; // will become an empty configuration object
+                                            // during configure() so why bother here...
+    String INPUT_MODULE_ROLE = InputModule.ROLE;
+    String INPUT_MODULE_SELECTOR = INPUT_MODULE_ROLE+"Selector";
+
+    /* (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;
+    }
+
+    public void configure(Configuration config) throws ConfigurationException {
+        this.defaultParam = config.getChild("parameter-name").getValue(null);
+        this.inputConf = config.getChild("input-module");
+        this.defaultInput = this.inputConf.getAttribute("name",this.defaultInput);
+    }
+
+    protected String getMatchString(Map objectModel, Parameters parameters) {
+
+        String paramName = parameters.getParameter("parameter-name", this.defaultParam);
+        String inputName = parameters.getParameter("input-module", this.defaultInput);
+
+        if (paramName == null) {
+            if (getLogger().isWarnEnabled()) 
+                getLogger().warn("No parameter name given. Trying to continue");
+        }
+        if (inputName == null) {
+            if (getLogger().isWarnEnabled()) 
+                getLogger().warn("No input module given. FAILING");
+            return null;
+        }
+
+        InputModule input = null;
+        ServiceSelector inputSelector = null;
+        Object result = null;
+
+        // one could test whether the input module is ThreadSafe and
+        // keep a reference for that instance. Then one would need
+        // to implement Disposable in order to release it at EOL
+        // That would probably speed up things a lot. Especially, since
+        // matchers are invoked very often.
+        // Perhaps a CachingWildcardMatcher ?
+
+        try {
+            // obtain input module
+            inputSelector=(ServiceSelector) this.manager.lookup(INPUT_MODULE_SELECTOR); 
+            if (inputName != null && inputSelector != null && inputSelector.isSelectable(inputName)){
+                input = (InputModule) inputSelector.select(inputName);
+            }
+            if (input != null) {
+                result = input.getAttribute(paramName, this.inputConf, objectModel);
+            }
+        } catch (Exception e) {
+            if (getLogger().isWarnEnabled()) 
+                getLogger().warn("A problem occurred acquiring Parameter '" + paramName 
+                                 + "' from '" + inputName + "': " + e.getMessage());
+        } finally {
+            // release components
+            if (inputSelector != null) {
+                if (input != null)
+                    inputSelector.release(input);
+                this.manager.release(inputSelector);
+            }
+        }
+
+        if (getLogger().isDebugEnabled())
+            getLogger().debug(" using "+inputName+" obtained value "+result);
+
+        if (result instanceof String) {
+            return (String) result;
+        } else {
+            return result.toString();
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/matching/modular/WildcardMatcher.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/AbstractReader.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/AbstractReader.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/AbstractReader.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/AbstractReader.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,111 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.reading;
+
+import org.apache.avalon.excalibur.pool.Recyclable;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.SourceResolver;
+import org.xml.sax.SAXException;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Map;
+
+/**
+ * A reader can be used to generate binary output for a request. This
+ * abstract class helps in implementing a custom reader.
+ *
+ * @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a>
+ * @version CVS $Id: AbstractReader.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+public abstract class AbstractReader
+  extends AbstractLogEnabled
+  implements Reader, Recyclable {
+
+    /** The current <code>SourceResolver</code>. */
+    protected SourceResolver resolver;
+    /** The current <code>Map</code> of the object model. */
+    protected Map objectModel;
+    /** The current <code>Parameters</code>. */
+    protected Parameters parameters;
+    /** The source URI associated with the request or <b>null</b>. */
+    protected String source;
+    /** The <code>OutputStream</code> to write on. */
+    protected OutputStream out;
+
+    /**
+     * Set the <code>SourceResolver</code> the object model <code>Map</code>,
+     * the source and sitemap <code>Parameters</code> used to process the request.
+     */
+    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
+    throws ProcessingException, SAXException, IOException {
+        this.resolver=resolver;
+        this.objectModel=objectModel;
+        this.source=src;
+        this.parameters=par;
+    }
+
+    /**
+     * Set the <code>OutputStream</code>
+     */
+    public void setOutputStream(OutputStream out) {
+        if ( out instanceof BufferedOutputStream 
+             || out instanceof org.apache.cocoon.util.BufferedOutputStream ) {
+            this.out = out;
+        } else {
+            this.out = new BufferedOutputStream(out, 1536);
+        }
+    }
+
+    /**
+     * Get the mime-type of the output of this <code>Reader</code>
+     * This default implementation returns null to indicate that the
+     * mime-type specified in the sitemap is to be used
+     */
+    public String getMimeType() {
+        return null;
+    }
+
+    /**
+     * @return the time the read source was last modified or 0 if it is not
+     *         possible to detect
+     */
+    public long getLastModified() {
+        return 0;
+    }
+
+    /**
+     * Recycle the component
+     */
+    public void recycle() {
+        this.out = null;
+        this.resolver = null;
+        this.source = null;
+        this.parameters = null;
+        this.objectModel = null;
+    }
+
+    /**
+     * Test if the component wants to set the content length
+     */
+    public boolean shouldSetContentLength() {
+        return false;
+    }
+
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/AbstractReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ImageReader.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ImageReader.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ImageReader.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ImageReader.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,338 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed 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.reading;
+
+import java.awt.color.ColorSpace;
+import java.awt.geom.AffineTransform;
+import java.awt.image.AffineTransformOp;
+import java.awt.image.BufferedImage;
+import java.awt.image.ColorConvertOp;
+import java.awt.image.RescaleOp;
+import java.awt.image.WritableRaster;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.Map;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.reading.ResourceReader;
+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.JPEGDecodeParam;
+import com.sun.image.codec.jpeg.JPEGEncodeParam;
+import com.sun.image.codec.jpeg.JPEGImageDecoder;
+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
+ * the requested resource should be written to the <code>OutputStream</code>
+ * or if it can signal that it hasn't changed.
+ *
+ * Parameters:
+ *   <dl>
+ *     <dt>&lt;width&gt;</dt>
+ *     <dd> This parameter is optional. When specified, it determines the
+ *          width of the binary image.
+ *          If no height parameter is specified, the aspect ratio
+ *          of the image is kept. The parameter may be expressed as an int or a percentage.
+ *     </dd>
+ *     <dt>&lt;height&gt;</dt>
+ *     <dd> This parameter is optional. When specified, it determines the
+ *          height of the binary image.
+ *          If no width parameter is specified, the aspect ratio
+ *          of the image is kept. The parameter may be expressed as an int or a percentage.
+ *     </dd>
+ *     <dt>&lt;scale(Red|Green|Blue)&gt;</dt>
+ *     <dd>This parameter is optional. When specified it will cause the
+ *         specified color component in the image to be multiplied by the
+ *         specified floating point value.
+ *     </dd>
+ *     <dt>&lt;offset(Red|Green|Blue)&gt;</dt>
+ *     <dd>This parameter is optional. When specified it will cause the
+ *         specified color component in the image to be incremented by the
+ *         specified floating point value.
+ *     </dd>
+ *     <dt>&lt;grayscale&gt;</dt>
+ *     <dd>This parameter is optional. When specified and set to true it
+ *         will cause each image pixel to be normalized. Default is "false".
+ *     </dd>
+ *     <dt>&lt;allow-enlarging&gt;</dt>
+ *     <dd>This parameter is optional. By default, if the image is smaller
+ *         than the specified width and height, the image will be enlarged.
+ *         In some circumstances this behaviour is undesirable, and can be
+ *         switched off by setting this parameter to "<code>false</code>" so that
+ *         images will be reduced in size, but not enlarged. The default is
+ *         "<code>true</code>".
+ *     </dd>
+ *     <dt>&lt;quality&gt;</dt>
+ *     <dd>This parameter is optional. By default, the quality uses the
+ *         default for the JVM. If it is specified, the proper JPEG quality
+ *         compression is used. The range is 0.0 to 1.0, if specified. 
+ *     </dd>
+ *   </dl>
+ *
+ * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
+ * @author <a href="mailto:stephan@apache.org">Stephan Michels</a>
+ * @author <a href="mailto:tcurdt@apache.org">Torsten Curdt</a>
+ * @author <a href="mailto:eric@plauditdesign.com">Eric Caron</a>
+ * @version CVS $Id: ImageReader.java 289507 2005-09-16 12:07:41Z jheymans $
+ */
+final public class ImageReader extends ResourceReader {
+    private static final boolean GRAYSCALE_DEFAULT = false;
+    private static final boolean ENLARGE_DEFAULT = true;
+    private static final boolean FIT_DEFAULT = false;
+
+    private int width;
+    private int height;
+    private float[] scaleColor = new float[3];
+    private float[] offsetColor = new float[3];
+    private float[] quality = new float[1];
+
+    private boolean enlarge;
+    private boolean fitUniform;
+    private boolean usePercent;
+    private RescaleOp colorFilter;
+    private ColorConvertOp grayscaleFilter;
+
+
+    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
+    throws ProcessingException, SAXException, IOException {
+
+        char lastChar;
+        String tmpWidth = par.getParameter("width", "0");
+        String tmpHeight = par.getParameter("height", "0");
+
+        this.scaleColor[0] = par.getParameterAsFloat("scaleRed", -1.0f);
+        this.scaleColor[1] = par.getParameterAsFloat("scaleGreen", -1.0f);
+        this.scaleColor[2] = par.getParameterAsFloat("scaleBlue", -1.0f);
+        this.offsetColor[0] = par.getParameterAsFloat("offsetRed", 0.0f);
+        this.offsetColor[1] = par.getParameterAsFloat("offsetGreen", 0.0f);
+        this.offsetColor[2] = par.getParameterAsFloat("offsetBlue", 0.0f);
+        this.quality[0] = par.getParameterAsFloat("quality", 0.9f);
+
+        boolean filterColor = false;
+        for (int i = 0; i < 3; ++i) {
+            if (this.scaleColor[i] != -1.0f) {
+                filterColor = true;
+            } else {
+                this.scaleColor[i] = 1.0f;
+            }
+            if (this.offsetColor[i] != 0.0f) {
+                filterColor = true;
+            }
+        }
+
+        if (filterColor) {
+            this.colorFilter = new RescaleOp(scaleColor, offsetColor, null);
+        }
+
+        usePercent = false;
+        lastChar = tmpWidth.charAt(tmpWidth.length() - 1);
+        if (lastChar == '%') {
+            usePercent = true;
+            width = Integer.parseInt(tmpWidth.substring(0, tmpWidth.length() - 1));
+        } else {
+            width = Integer.parseInt(tmpWidth);
+        }
+
+        lastChar = tmpHeight.charAt(tmpHeight.length() - 1);
+        if(lastChar == '%') {
+            usePercent = true;
+            height = Integer.parseInt(tmpHeight.substring(0, tmpHeight.length() - 1));
+        } else {
+            height = Integer.parseInt(tmpHeight);
+        }
+
+        if (par.getParameterAsBoolean("grayscale", GRAYSCALE_DEFAULT)) {
+            this.grayscaleFilter = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
+        }
+
+        this.enlarge = par.getParameterAsBoolean("allow-enlarging", ENLARGE_DEFAULT);
+        this.fitUniform = par.getParameterAsBoolean("fit-uniform", FIT_DEFAULT);
+
+        super.setup(resolver, objectModel, src, par);
+    }
+
+    protected void setupHeaders() {
+        // Reset byte ranges support for dynamic response
+        if (byteRanges && hasTransform()) {
+            byteRanges = false;
+        }
+
+        super.setupHeaders();
+    }
+
+    /**
+     * @return True if image transform is specified
+     */
+    private boolean hasTransform() {
+        return width > 0 || height > 0 || null != colorFilter || null != grayscaleFilter || (this.quality[0] != 0.9f);
+    }
+
+    /**
+     * Returns the affine transform that implements the scaling.
+     * The behavior is the following: if both the new width and height values
+     * are positive, the image is rescaled according to these new values and
+     * the original aspect ratio is lost.
+     * Otherwise, if one of the two parameters is zero or negative, the
+     * aspect ratio is maintained and the positive parameter indicates the
+     * scaling.
+     * If both new values are zero or negative, no scaling takes place (a unit
+     * transformation is applied).
+     */
+    private AffineTransform getTransform(double ow, double oh, double nw, double nh) {
+        double wm = 1.0d;
+        double hm = 1.0d;
+
+        if (fitUniform) {
+            //
+            // Compare aspect ratio of image vs. that of the "box"
+            // defined by nw and nh
+            //
+            if (ow/oh > nw/nh) {
+                nh = 0;    // Original image is proportionately wider than the box,
+                        // so scale to fit width
+            } else {
+                nw = 0;    // Scale to fit height
+            }
+        }
+
+        if (nw > 0) {
+            wm = nw / ow;
+            if (nh > 0) {
+                hm = nh / oh;
+            } else {
+                hm = wm;
+            }
+        } else {
+            if (nh > 0) {
+                hm = nh / oh;
+                wm = hm;
+            }
+        }
+
+        if (!enlarge) {
+            if ((nw > ow && nh <= 0) || (nh > oh && nw <=0)) {
+                wm = 1.0d;
+                hm = 1.0d;
+            } else if (nw > ow) {
+                wm = 1.0d;
+            } else if (nh > oh) {
+                hm = 1.0d;
+            }
+        }
+        return new AffineTransform(wm, 0.0d, 0.0d, hm, 0.0d, 0.0d);
+    }
+
+    protected void processStream(InputStream inputStream) throws IOException, ProcessingException {
+        if (hasTransform()) {
+            if (getLogger().isDebugEnabled()) {
+                getLogger().debug("image " + ((width == 0) ? "?" : Integer.toString(width))
+                                  + "x"    + ((height == 0) ? "?" : Integer.toString(height))
+                                  + " expires: " + expires);
+            }
+
+            try {
+                JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(inputStream);
+                BufferedImage original = decoder.decodeAsBufferedImage();
+                BufferedImage currentImage = original;
+
+                if (width > 0 || height > 0) {
+                    JPEGDecodeParam decodeParam = decoder.getJPEGDecodeParam();
+                    double ow = decodeParam.getWidth();
+                    double oh = decodeParam.getHeight();
+
+                    if (usePercent == true) {
+                        if (width > 0) {
+                            width = Math.round((int)(ow * width) / 100);
+                        }
+                        if (height > 0) {
+                            height = Math.round((int)(oh * height) / 100);
+                        }
+                    }
+
+                    AffineTransformOp filter = new AffineTransformOp(getTransform(ow, oh, width, height), AffineTransformOp.TYPE_BILINEAR);
+                    WritableRaster scaledRaster = filter.createCompatibleDestRaster(currentImage.getRaster());
+
+                    filter.filter(currentImage.getRaster(), scaledRaster);
+
+                    currentImage = new BufferedImage(original.getColorModel(), scaledRaster, true, null);
+                }
+
+                if (null != grayscaleFilter) {
+                    grayscaleFilter.filter(currentImage, currentImage);
+                }
+
+                if (null != colorFilter) {
+                    colorFilter.filter(currentImage, currentImage);
+                }
+                JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
+                JPEGEncodeParam p = encoder.getDefaultJPEGEncodeParam(currentImage);
+                p.setQuality(this.quality[0], true);
+                encoder.setJPEGEncodeParam(p);
+                encoder.encode(currentImage);
+                out.flush();
+            } catch (ImageFormatException e) {
+                throw new ProcessingException("Error reading the image. " +
+                                              "Note that only JPEG images are currently supported.");
+            } finally {
+              // Bugzilla Bug 25069, close inputStream in finally block
+              // this will close inputStream even if processStream throws
+              // an exception
+              inputStream.close();
+            }
+        } else {
+            // only read the resource - no modifications requested
+            if (getLogger().isDebugEnabled()) {
+                getLogger().debug("passing original resource");
+            }
+            super.processStream(inputStream);
+        }
+    }
+
+    /**
+     * Generate the unique key.
+     * This key must be unique inside the space of this component.
+     *
+     * @return The generated key consists of the src and width and height, and the color transform
+     * parameters
+    */
+    public Serializable getKey() {
+        return this.inputSource.getURI()
+                + ':' + this.width
+                + ':' + this.height
+                + ":" + this.scaleColor[0]
+                + ":" + this.scaleColor[1]
+                + ":" + this.scaleColor[2]
+                + ":" + this.offsetColor[0]
+                + ":" + this.offsetColor[1]
+                + ":" + this.offsetColor[2]
+                + ":" + this.quality[0]
+                + ":" + ((null == this.grayscaleFilter) ? "color" : "grayscale")
+                + ":" + super.getKey();
+    }
+
+    public void recycle(){
+        super.recycle();
+        this.colorFilter = null;
+        this.grayscaleFilter = null;
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ImageReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/Reader.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/Reader.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/Reader.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/Reader.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,46 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.reading;
+
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.sitemap.SitemapModelComponent;
+import org.apache.cocoon.sitemap.SitemapOutputComponent;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+
+/**
+ * A reader can be used to generate binary output for a request.
+ *
+ * @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a>
+ * @version CVS $Id: Reader.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+public interface Reader extends SitemapModelComponent, SitemapOutputComponent {
+
+    String ROLE = Reader.class.getName();
+
+    /**
+     * Generate the response.
+     */
+    void generate()
+    throws IOException, SAXException, ProcessingException;
+
+    /**
+     * @return the time the read source was last modified or 0 if it is not
+     *         possible to detect
+     */
+    long getLastModified();
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/Reader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ResourceReader.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ResourceReader.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ResourceReader.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ResourceReader.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,363 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed 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.reading;
+
+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.parameters.ParameterException;
+import org.apache.avalon.framework.parameters.Parameters;
+
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.caching.CacheableProcessingComponent;
+import org.apache.cocoon.components.source.SourceUtil;
+import org.apache.cocoon.environment.Context;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.environment.Response;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.environment.http.HttpResponse;
+import org.apache.cocoon.util.ByteRange;
+
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceException;
+import org.apache.excalibur.source.SourceValidity;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The <code>ResourceReader</code> component is used to serve binary data
+ * in a sitemap pipeline. It makes use of HTTP Headers to determine if
+ * the requested resource should be written to the <code>OutputStream</code>
+ * or if it can signal that it hasn't changed.
+ *
+ * <p>Configuration:
+ * <dl>
+ *   <dt>&lt;expires&gt;</dt>
+ *   <dd>This parameter is optional. When specified it determines how long
+ *       in miliseconds the resources can be cached by any proxy or browser
+ *       between Cocoon and the requesting visitor. Defaults to -1.
+ *   </dd>
+ *   <dt>&lt;quick-modified-test&gt;</dt>
+ *   <dd>This parameter is optional. This boolean parameter controls the
+ *       last modified test. If set to true (default is false), only the
+ *       last modified of the current source is tested, but not if the
+ *       same source is used as last time
+ *       (see http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=102921894301915 )
+ *   </dd>
+ *   <dt>&lt;byte-ranges&gt;</dt>
+ *   <dd>This parameter is optional. This boolean parameter controls whether
+ *       Cocoon should support byterange requests (to allow clients to resume
+ *       broken/interrupted downloads).
+ *       Defaults to true.
+ * </dl>
+ *
+ * <p>Default configuration:
+ * <pre>
+ *   &lt;expires&gt;-1&lt;/expires&gt;
+ *   &lt;quick-modified-test&gt;false&lt;/quick-modified-test&gt;
+ *   &lt;byte-ranges&gt;true&lt;/byte-ranges&gt;
+ * </pre>
+ *
+ * <p>In addition to reader configuration, above parameters can be passed
+ * to the reader at the time when it is used.
+ *
+ * @author <a href="mailto:Giacomo.Pati@pwr.ch">Giacomo Pati</a>
+ * @author <a href="mailto:tcurdt@apache.org">Torsten Curdt</a>
+ * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ * @version CVS $Id: ResourceReader.java 155099 2005-02-23 22:48:09Z vgritsenko $
+ */
+public class ResourceReader extends AbstractReader
+                            implements CacheableProcessingComponent, Configurable {
+
+    /**
+     * The list of generated documents
+     */
+    private static final Map documents = new HashMap();
+
+    protected long configuredExpires;
+    protected boolean configuredQuickTest;
+    protected int configuredBufferSize;
+    protected boolean configuredByteRanges;
+
+    protected long expires;
+    protected boolean quickTest;
+    protected int bufferSize;
+    protected boolean byteRanges;
+
+    protected Response response;
+    protected Request request;
+    protected Source inputSource;
+
+    /**
+     * Read reader configuration
+     */
+    public void configure(Configuration configuration) throws ConfigurationException {
+        // VG Parameters are deprecated as of 2.2.0-Dev/2.1.6-Dev
+        final Parameters parameters = Parameters.fromConfiguration(configuration);
+        this.configuredExpires = parameters.getParameterAsLong("expires", -1);
+        this.configuredQuickTest = parameters.getParameterAsBoolean("quick-modified-test", false);
+        this.configuredBufferSize = parameters.getParameterAsInteger("buffer-size", 8192);
+        this.configuredByteRanges = parameters.getParameterAsBoolean("byte-ranges", true);
+
+        // Configuration has precedence over parameters.
+        this.configuredExpires = configuration.getChild("expires").getValueAsLong(configuredExpires);
+        this.configuredQuickTest = configuration.getChild("quick-modified-test").getValueAsBoolean(configuredQuickTest);
+        this.configuredBufferSize = configuration.getChild("buffer-size").getValueAsInteger(configuredBufferSize);
+        this.configuredByteRanges = configuration.getChild("byte-ranges").getValueAsBoolean(configuredByteRanges);
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(Parameters)
+     */
+    public void parameterize(Parameters parameters) throws ParameterException {
+    }
+
+    /**
+     * Setup the reader.
+     * The resource is opened to get an <code>InputStream</code>,
+     * the length and the last modification date
+     */
+    public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
+    throws ProcessingException, SAXException, IOException {
+        super.setup(resolver, objectModel, src, par);
+
+        this.request = ObjectModelHelper.getRequest(objectModel);
+        this.response = ObjectModelHelper.getResponse(objectModel);
+
+        this.expires = par.getParameterAsLong("expires", this.configuredExpires);
+        this.quickTest = par.getParameterAsBoolean("quick-modified-test", this.configuredQuickTest);
+        this.bufferSize = par.getParameterAsInteger("buffer-size", this.configuredBufferSize);
+        this.byteRanges = par.getParameterAsBoolean("byte-ranges", this.configuredByteRanges);
+
+        try {
+            this.inputSource = resolver.resolveURI(src);
+        } catch (SourceException e) {
+            throw SourceUtil.handle("Error during resolving of '" + src + "'.", e);
+        }
+
+        setupHeaders();
+    }
+
+    /**
+     * Setup the response headers: Accept-Ranges, Expires.
+     */
+    protected void setupHeaders() {
+        // Tell the client whether we support byte range requests or not
+        if (byteRanges) {
+            response.setHeader("Accept-Ranges", "bytes");
+        } else {
+            response.setHeader("Accept-Ranges", "none");
+        }
+
+        if (expires > 0) {
+            response.setDateHeader("Expires", System.currentTimeMillis() + expires);
+        } else if (expires == 0) {
+            // See Bug #14048
+            response.addHeader("Vary", "Host");
+        }
+    }
+
+    /**
+     * Recyclable
+     */
+    public void recycle() {
+        this.request = null;
+        this.response = null;
+        if (this.inputSource != null) {
+            super.resolver.release(this.inputSource);
+            this.inputSource = null;
+        }
+        super.recycle();
+    }
+
+    /**
+     * @return True if byte ranges support is enabled and request has range header.
+     */
+    protected boolean hasRanges() {
+        return this.byteRanges && this.request.getHeader("Range") != null;
+    }
+
+    /**
+     * Generate the unique key.
+     * This key must be unique inside the space of this component.
+     *
+     * @return The generated key hashes the src
+     */
+    public Serializable getKey() {
+        return inputSource.getURI();
+    }
+
+    /**
+     * Generate the validity object.
+     *
+     * @return The generated validity object or <code>null</code> if the
+     *         component is currently not cacheable.
+     */
+    public SourceValidity getValidity() {
+        if (hasRanges()) {
+            // This is a byte range request so we can't use the cache, return null.
+            return null;
+        } else {
+            return inputSource.getValidity();
+        }
+    }
+
+    /**
+     * @return the time the read source was last modified or 0 if it is not
+     *         possible to detect
+     */
+    public long getLastModified() {
+        if (hasRanges()) {
+            // This is a byte range request so we can't use the cache, return null.
+            return 0;
+        }
+
+        if (quickTest) {
+            return inputSource.getLastModified();
+        }
+
+        final String systemId = (String) documents.get(request.getRequestURI());
+        if (systemId == null || inputSource.getURI().equals(systemId)) {
+            return inputSource.getLastModified();
+        }
+
+        documents.remove(request.getRequestURI());
+        return 0;
+    }
+
+    protected void processStream(InputStream inputStream)
+    throws IOException, ProcessingException {
+        byte[] buffer = new byte[bufferSize];
+        int length = -1;
+
+        String ranges = request.getHeader("Range");
+
+        ByteRange byteRange;
+        if (byteRanges && ranges != null) {
+            try {
+                ranges = ranges.substring(ranges.indexOf('=') + 1);
+                byteRange = new ByteRange(ranges);
+            } catch (NumberFormatException e) {
+                byteRange = null;
+
+                // TC: Hm.. why don't we have setStatus in the Response interface ?
+                if (response instanceof HttpResponse) {
+                    // Respond with status 416 (Request range not satisfiable)
+                    ((HttpResponse)response).setStatus(416);
+                    if (getLogger().isDebugEnabled()) {
+                        getLogger().debug("malformed byte range header [" + String.valueOf(ranges) + "]");
+                    }
+                }
+            }
+        } else {
+            byteRange = null;
+        }
+
+        long contentLength = inputSource.getContentLength();
+
+        if (byteRange != null) {
+            String entityLength;
+            String entityRange;
+            if (contentLength != -1) {
+                entityLength = "" + contentLength;
+                entityRange = byteRange.intersection(new ByteRange(0, contentLength)).toString();
+            } else {
+                entityLength = "*";
+                entityRange = byteRange.toString();
+            }
+
+            response.setHeader("Content-Range", entityRange + "/" + entityLength);
+            if (response instanceof HttpResponse) {
+                // Response with status 206 (Partial content)
+                ((HttpResponse)response).setStatus(206);
+            }
+
+            int pos = 0;
+            int posEnd;
+            while ((length = inputStream.read(buffer)) > -1) {
+                posEnd = pos + length - 1;
+                ByteRange intersection = byteRange.intersection(new ByteRange(pos, posEnd));
+                if (intersection != null) {
+                    out.write(buffer, (int) intersection.getStart() - pos, (int) intersection.length());
+                }
+                pos += length;
+            }
+        } else {
+            if (contentLength != -1) {
+                response.setHeader("Content-Length", Long.toString(contentLength));
+            }
+
+            while ((length = inputStream.read(buffer)) > -1) {
+                out.write(buffer, 0, length);
+            }
+        }
+
+        out.flush();
+    }
+
+    /**
+     * Generates the requested resource.
+     */
+    public void generate()
+    throws IOException, ProcessingException {
+        try {
+            InputStream inputStream;
+            try {
+                inputStream = inputSource.getInputStream();
+            } catch (SourceException e) {
+                throw SourceUtil.handle("Error during resolving of the input stream", e);
+            }
+
+            // Bugzilla Bug #25069: Close inputStream in finally block.
+            try {
+                processStream(inputStream);
+            } finally {
+                if (inputStream != null) {
+                    inputStream.close();
+                }
+            }
+
+            if (!quickTest) {
+                // if everything is ok, add this to the list of generated documents
+                // (see http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=102921894301915 )
+                documents.put(request.getRequestURI(), inputSource.getURI());
+            }
+        } catch (IOException e) {
+            getLogger().debug("Received an IOException, assuming client severed connection on purpose");
+        }
+    }
+
+    /**
+     * Returns the mime-type of the resource in process.
+     */
+    public String getMimeType() {
+        Context ctx = ObjectModelHelper.getContext(objectModel);
+        if (ctx != null) {
+            final String mimeType = ctx.getMimeType(source);
+            if (mimeType != null) {
+                return mimeType;
+            }
+        }
+
+        return inputSource.getMimeType();
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ResourceReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ServiceableReader.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ServiceableReader.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ServiceableReader.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ServiceableReader.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,45 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.reading;
+
+import org.apache.avalon.framework.service.ServiceException;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.Serviceable;
+
+/**
+ * The serviceable reader will allow any {@link Reader} implementation that
+ * extends this to access other Avalon components.
+ *
+ * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ * 
+ * @version CVS $Id: ServiceableReader.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+public abstract class ServiceableReader 
+    extends AbstractReader 
+    implements Serviceable {
+
+       
+    protected ServiceManager manager;
+     
+    /**
+	 * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+	 */
+	public void service(ServiceManager manager) 
+    throws ServiceException {
+        this.manager = manager;
+	}
+
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/ServiceableReader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/VirtualPipelineReader.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/VirtualPipelineReader.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/VirtualPipelineReader.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/VirtualPipelineReader.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,83 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * Licensed 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.reading;
+
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.environment.internal.EnvironmentHelper;
+import org.apache.cocoon.sitemap.impl.AbstractVirtualSitemapComponent;
+
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+public class VirtualPipelineReader extends AbstractVirtualSitemapComponent
+    implements Reader {
+
+    protected String getTypeName() {
+        return "reader";
+    }
+
+    /**
+     * Set the <code>OutputStream</code>
+     */
+    public void setOutputStream(OutputStream out) {
+        this.getMappedSourceEnvironment().setOutputStream(out);
+    }
+
+    /**
+     * Get the mime-type of the output of this <code>Reader</code>
+     */
+    public String getMimeType() {
+        return this.getPipeline().getMimeType();
+    }
+
+    /**
+     * @return the time the read source was last modified or 0 if it is not
+     *         possible to detect
+     */
+    public long getLastModified() {
+        return 0;
+    }
+
+    /**
+     * Test if the component wants to set the content length
+     */
+    public boolean shouldSetContentLength() {
+        return this.getPipeline().shouldSetContentLength();
+    }
+
+    public void generate()
+    throws IOException, SAXException, ProcessingException {
+
+        // Should use SourceResolver and context of the this
+        // components' sitemap, not caller sitemap
+        EnvironmentHelper.enterEnvironment(this.getVPCEnvironment());
+        try {
+            this.getPipeline().prepareInternal(this.getVPCEnvironment());
+        } finally {
+            EnvironmentHelper.leaveEnvironment();
+        }
+
+        // Should use SourceResolver of the this components' sitemap, not caller sitemap
+        EnvironmentHelper.enterEnvironment(this.getMappedSourceEnvironment());
+        try {
+            this.getPipeline().process(this.getMappedSourceEnvironment());
+        } finally {
+            EnvironmentHelper.leaveEnvironment();
+        }
+    }
+}

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/reading/VirtualPipelineReader.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message