cocoon-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jheym...@apache.org
Subject svn commit: r330548 [63/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/transformation/helpers/ModifiableSourceIncludeCacheStorageProxy.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/ModifiableSourceIncludeCacheStorageProxy.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/ModifiableSourceIncludeCacheStorageProxy.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/ModifiableSourceIncludeCacheStorageProxy.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,192 @@
+/*
+ * 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.transformation.helpers;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.cocoon.CascadingIOException;
+import org.apache.cocoon.util.HashUtil;
+import org.apache.excalibur.source.ModifiableSource;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
+
+/**
+ * This is the interface between the {@link IncludeCacheManager} and a
+ * {@link Source} object that stores the cached content in a directory
+ * manner.
+ * 
+ *  @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ *  @version CVS $Id: ModifiableSourceIncludeCacheStorageProxy.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ *  @since   2.1
+ */
+public final class ModifiableSourceIncludeCacheStorageProxy
+    implements IncludeCacheStorageProxy {
+
+    private SourceResolver resolver;
+    private String         parentURI;
+    private Logger         logger;
+    
+    /**
+     * Constructor
+     * @param resolver   For source resolving
+     * @param parentURI  The "directory"
+     * @param logger     A logger for debugging
+     */
+    public ModifiableSourceIncludeCacheStorageProxy(SourceResolver resolver,
+                                             String         parentURI,
+                                             Logger         logger) {
+        this.resolver = resolver;
+        this.parentURI= parentURI;
+        this.logger = logger;
+    }
+    
+    /**
+     * Calculate the URI for a child
+     * @param uri     Child URI
+     * @return String Absolute URI
+     */
+    private String getURI(String uri) {
+        final long hash = HashUtil.hash(uri);
+        final StringBuffer buffer = new StringBuffer(this.parentURI);
+        buffer.append('/');
+        if (hash < 0) {
+            buffer.append('M').append(hash * -1);
+        } else {
+            buffer.append(hash);
+        }
+        buffer.append(".cxml");
+        return buffer.toString();
+    }
+    
+    /**
+     * @see IncludeCacheStorageProxy#get(java.lang.String)
+     */
+    public Serializable get(String uri) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("WSCProxy: Getting content for " + uri);
+        }
+
+        Source child = null;
+        Serializable result = null;
+        try {
+            child = this.resolver.resolveURI(this.getURI(uri));
+
+            if (logger.isDebugEnabled()) {
+                logger.debug("WSCProxy: Resolved to " + child.getURI());
+            }
+
+            if (child.exists()) {
+                InputStream is = child.getInputStream();
+                ObjectInputStream ois = new ObjectInputStream(is);
+                result = (Serializable)ois.readObject();
+                ois.close();
+            }
+        } catch (Exception ignore) {
+        } finally {
+            this.resolver.release( child );
+        }
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("WSCProxy: Result for " + uri + " : " + (result == null ? "Not in cache" : "Found"));
+        }
+        return result;
+    }
+
+    /**
+     * @see IncludeCacheStorageProxy#put(java.lang.String, java.io.Serializable)
+     */
+    public void put(String uri, Serializable object) 
+    throws IOException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("WSCProxy: Storing content for " + uri);
+        }
+        Source child = null;
+        try {
+            child = this.resolver.resolveURI(this.getURI(uri));
+
+            if (logger.isDebugEnabled()) {
+                logger.debug("WSCProxy: Resolved to " + child.getURI());
+            }
+
+            OutputStream os;
+            if (child instanceof ModifiableSource) {
+                os = ((ModifiableSource)child).getOutputStream();
+            } else {
+                throw new IOException("Source " + uri + " is not writeable.");
+            }
+            ObjectOutputStream oos = new ObjectOutputStream(os);
+            oos.writeObject(object);
+            oos.flush();
+            oos.close();
+        } catch (IOException io) {
+            throw io;
+        } catch (Exception ignore) {
+            throw new CascadingIOException("Exception.", ignore);
+        } finally {
+            this.resolver.release( child );
+        }
+    }
+
+    /**
+     * @see IncludeCacheStorageProxy#remove(java.lang.String)
+     */
+    public void remove(String uri) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("WSCProxy: Removing content for " + uri);
+        }
+        Source child = null;
+        try {
+            child = this.resolver.resolveURI(this.getURI(uri));
+
+            if (logger.isDebugEnabled()) {
+                logger.debug("WSCProxy: Resolved to " + child.getURI());
+            }
+
+            if (child instanceof ModifiableSource) {
+                ((ModifiableSource)child).delete();
+            } else {
+                throw new IOException("Source " + uri + " is not writeable.");
+            }
+        } catch (Exception ignore) {
+        } finally {
+            this.resolver.release( child );
+        }
+    }
+
+    /**
+     * Compare
+     */
+    public boolean equals(Object object) {
+        if (object instanceof ModifiableSourceIncludeCacheStorageProxy) {
+            return this.parentURI.equals(((ModifiableSourceIncludeCacheStorageProxy)object).parentURI);
+        }
+        return false;
+    }
+
+    /**
+     * Generate a hash code
+     */
+    public int hashCode() {
+        return this.parentURI.hashCode();
+    }
+
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/NOPRecorder.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/NOPRecorder.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/NOPRecorder.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/NOPRecorder.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,103 @@
+/*
+ * 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.transformation.helpers;
+
+import org.apache.cocoon.xml.XMLConsumer;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.LexicalHandler;
+
+/**
+ * The base class for all recorders. Simply does nothing
+ *
+ * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
+ * @version CVS $Id: NOPRecorder.java 30941 2004-07-29 19:56:58Z vgritsenko $
+*/
+public abstract class NOPRecorder
+implements ContentHandler, LexicalHandler, XMLConsumer {
+
+    public NOPRecorder() {
+    }
+
+    public void setDocumentLocator(Locator locator) {
+    }
+
+    public void startDocument()
+    throws SAXException {
+    }
+
+    public void endDocument()
+    throws SAXException {
+    }
+
+    public void startPrefixMapping(String prefix, String uri)
+    throws SAXException {
+    }
+
+    public void endPrefixMapping(String prefix)
+    throws SAXException {
+    }
+
+    public void startElement(String namespace, String name, String raw,
+                         Attributes attr)
+    throws SAXException {
+    }
+
+    public void endElement(String namespace, String name, String raw)
+    throws SAXException {
+    }
+
+    public void characters(char ary[], int start, int length)
+    throws SAXException {
+    }
+
+    public void ignorableWhitespace(char ary[], int start, int length)
+    throws SAXException {
+    }
+
+    public void processingInstruction(String target, String data)
+    throws SAXException {
+    }
+
+    public void skippedEntity(String name)
+    throws SAXException {
+    }
+
+    public void startDTD(String name, String public_id, String system_id)
+    throws SAXException {
+    }
+
+    public void endDTD() throws SAXException {
+    }
+
+    public void startEntity(String name) throws SAXException {
+    }
+
+    public void endEntity(String name) throws SAXException {
+    }
+
+    public void startCDATA() throws SAXException {
+    }
+
+    public void endCDATA() throws SAXException {
+    }
+
+    public void comment(char ary[], int start, int length)
+    throws SAXException {
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/ParametersRecorder.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/ParametersRecorder.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/ParametersRecorder.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/ParametersRecorder.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,118 @@
+/*
+ * 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.transformation.helpers;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.excalibur.source.SourceParameters;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import java.util.Iterator;
+
+
+/**
+ * This class records SAX Events and generates Parameters from them
+ * The xml is flat and consists of elements which all have exactly one text node:
+ * <parone>value_one<parone>
+ * <partwo>value_two<partwo>
+ *
+ * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
+ * @version CVS $Id: ParametersRecorder.java 30941 2004-07-29 19:56:58Z vgritsenko $
+*/
+public final class ParametersRecorder
+extends NOPRecorder {
+
+    private SourceParameters parameters;
+    private String     key;
+    private StringBuffer buffer;
+
+    /**
+     * If source is null a new Parameters object is created
+     * Otherwise they are joined.
+     */
+    public ParametersRecorder() {
+        super();
+        this.parameters = new SourceParameters();
+    }
+
+    public SourceParameters getParameters(Parameters source) {
+        if (source != null) {
+            String[] names = source.getNames();
+//            Iterator names = source.getParameterNames();
+            if (names != null) {
+                String currentParameterName;
+                for(int i=0; i<names.length; i++) {
+                    currentParameterName = names[i];
+//                while (names.hasNext() == true) {
+//                    currentParameterName = (String)names.next();
+                    this.parameters.setParameter(currentParameterName, source.getParameter(currentParameterName, ""));
+                }
+            }
+        }
+        return parameters;
+    }
+
+    public SourceParameters getParameters(SourceParameters source) {
+        if (source != null) {
+            Iterator iter = source.getParameterNames();
+            Iterator valuesIter;
+            String value, parName;
+            while (iter.hasNext() == true) {
+                parName = (String)iter.next();
+                valuesIter = source.getParameterValues(parName);
+                while (valuesIter.hasNext() == true) {
+                    value = (String)valuesIter.next();
+                    this.parameters.setParameter(parName, value);
+                }
+            }
+        }
+        return parameters;
+    }
+
+    public void startElement(String namespace, String name, String raw,
+                         Attributes attr)
+    throws SAXException {
+        if (this.key == null) {
+            this.key = name;
+            this.buffer = new StringBuffer();
+        }
+    }
+
+    public void endElement(String namespace, String name, String raw)
+    throws SAXException {
+        if (this.key != null && this.key.equals(name) == true) {
+            String value = this.buffer.toString().trim();
+            if (value.length() > 0) {
+                this.parameters.setParameter(this.key, value);
+            }
+            this.buffer = null;
+            this.key = null;
+        }
+    }
+
+    public void characters(char ary[], int start, int length)
+    throws SAXException {
+        if (this.key != null && this.buffer != null) {
+            String value = new String(ary, start, length).trim();
+            if (value.length() > 0) {
+                buffer.append(value);
+            } else {
+                buffer.append(' ');
+            }
+        }
+    }
+
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/PreemptiveLoader.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/PreemptiveLoader.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/PreemptiveLoader.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/PreemptiveLoader.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,164 @@
+/*
+ * 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.transformation.helpers;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.cocoon.caching.CachedResponse;
+import org.apache.cocoon.components.sax.XMLSerializer;
+import org.apache.cocoon.components.source.SourceUtil;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.source.impl.validity.ExpiresValidity;
+
+/**
+ * The preemptive loader is a singleton that runs in the background
+ * and loads content into the cache.
+ * 
+ *  @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ *  @version CVS $Id: PreemptiveLoader.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ *  @since   2.1
+ */
+public final class PreemptiveLoader {
+
+    private static final PreemptiveLoader instance = new PreemptiveLoader();
+    
+    /** The list of proxies currently used for caching */
+    private Map   cacheStorageProxyMap = new HashMap(20);
+    /** The list of URIs to load */
+    private List  loadList = new ArrayList(50);
+    /** Is this thread still alive? */
+    boolean alive = false;
+    
+    /**
+     * Return singleton.
+     * @return PreemptiveLoader
+     */
+    static PreemptiveLoader getInstance() {
+        return instance;
+    }
+    
+    /**
+     * Add a new task
+     * @param proxy   The cache to store the content
+     * @param uri     The absolute URI to load
+     * @param expires The expires information used for the cache
+     */
+    public void add(IncludeCacheStorageProxy proxy, String uri, long expires) {
+        boolean addItem = true;
+        List uriList = (List)this.cacheStorageProxyMap.get(proxy);
+        if ( null == uriList ) {
+             uriList = new ArrayList(50);
+             this.cacheStorageProxyMap.put(proxy, uriList);
+        } else {
+            synchronized (uriList) {
+                // nothing to do: uri is alredy in list
+               if (uriList.contains(uri)) {
+                   addItem = false;
+               } 
+            }
+        }
+        if ( addItem ) {
+            uriList.add(uri);
+            this.loadList.add(new Object[] {proxy, uri, new Long(expires), uriList});
+        }
+
+        synchronized (this.cacheStorageProxyMap) {
+            this.cacheStorageProxyMap.notify();
+        }
+    }
+    
+    /**
+     * Start the preemptive loading
+     * @param manager   A component manager
+     * @param resolver  A source resolver
+     * @param logger    A logger
+     */
+    public void process(ServiceManager manager,
+                         SourceResolver  resolver,
+                         Logger          logger) {
+        this.alive = true;
+        if (logger.isDebugEnabled()) {
+            logger.debug("PreemptiveLoader: Starting preemptive loading");
+        }
+
+        while (this.alive) {
+            while (this.loadList.size() > 0) {
+                Object[] object = (Object[])this.loadList.get(0);
+                final String uri = (String)object[1];
+                this.loadList.remove(0);
+                synchronized (object[3]) {
+                    ((List)object[3]).remove(uri);
+                }
+                
+                Source source = null;
+                XMLSerializer serializer = null;
+
+                try {
+                    if (logger.isDebugEnabled()) {
+                        logger.debug("PreemptiveLoader: Loading " + uri);
+                    }
+
+                    source = resolver.resolveURI(uri);
+                    serializer = (XMLSerializer)manager.lookup(XMLSerializer.ROLE);
+                
+                    SourceUtil.toSAX(source, serializer);
+                
+                    SourceValidity[] validities = new SourceValidity[1];
+                    validities[0] = new ExpiresValidity(((Long)object[2]).longValue() * 1000); // milliseconds!
+                    CachedResponse response = new CachedResponse(validities,
+                                                                 (byte[])serializer.getSAXFragment());
+                    ((IncludeCacheStorageProxy)object[0]).put(uri, response);
+                     
+                } catch (Exception ignore) {
+                    // all exceptions are ignored!
+                } finally {
+                    resolver.release( source );
+                    manager.release( serializer );
+                }
+                if (logger.isDebugEnabled()) {
+                    logger.debug("PreemptiveLoader: Finished loading " + uri);
+                }
+            }
+            synchronized (this.cacheStorageProxyMap) {
+                try {
+                    this.cacheStorageProxyMap.wait();
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+        if (logger.isDebugEnabled()) {
+            logger.debug("PreemptiveLoader: Finished preemptive loading");
+        }
+    }
+    
+    /**
+     * Stop the loading. 
+     * The loader stops when all tasks from the queue are processed.
+     */
+    synchronized public void stop() {
+        this.alive = false;
+        synchronized (this.cacheStorageProxyMap) {
+            this.cacheStorageProxyMap.notify();
+        }
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/PreemptiveLoaderAction.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/PreemptiveLoaderAction.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/PreemptiveLoaderAction.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/PreemptiveLoaderAction.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,55 @@
+/*
+ * 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.transformation.helpers;
+
+import java.util.Map;
+
+import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.avalon.framework.thread.ThreadSafe;
+import org.apache.cocoon.acting.ServiceableAction;
+import org.apache.cocoon.environment.Redirector;
+import org.apache.cocoon.environment.SourceResolver;
+
+/**
+ * This action starts the preemptive loader and runs forever.
+ * 
+ *  @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ *  @version CVS $Id: PreemptiveLoaderAction.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ *  @since   2.1
+ */
+public class PreemptiveLoaderAction 
+    extends ServiceableAction
+    implements ThreadSafe {
+
+    /**
+     * This action starts the preemptive loading
+     * It runs forever and is stopped by the {@link DefaultIncludeCacheManager}.
+     * @see org.apache.cocoon.acting.Action#act(Redirector, SourceResolver, Map, String, Parameters)
+     */
+    public Map act(Redirector redirector,
+                    SourceResolver resolver,
+                    Map objectModel,
+                    String source,
+                    Parameters parameters)
+    throws Exception {
+        PreemptiveLoader loader = PreemptiveLoader.getInstance();
+        if (!loader.alive) {
+            loader.process(this.manager, resolver, this.getLogger());
+            return EMPTY_MAP;
+        }
+        return null;
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/StoreIncludeCacheStorageProxy.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/StoreIncludeCacheStorageProxy.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/StoreIncludeCacheStorageProxy.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/StoreIncludeCacheStorageProxy.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,90 @@
+/*
+ * 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.transformation.helpers;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+import org.apache.avalon.framework.logger.Logger;
+import org.apache.excalibur.store.Store;
+
+/**
+ * This is the interface between the {@link IncludeCacheManager} and the usual
+ * store.
+ * 
+ *  @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
+ *  @version CVS $Id: StoreIncludeCacheStorageProxy.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ *  @since   2.1
+ */
+public final class StoreIncludeCacheStorageProxy
+    implements IncludeCacheStorageProxy {
+
+    private Store  store;
+    
+    private Logger logger;
+    
+    /**
+     * Constructor
+     * @param store  The store for the cached content
+     * @param logger A logger for debugging
+     */
+    public StoreIncludeCacheStorageProxy(Store store, Logger logger) {
+        this.store = store;
+        this.logger = logger;
+    }
+    
+    /** A string representation for a key */
+    private String getKey(String uri) {
+        return "DCS:" + uri;
+    }
+    
+    /**
+     * @see IncludeCacheStorageProxy#get(java.lang.String)
+     */
+    public Serializable get(String uri) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("StoreProxy: Getting content for " + uri);
+        }
+
+        Serializable result = (Serializable)this.store.get(this.getKey(uri));
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("StoreProxy: Result for " + uri + " : " + (result == null ? "Not in cache" : "Found"));
+        }
+        return result;
+    }
+
+    /**
+     * @see IncludeCacheStorageProxy#put(java.lang.String, java.io.Serializable)
+     */
+    public void put(String uri, Serializable object) 
+    throws IOException {
+        if (logger.isDebugEnabled()) {
+            logger.debug("StoreProxy: Storing content for " + uri);
+        }
+        this.store.store(this.getKey(uri), object);
+    }
+
+    /**
+     * @see IncludeCacheStorageProxy#remove(java.lang.String)
+     */
+    public void remove(String uri) {
+        if (logger.isDebugEnabled()) {
+            logger.debug("StoreProxy: Removing content for " + uri);
+        }
+        this.store.remove(this.getKey(uri));
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/TextRecorder.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/TextRecorder.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/TextRecorder.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/helpers/TextRecorder.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,47 @@
+/*
+ * 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.transformation.helpers;
+
+/**
+ * This class records all character SAX events and creates a string
+ * from them.
+ *
+ * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
+ * @version $Id: TextRecorder.java 165681 2005-05-02 20:40:31Z vgritsenko $
+*/
+public final class TextRecorder extends NOPRecorder {
+
+    /**
+     * Buffer collecting all character events.
+     */
+    private StringBuffer buffer;
+
+    public TextRecorder() {
+        super();
+        this.buffer = new StringBuffer();
+    }
+
+    public void characters(char ary[], int start, int length) {
+        this.buffer.append(ary, start, length);
+    }
+
+    /**
+     * @return Recorded text so far, trimmed.
+     */
+    public String getText() {
+        return this.buffer.toString().trim();
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/ItemGroup.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/ItemGroup.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/ItemGroup.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/ItemGroup.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,56 @@
+/*
+ * 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.transformation.pagination;
+
+/**
+ * Container class for the immutable pagination rules for each page.
+ *
+ * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
+ * @version CVS $Id: ItemGroup.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+public class ItemGroup {
+    
+    private String name;
+    private String elementName;
+    private String elementURI;
+    
+    public ItemGroup (String name, String elementURI, String elementName) {
+        this.name = name;
+        this.elementURI = elementURI;
+        this.elementName = elementName;
+    }
+    
+    public boolean match(String elementName, String elementURI) {
+        return (this.elementName.equals(elementName) && this.elementURI.equals(elementURI));
+    }
+
+    public boolean match(String elementURI) {
+        return this.elementURI.equals(elementURI);
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public String getElementURI() {
+        return this.elementURI;
+    }
+    
+    public String getElementName() {
+        return this.elementName;
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/PageRules.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/PageRules.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/PageRules.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/PageRules.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,69 @@
+/*
+ * 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.transformation.pagination;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Container class for the immutable pagination rules for each page.
+ *
+ * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
+ * @author <a href="mailto:bhtek@yahoo.com">Boon Hian Tek</a>
+ * @version CVS $Id: PageRules.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+public class PageRules {
+
+    public String elementName;
+    public String elementURI;
+    public int elementCount = 0;
+    public int charCount = 0;
+    public int unitLinks = 0;
+    private List rangeLinks = new ArrayList();
+
+    public boolean match(String element, String namespace) {
+        boolean elementMatches = ((this.elementName!=null) &&
+                                  this.elementName.equals(element));
+
+        if (this.elementURI==null) {
+            return elementMatches;
+        } else {
+            return elementMatches && this.elementURI.equals(namespace);
+        }
+    }
+
+    public boolean match(String namespace) {
+        return ((this.elementURI!=null) &&
+                (this.elementURI.equals(namespace)));
+    }
+
+    public Integer[] getRangeLinks() {
+        return (Integer[]) this.rangeLinks.toArray(new Integer[this.rangeLinks.size()]);
+    }
+
+    public void addRangeLink(Integer rangeLink) {
+        this.rangeLinks.add(rangeLink);
+    }
+
+    public void addRangeLink(int rangeLink) {
+        this.addRangeLink(new Integer(rangeLink));
+    }
+
+    public void addRangeLink(String rangeLink) {
+        this.addRangeLink(new Integer(rangeLink));
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Pagesheet.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Pagesheet.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Pagesheet.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Pagesheet.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,468 @@
+/*
+ * 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.transformation.pagination;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.cocoon.Modifiable;
+import org.apache.cocoon.util.ResizableContainer;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Interprets the pagesheet rules to perform pagination.
+ *
+ * <pre>
+ * FIXME (SM): this code sucks! It was done to show the concept of
+ *             rule driven pagination (which I find very nice) but
+ *             it needs major refactoring in order to be sufficiently
+ *             stable to allow any input to enter without breaking
+ *             SAX well-formness. I currently don't have the time to make
+ *             it any better (along with implementing the char-based rule
+ *             that is mostly useful for text documents) but if you want
+ *             to blast the code and rewrite it better, you'll make me happy :)
+ * </pre>
+ *
+ * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
+ * @author <a href="mailto:bhtek@yahoo.com">Boon Hian Tek</a>
+ * @version CVS $Id: Pagesheet.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+
+/*
+
+This is an example pagesheet to show the power of this:
+
+  <?xml version="1.0"?>
+  <pagesheet xmlns="http://apache.org/cocoon/paginate/1.0">
+   <items>
+    <group name="pictures" element="file" namespace="http://apache.org/cocoon/directory/2.0"/>
+   </items>
+   <rules page="1">
+    <count type="element" name="file" namespace="http://apache.org/cocoon/directory/2.0" num="16"/>
+     <link type="unit" num="2"/>
+     <link type="range" value="10"/>
+   </rules>
+   <rules>
+    <count type="element" name="file" namespace="http://apache.org/cocoon/directory/2.0" num="16"/>
+     <link type="unit" num="5"/>
+     <link type="range" value="20"/>
+   </rules>
+   <rules>
+     <count type="element" name="file" namespace="http://apache.org/cocoon/directory/2.0" num="16"/>
+     <link type="unit" num="5"/>
+     <link type="range" value="2"/>
+     <link type="range" value="5"/>
+     <link type="range" value="10"/>
+     <link type="range" value="20"/>
+     <link type="range" value="100"/>
+   </rules>
+  </pagesheet>
+
+which indicates that:
+
+ 1) there is one item group called "picture" and each item is given by the
+    element "file" of the namespace "http://apache.org/cocoon/directory/2.0".
+
+ 2) for the first page, the pagination rules indicate that there are two unit
+    links (two above and two below, so linking to page -2 -1 0 +1 +2) and
+    range links have value 10 (so they link to page -10 and +10).
+
+ 3) for the rest of the pages, there are three unit links (-3 -2 -1 0 +1 +2 +3)
+    and range goes 20 (so +20 and -20).
+
+ 4) if more than one ranges are defined, range links will be created in sequence
+
+ 5) range links will be from big to small (eg. 20, 10, then 5) for backward links,
+    range links will be from small to big (eg. 5, 10, then 20) for forward links
+
+ 6) range link(s) will have an attribute 'range' to indicate the range size
+
+*/
+public class Pagesheet extends DefaultHandler implements Cloneable, Modifiable {
+
+    // Used only during parsing of pagesheet document
+    private int level = 0;
+    private int pg = 0;
+    private long lastModified;
+    private PageRules rules;
+
+    // Loaded pagesheet information
+    ResizableContainer pageRules;
+
+    Map itemGroupsPerName;
+    Map itemGroupsPerElement;
+    Map itemListsPerName;
+    Map itemListsPerElement;
+
+    // Runtime information
+    private ResizableContainer pages;
+    private Page currentPage = null;
+    private int pageCounter = 1;
+    private int elementCounter = 0;
+    private int descendant = 0;
+
+    private static class Page {
+        public int elementStart;
+        public int elementEnd;
+        public int characters;
+
+        public Page(PageRules rules, int elementStart) {
+            this.elementStart = elementStart;
+
+            if (rules.elementCount>0) {
+                this.elementEnd = this.elementStart+rules.elementCount-1;
+            } else {
+                this.elementEnd = this.elementStart+1;
+            }
+        }
+
+        public boolean validInPage(int elementCounter) {
+            return (this.elementStart<=elementCounter) &&
+                   (elementCounter<=this.elementEnd);
+        }
+    }
+
+    private static class ItemList extends ArrayList {
+        public ItemList(int capacity) {
+            super(capacity);
+        }
+
+        public void addItem(int page) {
+            this.add(new Integer(page));
+        }
+
+        public int getPageForItem(int item) {
+            Integer i = (Integer) this.get(item-1);
+
+            return (i==null) ? 0 : i.intValue();
+        }
+
+        public boolean valid(int item) {
+            return (item==this.size());
+        }
+    }
+
+
+    public Pagesheet() {
+        this.pages = new ResizableContainer(2);
+    }
+
+    private Pagesheet(ResizableContainer rules, Map itemGroupsPerName,
+                      Map itemGroupsPerElement) {
+        this.pageRules = rules;
+        this.itemGroupsPerName = itemGroupsPerName;
+        this.itemGroupsPerElement = itemGroupsPerElement;
+
+        this.pages = new ResizableContainer(5);
+
+        if ((this.itemGroupsPerName!=null) &&
+            (this.itemGroupsPerElement!=null)) {
+            this.itemListsPerName = new HashMap(itemGroupsPerName.size());
+            this.itemListsPerElement = new HashMap(itemGroupsPerName.size());
+
+            Iterator iter = itemGroupsPerName.values().iterator();
+
+            for (; iter.hasNext(); ) {
+                ItemGroup group = (ItemGroup) iter.next();
+                ItemList list = new ItemList(10);
+
+                this.itemListsPerName.put(group.getName(), list);
+                this.itemListsPerElement.put(group.getElementURI()+
+                                             group.getElementName(), list);
+            }
+        }
+    }
+
+    // --------------- interprets the pagesheet document ----------------
+
+    public void startPrefixMapping(String prefix,
+                                   String uri) throws SAXException {
+        if ( !uri.equals(Paginator.PAGINATE_URI)) {
+            throw new SAXException("The pagesheet's namespace is not supported.");
+        }
+    }
+
+    public void startElement(String uri, String loc, String raw,
+                             Attributes a) throws SAXException {
+        level++;
+        switch (level) {
+            case 1 :
+                if (loc.equals("pagesheet")) {
+                    // This object represents pagesheet
+                    return;
+                }
+                break;
+
+            case 2 :
+                if (loc.equals("rules")) {
+                    if (this.pageRules == null) {
+                        this.pageRules = new ResizableContainer(2);
+                    }
+                    String key = a.getValue("page");
+
+                    if (key!=null) {
+                        try {
+                            pg = Integer.parseInt(key);
+                        } catch (NumberFormatException e) {
+                            throw new SAXException("Syntax error: the attribute 'rules/@page' must contain a number");
+                        }
+                    } else {
+                        pg = 0;
+                    }
+                    rules = new PageRules();
+                    return;
+                } else if (loc.equals("items")) {
+                    if (this.itemGroupsPerName==null) {
+                        this.itemGroupsPerName = new HashMap(2);
+                    }
+                    if (this.itemGroupsPerElement==null) {
+                        this.itemGroupsPerElement = new HashMap(2);
+                    }
+                    return;
+                }
+                break;
+
+            case 3 :
+                if (loc.equals("count")) {
+                    rules.elementName = a.getValue("name");
+                    rules.elementURI = a.getValue("namespace");
+
+                    if (a.getValue("type").equals("element")) {
+                        try {
+                            rules.elementCount = Integer.parseInt(a.getValue("num"));
+                        } catch (NumberFormatException e) {
+                            throw new SAXException("Syntax error: the attribute 'count/@num' must contain a number");
+                        }
+                    } else if (a.getValue("type").equals("chars")) {
+                        try {
+                            rules.charCount = Integer.parseInt(a.getValue("num"));
+                        } catch (NumberFormatException e) {
+                            throw new SAXException("Syntax error: the attribute 'count/@num' must contain a number.");
+                        }
+                    } else {
+                        throw new SAXException("Syntax error: count type not supported.");
+                    }
+                    return;
+                } else if (loc.equals("link")) {
+                    if (a.getValue("type").equals("unit")) {
+                        try {
+                            rules.unitLinks = Integer.parseInt(a.getValue("num"));
+                        } catch (NumberFormatException e) {
+                            throw new SAXException("Syntax error: the attribute 'link/@num' must contain a number.");
+                        }
+                    } else if (a.getValue("type").equals("range")) {
+                        try {
+                            rules.addRangeLink(a.getValue("value"));
+                        } catch (NumberFormatException e) {
+                            throw new SAXException("Syntax error: the attribute 'link/@value' must contain a number.");
+                        }
+                    } else {
+                        throw new SAXException("Syntax error: link type not supported.");
+                    }
+                    return;
+                } else if (loc.equals("group")) {
+                    String name = a.getValue("name");
+
+                    if (name==null) {
+                        throw new SAXException("Syntax error: the attribute 'group/@name' must be present.");
+                    }
+                    String elementName = a.getValue("element");
+
+                    if (elementName==null) {
+                        throw new SAXException("Syntax error: the attribute 'group/@element' must be present.");
+                    }
+                    String elementURI = a.getValue("namespace");
+                    ItemGroup group = new ItemGroup(name, elementURI,
+                                                    elementName);
+
+                    this.itemGroupsPerName.put(name, group);
+                    this.itemGroupsPerElement.put(elementURI+elementName,
+                                                  group);
+                    return;
+                }
+        }
+        throw new SAXException("Syntax error: element "+raw+
+                               " is not recognized or is misplaced.");
+    }
+
+    public void endElement(String uri, String loc,
+                           String raw) throws SAXException {
+        level--;
+        if (loc.equals("rules")) {
+            pageRules.set(pg, rules);
+        }
+    }
+
+    public void endDocument() throws SAXException {
+        if (pageRules.size() == 0) {
+            throw new SAXException("Pagesheet must contain at least a set of pagination rules.");
+        }
+        if (pageRules.get(0) == null) {
+            throw new SAXException("Pagesheet must contain the global pagination rules.");
+        }
+    }
+
+    // --------------- process the received element events ----------------
+
+    public void processStartElement(String uri, String name) {
+        PageRules rules = getPageRules(pageCounter);
+
+        if (rules.match(name, uri)) {
+            elementCounter++;
+            descendant++;
+
+            if (currentPage==null) {
+                currentPage = new Page(rules, 1);
+            }
+
+            if (elementCounter>currentPage.elementEnd) {
+                /*System.out.println(">>>> "+pageCounter+
+                                   ": Starting new page!!! >>> "+
+                                   elementCounter);*/
+                pageCounter++;
+                currentPage = new Page(rules, currentPage.elementEnd+1);
+            }
+
+            pages.set(pageCounter, currentPage);
+        }
+
+        if (itemGroupsPerElement!=null) {
+            String qname = uri+name;
+            ItemGroup group = (ItemGroup) this.itemGroupsPerElement.get(qname);
+
+            if ((group!=null) && (group.match(uri))) {
+                ItemList list = (ItemList) this.itemListsPerElement.get(qname);
+
+                if (list!=null) {
+                    list.addItem(pageCounter);
+                }
+            }
+        }
+    }
+
+    public void processEndElement(String uri, String name) {
+        PageRules rules = getPageRules(pageCounter);
+
+        if (rules.match(name, uri)) {
+            descendant--;
+
+            if ((rules.charCount>0) &&
+                (currentPage.characters>rules.charCount)) {
+                // We are over character limit. Flip the page.
+                // System.out.println(">>>> " + pageCounter + ": Flipping page!!!");
+                currentPage.elementEnd = elementCounter;
+            } else if (rules.elementCount==0) {
+                // No limit on elements is specified, and limit on characters is not reached yet.
+                currentPage.elementEnd++;
+            }
+        }
+    }
+
+    public void processCharacters(char[] ch, int index, int len) {
+        if (descendant>0) {
+            // Count amount of characters in the currect page.
+            // System.out.println(">>>> " + pageCounter + ": " + new String(ch, index, len) + " (" + len + " bytes)");
+            currentPage.characters += len;
+        }
+    }
+
+    // --------------- return the pagination information ----------------
+
+    public boolean isInPage(int page, int item, String itemGroup) {
+        return ((descendant==0) || valid(page, item, itemGroup));
+    }
+
+    public int getTotalPages() {
+        return pageCounter;
+    }
+
+    public int getTotalItems(String itemGroup) {
+        if (this.itemListsPerName==null) {
+            return 0;
+        }
+        ItemList list = (ItemList) this.itemListsPerName.get(itemGroup);
+
+        return (list==null) ? 0 : list.size();
+    }
+
+    public int getPageForItem(int item, String itemGroup) {
+        if (this.itemListsPerName==null) {
+            return 0;
+        }
+        ItemList list = (ItemList) this.itemListsPerName.get(itemGroup);
+
+        return (list==null) ? 0 : list.getPageForItem(item);
+    }
+
+    public int itemCount(String elementURI, String elementName) {
+        if (this.itemListsPerElement==null) {
+            return 0;
+        }
+        ItemList list = (ItemList) this.itemListsPerElement.get(elementURI+
+                            elementName);
+
+        return (list==null) ? 0 : list.size();
+    }
+
+    public String getItemGroupName(String elementURI, String elementName) {
+        if (this.itemListsPerElement==null) {
+            return null;
+        }
+        return ((ItemGroup) this.itemGroupsPerElement.get(elementURI+
+            elementName)).getName();
+    }
+
+    // ---------------- miscellaneous methods ----------------------------
+
+    private boolean valid(int page, int item, String itemGroup) {
+        if (item==0) {
+            Page p = (Page) pages.get(page);
+
+            return (p!=null) && (p.validInPage(elementCounter));
+        } else {
+            if (this.itemListsPerElement==null) {
+                return false;
+            }
+            ItemList list = (ItemList) this.itemListsPerName.get(itemGroup);
+
+            return (list!=null) && (list.valid(item));
+        }
+    }
+
+    public PageRules getPageRules(int page) {
+        PageRules p = (PageRules) pageRules.get(page);
+
+        return (p!=null) ? p : (PageRules) pageRules.get(0);
+    }
+
+    public void setLastModified(long lastModified) {
+        this.lastModified = lastModified;
+    }
+
+    public boolean modifiedSince(long date) {
+        return (this.lastModified == 0 || date!=this.lastModified);
+    }
+
+    public Object clone() {
+        return new Pagesheet(pageRules, itemGroupsPerName,
+                             itemGroupsPerElement);
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Paginator.java
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Paginator.java?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Paginator.java (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Paginator.java Thu Nov  3 05:41:06 2005
@@ -0,0 +1,632 @@
+/*
+ * 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.transformation.pagination;
+
+import org.apache.avalon.framework.activity.Disposable;
+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.Serviceable;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.caching.CacheableProcessingComponent;
+import org.apache.cocoon.environment.ObjectModelHelper;
+import org.apache.cocoon.environment.Request;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.transformation.AbstractTransformer;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceException;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.source.impl.validity.AggregatedValidity;
+import org.apache.excalibur.source.impl.validity.TimeStampValidity;
+import org.apache.excalibur.store.Store;
+import org.apache.excalibur.xml.sax.SAXParser;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * A paginating transformer.
+ *
+ * @author     <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
+ * @author     <a href="mailto:stephan@apache.org">Stephan Michels</a>
+ * @author <a href="mailto:bhtek@yahoo.com">Boon Hian Tek</a>
+ * @version    CVS $Id: Paginator.java 30941 2004-07-29 19:56:58Z vgritsenko $
+ */
+public class Paginator extends AbstractTransformer
+  implements Serviceable, Disposable, CacheableProcessingComponent {
+
+    public static final String PAGINATE_URI = "http://apache.org/cocoon/paginate/1.0";
+    public static final String PAGINATE_PREFIX = "page";
+    public static final String PAGINATE_PREFIX_TOKEN = PAGINATE_PREFIX + ":";
+
+    private ServiceManager manager;
+    private SAXParser parser;
+    private Store store;
+    private SourceResolver resolver;
+    private Source inputSource;
+    private int page;
+    private int item;
+    private String itemGroup;
+    private String requestURI;
+    private Request request;
+    private Pagesheet pagesheet;
+    private int level;
+    private boolean prefixMapping;
+
+    /**
+     * Set the current <code>ServiceManager</code> instance used by this
+     * <code>Serviceable</code>.
+     *
+     * @param  manager  Description of the Parameter
+     */
+    public void service(ServiceManager manager) throws ServiceException {
+        try {
+            this.manager = manager;
+            getLogger().debug("Looking up "+SAXParser.ROLE);
+            this.parser = (SAXParser) manager.lookup(SAXParser.ROLE);
+
+            getLogger().debug("Looking up " + Store.TRANSIENT_STORE);
+            this.store = (Store) manager.lookup(Store.TRANSIENT_STORE);
+        } catch (Exception e) {
+            getLogger().error("Could not find component", e);
+        }
+    }
+
+    /**
+     * Dispose this component.
+     */
+    public void dispose() {
+        if (this.parser!=null) {
+            this.manager.release(this.parser);
+        } else {
+            this.parser = null;
+        }
+        if (this.store!=null) {
+            this.manager.release(this.store);
+        } else {
+            this.store = null;
+        }
+    }
+
+    /**
+     * Setup the transformer.
+     */
+    public void setup(SourceResolver resolver, Map objectModel, String src,
+                      Parameters par)
+                        throws ProcessingException, SAXException,
+                               IOException {
+
+        if (src == null) {
+            throw new ProcessingException("I need the paginate instructions (pagesheet) to continue. Set the 'src' attribute.");
+        }
+
+        try {
+            this.level = 0;
+            this.prefixMapping = false;
+            this.resolver = resolver;
+            this.inputSource = resolver.resolveURI(src);
+            if (getLogger().isDebugEnabled()) {
+                getLogger().debug("Using pagesheet: '"+
+                                  this.inputSource.getURI()+"' in "+this+
+                                  ", last modified: "+
+                                  this.inputSource.getLastModified());
+            }
+            this.page = par.getParameterAsInteger("page", 1);
+            this.item = par.getParameterAsInteger("item", 0);
+            this.itemGroup = par.getParameter("item-group", "");
+            if (getLogger().isDebugEnabled()) {
+                getLogger().debug("Paginating with [page = "+this.page+
+                                  ", item = "+this.item+", item-group = "+
+                                  this.itemGroup+"]");
+            }
+
+            this.request = ObjectModelHelper.getRequest(objectModel);
+            this.requestURI = request.getRequestURI();
+
+            // Get the pagesheet factory from the Store if available,
+            // otherwise load it and put it into the store for further request
+            if (store!=null) {
+                pagesheet = (Pagesheet) store.get(src);
+            }
+
+            // If not in the store or if pagesheet has changed, loads and stores it
+            if ((pagesheet==null) ||
+                pagesheet.modifiedSince(inputSource.getLastModified())) {
+                pagesheet = new Pagesheet();
+                pagesheet.setLastModified(inputSource.getLastModified());
+                parser.parse(new InputSource(inputSource.getInputStream()),
+                             pagesheet);
+                if (store!=null) {
+                    store.store(src, pagesheet);
+                }
+            }
+
+            // Clone it in order to avoid concurrency collisions since the
+            // implementation is not reentrant.
+            this.pagesheet = (Pagesheet) this.pagesheet.clone();
+        } catch (SourceException se) {
+            throw new ProcessingException("Could not retrieve source '" +
+                                          src + "'", se);
+        }
+    }
+
+    public void recycle() {
+        if (null != this.inputSource) {
+            this.resolver.release(this.inputSource);
+            this.inputSource = null;
+        }
+        this.resolver = null;
+        super.recycle();
+    }
+
+    /**
+     * Generate the unique key. This key must be unique inside the space of
+     * this component. This method must be invoked before the
+     * generateValidity() method.
+     *
+     * @return The generated key or <code>null</code> if the component is
+     *         currently not cacheable.
+     */
+    public Serializable getKey() {
+        if (this.inputSource.getLastModified()!=0) {
+            return this.inputSource.getURI()+page;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Generate the validity object. Before this method can be invoked the
+     * generateKey() method must be invoked.
+     *
+     * @return The generated validity object or <code>null</code> if the
+     *         component is currently not cacheable.
+     */
+    public SourceValidity getValidity() {
+        if (this.inputSource.getLastModified()!=0) {
+            AggregatedValidity validity = new AggregatedValidity();
+
+            validity.add(new TimeStampValidity(page));
+            validity.add(this.inputSource.getValidity());
+            return validity;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Receive notification of the beginning of an element.
+     *
+     * @param uri The Namespace URI, or the empty string if the
+     *            element has no Namespace URI or if Namespace processing is not being
+     *            performed.
+     * @param loc The local name (without prefix), or the empty
+     *            string if Namespace processing is not being performed.
+     * @param raw The raw XML 1.0 name (with prefix), or the empty
+     *            string if raw names are not available.
+     * @param a The attributes attached to the element. If there
+     *          are no attributes, it shall be an empty Attributes object.
+     */
+    public void startElement(String uri, String loc, String raw,
+                             Attributes a) throws SAXException {
+        if ( !prefixMapping) {
+            super.startPrefixMapping(PAGINATE_PREFIX, PAGINATE_URI);
+            this.prefixMapping = true;
+        }
+        level++;
+        pagesheet.processStartElement(uri, loc);
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            int itemCount = pagesheet.itemCount(uri, loc);
+
+            if (itemCount>0) {
+                String itemGroup = pagesheet.getItemGroupName(uri, loc);
+                AttributesImpl atts = new AttributesImpl(a);
+
+                atts.addAttribute(PAGINATE_URI, "item",
+                                  PAGINATE_PREFIX_TOKEN+"item", "CDATA",
+                                  String.valueOf(itemCount));
+                atts.addAttribute(PAGINATE_URI, "item-group",
+                                  PAGINATE_PREFIX_TOKEN+"item-group",
+                                  "CDATA", itemGroup);
+                super.startElement(uri, loc, raw, atts);
+            } else {
+                super.startElement(uri, loc, raw, a);
+            }
+        }
+    }
+
+    /**
+     * Receive notification of the end of an element.
+     *
+     * @param uri The Namespace URI, or the empty string if the
+     *            element has no Namespace URI or if Namespace processing is not being
+     *            performed.
+     * @param loc The local name (without prefix), or the empty
+     *            string if Namespace processing is not being performed.
+     * @param raw The raw XML 1.0 name (with prefix), or the empty
+     *            string if raw names are not available.
+     */
+    public void endElement(String uri, String loc,
+                           String raw) throws SAXException {
+        level--;
+
+        // Prevent infinite recursive loop.
+        if (PAGINATE_URI.equals(uri)) {
+            super.endElement(uri, loc, raw);
+            return;
+        }
+
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            if (level==0) {
+                if (item==0) {
+                    int totalPages = pagesheet.getTotalPages();
+                    PageRules rules = pagesheet.getPageRules(page);
+
+                    Integer[] rangeLinks = rules.getRangeLinks();
+                    int unitLinks = rules.unitLinks;
+                    int currentPage = page;
+
+                    // call add paginate
+                    addPaginateTags(rangeLinks, unitLinks, currentPage,
+                                    totalPages, requestURI, this);
+
+                } else {
+                    int totalItems = pagesheet.getTotalItems(itemGroup);
+                    AttributesImpl atts = new AttributesImpl();
+
+                    atts.addAttribute("", "current", "current", "CDATA",
+                                      String.valueOf(item));
+                    atts.addAttribute("", "total", "total", "CDATA",
+                                      String.valueOf(totalItems));
+                    atts.addAttribute("", "current-uri", "current-uri",
+                                      "CDATA", requestURI);
+                    atts.addAttribute("", "clean-uri", "clean-uri",
+                                      "CDATA", cleanURI(requestURI, item));
+                    atts.addAttribute("", "page", "page", "CDATA",
+                                      String.valueOf(pagesheet.getPageForItem(item,
+                                          itemGroup)));
+                    super.startElement(PAGINATE_URI, "item",
+                                       PAGINATE_PREFIX_TOKEN+"item", atts);
+                    if (item>1) {
+                        atts.clear();
+                        atts.addAttribute("", "type", "type", "CDATA",
+                                          "prev");
+                        atts.addAttribute("", "uri", "uri", "CDATA",
+                                          encodeURI(requestURI, item,
+                                                    item-1));
+                        super.startElement(PAGINATE_URI, "link",
+                                           PAGINATE_PREFIX_TOKEN+"link",
+                                           atts);
+                        super.endElement(PAGINATE_URI, "link",
+                                         PAGINATE_PREFIX_TOKEN+"link");
+                    }
+                    if (item<=totalItems) {
+                        atts.clear();
+                        atts.addAttribute("", "type", "type", "CDATA",
+                                          "next");
+                        atts.addAttribute("", "uri", "uri", "CDATA",
+                                          encodeURI(requestURI, item,
+                                                    item+1));
+                        super.startElement(PAGINATE_URI, "link",
+                                           PAGINATE_PREFIX_TOKEN+"link",
+                                           atts);
+                        super.endElement(PAGINATE_URI, "link",
+                                         PAGINATE_PREFIX_TOKEN+"link");
+                    }
+                    super.endElement(PAGINATE_URI, "item",
+                                     PAGINATE_PREFIX_TOKEN+"item");
+                }
+
+                super.endPrefixMapping(PAGINATE_PREFIX);
+            }
+
+            super.endElement(uri, loc, raw);
+        }
+
+        pagesheet.processEndElement(uri, loc);
+    }
+
+    public static void addPaginateTags(Integer[] rangeLinks, int unitLinks,
+                                       int currentPage, int totalPages,
+                                       String requestURI,
+                                       AbstractTransformer saxTransformer)
+                                         throws SAXException {
+        AttributesImpl atts = new AttributesImpl();
+
+        atts.addAttribute("", "current", "current", "CDATA",
+                          String.valueOf(currentPage));
+        atts.addAttribute("", "total", "total", "CDATA",
+                          String.valueOf(totalPages));
+        atts.addAttribute("", "current-uri", "current-uri", "CDATA",
+                          requestURI);
+        atts.addAttribute("", "clean-uri", "clean-uri", "CDATA",
+                          Paginator.cleanURI(requestURI, currentPage));
+        saxTransformer.startElement(Paginator.PAGINATE_URI, "page",
+                                    Paginator.PAGINATE_PREFIX_TOKEN+"page",
+                                    atts);
+
+        for (int i = rangeLinks.length-1; i>-1; i--) {
+            int rangeLink = rangeLinks[i].intValue();
+
+            if ((rangeLink>0) && (currentPage-rangeLink>=1)) {
+                atts.clear();
+                atts.addAttribute("", "type", "type", "CDATA", "prev");
+                atts.addAttribute("", "range", "range", "CDATA",
+                                  rangeLinks[i].toString());
+                atts.addAttribute("", "uri", "uri", "CDATA",
+                                  Paginator.encodeURI(requestURI,
+                                                      currentPage,
+                                                      currentPage-rangeLink));
+                atts.addAttribute("", "page", "page", "CDATA",
+                                  String.valueOf(currentPage-rangeLink));
+                saxTransformer.startElement(Paginator.PAGINATE_URI,
+                                            "range-link",
+                                            Paginator.PAGINATE_PREFIX_TOKEN+
+                                            "range-link", atts);
+                saxTransformer.endElement(Paginator.PAGINATE_URI,
+                                          "range-link",
+                                          Paginator.PAGINATE_PREFIX_TOKEN+
+                                          "range-link");
+            }
+        }
+
+        for (int i = currentPage-unitLinks; i<currentPage; i++) {
+            if (i>0) {
+                atts.clear();
+                atts.addAttribute("", "type", "type", "CDATA", "prev");
+                atts.addAttribute("", "uri", "uri", "CDATA",
+                                  Paginator.encodeURI(requestURI,
+                                                      currentPage, i));
+                atts.addAttribute("", "page", "page", "CDATA",
+                                  String.valueOf(i));
+                saxTransformer.startElement(Paginator.PAGINATE_URI, "link",
+                                            Paginator.PAGINATE_PREFIX_TOKEN+
+                                            "link", atts);
+                saxTransformer.endElement(Paginator.PAGINATE_URI, "link",
+                                          Paginator.PAGINATE_PREFIX_TOKEN+
+                                          "link");
+            }
+        }
+        for (int i = currentPage+1; i<=currentPage+unitLinks; i++) {
+            if (i<=totalPages) {
+                atts.clear();
+                atts.addAttribute("", "type", "type", "CDATA", "next");
+                atts.addAttribute("", "uri", "uri", "CDATA",
+                                  Paginator.encodeURI(requestURI,
+                                                      currentPage, i));
+                atts.addAttribute("", "page", "page", "CDATA",
+                                  String.valueOf(i));
+                saxTransformer.startElement(Paginator.PAGINATE_URI, "link",
+                                            Paginator.PAGINATE_PREFIX_TOKEN+
+                                            "link", atts);
+                saxTransformer.endElement(Paginator.PAGINATE_URI, "link",
+                                          Paginator.PAGINATE_PREFIX_TOKEN+
+                                          "link");
+            }
+        }
+
+        for (int i = 0; i<rangeLinks.length; i++) {
+            int rangeLink = rangeLinks[i].intValue();
+
+            if ((rangeLink>0) && (currentPage+rangeLink<=totalPages)) {
+                atts.clear();
+                atts.addAttribute("", "type", "type", "CDATA", "next");
+                atts.addAttribute("", "range", "range", "CDATA",
+                                  rangeLinks[i].toString());
+                atts.addAttribute("", "uri", "uri", "CDATA",
+                                  Paginator.encodeURI(requestURI,
+                                                      currentPage,
+                                                      currentPage+rangeLink));
+                atts.addAttribute("", "page", "page", "CDATA",
+                                  String.valueOf(currentPage+rangeLink));
+                saxTransformer.startElement(Paginator.PAGINATE_URI,
+                                            "range-link",
+                                            Paginator.PAGINATE_PREFIX_TOKEN+
+                                            "range-link", atts);
+                saxTransformer.endElement(Paginator.PAGINATE_URI,
+                                          "range-link",
+                                          Paginator.PAGINATE_PREFIX_TOKEN+
+                                          "range-link");
+            }
+        }
+
+        saxTransformer.endElement(Paginator.PAGINATE_URI, "page",
+                                  Paginator.PAGINATE_PREFIX_TOKEN+"page");
+    }
+
+    /**
+     * Receive notification of character data.
+     *
+     * @param c The characters from the XML document.
+     * @param start The start position in the array.
+     * @param len The number of characters to read from the array.
+     */
+    public void characters(char c[], int start, int len) throws SAXException {
+        pagesheet.processCharacters(c, start, len);
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            super.characters(c, start, len);
+        }
+    }
+
+    /**
+     * Receive notification of ignorable whitespace in element content.
+     *
+     * @param c The characters from the XML document.
+     * @param start The start position in the array.
+     * @param len The number of characters to read from the array.
+     */
+    public void ignorableWhitespace(char c[], int start,
+                                    int len) throws SAXException {
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            super.ignorableWhitespace(c, start, len);
+        }
+    }
+
+    /**
+     * Receive notification of a processing instruction.
+     *
+     * @param target The processing instruction target.
+     * @param data The processing instruction data, or null if none
+     *             was supplied.
+     */
+    public void processingInstruction(String target,
+                                      String data) throws SAXException {
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            super.processingInstruction(target, data);
+        }
+    }
+
+    /**
+     * Receive notification of a skipped entity.
+     *
+     * @param name The name of the skipped entity. If it is a
+     *             parameter entity, the name will begin with '%'.
+     */
+    public void skippedEntity(String name) throws SAXException {
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            super.skippedEntity(name);
+        }
+    }
+
+    /**
+     * Report the start of DTD declarations, if any.
+     *
+     * @param name The document type name.
+     * @param publicId The declared public identifier for the external
+     *                 DTD subset, or null if none was declared.
+     * @param systemId The declared system identifier for the external
+     *                 DTD subset, or null if none was declared.
+     */
+    public void startDTD(String name, String publicId,
+                         String systemId) throws SAXException {
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            super.startDTD(name, publicId, systemId);
+        } else {
+            throw new SAXException("Recieved startDTD not in page.");
+        }
+    }
+
+    /**
+     * Report the end of DTD declarations.
+     */
+    public void endDTD() throws SAXException {
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            super.endDTD();
+        } else {
+            throw new SAXException("Recieved endDTD not in page.");
+        }
+    }
+
+    /**
+     * Report the beginning of an entity.
+     *
+     *@param name The name of the entity. If it is a parameter
+     *            entity, the name will begin with '%'.
+     */
+    public void startEntity(String name) throws SAXException {
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            super.startEntity(name);
+        }
+    }
+
+    /**
+     * Report the end of an entity.
+     *
+     * @param name The name of the entity that is ending.
+     */
+    public void endEntity(String name) throws SAXException {
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            super.endEntity(name);
+        }
+    }
+
+    /**
+     * Report the start of a CDATA section.
+     */
+    public void startCDATA() throws SAXException {
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            super.startCDATA();
+        }
+    }
+
+    /**
+     * Report the end of a CDATA section.
+     */
+    public void endCDATA() throws SAXException {
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            super.endCDATA();
+        }
+    }
+
+    /**
+     * Report an XML comment anywhere in the document.
+     *
+     * @param ch An array holding the characters in the comment.
+     * @param start The starting position in the array.
+     * @param len The number of characters to use from the array.
+     */
+    public void comment(char ch[], int start, int len) throws SAXException {
+        if (pagesheet.isInPage(page, item, itemGroup)) {
+            super.comment(ch, start, len);
+        }
+    }
+
+    /**
+     * Removes the pagination encoding from the URI by removing the page number
+     * and the previous and next character.
+     */
+    public static String cleanURI(String uri, int current) {
+        String currentS = String.valueOf(current);
+        int index = uri.lastIndexOf(currentS);
+
+        if (index==-1) {
+            return uri;
+        } else {
+            return uri.substring(0, index-1)+
+                   uri.substring(index+currentS.length()+1);
+        }
+    }
+
+    /**
+     * Encode the next page in the given URI. First tries to use the existing
+     * encoding by replacing the current page number, but if the current
+     * encoding is not found it appends "(xx)" to the filename (before the file
+     * extention, if any) where "xx" is the next page value.
+     */
+    public static String encodeURI(String uri, int current, int next) {
+        String currentS = String.valueOf(current);
+        String nextS = String.valueOf(next);
+        int index = uri.lastIndexOf(currentS);
+
+        if (index==-1) {
+            index = uri.lastIndexOf('.');
+            if (index==-1) {
+                return uri+"("+nextS+")";
+            } else {
+                return uri.substring(0, index)+"("+nextS+")."+
+                       uri.substring(index+1);
+            }
+        } else {
+            return uri.substring(0, index)+nextS+
+                   uri.substring(index+currentS.length());
+        }
+    }
+}

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

Added: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Paginator.xconf
URL: http://svn.apache.org/viewcvs/cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Paginator.xconf?rev=330548&view=auto
==============================================================================
--- cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Paginator.xconf (added)
+++ cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Paginator.xconf Thu Nov  3 05:41:06 2005
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<!--
+  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.
+-->
+
+<xconf xpath="/cocoon" unless="component[@role='org.apache.cocoon.transformation.pagination.Paginator']">
+
+    <!-- ======================= Paginator =========================== -->
+  <component 
+     class="org.apache.cocoon.transformation.pagination.Paginator" 
+     role="org.apache.cocoon.transformation.pagination.Paginator"
+     logger="core.paginator"/>
+     
+</xconf>

Propchange: cocoon/whiteboard/maven2/cocoon-flat-layout/cocoon-core/src/main/java/org/apache/cocoon/transformation/pagination/Paginator.xconf
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message