svn commit: r1329674 [5/10] - in /cocoon/trunk/site/cocoon-core-site: ./ core/ core/2.2/ core/2.2/src/ core/2.2/src/site/ core/2.2/src/site/resources/ core/2.2/src/site/resources/images/ core/2.2/src/site/xdoc/ src/site/ src/site/resources/ src/site/re...

[email protected]
Newsgroups gmane.text.xml.cocoon.cvs
Message-ID <[email protected]>
Added: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/681_1_1.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/681_1_1.xml?rev=1329674&view=auto
==============================================================================
--- cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/681_1_1.xml (added)
+++ cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/681_1_1.xml Tue Apr 24 12:33:07 2012
@@ -0,0 +1,318 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+      Licensed to the Apache Software Foundation (ASF) under one
+      or more contributor license agreements.  See the NOTICE file
+      distributed with this work for additional information
+      regarding copyright ownership.  The ASF licenses this file
+      to you under the Apache License, Version 2.0 (the
+      "License"); you may not use this file except in compliance
+      with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing,
+      software distributed under the License is distributed on an
+      "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+      KIND, either express or implied.  See the License for the
+      specific language governing permissions and limitations
+      under the License.
+    --><document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/XDOC/2.0" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"><properties><title>Cocoon Core - Creating a Reader</title><author email="[email protected]">Apache Cocoon Documentation Team</author></properties><body>
+         <div id="contentBody"><div id="bodyText"><h1 class="docTitle">Creating a Reader</h1><h1>Creating a Reader</h1><p>Readers are the components that send you a stream without the XML processing
+that normally happens in a pipeline. Cocoon already comes with some readers out
+of the box such as your FileReader which serializes files from your webapp
+context. What if you need something that doesn't come from the file system? What
+if you need to create content on the fly but the XML processing gets in the way?
+That's where the Reader comes to play. Even though there is a DatabaseReader in
+the Cocoon's SQL block, we are going to go through the process of creating a
+cacheable database reader here.</p><p>In the sitemap we use the reader we are going to develop like this:</p><pre>&lt;map:match pattern="attachment/*"&gt;
+  &lt;map:read type="db-attachments" src="{1}"/&gt;
+&lt;/map:match&gt;
+</pre><p>The sitemap snippet above matches anything in the attachment path followed by
+the ID for the attachment. It then passes the ID into the <tt>src</tt>
+attribute for our reader. Why not include the nice neat little extension for the
+file after the ID? We actually have a very good reason: Microsoft. If you recall
+from the <a href="674_1_1.html">SitemapOutputComponent Contracts</a> page, Internet
+Explorer likes to pretend its smarter than you are. If you have a file extension
+on the URL that IE knows, it will ignore your mime-type settings that you
+provide. However, if you don't provide any clues then IE has to fall back to
+respecting the standard.</p><section name="How Does the Sitemap Treat a Reader?" style="background:none;padding:0;"/><p>A Sitemap fills two of the core contracts with the Sitemap. It is both a
+SitemapModelComponent and a SitemapOutputComponent. You <em>can</em> make it a
+CacheableProcessingComponent as well, which will help reduce the load on your
+database by avoiding the need to retrieve your attachments all the time. In
+fact, unless you have a good reason not to, you should always make your
+components cacheable just for the flexibility in deployment later. I recommend
+you read the articles on the core contracts to understand where to find the
+resources you need.</p><p>A sitemap will fulfill all its core contracts first. It will then query the
+reader using the <tt>getLastModified()</tt> method. The results of that method
+will be added to the response header for browser caching purposes--although it
+is only done for the CachingPipeline. Lastly, the sitemap will call the
+<tt>generate()</tt> method to create and send the results back to the client.
+It's a one stop shop, and because the Reader is both a SitemapModelComponent and
+a SitemapOutputComponent it is the beginning and the end of your pipeline.</p><p>Considering the order in which the processing happens, the sooner you can
+send a response to the Sitemap because of a failure the better.</p><section name="ServiceableReader: A Good Start" style="background:none;padding:0;"/><p>The ServiceableReader provides a good basis for building our database bound
+AttachmentReader. The ServiceableReader implements the Recyclable, LogEnabled
+and Serviceable interfaces and captures some of the information you will need
+for you. We will need these three interfaces to get a reference to the
+DataSourceComponent, our Logger, and to clean up our request based artifacts.
+You might want to implement the Parameterizable or Configurable interfaces if
+you want to decide which particular database we will be hitting in your own
+code. For now, we are going to hard code the information.</p><h3>The Skeleton</h3><p>Our skeleton code will look like this:</p><pre>import org.apache.avalon.excalibur.datasource.DataSourceComponent;
+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.ServiceSelector;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.ResourceNotFoundException;
+import org.apache.cocoon.caching.CacheableProcessingComponent;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.reading.ServiceableReader;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.source.impl.validity.TimeStampValidity;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Map;
+
+public class AttachmentReader extends ServiceableReader implements CacheableProcessingComponent, Disposable
+{
+    private static final int BUFFER = 1024;
+    public static String DB_RESOURCE_NAME = "ourdb"; // warning: static database table name
+
+    // ... skip many methods covered later
+
+    public void setup( SourceResolver sourceResolver, Map model, String src, Parameters params )
+        throws IOException, ProcessingException, SAXException
+    {
+        // ... skip setup code for now
+    }
+
+    public void generate() throws IOException, SAXException, ProcessingException
+    {
+        // ... skip generate code for now
+    }
+}
+</pre><p>If you'll notice we added the Disposable interface to the contract as well.
+This is so that we can be good citizens and release our components when we are
+done with them. Anything pooled needs to be released.</p><h3>Getting a Reference to Our DataSourceComponent</h3><p>While it's probably safe to treat your DataSourceComponent and your
+ServiceManager as singletons in the system, we still want to be responsible.
+First things first, let's get our DataSourceComponent and hold on to it as long
+as this Reader is around. To do this we will need to add two more class fields:
+</p><pre>    private DataSourceComponent datasource;
+    private ServiceSelector dbselector;
+</pre><p>Now we are going to override the <tt>service()</tt> method and implement the
+<tt>dispose()</tt> method to get and cleanup after ourselves. First lets start
+with getting the DataSourceComponent. Because Cocoon is configured to deal with
+multiple databases, you will need to use a ServiceSelector to choose the
+DataSourceComponent corresponding to your desired database.</p><pre>    @Override
+    public void service(ServiceManager services) throws ServiceException
+    {
+        super.service(services);
+
+        dbselector = (ServiceSelector) manager.lookup(DataSourceComponent.ROLE + "Selector");
+        datasource = (DataSourceComponent) dbselector.select(DB_RESOURCE_NAME);
+    }
+</pre><div class="note"><div><strong>Note: </strong>The <tt>@Override</tt> annotation above is used by the Java
+compiler to ensure that you are overriding a parent class's method. It only
+works in Java 5. If you are developing against an earlier version of Java remove
+that line so that you can compile the class. That goes for every time you see
+it.</div></div><p>We ensured that we called the superclass's <tt>service()</tt> method so that
+we didn't upset the expectations of anyone wanting to extend our class. Keeping
+the user's expectations in mind always helps to produce a good product--and in
+this case the user is a developer. Next, we retrieved the selector for the
+DataSourceComponent and stored it in the class field we created earlier. Then we
+did the same for the actual DataSouceComponent itself. Now we have access to the
+component when we need it. We didn't get an actual connection yet because the
+connections are pooled. If we held onto a connection for the life of the
+component then we would run out and the application would come to a screaching
+halt waiting for a connection to become available.</p><p>Since we are still dealing with managing the component itself, let's do the
+cleanup code next. The Avalon framework uses the <tt>Disposable.dispose()</tt>
+callback method to let the component know when it is safe to release all the
+components it is using and perform other cleanup.</p><pre>    public void dispose()
+    {
+        dbselector.release(datasource);
+        manager.release(dbselector);
+        datasource = null;
+        manager = null;
+    }
+</pre><p>While setting the fields to <tt>null</tt> might not be necessary with modern
+day garbage collectors, it still doesn't hurt. By releasing those components we
+ensure that Cocoon can shut down nicely and safely when it is time.</p><h3>Make sure PDFs Work</h3><p>Since we expect to have PDF documents in our database alongside pictures and
+other types of documents, we need to make sure they display properly. Since the
+bug in the IE Acrobat Reader plugin wasn't fixed until version 7 we need to make
+sure the content length is returned. There is some overhead with this as Cocoon
+has to cache the results to get the content length, but because we are going to
+cache it anyway there is little difference on when it gets sent to the cache.
+This is how we do it:</p><pre>    @Override
+    public boolean shouldSetContentLength()
+    {
+        return true;
+    }
+</pre><h3>Setting up for the Read (Cache directives, finding the resource, etc.)</h3><p>In the <tt>setup()</tt> method we need to ask the database for the
+meta-information about our attachment. You may be curious why we need to do it
+in the setup as opposed to the generate phase of the Reader. The answer is
+simply this: the sitemap has already asked the Reader for all caching related
+information and it is too late to do it then. We'll assume the attachments table
+is really simple and it has an ID, a mimeType, a timeStamp, and the attachment
+content. We need to get our component and query it. You can never rely on your
+connection pooling code to clean up your open statements and resultsets, so we
+will have to do that ourselves. Let's add some more class fields to support the
+cache directives and cache the blob reference:</p><pre>    private TimeStampValidity m_validity;
+    private InputStream m_content;
+    private String m_mimeType;
+</pre><p>Since our AttachementReader is pooled and recyclable, let's make sure we
+clean these values up when the AttachmentReader is returned to the pool:</p><pre>    @Override
+    public void recycle()
+    {
+        super.recycle();
+        if ( null != m_content ) try{ m_content.close(); } catch(Exception e) {/*ignore*/}
+        m_content = null;
+        m_validity = null;
+        m_mimeType = null;
+    }
+</pre><p>The next code snippet is the content of the setup() method from the code
+skeleton above. Let's break it down to understand what's going on. First we call
+the superclass's version of the method so that all expectations of the class
+hold true:</p><pre>    super.setup(sourceResolver, objectModel, src, params);
+</pre><p>Next we set up the holders for the connection, statement and resultset so
+that we can clean them up later.</p><pre>    Connection con = null;
+    ResultSet rs = null;
+    Statement stm = null;
+</pre><p>Now we have the meat of the method. We get a connection from the
+DataSourceComponent, and for good measure we set the AutoCommit to false. You
+can adjust this to your taste, but for a read we really don't need transactions.
+There is some standard query code next, and the part I want to point out is how
+we deal with the resultset. If you notice we have two courses of action
+depending on whether the record was found or not. If we did find the record we
+set the mimeType, validity, and content fields for the class. Otherwise, we
+throw <tt>ResourceNotFoundException</tt>. That exception is how Cocoon knows to
+differentiate between a 404 (HTTP Resource Not Found) and a 500 (HTTP Server
+Error) error.</p><pre>    try
+    {
+        final String sql = "SELECT mimeType, sourceDate, attachmentData FROM attachments" +
+        " WHERE attachmentId = '" + source + "'";
+
+        con = datasource.getConnection();
+        con.setAutoCommit(false);
+        stm = con.createStatement();
+        rs = stm.executeQuery(sql);
+
+        if (rs.next())
+        {
+            m_mimeType = rs.getString(1);
+            m_validity = new TimeStampValidity( rs.getTimestamp(2).getTime() );
+            m_content = rs.getBlob(3).getBinaryStream();
+        }
+        else
+        {
+            throw new ResourceNotFoundException("Could not find the record");
+        }
+    }
+</pre><p>If for some reason we catch a <tt>SQLException</tt> from the database, it is
+certainly not expected so we rethrow it wrapped with a general
+<tt>ProcessingException</tt>.</p><pre>    catch (SQLException se)
+    {
+        throw new ProcessingException(se);
+    }
+</pre><p>Lastly we cleanup our database objects in the finally method. Without that we
+run into database server memory leaks as the database keeps resources open for
+queries on the server side. Even the big name databases are sensitive to this.
+The JDBCDataSourceComponent connection pooling code does cache the resultsets
+and statements to make sure they are closed when you close the connection, but
+you might want to use a generic J2EEDataSourceComponent which may or may not do
+that for you. Never make assumptions and always clean up after yourself.</p><pre>    finally
+    {
+        if (rs != null) try{ rs.close(); } catch(SQLException se) {/*ignore*/}
+        if (stm != null) try{ stm.close(); } catch(SQLException se) {/*ignore*/}
+        if (con != null) try{ con.close(); } catch(SQLException se) {/*ignore*/}
+    }
+</pre><p>The setup is done. Now we just need to let the sitemap know what we found.
+The first thing is to let the sitemap know what kind of attachment we are
+sending. As you recall, we stored that in the class field "m_mimeType", and the
+<tt>getMimeType()</tt> method from SitemapOutputComponent informs the sitemap.
+</p><pre>    @Override
+    public String getMimeType()
+    {
+        return m_mimeType;
+    }
+</pre><p>Now we want to let the sitemap know the last modified timestamp for the
+attachment. Since we stored this information in the "m_validity" field we will
+send the information from that field. There is a problem though: what if the
+resource was not found? We might get a NullPointerException if the m_validity
+field was never set. Even though the Sitemap shouldn't call this method in the
+event that we couldn't find a resource we still don't want to take any chances.
+A properly guarded <tt>getLastModified()</tt> method would be:</p><pre>    @Override
+    public long getLastModified()
+    {
+        return (null == m_validity) ? -1L : m_validity.getTimeStamp();
+    }
+</pre><h3>The Caching Clues</h3><p>Lastly we want to provide the caching information to the CachingPipeline when
+needed. Since our source is an ID (from <tt>&lt;map:read src="{1}"/&gt;</tt>) it
+is probably the best cache key for our component. Let's just use it:</p><pre>    public Serializable getKey()
+    {
+        return source;
+    }
+</pre><p>We stored the TimeStampValidity object when we set up the attachment
+information, so let's just give that back. Alternatively you could use an
+ExpiresValidity to completely avoid hits to the database altogether--but for now
+this is good enough.</p><pre>    public SourceValidity getValidity()
+    {
+        return m_validity;
+    }
+</pre><h3>Sending the Payload</h3><p>All this work was done just so we could send the results back to the client,
+and now we get to see the code that does it.</p><p>Don't try to read the entire attachment into memory and then
+send it on to the user. It isn't necessary and it kills your scalability.
+Instead grab little chunks at a time and send it on to the output stream as you
+get it. You'll find that it feels faster on the client end as well.</p><p>The next code snippet is the contents of the <tt>generate() </tt>method from
+the class skeleton above. All we are doing is pulling a little data at a time
+from the database and sending it directly to the user. Wait a minute! I hear you
+shout. What about the connection we just closed in the setup method? Remember
+that the connection isn't closed until the pool retires it. You will never
+practically need to worry about the system severing your connection to the
+database mid-stream. Try it. Throw a load test at the system just to make sure
+I'm not smoking some controlled substances. Nevertheless, without much further
+ado, the code:</p><pre>    public void generate() throws IOException, SAXException, ProcessingException
+    {
+        try
+        {
+            byte[] buffer = new byte[BUFFER];
+            int len = 0;
+            
+            while ((len = m_content.read(buffer)) &gt;= 0)
+            {
+                out.write(buffer, 0, len);
+            }
+            
+            out.flush();
+        }
+        finally
+        {
+            out.close();
+            m_content.close();
+            m_content = null;
+        }
+    }
+</pre><p>We close the stream in the finally clause. If there are any exceptions
+thrown, they are propogated up without rewrapping them. You may wonder why we
+close the <tt>m_content</tt> stream here and in the <tt>recycle()</tt> method
+above. The answer is assurance. The <tt>generate()</tt> method is only called
+when the resource exists so the content stream won't get closed. Additionally,
+most database drivers tend to wait on all open streams to be closed manually
+before the connection with the server is severed. Of course there are timeout
+limits as well, but we don't want to use them if we can avoid it. By including
+the call to close the attachment data stream in the <tt>generate()</tt> method,
+we shorten the amount of time that there might be resources tied up with the
+stream.</p><section name="Summary" style="background:none;padding:0;"/><p>We're done. It seems like we did a lot here, and that's because we did. If we
+simply did direct generation of the data the class would have been simpler. By
+incorporating a database into the mix we've covered most of the things you might
+be curious about. Things like how to access other components from your
+component, how to make sure our component is cacheable, and some real gotchas
+that you do want to avoid. The example we have here will be very performant, and
+is not too different from Cocoon's DatabaseReader. Of course, by doing it
+ourselves we get to learn a bit more about how things work inside of Cocoon.</p></div></div>
+       </body></document>
\ No newline at end of file

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/681_1_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/681_1_1.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/681_1_1.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/688_1_1.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/688_1_1.xml?rev=1329674&view=auto
==============================================================================
--- cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/688_1_1.xml (added)
+++ cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/688_1_1.xml Tue Apr 24 12:33:07 2012
@@ -0,0 +1,287 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+      Licensed to the Apache Software Foundation (ASF) under one
+      or more contributor license agreements.  See the NOTICE file
+      distributed with this work for additional information
+      regarding copyright ownership.  The ASF licenses this file
+      to you under the Apache License, Version 2.0 (the
+      "License"); you may not use this file except in compliance
+      with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing,
+      software distributed under the License is distributed on an
+      "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+      KIND, either express or implied.  See the License for the
+      specific language governing permissions and limitations
+      under the License.
+    --><document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/XDOC/2.0" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"><properties><title>Cocoon Core - Creating a Generator</title><author email="[email protected]">Apache Cocoon Documentation Team</author></properties><body>
+         <div id="contentBody"><div id="bodyText"><h1 class="docTitle">Creating a Generator</h1><h1>Creating a Generator</h1><p>One of the most common types of components to create in Cocoon is to create a
+Generator. Whether you realize it or not, every time you write an XSP page, you
+are creating a Generator. XSP pages do a number of things for you, but there is
+a considerable amount of overhead involved with compiling and debugging. After
+all, when your XSP page isn't rendering like you expect and the XML is
+well-formed, where do you turn? You can examine the Java code that is generated
+from the XSP, but that can have its own set of challenges. I had a perfectly
+valid Java source file generated for Java 5's javac program, but it wouldn't
+compile in Cocoon. Why? The default compiler included with Cocoon doesn't
+support Java 5.</p><p>Sometimes our needs are so simple and so narrowly defined that it would be
+much easier for us to create our Generator right in our own IDE using all of the
+creature features that are included. Eclipse and IDEA are both wonderfully rich
+environments to develop Java code. Generators are much simpler beasts than your
+transformers and your serializers, so it makes creating them directly even more
+enticing. Cocoon does have some wonderful generators like the
+JXTemplateGenerator and others, but we are going to delve into the world of
+creating our own.</p><section name="How the Sitemap Treats a Generator" style="background:none;padding:0;"/><p>In the eyes of the Sitemap, all XML pipelines start with the Generator. By
+definition, a Generator is the first <a href="689_1_1.html">XMLProducer</a> in the
+pipeline. It is the source of all SAX events that the pipeline handles. It is
+also a <a href="673_1_1.html">SitemapModelComponent</a>, so it must follow those
+contracts as well. Lastly, it can be a
+<a href="675_1_1.html">CacheableProcessingComponent</a> satisfying those contracts
+as well. As usual, the order of contracts honored starts with the
+SitemapModelComponent, then the CacheableProcessingComponent contracts, and
+lastly the XMLProducer contracts. If the results of the Generator can be cached,
+Cocoon will attempt use the cache and bypass the Generator altogether if
+possible. The Caching mechanism can take the place of the Generator because it
+can recreate a SAX stream on demand as an XMLProducer.</p><p>In the big scheme of things, the Sitemap will <tt>setup()</tt> the Generator,
+and then assemble the XML pipeline. After Cocoon assembles the pipeline,
+chaining all XMLProducers to XMLConsumers (remember that an XMLPipe is both),
+Cocoon will call the <tt>generate()</tt> method on the Generator. That is the
+signal to start producing results, so send out the SAX events and have fun.</p><section name="Building our Own Generator" style="background:none;padding:0;"/><p>We are going to keep things easy for our generator. As usual, we will make
+the results cacheable because that is just good policy. In the spirit of trying
+to be useful, as well as trying to keep things manageably simple, let's create a
+BeanGenerator. The XML generated will be very simple, utilizing the JavaBean
+contracts and creating an element for each property, and embedding the value of
+the property within that element. There won't be any attributes, and the
+namespace will match the the JavaBean's fully qualified class name. If a
+property has something other than a primitive type, a String or an equivalent
+(like Integer and Boolean) as its value, that object will be treated as a Bean.
+</p><p>To realize these requirements we have to find a bean, and then "render it".
+In this case the XML rendering of the bean will be recursive. The general
+approach will use Java's reflection mechanisms, and only worry about properties.
+There will be a certain amount of risk involved with a complex bean that
+includes references to other beans in that if you have two beans referring to
+each other you will have an infinite loop. Detecting these is outside the scope
+of what we are trying to do, and that is generally bad design anyway so we won't
+worry too much about it. Yes there is overhead with the beans Introspector but
+we are writing for the general case.</p><p>To set up our generator, we need to use a serializer that shows us what the
+results are, so we will set up our sitemap to use our generator like this:</p><pre>&lt;map:match pattern="bean/*.xml"&gt;
+  &lt;map:generate type="bean" src="{1}"/&gt;
+  &lt;map:serialize type="xml"/&gt;
+&lt;/map:match&gt;
+</pre><p>Even though it is generally bad design to have a static anything in a Cocoon
+application we are going to use a helper class called "BeanPool" with the get()
+and put() methods that are familiar from the HashMap. So that it is easier for
+you to change the behavior of the BeanGenerator, we will provide a nice
+protected method called <tt>findBean()</tt> which is meant to be overridden with
+something more robust.</p><h3>The Skeleton</h3><p>Our skeleton code will look like this:</p><pre>import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.ResourceNotFoundException;
+import org.apache.cocoon.caching.CacheableProcessingComponent;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.generation.AbstractGenerator;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.source.NOPValidity;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+import java.beans.Introspector;
+import java.beans.BeanInfo;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.io.IOException;
+import java.io.Serializable;
+
+public class BeanGenerator extends AbstractGenerator implements CacheableProcessingComponent
+{
+    private static final Attributes ATTR = new AttributesImpl();
+    private Object m_bean;
+
+    protected Object findBean(String key)
+    {
+        // replace this with something more robust.
+        return BeanPool.get(key);
+    }
+
+    public void setup( SourceResolver sourceResolver, Map model, String src, Parameters params )
+        throws IOException, ProcessingException, SAXException
+    {
+        // ... skip setup code for now
+    }
+
+    public void generate() throws IOException, SAXException, ProcessingException
+    {
+        // ... skip generate code for now
+    }
+
+    // ... skip other methods later.
+}
+</pre><p>As you can see, we have our simplified <tt>findBean()</tt> method which can
+be replaced with something more robust later. All you need to do to populate the
+BeanPool is to call the <tt>BeanPool.put(String key, Object bean)</tt> method
+from somewhere else.</p><h3>Setting up to Generate</h3><p>Before we can generate anything let's start with the <tt>setup()</tt> code:
+</p><pre>    super.setup( sourceResolver, model, src, params );
+    m_bean = findBean(src);
+
+    if ( null == m_bean )
+    {
+        throw new ResourceNotFoundException(String.format("Could not find bean: %s", source));
+    }
+</pre><p>What we did is call the setup method from AbstractGenerator which populates
+some class fields for us (like the <tt>source</tt> field), then we tried to find
+the bean using the key provided. If the bean is <tt>null</tt>, then we follow
+the principle of least surprise and throw the <tt>ResourceNotFoundException
+</tt>so the Sitemap knows that we simply don't have the bean available instead
+of generating some lame 500 server error. That's all we have to do to set up
+this particular Generator. Oh, and since we do have the <tt>m_bean</tt> field
+populated we do want to clean up after ourselves properly. Let's add the
+recycle() method from Recyclable so that we don't give an old result when a bean
+can't be found:</p><pre>   @Override
+   public void recycle()
+   {
+      super.recycle();
+      m_bean = null;
+   }
+</pre><h3>The Caching Clues</h3><p>We are going to make the caching for the BeanGenerator really simple. Ideally
+we would have something that listens for changes and invalidates the
+SourceValidity if there is a change to the bean we are rendering. Unfortunately
+that is outside our scope, and we will set up the key so that it never expires
+unless it is done manually. Since we are using the source property from the
+Sitemap as our key, let's just use that as our cache key:</p><pre>    public Serializable getKey()
+    {
+        return source;
+    }
+</pre><p>And lastly, our brain-dead validity implementation:</p><pre>    public SourceValidity getValidity()
+    {
+        return NOPValidity.SHARED_INSTANCE;
+    }
+</pre><p>Using this approach is a bit naive in the sense that it is very possible that
+the beans will have changed. We could use an ExpiresValidity instead to make
+things a bit more resilient to change, but that is an excersize for you, dear
+reader.</p><h3>Generating Output</h3><p>Now that we have our bean, we are ready to generate our output. The
+AbstractXMLProducer base class (AbstractGenerator inherits from that) stores the
+target in a class field named <tt>contentHandler</tt>. Simple enough. We'll
+start by implementing the generate() method, but we already know we need to
+handle beans differently than the standard String and primitive types. So let's
+stub out the method we will use for recursive serialization. Here we go:</p><pre>    public void generate()
+    {
+        contentHandler.startDocument();
+
+        renderBean(source, m_bean);
+
+        contentHandler.endDocument();
+    }
+</pre><p>All we did was call the start and end document for the whole XML Document.
+That is enough for a basic XML document with no content. The
+<tt>renderBean()</tt> method is where the magic happens:</p><pre>    public void renderBean(String root, Object bean)
+    {
+        String namespace = String.format( "java:%s", bean.getClass().getName() );
+        qName = String.format( "%s:%s", root,root );
+
+        contentHandler.startPrefixMapping( root, namespace );
+        contentHandler.startElement( namespace, root, qName, ATTR );
+
+        BeanInfo info = Introspector.getBeanInfo(bean.getClass());
+        PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
+
+        for ( PropertyDescriptor property : descriptors )
+        {
+            renderProperty( namespace, root, property );
+        }
+
+        contentHandler.endElement( namespace, root, qName );
+        contentHandler.endNamespace( root );
+    }
+</pre><p>So far we created the root element and started iterating over the properties.
+Our root element consists of a namespace a name and a qName. Our implementation
+is using the <tt>source</tt> for the initial root element so as long as we never
+have any special characters like a colon (':') we should be OK. Without going
+through the individual properties, a java.awt.Dimension object with a source of
+"dim" will be redered like this:</p><pre>&lt;dim:dim xmlns:dim="java:java.awt.Dimension"/&gt;
+</pre><p>Now for the properties:</p><pre>    private void renderProperty( String namespace, String root, PropertyDescriptor property )
+    {
+        Method reader = property.getReadMethod();
+        Class&lt;?&gt; type = property.getPropertyType();
+
+        // only output if there is something to read, and it is not an indexed type
+        if ( null != reader &amp;&amp; null != type )
+        {
+            String name = property.getName();
+            String qName = String.format( "%s:%s", root,name );
+            Object value = reader.invoke( m_bean );
+
+            contentHandler.startElement( namespace, name, qName, ATTR );
+
+            if ( isBean(type) )
+            {
+                renderBean( name, value )
+            }
+            else if ( null != value )
+            {
+                char[] chars = String.valueOf(value).toCharArray();
+                contentHandler.characters(chars, 0, chars.length);
+            }
+
+            contentHandler.endElement( namespace, name, qName );
+        }
+    }
+</pre><p>This method is a little more complex in that we have to figure out if the
+property is readable, and is a type we can handle. In this case, we don't read
+indexed properties (if you want to support that, you'll have to extend this code
+to do that), and we don't read any properties where there is no read method. We
+use the property name for the elements surrouding the property values. We get
+the value, and then we call the start and end elements for the property. Inside
+of the calls, we determine if the item is a bean, and if so we render the bean
+using the renderBean method (the recursive aspect); otherwise we render the
+content as text as long as it is not null. Once the <tt>isBean()</tt> method is
+implemented, our Dimension example above will produce the following result:</p><pre>&lt;dim:dim xmlns:dim="java:java.awt.Dimension"&gt;
+  &lt;dim:width&gt;32&lt;/dim:width&gt;
+  &lt;dim:height&gt;32&lt;/dim:height&gt;
+&lt;/dim:dim&gt;
+</pre><p>Ok, now for the last method to determine if a value is a bean or not:</p><pre>    private boolean isBean(Class&lt;?&gt; klass)
+    {
+        if ( Boolean.TYPE.equals( klass ) ) return false;
+        if ( Byte.TYPE.equals( klass ) ) return false;
+        if ( Character.TYPE.equals( klass ) ) return false;
+        if ( Double.TYPE.equals( klass ) ) return false;
+        if ( Float.TYPE.equals( klass ) ) return false;
+        if ( Integer.TYPE.equals( klass ) ) return false;
+        if ( Long.TYPE.equals( klass ) ) return false;
+        if ( Short.TYPE.equals( klass ) ) return false;
+        if ( java.util.Date.class.equals( klass ) ) return false; // treat dates as value objects
+        if ( klass.getName().startsWith( "java.lang" ) ) return false;
+
+        return true;
+    }
+</pre><p>The isBean() method will treat all primitives, Strings, Dates, and anything
+in "java.lang" as value objects. This captures the boxed versions of primitives
+as well as the unboxed versions. Everything else is treated as a bean.</p><section name="Summary" style="background:none;padding:0;"/><p>Generators aren't too difficult to write, but the tricky parts are there due
+to namespaces. As long as you are familiar with the SAX API you should not have
+any problems. The complexity in our generator is really from the reflection
+logic used to discover how to render an object. You might ask why we didn't use
+the XMLEncoder in the java.beans package. The answer has to do with the fact
+that the facility is based on IO streams, and can't be easily adapted to XML
+streams. At any rate, we have something that can work with a wide range of
+classes. Our XML is easy to understand. Here is a snippet from a more complex
+example:</p><pre>&lt;line:line xmlns:line="java:com.mycompany.shapes.Line"&gt;
+  &lt;line:name&gt;This line has a name&lt;/line:name&gt;
+  &lt;line:topLeft&gt;
+    &lt;topLeft:topLeft xmlns:topLeft="java:java.awt.Point"&gt;
+      &lt;topLeft:x&gt;1&lt;/topLeft:x&gt;
+      &lt;topLeft:y&gt;1&lt;/topLeft:y&gt;
+    &lt;/topLeft:topLeft&gt;
+  &lt;/line:topLeft&gt;
+  &lt;line:bottomRight&gt;
+    &lt;bottomRight:bottomRight xmlns:bottomRight="java:java.awt.Point"&gt;
+      &lt;bottomRight:x&gt;20&lt;/bottomRight:x&gt;
+      &lt;bottomRight:y&gt;20&lt;/bottomRight:y&gt;
+    &lt;/bottomRight:topLeft&gt;
+  &lt;/bottomRight:topLeft&gt;
+&lt;/line:line&gt;
+</pre><p>Our theoretical line object contained a name and two java.awt.Point objects
+which in turn had an x and a y property. It is easier to understand when you
+have domain specific beans that are backed to a database. Nevertheless, we have
+a generator that satisfies a general purpose and can be extended later on to
+support our needs as they change.</p></div></div>
+       </body></document>
\ No newline at end of file

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/688_1_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/688_1_1.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/688_1_1.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/689_1_1.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/689_1_1.xml?rev=1329674&view=auto
==============================================================================
--- cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/689_1_1.xml (added)
+++ cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/689_1_1.xml Tue Apr 24 12:33:07 2012
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+      Licensed to the Apache Software Foundation (ASF) under one
+      or more contributor license agreements.  See the NOTICE file
+      distributed with this work for additional information
+      regarding copyright ownership.  The ASF licenses this file
+      to you under the Apache License, Version 2.0 (the
+      "License"); you may not use this file except in compliance
+      with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing,
+      software distributed under the License is distributed on an
+      "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+      KIND, either express or implied.  See the License for the
+      specific language governing permissions and limitations
+      under the License.
+    --><document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/XDOC/2.0" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"><properties><title>Cocoon Core - XML Pipeline Contracts</title><author email="[email protected]">Apache Cocoon Documentation Team</author></properties><body>
+         <div id="contentBody"><div id="bodyText"><h1 class="docTitle">XML Pipeline Contracts</h1><h1>XML Pipeline Contracts</h1><p>The XMLProducer contract is part of how Cocoon assembles the actual SAX
+pipeline to handle a particular request. It is a little different from the
+Sitemap related interfaces in that the focus is on the assembled pipeline
+instead of the decisions of which elements to use in the pipeline. If you think
+of the pipeline in a strict engineering mindset, an XMLProducer is a
+<em>source</em> of SAX events and an XMLConsumer is a <em>sink</em> for SAX
+events.  An XMLPipe is both a source and a sink of SAX Events.</p><section name="The XMLProducer" style="background:none;padding:0;"/><p>The XMLProducer is a very simple beast, comprised of only one method to give
+the component the next element of the pipeline.  Cocoon calls the
+<tt>setConsumer()</tt> method with the reference to the next XMLConsumer in the
+pipeline.  The approach allows the XMLProducer to call the different SAX related
+methods on the XMLConsumer without knowing ahead of time what that consumer will
+be.  The design is very simple and very powerful in that it allows Cocoon to
+daisy chain several components in any order and then execute the pipeline.</p><p>Any producer can be paired with any consumer and we have a pipeline.  The
+core design is very powerful and allows the end user to mix and match sitemap
+components as they see fit.  Cocoon will always call setConsumer() on every
+XMLProducer in a pipeline or it will throw an exception saying that the pipeline
+is invalid (i.e. there is no serializer for the pipeline).  The only contract
+that the XMLProducer has to worry about is that it must always make calls to the
+XMLConsumer passed in through the <tt>setConsumer()</tt> method.</p><section name="The XMLConsumer" style="background:none;padding:0;"/><p>An XMLConsumer is much more complex due to the interfaces it implements.  An
+XMLConsumer is also a SAX ContentHandler and a SAX LexicalHandler.  That means
+the XMLConsumer has to respect all the contracts with the SAX interfaces.  SAX
+stands for Serialized API for XML.  A document start, and each element start
+must be matched by the corresponding element end or document end.  So why does
+Cocoon use SAX instead of manipulating a DOM?  For two main reasons: performance
+and scalability.  A DOM tree is much more heavy on system memory than successive
+calls to an API.  SAX events can be sent as soon as they are read from the
+originating XML, the parsing and processing can happen essentially at the same
+time.</p><p>Most people's needs will be handled just fine with the ContentHandler
+interface, as that declares your namespaces.  However if you need lexical
+support to resolve entity names and such, you need the LexicalHandler
+interface.  The AbstractXMLConsumer base class can make implementing this
+interface easier so that you only need to override the events you intend to do
+anything with.</p><section name="The XMLPipe" style="background:none;padding:0;"/><p>The XMLPipe is both an XMLProducer and an XMLConsumer.  All the Transformers
+implement this interface for example.  By having an XMLPipe interface, we can
+chain more than one pipeline component together.  What this means is that Cocoon
+will honor all the XMLProducer contracts in a pipeline first.  The SAX pipeline
+will be completely assembled before any SAX calls are issued.  Cocoon does not
+want any stray calls to get lost.  There can be zero or more XMLPipes in a
+pipeline, but there must always be at least one XMLProducer and XMLConsumer
+pair.</p><p>Because an XMLPipe is both a source and a sink for SAX events, the basic
+contract that you need to worry about is that you must forward any SAX events on
+that you are not intercepting and transforming.  As you receive your
+<tt>startDocument</tt> event, pass it on to the XMLConsumer you received as part
+of the XMLProducer side of the contract.  An example ASCII art will help make it
+a bit more clear:</p><pre>XMLProducer -&gt; (XMLConsumer)XMLPipe(XMLProducer) -&gt; XMLConsumer
+</pre><p>A typical example would be using the FileGenerator (an XMLProducer), sending
+events to an XSLTTransformer (an XMLPipe), which then sends events to an
+HTMLSerializer (an XMLConsumer).  The XSLTTransformer acts as an XMLConsumer to
+the FileGenerator, and also acts as an XMLProducer to the HTMLSerializer.  It is
+still the responsibility of the XMLPipe component to ensure that the XML passed
+on to the next component is valid--provided the XML received from the previous
+component is valid.  In layman's terms it means if you don't intend to alter the
+input, just pass it on.  In most cases we just want to transform a small snippet
+of XML.  For example, inserting a snippet of XML based on an embedded element in
+a certain namespace.  Anything that doesn't belong to the namespace you are
+worried about should be passed on as is.</p></div></div>
+       </body></document>
\ No newline at end of file

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/689_1_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/689_1_1.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/689_1_1.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/690_1_1.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/690_1_1.xml?rev=1329674&view=auto
==============================================================================
--- cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/690_1_1.xml (added)
+++ cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/690_1_1.xml Tue Apr 24 12:33:07 2012
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+      Licensed to the Apache Software Foundation (ASF) under one
+      or more contributor license agreements.  See the NOTICE file
+      distributed with this work for additional information
+      regarding copyright ownership.  The ASF licenses this file
+      to you under the Apache License, Version 2.0 (the
+      "License"); you may not use this file except in compliance
+      with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing,
+      software distributed under the License is distributed on an
+      "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+      KIND, either express or implied.  See the License for the
+      specific language governing permissions and limitations
+      under the License.
+    --><document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/XDOC/2.0" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"><properties><title>Cocoon Core - Writing Cache Efficient Components</title><author email="[email protected]">Apache Cocoon Documentation Team</author></properties><body>
+         <div id="contentBody"><div id="bodyText"><h1 class="docTitle">Writing Cache Efficient Components</h1><h1>Writing Cache Efficient Components</h1><p>The bulk of this document is based heavily on documentation that Sylvain
+Wallez wrote on
+<a href="http://wiki.apache.org/cocoon/WritingForCacheEfficiency">Writing for
+Cache Efficiency</a>. We're just reorganizing the information in a way that's
+easier to digest. As you recall, to enable caching for a sitemap component you
+have to implement the <a href="675_1_1.html">CacheableProcessingComponent
+contracts</a>. Unfortunately, that does not give you an idea of how to minimize
+the impact of verifying the cache validity of a component. The general strategy
+that works best for cacheable components is lazy evaluation, or wait until the
+last possible moment before you do your calculations--because you may not need
+them.</p><section name="Understanding the Order of Calls" style="background:none;padding:0;"/><p>In order to know when to actually do the complex set up for any given
+resource, it helps to know the exact order of calls as it relates to that
+component.  From the perspective of this document you can assume the pipeline
+has already been set up, and we are now getting the components ready.  Cocoon is
+deterministic in the sense that the call order is the same every time.  Making
+your caching more efficient requires that you take advantage of this knowledge. 
+First the sequence of events:</p><ol type="1">
+<li>Cocoon calls <tt>setup()</tt>--which includes serializers that implement
+SitemapModelComponent.</li>
+<li>Cocoon calls <tt>getMimeType()</tt> on the serializer (or reader).</li>
+<li>Cocoon calls <tt>getKey()</tt> on all CacheableProcessingComponents.</li>
+<li>Cocoon checks the cache for any Validity objects matching that key.</li>
+<li>If there is an entry matching, Cocoon validates the Validity object;
+otherwise we jump to step 7.</li>
+<li>If the Validity object is still valid, Cocoon uses the cached entry in place
+of calling your component; or if the Validity object is invalid, Cocoon will
+then call your component; otherwise, Cocoon falls through to the next step.</li>
+<li>If we have gotten to this point, Cocoon will call the <tt>getValidity()</tt>
+method on your CacheableProcessingComponent.  Cocoon will then compare the
+previous validity object against the new one, or if this is the first call to
+<tt>getValidity()</tt> then we validate the returned validity object.  If the
+cache entry is valid Cocoon uses the cached results, otherwise we call the
+component.</li>
+<li>If the validity still can't be determined the next step is dependant on the
+cache component (i.e. default to better performance with the risk of stale data
+or default to safety and fresh data).</li>
+<li>Assuming we have gotten this far and the key is either not in the cache or
+the entry is stale, Cocoon calls <tt>setXMLConsumer()</tt> on all the
+XMLProducer components (typically generators and transformers), and
+<tt>setOutputStream()</tt> on the Serializer or Reader.</li>
+<li>Cocoon calls the <tt>generate()</tt> method on the Generator or Reader.</li>
+</ol>That's a lot of steps, providing as many opportunities to use a cache as
+possible.  It also provides the opportunity to delay when we incur certain
+checks until the last possible moment.<div class="note"><div><strong>Note: </strong>The Cocoon team has been working on an adaptive cache which
+performs cost calculations.  It measures the cost of generating/transforming a
+result, the cost of determining its cache validity, and its own influence on the
+system.  The bottom line is that just because something may be a valid entry, it
+may still be cheaper to generate the resource in terms of that cost function
+than to use the cached value.  The only guarantees that you have for when
+something is going to be called are the methods from the sitemap interfaces and
+the big component interfaces (i.e. the Generator, Transformer, Serializer, and
+Reader).  Don't perform any critical setup inside a CacheableProcessingComponent
+method.</div></div><section name="Case Study: Improving the TraxTransformer" style="background:none;padding:0;"/>Back in 2003, the TraxTransformer performed all caching and heavy payload
+setup within the <tt>setup()</tt> method.  What this meant was that the
+TransformerHandler object was being created for the XSLT file at the same time
+the FileValidity object for that file was set up.  The TransformerHandler object
+is heavy, and there is alot of work in setting that thing up.  The affect is
+that the TraxTransformer incurred the cost of setting up the TransformerHandler
+whether it was used or not.  When the pipeline pulled from the cache, the
+TransformerHandler was created and discarded.  You have the overhead of the
+garbage collection along with unused objects.Sylvain saw the problem, and delayed creating the TransformerHandler until
+Cocoon called the <tt>setXMLConsumer()</tt> method.  This ensured that every
+opportunity was given to check cache validity and we only incurred the cost of
+creating the TransformerHandler when Cocoon was really going to use it.  Another
+safe place to put the completed setup code is on the <tt>startDocument()</tt>
+SAX method.  At this point it is clear we are currently using the
+TransformerHandler, so it will also work.After everything was said and done, the TraxTransformer performed between 5%
+to 30% better depending on the complexity of the TransformerHandler.  The key
+was delaying the heavy lifting until it was actually needed.<section name="AggregateValidity and DelayedAggregateValidity" style="background:none;padding:0;"/>Some components like the DirectoryGenerator and the TraxTransformer rely on
+the validity of other factors than just a template or a set of files.  These
+components often can't determine the validity at setup time.  The solution is to
+use the AggregateValidity and more specifically the DelayedAggregateValidity. 
+The aggregated validity object provides an interface for you to add additional
+validity components inside and returns the result of the set (typically if one
+validity object is undertermined or invalid the whole set is).  You can add to
+the aggregated validity object as the pipeline is executed.  Every time the
+TraxTransformer includes another XML document using the <tt>document()</tt>
+function in XSLT, it's FileValidity is added to the aggregated validity object.
+The DirectoryGenerator relies on an internal pipeline to be run, and because
+we don't know the validity until after the pipeline is run, it is impossible to
+set up the validity objects ahead of time.  The solution in this case is to use
+the DelayedAggregateValidity object.  Placeholders are given using the
+DelayedValidity interface, and when the solid validity object is ready it can be
+used.  Essentially the full validity object is assembled as the pipeline is
+run.  The next time the aggregated validity object is inspected it is set up
+already.While these are possible solutions to a complex problem, they do incur their
+own overhead.  Done well, the overhead is still less than creating the content
+fresh every time--but care should be taken that we don't have a huge validity
+object tree by having aggregate validity objects including aggregate validity
+objects that include aggregate validity objects.  In short, you have to keep it
+simple.  The general rule of thumb is that if you can't write a simple unit test
+for it, you probably need to start looking to simplify.  Cocoon has many tools
+for caching and cache control, understanding how things work will help you write
+more efficient components.</div></div>
+       </body></document>
\ No newline at end of file

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/690_1_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/690_1_1.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/690_1_1.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/694_1_1.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/694_1_1.xml?rev=1329674&view=auto
==============================================================================
--- cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/694_1_1.xml (added)
+++ cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/694_1_1.xml Tue Apr 24 12:33:07 2012
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+      Licensed to the Apache Software Foundation (ASF) under one
+      or more contributor license agreements.  See the NOTICE file
+      distributed with this work for additional information
+      regarding copyright ownership.  The ASF licenses this file
+      to you under the Apache License, Version 2.0 (the
+      "License"); you may not use this file except in compliance
+      with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing,
+      software distributed under the License is distributed on an
+      "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+      KIND, either express or implied.  See the License for the
+      specific language governing permissions and limitations
+      under the License.
+    --><document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/XDOC/2.0" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"><properties><title>Cocoon Core - Creating a Transformer</title><author email="[email protected]">Apache Cocoon Documentation Team</author></properties><body>
+         <div id="contentBody"><div id="bodyText"><h1 class="docTitle">Creating a Transformer</h1><h1>Creating a Transformer</h1><p>In 90% of all cases XSLT will perform all your transformation needs better
+than anything else out there.  I'll be completely blunt and say that creating a
+transformer that does anything truly substantial is not for the faint of heart. 
+The issue has to do with using SAX event streams to process the XML.  SAX vs.
+DOM was a design tradeoff to favor scalability over ease of use.  A particularly
+large DOM tree can cripple a web application and you lose all the benefit of
+such a powerful architecture like Cocoon.</p><p>The transformer we are going to create in this tutorial is actually very
+trivial.  You'll have to take the lessons from this and expand them if you want
+to do something more exciting.  We will be using a transformer to insert a
+timestamp when we see an element called "time-stamp" in a specified namespace. 
+Along the way we will look at some ways of lowering the impact of having your
+transformer in the pipeline.  To use our transformer we will have a sitemap
+snippet similar to the following:</p><pre>&lt;map:match pattern="timed-hello.xml"&gt;
+  &lt;map:generate src="hello.xml"/&gt;
+  &lt;map:transformer type="time"/&gt;
+  &lt;map:serialize/&gt;
+&lt;/map:match&gt;
+</pre><p>Notice that we didn't have a "src" attribute for our transformer?  In this
+case our example is so trivial that we really don't need one.  If we wanted to
+add a little more functionality we could pass in a format using the src
+attribute, but that could also be done by modifying our markup.  Just so we are
+complete in what we expect to do, we want to take the following XML:</p><pre>&lt;ts:time xmlns:ts="unc:time"/&gt;
+</pre><p>into the current date and time ending with the minute (ex. Sep. 16, 2005
+12:59 PM).</p><section name="How the Sitemap Treats a Transformer" style="background:none;padding:0;"/><p>All Transformer components are SitemapModelComponents and XMLPipelines, in
+addition they can be CacheableProcessingComponents.  All of those contracts have
+been covered in depth already.  Once the sitemap determines that we need to pass
+results through your transformer (i.e. there are no cached entries for the
+pipeline up to this point), the <tt>setXMLConsumer()</tt> method is called, and
+you know the pipeline is being processed as soon as you receive the
+<tt>startDocument()</tt> event.</p><section name="AbstractTransformer: A Good Start" style="background:none;padding:0;"/><p>The AbstractTransformer has everything you need to pass SAX events through
+unmolested.  You have the different objects from the setup method accessible as
+fields in the class, and the XMLPipeline contract is already set up to pass
+through the SAX events to the XMLConsumer.  We will only need to do a couple
+things to set up caching properly.  In fact because our input doesn't rely on
+any external source of information we can have a constant for the cache key: the
+namespace we are transforming.</p><h3>The Transformer Skeleton</h3><p>The skeleton code does nothing more than set up the cache validity object we
+will be using.  You might be thinking that we can't cache anything so dynamic as
+the time of day, but we can cache it for as long as the shortest amount of time
+we are displaying.  If you are being slammed with 150 simultaneous users a
+second all asking for something that has the time of day inserted, we should be
+able to generate it once and reuse the results until the clock advances.</p><pre>import org.apache.avalon.framework.parameters.Parameters;
+import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.caching.CacheableProcessingComponent;
+import org.apache.cocoon.environment.SourceResolver;
+import org.apache.cocoon.transformation.AbstractTransformer;
+import org.apache.excalibur.source.SourceValidity;
+import org.apache.excalibur.source.ExpiresValidity;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import java.io.IOException;
+import java.text.SimpleDateFormatter;
+
+public class TimeTransformer extends AbstractTransformer implements CacheableProcessingComponent
+{
+    private static final String FORMAT = "MMM d, YYYY hh:mm a";
+    private static final String NAMESPACE = "unc:time";
+    private static final long MINUTE = 60 * 1000;
+    private SourceValidity cacheValidity = null;
+    private final SimpleDateFormatter formatter = null;
+
+    public void setup( SourceResolver sourceResolver, Map model, String src, Parameters params )
+        throws IOException, ProcessingException, SAXException
+    {
+        super.setup( sourceResolver, model, src, params );
+        cacheValidity = new ExpiresValidity(System.currentTimeMillis() + MINUTE);
+    }
+
+    // ... skip other methods later.
+}</pre><p>We set up some constants that will be used later such as our time format, the
+namespace we are checking, and the number of milliseconds that make up a
+minute.  The other two instance fields are the cacheValidity object and the date
+formatter.  Because by definition none of the formatters are threadsafe, we have
+to create a new one for each instance of this transformer.  Technically speaking
+we could make it a ThreadLocal object, but we wanted to keep things simple here.
+</p><h3>The Cache Clues</h3><p>Since the caching aspect of this component is really simple, let's just get
+it out of the way here.  First thing is that the key for this transformer should
+not change with the time of day, so let's use the namespace we are checking as
+the cache key:</p><pre>    public Serializable getKey()
+    {
+        return NAMESPACE;
+    }</pre><p>And finally, we already set up our validity object in the <tt>setup()</tt>
+call in the skeleton code.  Let's just pass it back.</p><pre>    public SourceValidity getValidity()
+    {
+        return cacheValidity;
+    }
+</pre><h3>Performing the Transformation</h3><p>At this point the only thing we didn't do yet is set up our date formatter. 
+We have two choices: delayed evaluation or structured evaluation.  With delayed
+evaluation we wait until we actually have a <tt>ts:time</tt> element to
+transform before we set up the formatter.  With structured evaluation we take
+advantage of the fact that <tt>startDocument()</tt> is called before anything
+else and we do it then.  The actual solution to the problem depends on the
+liklihood of always having an element to transform and the cost of creating the
+objects you need to work with.  Because our case is really simple, its a
+tossup.  We'll go with structured evaluation just because it's clearer code:</p><pre>    public void startDocument()
+    {
+        super.startDocument();
+        formatter = new SimpleDateFormatter(FORMAT);
+    }
+
+    public void endDocument()
+    {
+        super.endDocument();
+        formatter = null; // just cleanup for the garbage collector's sake
+    }
+</pre><p>All that's left is to actually perform the transformation.  Again, we need to
+override two methods because of the <tt>startElement()</tt> and
+<tt>endElement()</tt> pairing.  To make things more interesting we will even add
+some simple validation to our code.  There should be no embedded text inside the
+element we are listening for, so we will include a new field which is a boolean
+flag for whether we are in the timestamp element or not:</p><pre>    private boolean isInTimeElement = false;
+
+    public void startElement(String namespace, String name, String qName, Attributes attrib)
+    {
+        if ( isInTimeElement ) throw new SAXException("Cannot have embedded elements");
+
+        if ( NAMESPACE.equals( namespace ) )
+        {
+            if ( "time".equals(name) )
+            {
+                isInTimeElement = true;
+                String formattedDate = formatter.format( new Date() );
+                contentHandler.characters(formattedDate.toCharArray(), 0, formattedDate.length());
+
+                return;
+            }
+            else
+            {
+                throw new SAXException("Only the \"time\" element is valid");
+            }
+        }
+
+        super.startElement(namespace, name, qName, attrib);
+    }
+</pre><p>Before we move on to the characters() evaluation, let's spend some time with
+the code above.  First we check if it is legal to have sub-elements, which of
+course only happens when we are not in a time element.  Next, we check if the
+element we recieved is one we have to worry about.  If we are in the right
+namespace, we check the element name and throw an exception if the element name
+is anything other than "time".  Assuming we have the time element in our
+namespace we substitute the <tt>startElement()</tt> call with the coresponding
+<tt>characters</tt><tt>()</tt> call, turn on the <tt>isInTimeElement</tt> flag,
+and finally return immediately.  Otherwise we will simply forward on the
+<tt>startElement()</tt> call as usual.  Another thing to note is that we called
+the <tt>characters()</tt> event directly on the content handler instead of
+calling our own transformer.  We did that to make sure that our validation code
+doesn't reject the date string we want to pass on.  Now to validate our own
+<tt>characters()</tt> method:</p><pre>    public void characters(char[] chars, int start, int end)
+    {
+        if ( isInTimeElement ) throw new SAXException("Cannot have embedded text");
+
+        super.characters(chars, start, end);
+    }
+</pre><p>The <tt>characters()</tt> event is really simple, and we only throw an
+exception if the user tried to embed characters inside the timestamp element. 
+Now for the endElement() so that we can turn of the <tt>isInTimeElement</tt>
+flag and swallow the matching <tt>endElement()</tt> event for our timestamp
+element:</p><pre>    public void endElement(String namespace, String name, String qName)
+    {
+        if ( NAMESPACE.equals(namespace) &amp;&amp; "time".equals(name) )
+        {
+            isInTimeElement = false;
+            return;
+        }
+
+        super.endElement(namespace, name, qName)
+    }
+</pre><p>Now we are done with the component.</p><section name="Additional Things to Consider for Transformers" style="background:none;padding:0;"/><p>There are a couple things to keep in mind when dealing with SAX streams and
+designing your transformers.  First, it takes more time to iterate through a set
+of attributes for every element looking for an attribute in your namespace than
+it does to look for an element with the namespace you desire.  In short,
+elements are faster to evaluate than attributes.  Use them when you can. 
+Secondly, remember to evaluate namespaces/name combinations and not QNames.  A
+QName (or Qualified Name in XML speak) is name including the prefix matching a
+namespace.  The only time you should look at the QName is if you need to treat
+different "contexts" of transformation for the namespace.  In other words unless
+you need to treat "ts:time" separate from "nt:time" ignore the QName--most of
+the time you just care whether or not you are dealing with a particular
+namespace.</p><p>Lastly, validation is a tricky thing.  Many times you want validation in
+development but not in production because it is expensive to do.  In our example
+we included validation but never provided a way to turn it off.  For this case
+the validation is so trivial that it's acceptable to keep the logic in
+production--but it does make the code a bit more complex.  Sometimes the
+validation code can be a source of errors.  Test your validation code, but
+assume that you are receiving valid XML.  After all this is a transformer.  The
+Generator should have been tested to make sure that the XML generated is valid.
+</p><p>As a final measure to ensure your transformer isn't turning previously valid
+XML into invalid XML.  A quick test is to take a valid XML document and
+transform it using your transformer--serializing to a stream and feeding that
+into a validating XML parser.  It seems weird, but it is a simple test to set up
+for all transformers to make sure they don't introduce errors of their own.</p></div></div>
+       </body></document>
\ No newline at end of file

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/694_1_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/694_1_1.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/694_1_1.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/725_1_1.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/725_1_1.xml?rev=1329674&view=auto
==============================================================================
--- cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/725_1_1.xml (added)
+++ cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/725_1_1.xml Tue Apr 24 12:33:07 2012
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+      Licensed to the Apache Software Foundation (ASF) under one
+      or more contributor license agreements.  See the NOTICE file
+      distributed with this work for additional information
+      regarding copyright ownership.  The ASF licenses this file
+      to you under the Apache License, Version 2.0 (the
+      "License"); you may not use this file except in compliance
+      with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing,
+      software distributed under the License is distributed on an
+      "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+      KIND, either express or implied.  See the License for the
+      specific language governing permissions and limitations
+      under the License.
+    --><document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/XDOC/2.0" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"><properties><title>Cocoon Core - Creating a Serializer</title><author email="[email protected]">Apache Cocoon Documentation Team</author></properties><body>
+         <div id="contentBody"><div id="bodyText"><h1 class="docTitle">Creating a Serializer</h1><h1>Creating a Serializer</h1><p>For most problems, Cocoon has a serializer ready for you.  However, you may
+have to deal with some new unique binary format which is fed by your XML.  The
+SVG to PNG serializer works in this way as does the FOP to PDF serializer. 
+Given that there are only so many ways to present data on the web, it is very
+difficult to come up with an example serializer that is new and useful. 
+Nevertheless we will present the <a href="http://www.yaml.org">YAML</a>
+serializer.  There is no real direct mapping of concepts, but the only thing
+that you can't map directly in YAML to XML is the attributes.</p></div></div>
+       </body></document>
\ No newline at end of file

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/725_1_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/725_1_1.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/725_1_1.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/808_1_1.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/808_1_1.xml?rev=1329674&view=auto
==============================================================================
--- cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/808_1_1.xml (added)
+++ cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/808_1_1.xml Tue Apr 24 12:33:07 2012
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+      Licensed to the Apache Software Foundation (ASF) under one
+      or more contributor license agreements.  See the NOTICE file
+      distributed with this work for additional information
+      regarding copyright ownership.  The ASF licenses this file
+      to you under the Apache License, Version 2.0 (the
+      "License"); you may not use this file except in compliance
+      with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing,
+      software distributed under the License is distributed on an
+      "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+      KIND, either express or implied.  See the License for the
+      specific language governing permissions and limitations
+      under the License.
+    --><document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/XDOC/2.0" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"><properties><title>Cocoon Core - map:sitemap</title><author email="[email protected]">Apache Cocoon Documentation Team</author></properties><body>
+         <div id="contentBody"><div id="bodyText"><h1 class="docTitle">map:sitemap</h1><h1>Attributes</h1><h1>Occurence</h1><section name="Children" style="background:none;padding:0;"/><p>This element can have the following children:</p><ul><li>map:action-sets</li><li>map:components</li><li>map:flow</li><li>map:pipelines</li><li>map:resources</li><li>map:views</li></ul></div></div>
+       </body></document>
\ No newline at end of file

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/808_1_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/808_1_1.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/808_1_1.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/809_1_1.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/809_1_1.xml?rev=1329674&view=auto
==============================================================================
--- cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/809_1_1.xml (added)
+++ cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/809_1_1.xml Tue Apr 24 12:33:07 2012
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+      Licensed to the Apache Software Foundation (ASF) under one
+      or more contributor license agreements.  See the NOTICE file
+      distributed with this work for additional information
+      regarding copyright ownership.  The ASF licenses this file
+      to you under the Apache License, Version 2.0 (the
+      "License"); you may not use this file except in compliance
+      with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing,
+      software distributed under the License is distributed on an
+      "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+      KIND, either express or implied.  See the License for the
+      specific language governing permissions and limitations
+      under the License.
+    --><document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/XDOC/2.0" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"><properties><title>Cocoon Core - map:components</title><author email="[email protected]">Apache Cocoon Documentation Team</author></properties><body>
+         <div id="contentBody"><div id="bodyText"><h1 class="docTitle">map:components</h1><h1>Attributes</h1><h1>Occurence</h1><section name="Children" style="background:none;padding:0;"/><p>This element can have the following children:</p><ul><li>map:actions</li><li>map:generators</li><li>map:matchers</li><li>map:pipes</li><li>map:selectors</li><li>map:serializers</li><li>map:transformers</li></ul></div></div>
+       </body></document>
\ No newline at end of file

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/809_1_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/809_1_1.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/809_1_1.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/810_1_1.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/810_1_1.xml?rev=1329674&view=auto
==============================================================================
--- cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/810_1_1.xml (added)
+++ cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/810_1_1.xml Tue Apr 24 12:33:07 2012
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+      Licensed to the Apache Software Foundation (ASF) under one
+      or more contributor license agreements.  See the NOTICE file
+      distributed with this work for additional information
+      regarding copyright ownership.  The ASF licenses this file
+      to you under the Apache License, Version 2.0 (the
+      "License"); you may not use this file except in compliance
+      with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing,
+      software distributed under the License is distributed on an
+      "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+      KIND, either express or implied.  See the License for the
+      specific language governing permissions and limitations
+      under the License.
+    --><document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/XDOC/2.0" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"><properties><title>Cocoon Core - map:actions</title><author email="[email protected]">Apache Cocoon Documentation Team</author></properties><body>
+         <div id="contentBody"><div id="bodyText"><h1 class="docTitle">map:actions</h1><h1>Attributes</h1><table class="bodyTable">
+<tbody>
+<tr class="a">
+<th>
+<p>Name</p>
+</th>
+<th>
+<p>Description</p>
+</th>
+</tr>
+<tr class="b">
+<td>
+<p>default</p>
+</td>
+<td>
+<p>The action to be used if no type attribute is present on map:act.</p>
+</td>
+</tr>
+</tbody>
+</table><h1>Occurence</h1><section name="Children" style="background:none;padding:0;"/><p>This element can have the following children:</p><ul><li>map:action</li></ul></div></div>
+       </body></document>
\ No newline at end of file

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/810_1_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/810_1_1.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/810_1_1.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/811_1_1.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/811_1_1.xml?rev=1329674&view=auto
==============================================================================
--- cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/811_1_1.xml (added)
+++ cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/811_1_1.xml Tue Apr 24 12:33:07 2012
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+      Licensed to the Apache Software Foundation (ASF) under one
+      or more contributor license agreements.  See the NOTICE file
+      distributed with this work for additional information
+      regarding copyright ownership.  The ASF licenses this file
+      to you under the Apache License, Version 2.0 (the
+      "License"); you may not use this file except in compliance
+      with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing,
+      software distributed under the License is distributed on an
+      "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+      KIND, either express or implied.  See the License for the
+      specific language governing permissions and limitations
+      under the License.
+    --><document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/XDOC/2.0" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"><properties><title>Cocoon Core - map:action</title><author email="[email protected]">Apache Cocoon Documentation Team</author></properties><body>
+         <div id="contentBody"><div id="bodyText"><h1 class="docTitle">map:action</h1><h1>Attributes</h1><table class="bodyTable">
+<tbody>
+<tr class="a">
+<th>
+<p>Name</p>
+</th>
+<th>
+<p>Description</p>
+</th>
+</tr>
+<tr class="b">
+<td>
+<p>name</p>
+</td>
+<td>
+<p>A name for this type of action.</p>
+</td>
+</tr>
+<tr class="a">
+<td>
+<p>src</p>
+</td>
+<td>
+<p>Fully qualified class name of the action implementation.</p>
+</td>
+</tr>
+</tbody>
+</table><h1>Occurence</h1><section name="Children" style="background:none;padding:0;"/><p>This element can have the following children:</p><ul/></div></div>
+       </body></document>
\ No newline at end of file

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/811_1_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/811_1_1.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/811_1_1.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/812_1_1.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/812_1_1.xml?rev=1329674&view=auto
==============================================================================
--- cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/812_1_1.xml (added)
+++ cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/812_1_1.xml Tue Apr 24 12:33:07 2012
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?><!--
+      Licensed to the Apache Software Foundation (ASF) under one
+      or more contributor license agreements.  See the NOTICE file
+      distributed with this work for additional information
+      regarding copyright ownership.  The ASF licenses this file
+      to you under the Apache License, Version 2.0 (the
+      "License"); you may not use this file except in compliance
+      with the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing,
+      software distributed under the License is distributed on an
+      "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+      KIND, either express or implied.  See the License for the
+      specific language governing permissions and limitations
+      under the License.
+    --><document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/XDOC/2.0" xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"><properties><title>Cocoon Core - map:generators</title><author email="[email protected]">Apache Cocoon Documentation Team</author></properties><body>
+         <div id="contentBody"><div id="bodyText"><h1 class="docTitle">map:generators</h1><h1>Attributes</h1><table class="bodyTable">
+<tbody>
+<tr class="a">
+<th>
+<p>Name</p>
+</th>
+<th>
+<p>Description</p>
+</th>
+</tr>
+<tr class="b">
+<td>
+<p>default</p>
+</td>
+<td>
+<p>The generator to be used if no type attribute is present on map:generate.</p>
+</td>
+</tr>
+</tbody>
+</table><h1>Occurence</h1><section name="Children" style="background:none;padding:0;"/><p>This element can have the following children:</p><ul><li>map:generator</li></ul></div></div>
+       </body></document>
\ No newline at end of file

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/812_1_1.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/812_1_1.xml
------------------------------------------------------------------------------
    svn:keywords = Date Revision Author HeadURL Id

Propchange: cocoon/trunk/site/cocoon-core-site/core/2.2/src/site/xdoc/812_1_1.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.