jefft       2003/01/22 05:15:46

  Modified:    .        project-info.xml properties.xml
               src/java/org/apache/cocoon/components/modules modules.xconf
  Added:       src/blocks/linkrewriter/conf linkrewriter.xconf
               src/blocks/linkrewriter/java/org/apache/cocoon/transformation
                        LinkRewriterTransformer.java
                        VariableRewriterTransformer.java
               
src/blocks/linkrewriter/java/org/apache/cocoon/transformation/helpers
                        InterpolatingConfigurationHandler.java
                        VariableConfiguration.java
               src/blocks/linkrewriter/samples samples.xml sitemap.xmap
               src/blocks/linkrewriter/samples/bookdemo README.txt
                        sitemap.xmap
               src/blocks/linkrewriter/samples/bookdemo/docs book.xml
                        index.html overview.html
               src/blocks/linkrewriter/samples/bookdemo/docs/installing
                        index.html
               src/blocks/linkrewriter/samples/bookdemo/stylesheets
                        absolutize-linkmap.xsl document2html.xsl
                        dotdots.xsl relativize-linkmap.xsl
                        simple-page2html.xsl simple-xml2html.xsl
               src/blocks/linkrewriter/samples/sitedemo README.txt
                        linkmap.xml sitemap.xmap
               src/blocks/linkrewriter/samples/sitedemo/docs index.xml
               src/blocks/linkrewriter/samples/sitedemo/stylesheets
                        absolutize-linkmap.xsl dotdots.xsl
                        relativize-linkmap.xsl
  Removed:     src/java/org/apache/cocoon/transformation
                        LinkRewriterTransformer.java
               src/java/org/apache/cocoon/transformation/helpers
                        InterpolatingConfigurationHandler.java
                        VariableConfiguration.java
               src/webapp/samples/linkrewriter-bookdemo README.txt
                        sitemap.xmap
               src/webapp/samples/linkrewriter-bookdemo/docs book.xml
                        index.html index.xml overview.html
               src/webapp/samples/linkrewriter-bookdemo/docs/installing
                        index.html
               src/webapp/samples/linkrewriter-bookdemo/stylesheets
                        absolutize-linkmap.xsl document2html.xsl
                        dotdots.xsl relativize-linkmap.xsl
                        simple-page2html.xsl simple-xml2html.xsl
               src/webapp/samples/linkrewriter-sitedemo README.txt
                        linkmap.xml sitemap.xmap
               src/webapp/samples/linkrewriter-sitedemo/docs index.xml
               src/webapp/samples/linkrewriter-sitedemo/stylesheets
                        absolutize-linkmap.xsl dotdots.xsl
                        relativize-linkmap.xsl
  Log:
  Move LinkRewriterTransformer to its own block, since with all the samples and
  helper classes it is quite big.  This will also allow it to evolve faster
  independent of cocoon.jar.
  
  Revision  Changes    Path
  1.6       +20 -0     xml-cocoon2/project-info.xml
  
  Index: project-info.xml
  ===================================================================
  RCS file: /home/cvs/xml-cocoon2/project-info.xml,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- project-info.xml  17 Jan 2003 11:33:50 -0000      1.5
  +++ project-info.xml  22 Jan 2003 13:15:44 -0000      1.6
  @@ -464,6 +464,26 @@
     </project>
   
   
  +  <project name="linkrewriter-block">
  +    <package>org.apache.cocoon</package>
  +    
  +    <ant target="block">
  +      <property name="block-name" value="linkrewriter"/>
  +    </ant>
  +    
  +    <depend project="xml-cocoon2"/>
  +    
  +    <work nested="tools/anttasks"/>
  +    <home nested="build/cocoon"/>
  +    
  +    <jar name="linkrewriter-block.jar"/>
  +
  +    <nag from="Jeff Turner &lt;[EMAIL PROTECTED]&gt;"
  +         to="[email protected]"/>
  +         
  +  </project>
  +
  +
     <project name="bsf-block">
       <package>org.apache.cocoon</package>
       
  
  
  
  1.28      +1 -0      xml-cocoon2/properties.xml
  
  Index: properties.xml
  ===================================================================
  RCS file: /home/cvs/xml-cocoon2/properties.xml,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- properties.xml    17 Jan 2003 11:33:50 -0000      1.27
  +++ properties.xml    22 Jan 2003 13:15:44 -0000      1.28
  @@ -138,6 +138,7 @@
           <python include="true"/>
           <lucene include="true"/>        
           <html include="true"/>
  +        <linkrewriter include="true"/>
           <bsf include="true"/>
           <profiler include="true"/>        
           <velocity include="true"/>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/conf/linkrewriter.xconf
  
  Index: linkrewriter.xconf
  ===================================================================
  <?xml version="1.0"?>
  
  <xconf xpath="/cocoon/input-modules" unless="[EMAIL PROTECTED]'linkmap']">
  
        <!-- For the sitedemo sample -->
        <component-instance
          class="org.apache.cocoon.components.modules.input.XMLFileModule"
          logger="core.modules.xml" name="linkmap">
          <file src="cocoon://samples/linkrewriter/sitedemo/linkmap"/>
          <!-- Shouldn't this be the default? -->
          <reloadable>true</reloadable>
        </component-instance>
         <component-instance
           
class="org.apache.cocoon.components.modules.input.SimpleMappingMetaModule"
           logger="core.modules.mapper" name="site">
           <input-module name="linkmap"/>
           <prefix>/site/</prefix>
           <suffix>/@href</suffix>
         </component-instance>
  
         <!-- For the bookdemo sample -->
         <component-instance
          class="org.apache.cocoon.components.modules.input.XMLFileModule"
          logger="core.modules.xml" name="book-raw">
          <!-- Shouldn't this be the default? -->
          <file src="cocoon://samples/linkrewriter/bookdemo/docs/book.xml"/>
          <reloadable>true</reloadable>
        </component-instance>
         <component-instance
           
class="org.apache.cocoon.components.modules.input.SimpleMappingMetaModule"
           logger="core.modules.mapper" name="book">
           <input-module name="book-raw"/>
         </component-instance>
   
  </xconf>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/java/org/apache/cocoon/transformation/LinkRewriterTransformer.java
  
  Index: LinkRewriterTransformer.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.transformation;
  
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.cocoon.ProcessingException;
  import org.apache.excalibur.source.Source;
  import org.apache.excalibur.source.SourceException;
  import org.apache.cocoon.components.source.WriteableSource;
  import org.apache.cocoon.components.source.SourceUtil;
  
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.DefaultConfiguration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.ComponentSelector;
  
  import org.apache.cocoon.environment.SourceResolver;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.Attributes;
  import org.xml.sax.Locator;
  import org.xml.sax.SAXException;
  import org.xml.sax.helpers.AttributesImpl;
  
  import org.apache.cocoon.transformation.helpers.VariableConfiguration;
  import org.apache.cocoon.components.language.markup.xsp.XSPModuleHelper;
  
  import java.io.PrintWriter;
  import java.io.OutputStreamWriter;
  import java.io.IOException;
  import java.util.Date;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Set;
  import java.util.HashSet;
  import java.util.StringTokenizer;
  import java.net.MalformedURLException;
  
  /** 
   * Rewrites URIs in links to a value determined by an InputModule.
   * The URI scheme identifies the InputModule to use, and the rest of the URI 
is
   * used as the attribute name.
   * <h3>Example</h3>
   * For instance, if we had an [EMAIL PROTECTED]
   * org.apache.cocoon.components.modules.input.XMLFileModule}, configured to
   * read values from an XML file:
   * <pre>
   * &lt;site>
   *   &lt;faq>
   *     &lt;how_to_boil_eggs href="faq/eggs.html"/>
   *   &lt;/faq>
   * &lt;/site>
   * </pre>
   * mapped to the prefix 'site:', then &lt;link
   * href="site:/site/faq/how_to_boil_eggs/@href"> would be replaced with
   * &lt;link href="faq/eggs.html"&gt;
   * <p>
   * InputModules are configured twice; first statically in
   * <code>cocoon.xconf</code>, and then dynamically at runtime, with dynamic
   * configuration (if any) taking precedence.  LinkRewriterTransformer allows
   * you to pass a dynamic configuration to used InputModules as follows.
   * <p>
   * First, a template Configuration is specified in the static
   * &lt;map:components> block of the sitemap:
   * <pre>
   *  &lt;map:transformer name="linkrewriter"
   *    src="org.apache.cocoon.transformation.LinkRewriterTransformer">
   *    &lt;input-module name="site" src="cocoon://samples/link/linkmap" 
reloadable="true"/>
   *    &lt;input-module name="mapper">
   *      &lt;input-module name="site" src="{src}" reloadable="true"/>
   *      &lt;prefix>/site/&lt;/prefix>
   *      &lt;suffix>/@href&lt;/suffix>
   *    &lt;/input-module>
   *  &lt;/map:transformer>
   * </pre>
   * Here, we have established dynamic configuration templates for two modules,
   * 'site' (an [EMAIL PROTECTED] 
org.apache.cocoon.components.modules.input.XMLFileModule}
   * and 'mapper' (A [EMAIL PROTECTED]
   * org.apache.cocoon.components.modules.input.SimpleMappingMetaModule}.  All
   * other InputModules will use their static configs.  Note that the dynamic
   * config syntax different to the static config syntax (attributes instead of
   * elements).  Note also that, when configuring a Meta InputModule like
   * 'mapper', we need to also configure the 'inner' module (here, 'site') with 
a
   * nested &lt;input-module>.
   * <p>
   * There is one further twist; to have <em>really</em> dynamic configuration,
   * we need information available only when the transformer actually runs.  
This
   * is why the above config was called a "template" Configuration; it needs to
   * be 'instantiated' and provided extra info, namely:
   * <ul>
   *  <li>The {src} string will be replaced with the map:transform @src 
attribute value.
   *  <li>Any other {variables} will be replaced with map:parameter values
   * </ul>
   * With the above config template, we can have a matcher like:
   *
   * <pre>
   *    &lt;map:match pattern="**welcome">
   *      &lt;map:generate src="index.xml"/>
   *      &lt;map:transform type="linkrewriter" src="cocoon:/{1}linkmap"/>
   *      &lt;map:serialize type="xml"/>
   *    &lt;/map:match>
   * </pre>
   *
   * Which would cause the 'mapper' XMLFileModule to be configured with a
   * different XML file, depending on the request.
   * <p>
   * Similarly, we could use a dynamic prefix:
   * <pre>
   *      &lt;prefix>{prefix}&lt;/prefix>
   * </pre>
   * in the template config, and:
   * <pre>
   *   &lt;map:parameter name="prefix" value="/site/"/>
   * </pre>
   * in the map:transform
   * <p>
   *
   * <h3>Configuration</h3>
   * <p>
   * The following map:parameter's are recognised:
   * <dl>
   *  <dt>link-attrs</dt>
   *  <dd>Space-separated list of attributes to consider links (to be
   *  transformed). Defaults to 'href'.</dd>
   *  <dt>schemes</dt>
   *  <dd>Space-separated list of URI schemes to explicitly include.  If 
specified, all URIs with unlisted schemes will not be converted.</dd>
   *  <dt>exclude-schemes</dt>
   *  <dd>Space-separated list of URI schemes to explicitly exclude.</dd>
   *  <dt>bad-link-str</dt>
   *  <dd>String to use for links with a correct InputModule prefix, but no 
value
   *  therein.  Defaults to the original URI.</dd>
   * </dl>
   *
   * <p>
   * Note that currently, only links in the default ("") namespace are 
converted.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]">Jeff Turner</a>
   */
  public class LinkRewriterTransformer
      extends AbstractSAXTransformer implements Initializable, Configurable
  {
  
      private static String NAMESPACE="";
      private static String lf = System.getProperty("line.separator", "\n");
  
      /** A list of attributes considered 'links' */
      private Set linkAttrs;
  
      /** List containing schemes (protocols) of links to log */
      private Set inSchemes;
      private Set outSchemes;
  
      /** Links matching one of the acceptable schemes. */
      private Set links;
  
      /** Configuration passed to the component once through configure(). */
      private Configuration origConf; 
  
      /** Derivation of origConf with variables obtained from setup() 
parameters.
       * Recreated once per invocation. */
      private Configuration conf; 
  
      private XSPModuleHelper modHelper;
  
      private String badLinkStr;
  
      /**
       * Configure this component from the map:transformer block.  Called before
       * initialization and setup.
       */
      public void configure(Configuration conf)
          throws ConfigurationException {
          this.origConf = conf;
      }
   
      /**
       * Initiate resources prior to this component becoming active.
       */
      public void initialize() throws Exception {
          this.namespaceURI = NAMESPACE;
          this.modHelper = new XSPModuleHelper();
          modHelper.setup(this.manager);
      }
  
      /**
       * Setup this component to handle a map:transform instance.
       */
      public void setup(SourceResolver resolver, Map objectModel,
              String src, Parameters parameters)
          throws ProcessingException, SAXException, IOException
      {
          super.setup(resolver, objectModel, src, parameters);
          this.links = new HashSet();
          this.badLinkStr = parameters.getParameter("bad-link-str", null);
          this.linkAttrs = split(parameters.getParameter("link-attrs", "href"), 
" ");
          this.inSchemes = split(parameters.getParameter("schemes", ""), " ");
          this.outSchemes = split(parameters.getParameter("exclude-schemes", 
""), " ");
  
          // Generate conf
          VariableConfiguration varConf = new 
VariableConfiguration(this.origConf);
          varConf.addVariable("src", src);
          varConf.addVariables(parameters);
          try {
              this.conf = varConf.getConfiguration();
          } catch (ConfigurationException ce) {
              throw new ProcessingException("Couldn't create dynamic config ", 
ce);
          }
      }
  
      /** Split a string into a Set of strings.
       * @param str String to split
       * @param delim Delimiter character
       * @return A Set of strings in 'str'
       */
      private Set split(String str, String delim) {
          Set schemes = new HashSet();
          StringTokenizer st = new StringTokenizer(str, delim);
          while (st.hasMoreTokens()) {
              String pfx = st.nextToken();
              schemes.add(pfx);
          }
          return schemes;
      }
  
  
      /**
       * Start processing elements of our namespace.
       * This hook is invoked for each sax event with our namespace.
       * @param uri The namespace of the element.
       * @param name The local name of the element.
       * @param raw The qualified name of the element.
       * @param attr The attributes of the element.
       */
      public void startTransformingElement(String uri,
              String name,
              String raw,
              Attributes attr)
          throws ProcessingException, IOException, SAXException 
      {
          Attributes newAttrs = null;
          boolean matched = false;
  
          Iterator iter = linkAttrs.iterator();
          while (iter.hasNext()) {
              int attrIdx = attr.getIndex((String)iter.next());
              if (attrIdx != -1) {
                  String oldAttr = attr.getValue(attrIdx);
                  int i = oldAttr.indexOf(":");
                  if (i != -1) {
                      String scheme = oldAttr.substring(0, i);
                      String addr = oldAttr.substring(i+1);
                      if (outSchemes.contains(scheme)) {
                          if (getLogger().isDebugEnabled()) {
                              getLogger().debug("Ignoring link 
'"+scheme+":"+addr+"'");
                          }
                      } else if (inSchemes.contains(scheme)) {
                          matched = true;
                          newAttrs = getLinkAttr(attr, attrIdx, scheme, addr);
                          if (getLogger().isDebugEnabled()) {
                              getLogger().debug("Converted link '"+oldAttr+"' 
to '"+newAttrs.getValue(attrIdx)+"'");
                          }
                      } else {
                          if (inSchemes.size() == 0) {
                              // If the link wasn't deliberately excluded from a
                              // list of 'good' links, then include it.
                              matched = true;
                              newAttrs = getLinkAttr(attr, attrIdx, scheme, 
addr);
                              getLogger().debug("Converted link '"+oldAttr+"' 
to '"+newAttrs.getValue(attrIdx)+"'");
                          }
                      }
                  }
              }
          }
          if (matched) {
              super.startTransformingElement(uri, name, raw, newAttrs);
          } else {
              super.startTransformingElement(uri, name, raw, attr);
          }
      }
  
      /**
       * Rewrite link in a set of attributes.
       *
       * @param oldAttrs Attributes containing unconverted link.
       * @param linkIndex index of link to convert
       * @param scheme URI scheme (indicating InputModule) of link
       * @param addr URI scheme of link
       * @return an Attributes based on <code>oldAttrs</code>, but with one 
attribute rewritten.
       */
      private Attributes getLinkAttr(Attributes oldAttrs, int linkIndex, String 
scheme, String addr) {
          AttributesImpl newAttrs = new AttributesImpl(oldAttrs);
          try {
              String modValue = 
(String)modHelper.getAttribute(this.objectModel, getConf(scheme), scheme, addr, 
(badLinkStr!=null?badLinkStr:scheme+":"+addr));
              newAttrs.setValue(linkIndex, modValue);
          } catch (Exception e) {
              // Swallow IM errors, usually prefixes like 'http' that aren't
              // bound to an InputModule.
              getLogger().warn("## IM error: "+e, e);
          }
          return newAttrs;
      }
  
      /**
       * Retrieve a dynamic Configuration for a specific InputModule.
       * @param scheme InputModule name
       * @return Configuration for specified scheme, from the map:transformer 
block.
       */
      private Configuration getConf(String scheme) {
          Configuration[] schemeConfs = this.conf.getChildren();
          for (int i=0; i<schemeConfs.length; i++) {
              if (scheme.equals(schemeConfs[i].getAttribute("name", null))) {
                  return schemeConfs[i];
              }
          }
          return null;
      }
  
      /** Recycle this component for use in another map:transform. */
      public void recycle() {
          super.recycle();
          this.resolver = null;
          this.links = null;
          this.linkAttrs = null;
          this.inSchemes = null;
          this.outSchemes = null;
          this.conf = null;
          // Note: configure() and initialize() are not called after every
          //recycle, so don't null origConf
      }
  }
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/java/org/apache/cocoon/transformation/VariableRewriterTransformer.java
  
  Index: VariableRewriterTransformer.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.transformation;
  
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.cocoon.ProcessingException;
  import org.apache.excalibur.source.Source;
  import org.apache.excalibur.source.SourceException;
  import org.apache.cocoon.components.source.WriteableSource;
  import org.apache.cocoon.components.source.SourceUtil;
  
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.DefaultConfiguration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.ComponentSelector;
  
  import org.apache.cocoon.environment.SourceResolver;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.Attributes;
  import org.xml.sax.Locator;
  import org.xml.sax.SAXException;
  import org.xml.sax.helpers.AttributesImpl;
  
  import org.apache.cocoon.transformation.helpers.VariableConfiguration;
  import org.apache.cocoon.components.language.markup.xsp.XSPModuleHelper;
  
  import java.io.PrintWriter;
  import java.io.OutputStreamWriter;
  import java.io.IOException;
  import java.util.Date;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Set;
  import java.util.HashSet;
  import java.util.StringTokenizer;
  import java.net.MalformedURLException;
  
  /** 
   * Rewrites URIs in links to a value determined by an InputModule.
   * The URI scheme identifies the InputModule to use, and the rest of the URI 
is
   * used as the attribute name.
   * <h3>Example</h3>
   * For instance, if we had an [EMAIL PROTECTED]
   * org.apache.cocoon.components.modules.input.XMLFileModule}, configured to
   * read values from an XML file:
   * <pre>
   * &lt;site>
   *   &lt;faq>
   *     &lt;how_to_boil_eggs href="faq/eggs.html"/>
   *   &lt;/faq>
   * &lt;/site>
   * </pre>
   * mapped to the prefix 'site:', then &lt;link
   * href="site:/site/faq/how_to_boil_eggs/@href"> would be replaced with
   * &lt;link href="faq/eggs.html"&gt;
   * <p>
   * InputModules are configured twice; first statically in
   * <code>cocoon.xconf</code>, and then dynamically at runtime, with dynamic
   * configuration (if any) taking precedence.  VariableRewriterTransformer 
allows
   * you to pass a dynamic configuration to used InputModules as follows.
   * <p>
   * First, a template Configuration is specified in the static
   * &lt;map:components> block of the sitemap:
   * <pre>
   *  &lt;map:transformer name="linkrewriter"
   *    src="org.apache.cocoon.transformation.VariableRewriterTransformer">
   *    &lt;input-module name="site" src="cocoon://samples/link/linkmap" 
reloadable="true"/>
   *    &lt;input-module name="mapper">
   *      &lt;input-module name="site" src="{src}" reloadable="true"/>
   *      &lt;prefix>/site/&lt;/prefix>
   *      &lt;suffix>/@href&lt;/suffix>
   *    &lt;/input-module>
   *  &lt;/map:transformer>
   * </pre>
   * Here, we have established dynamic configuration templates for two modules,
   * 'site' (an [EMAIL PROTECTED] 
org.apache.cocoon.components.modules.input.XMLFileModule}
   * and 'mapper' (A [EMAIL PROTECTED]
   * org.apache.cocoon.components.modules.input.SimpleMappingMetaModule}.  All
   * other InputModules will use their static configs.  Note that the dynamic
   * config syntax different to the static config syntax (attributes instead of
   * elements).  Note also that, when configuring a Meta InputModule like
   * 'mapper', we need to also configure the 'inner' module (here, 'site') with 
a
   * nested &lt;input-module>.
   * <p>
   * There is one further twist; to have <em>really</em> dynamic configuration,
   * we need information available only when the transformer actually runs.  
This
   * is why the above config was called a "template" Configuration; it needs to
   * be 'instantiated' and provided extra info, namely:
   * <ul>
   *  <li>The {src} string will be replaced with the map:transform @src 
attribute value.
   *  <li>Any other {variables} will be replaced with map:parameter values
   * </ul>
   * With the above config template, we can have a matcher like:
   *
   * <pre>
   *    &lt;map:match pattern="**welcome">
   *      &lt;map:generate src="index.xml"/>
   *      &lt;map:transform type="linkrewriter" src="cocoon:/{1}linkmap"/>
   *      &lt;map:serialize type="xml"/>
   *    &lt;/map:match>
   * </pre>
   *
   * Which would cause the 'mapper' XMLFileModule to be configured with a
   * different XML file, depending on the request.
   * <p>
   * Similarly, we could use a dynamic prefix:
   * <pre>
   *      &lt;prefix>{prefix}&lt;/prefix>
   * </pre>
   * in the template config, and:
   * <pre>
   *   &lt;map:parameter name="prefix" value="/site/"/>
   * </pre>
   * in the map:transform
   * <p>
   *
   * <h3>Configuration</h3>
   * <p>
   * The following map:parameter's are recognised:
   * <dl>
   *  <dt>link-attrs</dt>
   *  <dd>Space-separated list of attributes to consider links (to be
   *  transformed). Defaults to 'href'.</dd>
   *  <dt>schemes</dt>
   *  <dd>Space-separated list of URI schemes to explicitly include.  If 
specified, all URIs with unlisted schemes will not be converted.</dd>
   *  <dt>exclude-schemes</dt>
   *  <dd>Space-separated list of URI schemes to explicitly exclude.</dd>
   *  <dt>bad-link-str</dt>
   *  <dd>String to use for links with a correct InputModule prefix, but no 
value
   *  therein.  Defaults to the original URI.</dd>
   * </dl>
   *
   * <p>
   * Note that currently, only links in the default ("") namespace are 
converted.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]">Jeff Turner</a>
   */
  public class VariableRewriterTransformer
      extends AbstractSAXTransformer implements Initializable, Configurable
  {
  
      private static String NAMESPACE="";
      private static String lf = System.getProperty("line.separator", "\n");
  
      /** A list of attributes considered 'links' */
      private Set linkAttrs;
  
      /** List containing schemes (protocols) of links to log */
      private Set inSchemes;
      private Set outSchemes;
  
      /** Links matching one of the acceptable schemes. */
      private Set links;
  
      /** Configuration passed to the component once through configure(). */
      private Configuration origConf; 
  
      /** Derivation of origConf with variables obtained from setup() 
parameters.
       * Recreated once per invocation. */
      private Configuration conf; 
  
      private XSPModuleHelper modHelper;
  
      private String badLinkStr;
  
      /**
       * Configure this component from the map:transformer block.  Called before
       * initialization and setup.
       */
      public void configure(Configuration conf)
          throws ConfigurationException {
          this.origConf = conf;
      }
   
      /**
       * Initiate resources prior to this component becoming active.
       */
      public void initialize() throws Exception {
          this.namespaceURI = NAMESPACE;
          this.modHelper = new XSPModuleHelper();
          modHelper.setup(this.manager);
      }
  
      /**
       * Setup this component to handle a map:transform instance.
       */
      public void setup(SourceResolver resolver, Map objectModel,
              String src, Parameters parameters)
          throws ProcessingException, SAXException, IOException
      {
          super.setup(resolver, objectModel, src, parameters);
          this.links = new HashSet();
          this.badLinkStr = parameters.getParameter("bad-link-str", null);
          this.linkAttrs = split(parameters.getParameter("link-attrs", "href"), 
" ");
          this.inSchemes = split(parameters.getParameter("schemes", ""), " ");
          this.outSchemes = split(parameters.getParameter("exclude-schemes", 
""), " ");
  
          // Generate conf
          VariableConfiguration varConf = new 
VariableConfiguration(this.origConf);
          varConf.addVariable("src", src);
          varConf.addVariables(parameters);
          try {
              this.conf = varConf.getConfiguration();
          } catch (ConfigurationException ce) {
              throw new ProcessingException("Couldn't create dynamic config ", 
ce);
          }
      }
  
      /** Split a string into a Set of strings.
       * @param str String to split
       * @param delim Delimiter character
       * @return A Set of strings in 'str'
       */
      private Set split(String str, String delim) {
          Set schemes = new HashSet();
          StringTokenizer st = new StringTokenizer(str, delim);
          while (st.hasMoreTokens()) {
              String pfx = st.nextToken();
              schemes.add(pfx);
          }
          return schemes;
      }
  
  
      /**
       * Start processing elements of our namespace.
       * This hook is invoked for each sax event with our namespace.
       * @param uri The namespace of the element.
       * @param name The local name of the element.
       * @param raw The qualified name of the element.
       * @param attr The attributes of the element.
       */
      public void startTransformingElement(String uri,
              String name,
              String raw,
              Attributes attr)
          throws ProcessingException, IOException, SAXException 
      {
          Attributes newAttrs = null;
          boolean matched = false;
  
          Iterator iter = linkAttrs.iterator();
          while (iter.hasNext()) {
              int attrIdx = attr.getIndex((String)iter.next());
              if (attrIdx != -1) {
                  String oldAttr = attr.getValue(attrIdx);
                  int i = oldAttr.indexOf(":");
                  if (i != -1) {
                      String scheme = oldAttr.substring(0, i);
                      String addr = oldAttr.substring(i+1);
                      if (outSchemes.contains(scheme)) {
                          if (getLogger().isDebugEnabled()) {
                              getLogger().debug("Ignoring link 
'"+scheme+":"+addr+"'");
                          }
                      } else if (inSchemes.contains(scheme)) {
                          matched = true;
                          newAttrs = getLinkAttr(attr, attrIdx, scheme, addr);
                          if (getLogger().isDebugEnabled()) {
                              getLogger().debug("Converted link '"+oldAttr+"' 
to '"+newAttrs.getValue(attrIdx)+"'");
                          }
                      } else {
                          if (inSchemes.size() == 0) {
                              // If the link wasn't deliberately excluded from a
                              // list of 'good' links, then include it.
                              matched = true;
                              newAttrs = getLinkAttr(attr, attrIdx, scheme, 
addr);
                              getLogger().debug("Converted link '"+oldAttr+"' 
to '"+newAttrs.getValue(attrIdx)+"'");
                          }
                      }
                  }
              }
          }
          if (matched) {
              super.startTransformingElement(uri, name, raw, newAttrs);
          } else {
              super.startTransformingElement(uri, name, raw, attr);
          }
      }
  
      /**
       * Process the SAX event.
       */
      public void characters(char[] p0, int p1, int p2)
      throws SAXException {
          if (this.ignoreEventsCount == 0) {
              if (this.ignoreEmptyCharacters == true) {
                  String value = new String(p0, p1, p2);
                  if (value.trim().length() > 0) {
                      super.characters(p0, p1, p2);
                  }
              } else {
                  super.characters(p0, p1, p2);
              }
          }
      }
  
      /**
       * Rewrite link in a set of attributes.
       *
       * @param oldAttrs Attributes containing unconverted link.
       * @param linkIndex index of link to convert
       * @param scheme URI scheme (indicating InputModule) of link
       * @param addr URI scheme of link
       * @return an Attributes based on <code>oldAttrs</code>, but with one 
attribute rewritten.
       */
      private Attributes getLinkAttr(Attributes oldAttrs, int linkIndex, String 
scheme, String addr) {
          AttributesImpl newAttrs = new AttributesImpl(oldAttrs);
          try {
              String modValue = 
(String)modHelper.getAttribute(this.objectModel, getConf(scheme), scheme, addr, 
(badLinkStr!=null?badLinkStr:scheme+":"+addr));
              newAttrs.setValue(linkIndex, modValue);
          } catch (Exception e) {
              // Swallow IM errors, usually prefixes like 'http' that aren't
              // bound to an InputModule.
              getLogger().warn("## IM error: "+e, e);
          }
          return newAttrs;
      }
  
      /**
       * Retrieve a dynamic Configuration for a specific InputModule.
       * @param scheme InputModule name
       * @return Configuration for specified scheme, from the map:transformer 
block.
       */
      private Configuration getConf(String scheme) {
          Configuration[] schemeConfs = this.conf.getChildren();
          for (int i=0; i<schemeConfs.length; i++) {
              if (scheme.equals(schemeConfs[i].getAttribute("name", null))) {
                  return schemeConfs[i];
              }
          }
          return null;
      }
  
      /** Recycle this component for use in another map:transform. */
      public void recycle() {
          super.recycle();
          this.resolver = null;
          this.links = null;
          this.linkAttrs = null;
          this.inSchemes = null;
          this.outSchemes = null;
          this.conf = null;
          // Note: configure() and initialize() are not called after every
          //recycle, so don't null origConf
      }
  }
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/java/org/apache/cocoon/transformation/helpers/InterpolatingConfigurationHandler.java
  
  Index: InterpolatingConfigurationHandler.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.transformation.helpers;
  
  import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
  import org.xml.sax.*;
  import org.xml.sax.helpers.AttributesImpl;
  import java.util.Map;
  import java.util.StringTokenizer;
  
  /**
   * A SAX ContentHandler that builds Avalon <code>Configuration</code> objects,
   * but also replaces variables of the form {var} with values from a map.
   *
   * @see VariableConfiguration
   * @author <a href="[EMAIL PROTECTED]">Jeff Turner</a>
   */
  
  public class InterpolatingConfigurationHandler extends 
SAXConfigurationHandler {
      private Map vars;
  
      /** Constructor.
       * @param vars The mappings from variable name to value.
       */
      public InterpolatingConfigurationHandler(Map vars) {
          this.vars = vars;
      }
  
      /** Replace {vars} in attributes.  */
      public void startElement(String uri, String localName, String qName, 
Attributes attr) throws SAXException {
          AttributesImpl newAttr = new AttributesImpl(attr);
          for (int i=0; i<attr.getLength(); i++) {
              newAttr.setValue(i, interp(attr.getValue(i)));
          }
          super.startElement(uri, localName, qName, newAttr);
      }
  
      /** Replace {vars} in element bodies.  */
      public void characters( final char[] ch, int start, int len )
          throws SAXException
      {
          StringBuffer buf = new StringBuffer();
          if (start!=0) buf.append(ch, 0, start-1);
          String newVal = interp(new String(ch,start, len));
          buf.append(newVal);
          buf.append(ch, start+len, ch.length-(start+len));
          super.characters(buf.toString().toCharArray(), start, 
newVal.length());
      }
  
  
      /**
       * Interpolate variable values into a string.
       *
       * @param str String with {var} tokens
       * @return <code>str</code>, with {variables} replaced by values.  If an
       * unknown variable token is encountered it is ignored.
       */
      private String interp(String str) {
          StringBuffer buf = new StringBuffer(str.length()*2);
          StringTokenizer tok = new StringTokenizer(str, "{}", true);
          int state = 0; // 0=outside, 1=inside
          while (tok.hasMoreTokens()) {
              String token = tok.nextToken();
              if (state == 0 && "{".equals(token)) {
                  state = 1;
              } else if (state == 1 && "}".equals(token)) {
                  state = 0;
              } else if (state == 0) {
                  buf.append(token);
              } else if (state == 1) {
                  //System.out.println("Replacing "+token+" with 
"+vars.get(token));
                  String val = (String)vars.get(token);
                  if (val == null) {
                      buf.append("{").append(token).append("}");
                  } else{ buf.append(val); }
              }
          }
          return buf.toString();
      }
  
  }
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/java/org/apache/cocoon/transformation/helpers/VariableConfiguration.java
  
  Index: VariableConfiguration.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.transformation.helpers;
  
  import org.apache.avalon.framework.configuration.DefaultConfiguration;
  import 
org.apache.avalon.framework.configuration.DefaultConfigurationSerializer;
  
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.parameters.Parameters;
  
  import org.xml.sax.SAXException;
  
  import java.util.Map;
  import java.util.HashMap;
  
  /**
   * An Avalon <code>Configuration</code> factory that allows {variables} to be
   * replaced with values from a lookup table.
   *
   * @author <a href="[EMAIL PROTECTED]">Jeff Turner</a>
   * @version $Revision: 1.1 $ $Date: 2003/01/22 13:15:44 $
   */
  
  public class VariableConfiguration {
      public static final String UNSET_VAR="unset";
      private Configuration conf;
      private Map vars = new HashMap();
  
      /** Constructor.
       * @param conf Template Configuration with {variables} to marking where
       * values should be interpolated.  May be <code>null</code>.
       */
      public VariableConfiguration(Configuration conf) {
          this.conf = conf;
          this.vars = vars;
      }
  
      /** Add a name-value pair.
       */
      public void addVariable(String name, String value) {
          vars.put(name, value);
      }
  
      /** Add a set of name-value pairs.
       */
      public void addVariables(Parameters params) {
          String[] names = params.getNames();
          for (int i=0; i<names.length; i++) {
              String paramVal = params.getParameter(names[i], null);
              if (paramVal != null) {
                  vars.put(names[i], paramVal);
              }
          }
      }
  
      /**
       * Get a generated Configuration with interpolated variable values.
       * @return The Configuration passed in the constructor, with {variable}
       * tokens in attributes and element bodies replaced with values (if
       * specified), or <code>null</code>.
       */
      public Configuration getConfiguration() throws SAXException, 
ConfigurationException {
  
          if (this.conf == null) return null;
          InterpolatingConfigurationHandler handler = new 
InterpolatingConfigurationHandler(this.vars);
          DefaultConfigurationSerializer ser = new 
DefaultConfigurationSerializer();
          ser.serialize(handler, this.conf);
          return handler.getConfiguration();
      }
  
  }
  
  
  
  1.1                  xml-cocoon2/src/blocks/linkrewriter/samples/samples.xml
  
  Index: samples.xml
  ===================================================================
  <?xml version="1.0" encoding="iso-8859-1"?>
  <!-- CVS: $Id: samples.xml,v 1.1 2003/01/22 13:15:45 jefft Exp $ -->
  <samples xmlns:xlink="http://www.w3.org/1999/xlink";>
    <group name="Back">
      <sample name="Back" href="../">
        to the samples main page
     </sample>
   </group>
    <group name="LinkRewriter Demos">
      <sample name="sitedemo" href="sitedemo/welcome">
        a demo with one page, 'welcome', with links that will have ..'s
        progressively added for each directory 'welcome' is in.  Eg, try
        <link href="sitedemo/welcome">welcome</link>, <link
          href="sitedemo/foo/welcome">foo/welcome</link>, <link
          href="sitedemo/foo/bar/welcome">foo/bar/welcome</link> and watch the
        links change.
     </sample>
     <sample name="bookdemo" href="bookdemo/index.html">
       a demonstration of using a book.xml file to resolve links between pages.
     </sample>
    </group>
   <!--
    <group name="Documentation">
      <sample name="Docs" href="../documents/index">
      The Cocoon documentation.
     </sample>
      <sample name="Tutorial" href="tutorial/home.html">
      A tutorial on Cocoon.
     </sample>
      <sample name="List of docs" href="../documents/doclist.html">
      Generated list of all documentation (aggregates each book.xml)
     </sample>
      <sample name="Slides" href="slides/slides">
      An old, but still relevant, presentation of Cocoon 1 shown at
      ApacheCon 2000 (an example of complex XSLT usage).
     </sample>
      <sample name="Search the docs" href="search/welcome">
      Search into the Cocoon documentation using Apache Lucene.
     </sample>
      <sample name="Check links" href="linkstatus/">
      Verify that there are no broken hyperlinks in the Cocoon documentation.
     </sample>
    </group>
    <group name="JSP with Cocoon">
      <sample name="JSP samples" href="jsp/">
      JSP usage with Cocoon
     </sample>
   </group>
   -->
  </samples>
  
  
  
  1.1                  xml-cocoon2/src/blocks/linkrewriter/samples/sitemap.xmap
  
  Index: sitemap.xmap
  ===================================================================
  <?xml version="1.0"?>
  
  <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0";>
    <!-- =========================== Components 
================================ -->
  
    <map:components>
  
      <map:generators default="file"/>
      <map:transformers default="xslt"/>
      <map:readers default="resource"/>
      <map:serializers default="html"/>
      <map:matchers default="wildcard"/>
      <map:selectors default="browser"/>
    </map:components>
  
  
    <!-- =========================== Pipelines 
================================= -->
  
    <map:pipelines>
  
      <map:pipeline>
       <map:match pattern="">
         <map:redirect-to uri="welcome"/>
       </map:match>
       <map:match pattern="welcome">
         <map:generate src="samples.xml"/>
         <map:transform src="../common/style/xsl/html/simple-samples2html.xsl"/>
         <map:serialize/>
  
       </map:match>
     </map:pipeline>
  
      <!-- pipeline mounting linkrewriter samples sitemaps -->
      <map:pipeline>
        <!-- mount everything else -->
        <map:match pattern="*/**">
          <map:mount check-reload="yes" src="{1}/" uri-prefix="{1}"/>
        </map:match>
      </map:pipeline>
  
    </map:pipelines>
  
  </map:sitemap>
  
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/bookdemo/README.txt
  
  Index: README.txt
  ===================================================================
  This demo shows a LinkRewriterTransformer reading from a relativized book.xml
  file, to resolve links in HTML.
  
  Please read ../linkrewriter-sitedemo/README.txt for more information.
  
  
  For this sample to work, the following section must be added to cocoon.xconf,
  inside /cocoon/input-modules:
           
        <component-instance
          class="org.apache.cocoon.components.modules.input.XMLFileModule"
          logger="core.modules.xml" name="book-raw">
          <!-- Shouldn't this be the default? -->
          <file src="cocoon://samples/linkrewriter/docs/book.xlm"/>
          <reloadable>true</reloadable>
        </component-instance>
         <component-instance
           
class="org.apache.cocoon.components.modules.input.SimpleMappingMetaModule"
           logger="core.modules.mapper" name="book">
           <input-module name="book-raw"/>
         </component-instance>
     
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/bookdemo/sitemap.xmap
  
  Index: sitemap.xmap
  ===================================================================
  <?xml version="1.0"?>
  
  <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0";>
  
  <!-- =========================== Components ================================ 
-->
  
   <map:components>
    <map:generators default="file"/>
    <map:transformers default="xslt">
      <map:transformer name="linkrewriter"
        src="org.apache.cocoon.transformation.LinkRewriterTransformer">
        <input-module name="book-raw" 
src="cocoon://samples/linkrewriter/bookdemo/linkmap" reloadable="true"/>
        <input-module name="book">
          <input-module name="book-raw" src="{src}" reloadable="true"/>
          <prefix>//[EMAIL PROTECTED]'</prefix>
          <suffix>']/@href</suffix>
        </input-module>
      </map:transformer>
    </map:transformers>
    <map:readers default="resource"/>
    <map:serializers default="html"/>
    <map:matchers default="wildcard"/>
    <map:selectors default="browser"/>
   </map:components>
  
  <!-- =========================== Pipelines ================================= 
-->
  
   <map:pipelines>
     <map:pipeline>
  
       <map:match pattern="">
         <map:redirect-to uri="index.html"/>
       </map:match>
  
       <map:match pattern="*.html">
         <map:generate src="docs/{1}.html"/>
         <map:transform type="linkrewriter" src="cocoon:/linkmap">
           <!--
           <map:parameter name="prefix" value="//[EMAIL PROTECTED]'"/>
           <map:parameter name="suffix" value="']/@href"/>
           -->
         </map:transform>
         <map:serialize/>
         <map:serialize type="xml"/>
       </map:match>
  
       <map:match pattern="**/*.html">
         <map:generate src="docs/{1}/{2}.html"/>
         <map:transform type="linkrewriter" src="cocoon:/{1}/linkmap"/>
         <map:serialize/>
         <map:serialize type="xml"/>
       </map:match>
  
       <map:match pattern="**linkmap">
         <map:generate src="docs/book.xml"/>
         <map:transform src="stylesheets/absolutize-linkmap.xsl"/>
         <map:transform src="stylesheets/relativize-linkmap.xsl">
           <map:parameter name="path" value="{0}"/>
         </map:transform>
         <map:serialize type="xml"/>
       </map:match>
  
     </map:pipeline>
   </map:pipelines>
  
  </map:sitemap>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/bookdemo/docs/book.xml
  
  Index: book.xml
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <!DOCTYPE book PUBLIC "-//APACHE//DTD Cocoon Documentation Book V1.0//EN" 
"dtd/book-cocoon-v10.dtd">
  
  <book software="Apache Cocoon" 
        title="Apache Cocoon Documentation" 
        copyright="1999-2002 The Apache Software Foundation"
        xmlns:xlink="http://www.w3.org/1999/xlink";>
  
    <menu label="About">
      <menu-item label="Index" href="index.html"/>
      <menu-item label="News" href="news.html"/>
      <menu-item label="License" href="license.html"/>
      <external label="Download" href="http://xml.apache.org/cocoon/dist/"/>
    </menu>
  
    <menu label="Documentation">
      <menu-item label="Introduction" href="introduction.html"/>
      <menu-item label="Installing" href="installing/index.html"/>
      <menu-item label="Overview" href="overview.html"/>
      <menu-item label="User Guide" href="userdocs/index.html"/>
      <menu-item label="Dev Guide" href="developing/index.html"/>
      <menu-item label="Tutorials" href="tutorial/index.html"/>
      <menu-item label="FAQs" href="faq/index.html"/>
      <menu-item label="How-Tos" href="howto/index.html"/>
      <menu-item label="Performance" href="performancetips.html"/>
      <menu-item label="Snippets" href="snippet/index.html"/>
      <menu-item label="ToC" href="doclist.html"/>
    </menu>
  
    <menu label="Status">
      <menu-item label="Changes" href="changes.html"/>
      <menu-item label="Todo" href="todo.html"/>
      <menu-item label="Planning notes" href="plan/index.html"/>
      <external label="Patch queue" 
href="http://nagoya.apache.org/bugzilla/buglist.cgi?bug_status=NEW&amp;bug_status=ASSIGNED&amp;bug_status=REOPENED&amp;email1=&amp;emailtype1=substring&amp;emailassigned_to1=1&amp;email2=&amp;emailtype2=substring&amp;emailreporter2=1&amp;bugidtype=include&amp;bug_id=&amp;changedin=&amp;votes=&amp;chfieldfrom=&amp;chfieldto=Now&amp;chfieldvalue=&amp;product=Cocoon+2&amp;short_desc=%5BPATCH%5D&amp;short_desc_type=allwordssubstr&amp;long_desc=&amp;long_desc_type=allwordssubstr&amp;bug_file_loc=&amp;bug_file_loc_type=allwordssubstr&amp;keywords=&amp;keywords_type=anywords&amp;field0-0-0=noop&amp;type0-0-0=noop&amp;value0-0-0=&amp;namedcmd=Cocoon+all&amp;newqueryname=cocoon+patch+queue&amp;tofooter=1&amp;order=Reuse+same+sort+as+last+time"/>
    </menu>
  
    <menu label="Community">
      <menu-item label="Cocoon Bylaws" href="bylaws-addendum.html"/>
      <menu-item label="Hall of Fame" href="who.html"/>
      <menu-item label="Contributing" href="contrib.html"/>
      <menu-item label="Mail Lists" href="mail-lists.html"/>
      <menu-item label="Mail Archives" href="mail-archives.html"/> 
    </menu>
  
    <menu label="Project">
      <external label="Bug Database" 
href="http://nagoya.apache.org/bugzilla/index.html"/>
      <external label="Code Repository" 
href="http://cvs.apache.org/viewcvs.cgi/xml-cocoon2/"/>
      <external label="Dev Snapshots" 
href="http://xml.apache.org/from-cvs/xml-cocoon2/"/>
    </menu>
  
    <menu label="Links">
      <menu-item label="Cocoon Links" href="link/index.html"/>  
      <menu-item label="Live Sites" href="link/livesites.html"/>
      <menu-item label="Cocoon Hosting" href="link/hosting.html"/>
    </menu>
  
    <menu label="Cocoon 1.x">
      <external label="Old Generation" href="http://xml.apache.org/cocoon1/"/> 
    </menu>
  
  </book>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/bookdemo/docs/index.html
  
  Index: index.html
  ===================================================================
  <html>
    <body>
        <p>[<a href="../">../</a>] [<a href="book:Index">index</a>] [<a 
href="book:Overview">overview</a>] [<a 
href="book:Installing">installing</a>]</p>
      <hr/>
      <h1>LinkRewriter demo</h1>
      <h2>/index.html</h2>
  
      <p>This subsitemap demonstrates the LinkRewriterTransformer, which 
rewrites
      links with the aid of configurable InputModules</p>
      <p>This particular demo is set up so that links of the form
      <code>book:XYZ</code> are resolved by looking in book.xml for the @label
      XYZ, and then using the associated href, with ..'s added as appropriate.
      This is done with an XMLFileModule and SimpleMappingMetaModule, defined in
      cocoon.xconf.
      </p>
      <p>Here are two links to demonstrate</p>
      <ul>
        <li><a href="book:Overview">book:Overview</a></li>
        <li><a href="book:Installing">book:Installing</a></li>
      </ul>
    </body>
  </html>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/bookdemo/docs/overview.html
  
  Index: overview.html
  ===================================================================
  <html>
    <body>
      <p>[<a href="../">../</a>] [<a href="book:Index">index</a>] [<a 
href="book:Overview">overview</a>] [<a 
href="book:Installing">installing</a>]</p>
      <hr/>
      <h1>Overview Page</h1>
      <h2>/overview.html</h2>
      <p>This is the overview.  Not much to see here.</p>
      <p><a href="book:Index">book:Index</a></p>
      <p><a href="book:Installing">book:Installing</a></p>
    </body>
  </html>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/bookdemo/docs/installing/index.html
  
  Index: index.html
  ===================================================================
  <html>
    <body>
      <p>[<a href="../">../</a>] [<a href="book:Index">index</a>] [<a 
href="book:Overview">overview</a>] [<a 
href="book:Installing">installing</a>]</p>
      <hr/>
      <h1>Installation Page</h1>
      <h2>installing/index.html</h2>
      <p>This page is in a subdirectory.  Notice how the same book:XYZ links are
      now rendered with ..'s, so that the correct directory is chosen.</p>
      <p><a href="book:Index">book:Index</a></p>
      <p><a href="book:Overview">book:Overview</a></p>
      <hr/>
      <p><a href="book:Installing">book:Installing</a></p>
    </body>
  </html>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/bookdemo/stylesheets/absolutize-linkmap.xsl
  
  Index: absolutize-linkmap.xsl
  ===================================================================
  <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  
  <xsl:template name="abs">
    <xsl:param name="node"/>
    <xsl:if test="$node/..">
      <xsl:call-template name="abs">
        <xsl:with-param name="node" select="$node/.."/>
      </xsl:call-template>
    </xsl:if>
    <xsl:value-of select="$node/@href"/>
  
  </xsl:template>
  
  <xsl:template match="@href">
    <xsl:attribute name="href">
    <xsl:call-template name="abs">
      <xsl:with-param name="node" select=".."/>
    </xsl:call-template>
    </xsl:attribute>
  </xsl:template>
  
  <xsl:template match="@*|node()" priority="-1">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  </xsl:stylesheet>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/bookdemo/stylesheets/document2html.xsl
  
  Index: document2html.xsl
  ===================================================================
  <?xml version="1.0"?>
  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"; 
version="1.0">
        <!-- 
====================================================================== -->
        <!-- document section -->
        <!-- 
====================================================================== -->
        <xsl:template match="/">
                <!-- checks if this is the included document to avoid 
neverending loop -->
                <xsl:if test="not(book)">
                        <document>
                                <xsl:choose>
                                        <xsl:when test="document/header/title">
                                                <title>
                                                        <xsl:value-of 
select="document/header/title"/>
                                                </title>
                                        </xsl:when>
                                        <xsl:otherwise>
                                                <title>NO TITLE</title>
                                        </xsl:otherwise>
                                </xsl:choose>
                                <body text="#000000" link="#039acc" 
vlink="#0086b2" alink="#cc0000" topmargin="4" leftmargin="4" marginwidth="4" 
marginheight="4" bgcolor="#ffffff">
                                        <xsl:apply-templates/>
                                </body>
                        </document>
                </xsl:if>
                <xsl:if test="book">
                        <xsl:apply-templates/>
                </xsl:if>
        </xsl:template>
        <!-- 
====================================================================== -->
        <!-- header section -->
        <!-- 
====================================================================== -->
        <xsl:template match="header">
                <!-- ignore on general document -->
        </xsl:template>
        <!-- 
====================================================================== -->
        <!-- body section -->
        <!-- 
====================================================================== -->
        <xsl:template match="s1">
                <font color="#0086b2" size="+2" face="verdana, helvetica, sans 
serif">
                        <xsl:value-of select="@title"/>
                </font>
                <hr size="1" style="color: #0086b2"/>
                <xsl:apply-templates/>
        </xsl:template>
        <xsl:template match="s2">
                <font color="#0086b2" size="+1" face="verdana, helvetica, sans 
serif">
                        <b><xsl:value-of select="@title"/></b>
                </font>
                <xsl:apply-templates/>
        </xsl:template>
        <xsl:template match="s3">
                <font color="#0086b2" size="+1" face="verdana, helvetica, sans 
serif">
                        <xsl:value-of select="@title"/>
                </font>
                <xsl:apply-templates/>
        </xsl:template>
        <xsl:template match="s4">
                <font color="#0086b2" face="verdana, helvetica, sans serif">
                        <b><xsl:value-of select="@title"/></b>
                </font>
                <xsl:apply-templates/>
        </xsl:template>
        <!-- 
====================================================================== -->
        <!-- footer section -->
        <!-- 
====================================================================== -->
        <xsl:template match="footer">
                <!-- ignore on general documents -->
        </xsl:template>
        <!-- 
====================================================================== -->
        <!-- paragraph section -->
        <!-- 
====================================================================== -->
        <xsl:template match="p">
                <p><font face="verdana,helvetica,sanserif" color="black">
                        <xsl:apply-templates/>
                </font></p>
        </xsl:template>
        <xsl:template match="note">
                <p>
                        <table width="100%" cellspacing="3" cellpadding="0" 
border="0">
                                <tr>
                                        <td width="28" valign="top">
                                                <img src="images/note.gif" 
width="28" height="29" vspace="0" hspace="0" border="0" alt="Note"/>
                                        </td>
                                        <td valign="top">
                                                <font size="-1" 
face="verdana,helvetica,sanserif" color="black">
                                                        <i>
                                                                
<xsl:apply-templates/>
                                                        </i>
                                                </font>
                                        </td>
                                </tr>
                        </table>
                </p>
        </xsl:template>
        <xsl:template match="source">
                <div align="center">
                        <table cellspacing="4" cellpadding="0" border="0">
                                <tr>
                                        <td bgcolor="#0086b2" width="1" 
height="1">
                                                <img src="images/void.gif" 
width="1" height="1" vspace="0" hspace="0" border="0"/>
                                        </td>
                                        <td bgcolor="#0086b2" height="1">
                                                <img src="images/void.gif" 
width="1" height="1" vspace="0" hspace="0" border="0"/>
                                        </td>
                                        <td bgcolor="#0086b2" width="1" 
height="1">
                                                <img src="images/void.gif" 
width="1" height="1" vspace="0" hspace="0" border="0"/>
                                        </td>
                                </tr>
                                <tr>
                                        <td bgcolor="#0086b2" width="1">
                                                <img src="images/void.gif" 
width="1" height="1" vspace="0" hspace="0" border="0"/>
                                        </td>
                                        <td bgcolor="#ffffff">
                                                <pre>
                                                        <xsl:apply-templates/>
                                                </pre>
                                        </td>
                                        <td bgcolor="#0086b2" width="1">
                                                <img src="images/void.gif" 
width="1" height="1" vspace="0" hspace="0" border="0"/>
                                        </td>
                                </tr>
                                <tr>
                                        <td bgcolor="#0086b2" width="1" 
height="1">
                                                <img src="images/void.gif" 
width="1" height="1" vspace="0" hspace="0" border="0"/>
                                        </td>
                                        <td bgcolor="#0086b2" height="1">
                                                <img src="images/void.gif" 
width="1" height="1" vspace="0" hspace="0" border="0"/>
                                        </td>
                                        <td bgcolor="#0086b2" width="1" 
height="1">
                                                <img src="images/void.gif" 
width="1" height="1" vspace="0" hspace="0" border="0"/>
                                        </td>
                                </tr>
                        </table>
                </div>
        </xsl:template>
        <xsl:template match="fixme">
                <!-- ignore on documentation -->
        </xsl:template>
        <!-- 
====================================================================== -->
        <!-- list section -->
        <!-- 
====================================================================== -->
        <xsl:template match="ul|ol">
                <blockquote>
                        <xsl:copy>
                                <xsl:apply-templates/>
                        </xsl:copy>
                </blockquote>
        </xsl:template>
        <xsl:template match="li">
                <xsl:copy><font face="verdana, helvetica, sans serif">
                        <xsl:apply-templates/>
                </font>
                  </xsl:copy>
          </xsl:template>
        <xsl:template match="sl">
                <ul>
                        <xsl:apply-templates/>
                </ul>
        </xsl:template>
          
          <xsl:template match="dl">
                <blockquote>
                <font face="verdana, helvetica, sans serif">
                  <dl>
                      <xsl:apply-templates/>
                  </dl>
                  </font>
                  </blockquote>
          </xsl:template>
          
          <xsl:template match="dt">
                  <dt>
                <strong>
                        <xsl:apply-templates/>
                </strong>
                <xsl:text> - </xsl:text>
                  </dt>
          </xsl:template>
          <xsl:template match="dd">
                  <dd>
                          <xsl:apply-templates/>
                  </dd>
          </xsl:template>
          
        <!-- 
====================================================================== -->
        <!-- table section -->
        <!-- 
====================================================================== -->
        <xsl:template match="table">
                <table width="100%" border="0" cellspacing="2" cellpadding="2">
                        <caption><font face="verdana,helvetica,sanserif">
                                <xsl:value-of select="caption"/>
                        </font></caption>
                        <xsl:apply-templates/>
                </table>
        </xsl:template>
        <xsl:template match="tr">
                <tr>
                        <xsl:apply-templates/>
                </tr>
        </xsl:template>
        <xsl:template match="th">
                <td bgcolor="#039acc" colspan="[EMAIL PROTECTED]" 
rowspan="[EMAIL PROTECTED]" valign="center" align="center">
                        <font color="white" size="-1" 
face="verdana,helvetica,sanserif">
                                <b>
                                        <xsl:apply-templates/>
                                </b>
                        </font>
                </td>
        </xsl:template>
        <xsl:template match="td">
                <td bgcolor="#a0ddf0" colspan="[EMAIL PROTECTED]" 
rowspan="[EMAIL PROTECTED]" valign="top" align="left">
                        <font color="black" size="-1" 
face="verdana,helvetica,sanserif">
                                <xsl:apply-templates/>
                        </font>
                </td>
        </xsl:template>
        <xsl:template match="tn">
                <td bgcolor="#ffffff" colspan="[EMAIL PROTECTED]" 
rowspan="[EMAIL PROTECTED]">&#160;</td>
        </xsl:template>
        <xsl:template match="caption">
                <!-- ignore since already used -->
        </xsl:template>
        <!-- 
====================================================================== -->
        <!-- markup section -->
        <!-- 
====================================================================== -->
        <xsl:template match="strong">
                <b>
                        <xsl:apply-templates/>
                </b>
        </xsl:template>
        <xsl:template match="em">
                <i>
                        <xsl:apply-templates/>
                </i>
        </xsl:template>
        <xsl:template match="code">
                <code>
                        <font face="courier, monospaced">
                                <xsl:apply-templates/>
                        </font>
                </code>
        </xsl:template>
        <!-- 
====================================================================== -->
        <!-- images section -->
        <!-- 
====================================================================== -->
        <xsl:template match="figure">
                <p align="center">
                        <xsl:choose>
                                <xsl:when test="string(@width) and 
string(@height)">
                                        <img src="[EMAIL PROTECTED]" 
alt="[EMAIL PROTECTED]" width="[EMAIL PROTECTED]" height="[EMAIL PROTECTED]" 
border="0" vspace="4" hspace="4"/>
                                </xsl:when>
                                <xsl:otherwise>
                                        <img src="[EMAIL PROTECTED]" 
alt="[EMAIL PROTECTED]" border="0" vspace="4" hspace="4"/>
                                </xsl:otherwise>
                        </xsl:choose>
                </p>
        </xsl:template>
        <xsl:template match="img">
                <img src="[EMAIL PROTECTED]" alt="[EMAIL PROTECTED]" border="0" 
vspace="4" hspace="4" align="right"/>
        </xsl:template>
        <xsl:template match="icon">
                <img src="[EMAIL PROTECTED]" alt="[EMAIL PROTECTED]" border="0" 
align="absmiddle"/>
        </xsl:template>
        <!-- 
====================================================================== -->
        <!-- links section -->
        <!-- 
====================================================================== -->
        <xsl:template match="link">
                <a href="[EMAIL PROTECTED]">
                        <xsl:apply-templates/>
                </a>
        </xsl:template>
        <xsl:template match="connect">
                <xsl:apply-templates/>
        </xsl:template>
        <xsl:template match="jump">
                <a href="[EMAIL PROTECTED]@anchor}">
                        <xsl:apply-templates/>
                </a>
        </xsl:template>
        <xsl:template match="fork">
                <a href="[EMAIL PROTECTED]" target="_blank">
                        <xsl:apply-templates/>
                </a>
        </xsl:template>
        <xsl:template match="anchor">
                <a name="[EMAIL PROTECTED]">
                        <xsl:comment>anchor</xsl:comment>
                </a>
        </xsl:template>
        <!-- 
====================================================================== -->
        <!-- specials section -->
        <!-- 
====================================================================== -->
        <xsl:template match="br">
                <br/>
        </xsl:template>
  </xsl:stylesheet>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/bookdemo/stylesheets/dotdots.xsl
  
  Index: dotdots.xsl
  ===================================================================
  <?xml version="1.0" encoding="utf-8"?>
  
  <!--
  Contains the 'dotdots' template, which, given a path, will output a set of
  directory traversals to get back to the source directory. Handles both '/' and
  '\' directory separators.
  
  Examples:
    Input                           Output 
      index.html                    ""
      dir/index.html                "../"
      dir/subdir/index.html         "../../"
      dir//index.html              "../"
      dir/                          "../"
      dir//                         "../"
      \some\windows\path            "../../"
      \some\windows\path\           "../../../"
      \Program Files\mydir          "../"
  
  Cannot handle ..'s in the path, so don't expect 'dir/subdir/../index.html' to
  work.
  
  [EMAIL PROTECTED]
  -->
  
  <xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  
    <xsl:template name="dotdots">
      <xsl:param name="path"/>
      <xsl:variable name="dirs" select="normalize-space(translate(concat($path, 
'x'), ' /\', '_  '))"/>
      <!-- The above does the following:
         o Adds a trailing character to the path. This prevents us having to 
deal
           with the special case of ending with '/'
         o Translates all directory separators to ' ', and normalize spaces,
                 cunningly eliminating duplicate '//'s. We also translate any 
real
                 spaces into _ to preserve them.
      -->
      <xsl:variable name="remainder" select="substring-after($dirs, ' ')"/>
      <xsl:if test="$remainder">
        <xsl:text>../</xsl:text>
        <xsl:call-template name="dotdots">
          <xsl:with-param name="path" select="translate($remainder, ' ', '/')"/>
                <!-- Translate back to /'s because that's what the template 
expects. -->
        </xsl:call-template>
      </xsl:if>
    </xsl:template>
  
  <!--
    Uncomment to test.
    Usage: saxon dotdots.xsl dotdots.xsl path='/my/test/path'
  
    <xsl:param name="path"/>
    <xsl:template match="/">
      <xsl:message>Path: <xsl:value-of select="$path"/></xsl:message>
      <xsl:call-template name="dotdots">
        <xsl:with-param name="path" select="$path"/>
      </xsl:call-template>
    </xsl:template>
   -->
  
  </xsl:stylesheet>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/bookdemo/stylesheets/relativize-linkmap.xsl
  
  Index: relativize-linkmap.xsl
  ===================================================================
  <?xml version="1.0"?>
  
  <!-- CVS: $Id: relativize-linkmap.xsl,v 1.1 2003/01/22 13:15:45 jefft Exp $ 
-->
  
  <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  
    <xsl:param name="path"/>
  
    <xsl:include href="dotdots.xsl"/>
  
    <!-- Path to site root, eg '../../' -->
    <xsl:variable name="root">
      <xsl:call-template name="dotdots">
        <xsl:with-param name="path" select="$path"/>
      </xsl:call-template>
    </xsl:variable>
  
    <xsl:template match="@href">
      <xsl:attribute name="href">
        <xsl:value-of select="$root"/><xsl:value-of select="."/>
      </xsl:attribute>
    </xsl:template>
  
    <xsl:template match="@*|node()" priority="-1">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:template>
  </xsl:stylesheet>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/bookdemo/stylesheets/simple-page2html.xsl
  
  Index: simple-page2html.xsl
  ===================================================================
  <?xml version="1.0"?>
  
  <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  
    <xsl:param name="view-source"/>
  
    <xsl:template match="page">
     <html>
      <head>
       <title>
        <xsl:value-of select="title"/>
       </title>
      </head>
      <body bgcolor="white" alink="red" link="blue" vlink="blue">
       <xsl:apply-templates/>
      </body>
     </html>
    </xsl:template>
  
    <xsl:template match="title">
     <h2 style="color: navy; text-align: center">
        <xsl:if test="not($view-source)">
           <xsl:apply-templates/>
        </xsl:if>     
        <xsl:if test="$view-source">
        <A>
           <xsl:attribute name="HREF">../view-source?filename=/<xsl:value-of 
select="$view-source"/></xsl:attribute>
                 <xsl:attribute name="TARGET">_blank</xsl:attribute>
           <xsl:apply-templates/>
        </A>
        </xsl:if>     
     </h2>
    </xsl:template>
  
    <xsl:template match="para">
     <p align="left">
      <i><xsl:apply-templates/></i>
     </p>
    </xsl:template>
  
  
    <xsl:template match="@*|node()" 
priority="-2"><xsl:copy><xsl:apply-templates 
select="@*|node()"/></xsl:copy></xsl:template>
    <xsl:template match="text()" priority="-1"><xsl:value-of 
select="."/></xsl:template>
  
  </xsl:stylesheet>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/bookdemo/stylesheets/simple-xml2html.xsl
  
  Index: simple-xml2html.xsl
  ===================================================================
  <!--
   |
   | XSLT REC Compliant Version of IE5 Default Stylesheet
   |
   | Original version by Jonathan Marsh ([EMAIL PROTECTED])
   | http://msdn.microsoft.com/xml/samples/defaultss/defaultss.xsl
   |
   | Conversion to XSLT 1.0 REC Syntax by Steve Muench ([EMAIL PROTECTED])
   | Added script support by Andrew Timberlake ([EMAIL PROTECTED])
   |
   +-->
  <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
     <xsl:output indent="no" method="html"/>
  
     <xsl:template match="/">
        <HTML>
           <HEAD>
              <SCRIPT>
                 <xsl:comment><![CDATA[
  //MSIE
  function f(e){
        if (e.className=="ci") {
                if (e.children(0).innerText.indexOf("\n")>0)
                        fix(e,"cb");
        }
        if (e.className=="di") {
                if (e.children(0).innerText.indexOf("\n")>0)
                        fix(e,"db");
        } e.id="";
  }
  function fix(e,cl){
        e.className=cl;
        e.style.display="block";
        j=e.parentElement.children(0);
        j.className="c";
        k=j.children(0);
        k.style.visibility="visible";
        k.href="#";
  }
  function ch(e) {
        mark=e.children(0).children(0);
        if (mark.innerText=="+") {
                mark.innerText="-";
                for (var i=1;i<e.children.length;i++) {
                        e.children(i).style.display="block";
                }
        }
        else if (mark.innerText=="-") {
                mark.innerText="+";
                for (var i=1;i<e.children.length;i++) {
                        e.children(i).style.display="none";
                }
        }
  }
  function ch2(e) {
        mark=e.children(0).children(0);
        contents=e.children(1);
        if (mark.innerText=="+") {
                mark.innerText="-";
                if (contents.className=="db"||contents.className=="cb") {
                        contents.style.display="block";
                }
                else {
                        contents.style.display="inline";
                }
        }
        else if (mark.innerText=="-") {
                mark.innerText="+";
                contents.style.display="none";
        }
  }
  function cl() {
        e=window.event.srcElement;
        if (e.className!="c") {
                e=e.parentElement;
                if (e.className!="c") {
                        return;
                }
        }
        e=e.parentElement;
        if (e.className=="e") {
                ch(e);
        }
        if (e.className=="k") {
                ch2(e);
        }
  }
  
  //mozilla
  function moz_f(){
        clean=document.getElementsByName('clean');
        for(i=0; i<clean.length;i++)
        {
                e = clean[i];
                if (e.className=="ci") {
                        if 
(e.childNodes[1].childNodes[0].nodeValue.indexOf("\n")>0)
                                moz_fix(e,"cb");
                }
                if (e.className=="di") {
                        if (e.childNodes[1].nodeValue.indexOf("\n")>0)
                                moz_fix(e,"db");
                }
        }
  }
  function moz_fix(e,cl){
        e.className=cl;
        e.style.display="block";
        j=e.parentNode.childNodes[1];
        j.className="c";
        k=j.childNodes[0];
        k.style.visibility="visible";
        k.href="#";
  }
  function moz_ch(e) {
        mark = e.childNodes[1].childNodes[1];
  
        if (mark.childNodes[0].nodeValue=="+") {
                mark.childNodes[0].nodeValue="-";
                for (var i=2;i<e.childNodes.length;i++) {
                        if(e.childNodes[i].nodeName != "#text")
                                e.childNodes[i].style.display="block";
                }
        }
        else if (mark.childNodes[0].nodeValue=="-") {
                mark.childNodes[0].nodeValue="+";
                for (var i=2;i<e.childNodes.length;i++) {
                        if(e.childNodes[i].nodeName != "#text")
                                e.childNodes[i].style.display="none";
                }
        }
  }
  function moz_ch2(e) {
        mark = e.childNodes[1].childNodes[0];
        contents=e.childNodes[2];
        if (mark.childNodes[0].nodeValue=="+") {
                mark.childNodes[0].nodeValue="-";
                if (contents.className=="db"||contents.className=="cb") {
                        contents.style.display="block";
                }
                else {
                        contents.style.display="inline";
                }
        }
        else if (mark.childNodes[0].nodeValue=="-") {
                mark.childNodes[0].nodeValue="+";
                contents.style.display="none";
        }
  }
  
  function moz_cl(evnt) {
        e=evnt.target.parentNode;
  
        if (e.className != "c") {
                e=e.parentNode
                if (e.className!="c") {
                        return;
                }
        }
        e=e.parentNode
        if (e.className=="e") {
                moz_ch(e);
        }
        if (e.className=="k") {
                moz_ch2(e);
        }
  }
  
  function ex(){}
  function h(){window.status=" ";}
  if(document.all)
        document.onclick=cl;
  else if(document.getElementById)
        document.onclick=moz_cl;
  ]]>
                </xsl:comment>
              </SCRIPT>
              <STYLE>
                BODY {font:x-small 'Verdana'; margin-right:1.5em}
                  .c  {cursor:hand}
                  .b  {color:red; font-family:'Courier New'; font-weight:bold;
                       text-decoration:none}
                  .e  {margin-left:1em; text-indent:-1em; margin-right:1em}
                  .k  {margin-left:1em; text-indent:-1em; margin-right:1em}
                  .t  {color:#990000}
                  .xt {color:#990099}
                  .ns {color:red}
                  .dt {color:green}
                  .m  {color:blue}
                  .tx {font-weight:bold}
                  .db {text-indent:0px; margin-left:1em; margin-top:0px;
                       margin-bottom:0px;padding-left:.3em;
                       border-left:1px solid #CCCCCC; font:small Courier}
                  .di {font:small Courier}
                  .d  {color:blue}
                  .pi {color:blue}
                  .cb {text-indent:0px; margin-left:1em; margin-top:0px;
                       margin-bottom:0px;padding-left:.3em; font:small Courier;
                       color:#888888}
                  .ci {font:small Courier; color:#888888}
                  PRE {margin:0px; display:inline}
             </STYLE>
           </HEAD>
           <BODY class="st">
                         <xsl:attribute 
name="onload"><![CDATA[if(document.getElementsByName && 
!document.all){moz_f();}]]></xsl:attribute>
              <xsl:apply-templates/>
           </BODY>
        </HTML>
     </xsl:template>
  
     <xsl:template match="processing-instruction()">
        <DIV class="e">
           <SPAN class="b">
                        <xsl:call-template name="nbsp-ref"/>
           </SPAN>
           <SPAN class="m">
              <xsl:text>&lt;?</xsl:text>
           </SPAN>
           <SPAN class="pi">
              <xsl:value-of select="name(.)"/>
              <xsl:value-of select="."/>
           </SPAN>
           <SPAN class="m">
              <xsl:text>?></xsl:text>
           </SPAN>
        </DIV>
     </xsl:template>
  
     <xsl:template match="processing-instruction('xml')">
        <DIV class="e">
           <SPAN class="b">
              <xsl:call-template name="nbsp-ref"/>
           </SPAN>
           <SPAN class="m">
              <xsl:text>&lt;?</xsl:text>
           </SPAN>
           <SPAN class="pi">
              <xsl:text>xml </xsl:text>
              <xsl:for-each select="@*">
                 <xsl:value-of select="name(.)"/>
                 <xsl:text>="</xsl:text>
                 <xsl:value-of select="."/>
                 <xsl:text>" </xsl:text>
              </xsl:for-each>
           </SPAN>
           <SPAN class="m">
              <xsl:text>?></xsl:text>
           </SPAN>
        </DIV>
     </xsl:template>
  
     <xsl:template match="@*">
        <SPAN>
           <xsl:attribute name="class">
              <xsl:if test="xsl:*/@*">
                <xsl:text>x</xsl:text>
              </xsl:if>
              <xsl:text>t</xsl:text>
           </xsl:attribute>
           <xsl:value-of select="name(.)"/>
        </SPAN>
        <SPAN class="m">="</SPAN>
        <B>
           <xsl:value-of select="."/>
        </B>
        <SPAN class="m">"</SPAN>
        <xsl:if test="position()!=last()">
           <xsl:text> </xsl:text>
        </xsl:if>
     </xsl:template>
  
     <xsl:template match="text()">
        <DIV class="e">
           <SPAN class="b"> </SPAN>
           <SPAN class="tx">
              <xsl:value-of select="."/>
           </SPAN>
        </DIV>
     </xsl:template>
  
     <xsl:template match="comment()">
        <DIV class="k">
           <SPAN>
              <A STYLE="visibility:hidden" class="b" onclick="return false" 
onfocus="h()">-</A>
              <SPAN class="m">
                 <xsl:text>&lt;!--</xsl:text>
              </SPAN>
           </SPAN>
           <SPAN class="ci" id="clean">
              <PRE>
                 <xsl:value-of select="."/>
              </PRE>
           </SPAN>
           <SPAN class="b">
              <xsl:call-template name="nbsp-ref"/>
           </SPAN>
           <SPAN class="m">
              <xsl:text>--></xsl:text>
           </SPAN>
           <SCRIPT>if(document.all)f(clean);</SCRIPT>
        </DIV>
     </xsl:template>
  
     <xsl:template match="*">
        <DIV class="e">
           <DIV STYLE="margin-left:1em;text-indent:-2em">
              <SPAN class="b">
                        <xsl:call-template name="nbsp-ref"/>
              </SPAN>
              <SPAN class="m">&lt;</SPAN>
              <SPAN>
                 <xsl:attribute name="class">
                    <xsl:if test="xsl:*">
                       <xsl:text>x</xsl:text>
                    </xsl:if>
                    <xsl:text>t</xsl:text>
                 </xsl:attribute>
                 <xsl:value-of select="name(.)"/>
                 <xsl:if test="@*">
                    <xsl:text> </xsl:text>
                 </xsl:if>
              </SPAN>
              <xsl:apply-templates select="@*"/>
              <SPAN class="m">
                 <xsl:text>/></xsl:text>
              </SPAN>
           </DIV>
        </DIV>
     </xsl:template>
  
     <xsl:template match="*[node()]">
        <DIV class="e">
           <DIV class="c">
              <A class="b" href="#" onclick="return false" onfocus="h()">-</A>
              <SPAN class="m">&lt;</SPAN>
              <SPAN>
                 <xsl:attribute name="class">
                    <xsl:if test="xsl:*">
                       <xsl:text>x</xsl:text>
                    </xsl:if>
                    <xsl:text>t</xsl:text>
                 </xsl:attribute>
                 <xsl:value-of select="name(.)"/>
                 <xsl:if test="@*">
                    <xsl:text> </xsl:text>
                 </xsl:if>
              </SPAN>
              <xsl:apply-templates select="@*"/>
              <SPAN class="m">
                 <xsl:text>></xsl:text>
              </SPAN>
           </DIV>
           <DIV>
              <xsl:apply-templates/>
              <DIV>
                 <SPAN class="b">
                                <xsl:call-template name="nbsp-ref"/>
                 </SPAN>
                 <SPAN class="m">
                    <xsl:text>&lt;/</xsl:text>
                 </SPAN>
                 <SPAN>
                    <xsl:attribute name="class">
                       <xsl:if test="xsl:*">
                          <xsl:text>x</xsl:text>
                       </xsl:if>
                       <xsl:text>t</xsl:text>
                    </xsl:attribute>
                    <xsl:value-of select="name(.)"/>
                 </SPAN>
                 <SPAN class="m">
                    <xsl:text>></xsl:text>
                 </SPAN>
              </DIV>
           </DIV>
        </DIV>
     </xsl:template>
  
     <xsl:template match="*[text() and not (comment() or 
processing-instruction())]">
        <DIV class="e">
           <DIV STYLE="margin-left:1em;text-indent:-2em">
              <SPAN class="b">
                        <xsl:call-template name="nbsp-ref"/>
              </SPAN>
              <SPAN class="m">
                 <xsl:text>&lt;</xsl:text>
              </SPAN>
              <SPAN>
                 <xsl:attribute name="class">
                    <xsl:if test="xsl:*">
                       <xsl:text>x</xsl:text>
                    </xsl:if>
                    <xsl:text>t</xsl:text>
                 </xsl:attribute>
                 <xsl:value-of select="name(.)"/>
                 <xsl:if test="@*">
                    <xsl:text> </xsl:text>
                 </xsl:if>
              </SPAN>
              <xsl:apply-templates select="@*"/>
              <SPAN class="m">
                 <xsl:text>></xsl:text>
              </SPAN>
              <SPAN class="tx">
                 <xsl:value-of select="."/>
              </SPAN>
              <SPAN class="m">&lt;/</SPAN>
              <SPAN>
                 <xsl:attribute name="class">
                    <xsl:if test="xsl:*">
                       <xsl:text>x</xsl:text>
                    </xsl:if>
                    <xsl:text>t</xsl:text>
                 </xsl:attribute>
                 <xsl:value-of select="name(.)"/>
              </SPAN>
              <SPAN class="m">
                 <xsl:text>></xsl:text>
              </SPAN>
           </DIV>
        </DIV>
     </xsl:template>
  
     <xsl:template match="*[*]" priority="20">
        <DIV class="e">
           <DIV STYLE="margin-left:1em;text-indent:-2em" class="c">
              <A class="b" href="#" onclick="return false" onfocus="h()">-</A>
              <SPAN class="m">&lt;</SPAN>
              <SPAN>
                 <xsl:attribute name="class">
                    <xsl:if test="xsl:*">
                       <xsl:text>x</xsl:text>
                    </xsl:if>
                    <xsl:text>t</xsl:text>
                 </xsl:attribute>
                 <xsl:value-of select="name(.)"/>
                 <xsl:if test="@*">
                    <xsl:text> </xsl:text>
                 </xsl:if>
              </SPAN>
              <xsl:apply-templates select="@*"/>
              <SPAN class="m">
                 <xsl:text>></xsl:text>
              </SPAN>
           </DIV>
           <DIV>
              <xsl:apply-templates/>
              <DIV>
                 <SPAN class="b">
                                <xsl:call-template name="nbsp-ref"/>
                 </SPAN>
                 <SPAN class="m">
                    <xsl:text>&lt;/</xsl:text>
                 </SPAN>
                 <SPAN>
                    <xsl:attribute name="class">
                       <xsl:if test="xsl:*">
                          <xsl:text>x</xsl:text>
                       </xsl:if>
                       <xsl:text>t</xsl:text>
                    </xsl:attribute>
                    <xsl:value-of select="name(.)"/>
                 </SPAN>
                 <SPAN class="m">
                    <xsl:text>></xsl:text>
                 </SPAN>
              </DIV>
           </DIV>
        </DIV>
     </xsl:template>
  
     <xsl:template name="nbsp-ref">
        <xsl:text>&#160;</xsl:text>
     </xsl:template>
  
  </xsl:stylesheet>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/sitedemo/README.txt
  
  Index: README.txt
  ===================================================================
  This LinkRewriterTransformer demo is what I used for primary testing.  It
  implements a 'linkmap' as described in this Forrest RT:
  
  http://marc.theaimsgroup.com/?l=forrest-dev&m=103444028129281&w=2
  
  Specifically, the file linkmap.xml is first absolutized, then relativized, 
then
  used to resolve links like <link href="site:index">.
  
  To install:
  
  1) run 'build.sh -Dinclude.webapp.libs=yes webapp-local'
  2) copy this directory into build/cocoon/webapp/samples/
  3) Edit build/cocoon/webapp/WEB-INF/cocoon.xconf, and add the following 
section
  inside /cocoon/input-modules:
  
  
        <component-instance
          class="org.apache.cocoon.components.modules.input.XMLFileModule"
          logger="core.modules.xml" name="linkmap">
          <file src="cocoon://samples/link/linkmap"/>
          <!-- Shouldn't this be the default? -->
          <reloadable>true</reloadable>
        </component-instance>
         <component-instance
           
class="org.apache.cocoon.components.modules.input.SimpleMappingMetaModule"
           logger="core.modules.mapper" name="site">
           <input-module name="linkmap"/>
           <prefix>/site/</prefix>
           <suffix>/@href</suffix>
         </component-instance>
  
  
  4) Restart your webserver, and request 
http://localhost:8080/cocoon/samples/linkrewriter-sitedemo/welcome
  
  You ought to get the following XML back:
  
  <samples>
    <group name="Raw XML containing hopefully-rewritten links">
      <sample name="Back" href="..">
  
        linkmap:/site/index/@href 
        <link href="index.html"/>
  
        site:index 
        <link href="index.html"/>
  
        site:faq/how_can_I_help 
        <link href="faq.html#how_can_I_help"/>
      </sample>
    </group>
  </samples>
  
  
  The href's are the things that were rewritten.
  
  Then add an arbitrary path before the /welcome, eg
  http://localhost:8080/cocoon/samples/linkrewriter-sitedemo/foo/bar/welcome
  You should get back 'relativized' links:
  
  <samples>
    <group name="Raw XML containing hopefully-rewritten links">
      <sample name="Back" href="..">
  
        linkmap:/site/index/@href 
        <link href="index.html"/>
  
        site:index 
        <link href="../../index.html"/>
  
        site:faq/how_can_I_help 
        <link href="../../faq.html#how_can_I_help"/>
      </sample>
    </group>
  </samples>
  
  
  Change the @src in line 14 to '{src}' to make the first one also be relative.
  
  
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/sitedemo/linkmap.xml
  
  Index: linkmap.xml
  ===================================================================
  <site href="">
    <index href="index.html"/>
    <dreams href="dreams.html"/>
    <faq href="faq.html">
      <how_can_I_help href="#how_can_I_help"/>
      <building_own_website href="#own_website"/>
      <building_fails_on_subsequent_builds href="#building_fails"/>
    </faq>
    <primer href="primer.html"/>
    <your-project href="your-project.html"/>
    <contrib href="contrib.html"/>
    <who href="who.html"/>
    <libre-intro href="libre-intro.html"/>
    <community href="community/">
      <howto href="howto/">
        <index href="index.html"/>
        <cvs-ssh href="cvs-ssh/">
          <howto-cvs-ssh href="howto-cvs-ssh.html"/>
        </cvs-ssh>
      </howto>
    </community>
  </site>
  
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/sitedemo/sitemap.xmap
  
  Index: sitemap.xmap
  ===================================================================
  <?xml version="1.0"?>
  
  <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0";>
  
  <!-- =========================== Components ================================ 
-->
  
   <map:components>
    <map:generators default="file"/>
    <map:transformers default="xslt">
      <map:transformer name="linkrewriter"
        src="org.apache.cocoon.transformation.LinkRewriterTransformer">
        <input-module name="linkmap" 
src="cocoon://samples/linkrewriter/sitedemo/linkmap" reloadable="true"/>
        <input-module name="site">
          <input-module name="linkmap" src="{src}" reloadable="true"/>
          <prefix>/site/</prefix>
          <suffix>/@href</suffix>
        </input-module>
      </map:transformer>
    </map:transformers>
    <map:readers default="resource"/>
    <map:serializers default="html"/>
    <map:matchers default="wildcard"/>
    <map:selectors default="browser"/>
   </map:components>
  
  <!-- =========================== Pipelines ================================= 
-->
  
   <map:pipelines>
     <map:pipeline>
  
       <map:match pattern="">
         <map:redirect-to uri="welcome"/>
       </map:match>
  
       <map:match pattern="**welcome">
         <map:generate src="docs/index.xml"/>
         <!-- Uses {src} and {prefix} var interpolation -->
         <map:transform type="linkrewriter" src="cocoon:/{1}linkmap">
           <map:parameter name="prefix" value="/site/"/>
         </map:transform>
         <map:serialize type="xml"/>
       </map:match>
  
       <map:match pattern="abs-linkmap">
         <map:generate src="linkmap.xml"/>
         <map:transform src="stylesheets/absolutize-linkmap.xsl"/>
         <map:serialize type="xml"/>
       </map:match>
  
       <map:match pattern="**linkmap">
         <map:generate src="linkmap.xml"/>
         <map:transform src="stylesheets/absolutize-linkmap.xsl"/>
         <map:transform src="stylesheets/relativize-linkmap.xsl">
           <map:parameter name="path" value="{0}"/>
         </map:transform>
         <map:serialize type="xml"/>
       </map:match>
  
     </map:pipeline>
   </map:pipelines>
  
  </map:sitemap>
  
  <!-- end of file -->
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/sitedemo/docs/index.xml
  
  Index: index.xml
  ===================================================================
  <?xml version="1.0" encoding="iso-8859-1"?>
  
  <samples xmlns:xlink="http://www.w3.org/1999/xlink";>
  
    <group name="Raw XML containing hopefully-rewritten links">
      <sample name="Back" href="..">
  
       linkmap:/site/index/@href <link href="linkmap:/site/index/@href"/>
  
       site:index <link href="site:index"/>
  
       site:faq/how_can_I_help <link href="site:faq/how_can_I_help"/>
     </sample>
    </group>
  </samples>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/sitedemo/stylesheets/absolutize-linkmap.xsl
  
  Index: absolutize-linkmap.xsl
  ===================================================================
  <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  
  <xsl:template name="abs">
    <xsl:param name="node"/>
    <xsl:if test="$node/..">
      <xsl:call-template name="abs">
        <xsl:with-param name="node" select="$node/.."/>
      </xsl:call-template>
    </xsl:if>
    <xsl:value-of select="$node/@href"/>
  
  </xsl:template>
  
  <xsl:template match="@href">
    <xsl:attribute name="href">
    <xsl:call-template name="abs">
      <xsl:with-param name="node" select=".."/>
    </xsl:call-template>
    </xsl:attribute>
  </xsl:template>
  
  <xsl:template match="@*|node()" priority="-1">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>
  </xsl:stylesheet>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/sitedemo/stylesheets/dotdots.xsl
  
  Index: dotdots.xsl
  ===================================================================
  <?xml version="1.0" encoding="utf-8"?>
  
  <!--
  Contains the 'dotdots' template, which, given a path, will output a set of
  directory traversals to get back to the source directory. Handles both '/' and
  '\' directory separators.
  
  Examples:
    Input                           Output 
      index.html                    ""
      dir/index.html                "../"
      dir/subdir/index.html         "../../"
      dir//index.html              "../"
      dir/                          "../"
      dir//                         "../"
      \some\windows\path            "../../"
      \some\windows\path\           "../../../"
      \Program Files\mydir          "../"
  
  Cannot handle ..'s in the path, so don't expect 'dir/subdir/../index.html' to
  work.
  
  [EMAIL PROTECTED]
  -->
  
  <xsl:stylesheet
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  
    <xsl:template name="dotdots">
      <xsl:param name="path"/>
      <xsl:variable name="dirs" select="normalize-space(translate(concat($path, 
'x'), ' /\', '_  '))"/>
      <!-- The above does the following:
         o Adds a trailing character to the path. This prevents us having to 
deal
           with the special case of ending with '/'
         o Translates all directory separators to ' ', and normalize spaces,
                 cunningly eliminating duplicate '//'s. We also translate any 
real
                 spaces into _ to preserve them.
      -->
      <xsl:variable name="remainder" select="substring-after($dirs, ' ')"/>
      <xsl:if test="$remainder">
        <xsl:text>../</xsl:text>
        <xsl:call-template name="dotdots">
          <xsl:with-param name="path" select="translate($remainder, ' ', '/')"/>
                <!-- Translate back to /'s because that's what the template 
expects. -->
        </xsl:call-template>
      </xsl:if>
    </xsl:template>
  
  <!--
    Uncomment to test.
    Usage: saxon dotdots.xsl dotdots.xsl path='/my/test/path'
  
    <xsl:param name="path"/>
    <xsl:template match="/">
      <xsl:message>Path: <xsl:value-of select="$path"/></xsl:message>
      <xsl:call-template name="dotdots">
        <xsl:with-param name="path" select="$path"/>
      </xsl:call-template>
    </xsl:template>
   -->
  
  </xsl:stylesheet>
  
  
  
  1.1                  
xml-cocoon2/src/blocks/linkrewriter/samples/sitedemo/stylesheets/relativize-linkmap.xsl
  
  Index: relativize-linkmap.xsl
  ===================================================================
  <?xml version="1.0"?>
  
  <!-- CVS: $Id: relativize-linkmap.xsl,v 1.1 2003/01/22 13:15:45 jefft Exp $ 
-->
  
  <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
  
    <xsl:param name="path"/>
  
    <xsl:include href="dotdots.xsl"/>
  
    <!-- Path to site root, eg '../../' -->
    <xsl:variable name="root">
      <xsl:call-template name="dotdots">
        <xsl:with-param name="path" select="$path"/>
      </xsl:call-template>
    </xsl:variable>
  
    <xsl:template match="@href">
      <xsl:attribute name="href">
        <xsl:value-of select="$root"/><xsl:value-of select="."/>
      </xsl:attribute>
    </xsl:template>
  
    <xsl:template match="@*|node()" priority="-1">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:template>
  </xsl:stylesheet>
  
  
  
  1.19      +0 -16     
xml-cocoon2/src/java/org/apache/cocoon/components/modules/modules.xconf
  
  Index: modules.xconf
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/modules/modules.xconf,v
  retrieving revision 1.18
  retrieving revision 1.19
  diff -u -r1.18 -r1.19
  --- modules.xconf     19 Jan 2003 03:21:09 -0000      1.18
  +++ modules.xconf     22 Jan 2003 13:15:46 -0000      1.19
  @@ -46,22 +46,6 @@
         <file src="http://slashdot.org/slashdot.rss"/>
       </component-instance>
   
  -    <!-- LinkRewritingTransformer Sample -->
  -    <component-instance
  -      class="org.apache.cocoon.components.modules.input.XMLFileModule"
  -      logger="core.modules.xml" name="linkmap">
  -      <file src="cocoon://samples/link/linkmap"/>
  -      <!-- Shouldn't this be the default? -->
  -      <reloadable>true</reloadable>
  -    </component-instance>
  -    <component-instance
  -      
class="org.apache.cocoon.components.modules.input.SimpleMappingMetaModule"
  -      logger="core.modules.mapper" name="site">
  -      <input-module name="linkmap"/>
  -      <prefix>/site/</prefix>
  -      <suffix>/@href</suffix>
  -    </component-instance>
  -    <!-- end LinkRewritingTransformer Sample -->
     </input-modules>
   
     <output-modules>
  
  
  

----------------------------------------------------------------------
In case of troubles, e-mail:     [EMAIL PROTECTED]
To unsubscribe, e-mail:          [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to