gianugo     02/02/03 08:50:35

  Added:       src/scratchpad/src/org/apache/cocoon/generation
                        XPathDirectoryGenerator.java
  Log:
  Added the new XPath enabled DirectoryGenerator to the scratchpad
  
  Revision  Changes    Path
  1.1                  
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/generation/XPathDirectoryGenerator.java
  
  Index: XPathDirectoryGenerator.java
  ===================================================================
  /*****************************************************************************
   * Copyright (C) The Apache Software Foundation. All rights reserved.        *
   * ------------------------------------------------------------------------- *
   * This software is published under the terms of the Apache Software License *
   * version 1.1, a copy of which has been included  with this distribution in *
   * the LICENSE file.                                                         *
   *****************************************************************************/
  
  package org.apache.cocoon.generation;
  
  import org.apache.avalon.excalibur.pool.Recyclable;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.avalon.excalibur.xml.xpath.XPathProcessor;
  
  import org.apache.cocoon.ProcessingException;
  import org.apache.cocoon.ResourceNotFoundException;
  import org.apache.cocoon.components.parser.Parser;
  import org.apache.cocoon.environment.Source;
  import org.apache.cocoon.environment.SourceResolver;
  
  import org.apache.cocoon.xml.dom.DOMStreamer;
  import org.apache.regexp.RE;
  import org.apache.regexp.RESyntaxException;
  
  import org.w3c.dom.Document;
  import org.w3c.dom.NodeList;
  import org.xml.sax.InputSource;
  import org.xml.sax.SAXException;
  import org.xml.sax.helpers.AttributesImpl;
  
  import java.io.File;
  import java.io.IOException;
  import java.net.URL;
  import java.text.SimpleDateFormat;
  import java.util.Date;
  import java.util.Map;
  import java.util.Stack;
  
  
  /**
   * Generates an XML directory listing performing XPath queries
   * on XML files. It can be used both as a plain DirectoryGenerator
   * or, using an "xpointerinsh" syntax it will perform an XPath
   * query on every XML resource.
   *
   * Sample usage:
   *
   * Sitemap: 
   * <map:match pattern="documents/**">
   *   <map:generate type="xpathdirectory" 
   *     src="docs/{1}#/article/title|/article/abstract" />
   *   <map:serialize type="xml" />
   * </map:match>  
   * 
   * Request:
   *   http://www.some.host/documents/test
  
   * Result:
   * <dir:directory 
   *   name="test" lastModified="1010400942000" 
   *   date="1/7/02 11:55 AM" requested="true" 
   *   xmlns:dir="http://apache.org/cocoon/directory/2.0">
   *   <dir:directory name="subdirectory" lastModified="1010400942000" date="1/7/02 
11:55 AM" /> 
   *   <dir:file name="test.xml" lastModified="1011011579000" date="1/14/02 1:32 
PM">
   *     <dir:xpath docid="test.xml" query="/article/title">
   *       <title>This is a test document</title> 
   *       <abstract>
   *         <para>Abstract of my test article</para> 
   *       </abstract>
   *     </dir:xpath>
   *   </dir:file>
   *   <dir:file name="test.gif" lastModified="1011011579000" date="1/14/02 1:32 
PM">
   * </dir:directory>
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Gianugo Rabellino</a>
   * @version CVS $Id: XPathDirectoryGenerator.java,v 1.1 2002/02/03 16:50:35 gianugo 
Exp $ 
   */
  
  public class XPathDirectoryGenerator extends DirectoryGenerator {
  
      /** Element &lt;result&gt; */
      protected static final String RESULT = "xpath";
      protected static final String QRESULT = PREFIX + ":" + RESULT;
      protected static final String RESULT_DOCID_ATTR = "docid";
      protected static final String QUERY_ATTR = "query";
  
      protected static final String CDATA  = "CDATA";
      protected String XPathQuery = null;
      protected XPathProcessor processor = null;
      protected Parser parser;
      protected Document doc;
  
      public void setup(SourceResolver resolver, Map objectModel, String src, 
Parameters par)
          throws ProcessingException, SAXException, IOException {
  
          super.setup(resolver, objectModel, src, par);
  
          // See if an XPath was specified
  
          int pointer;
  
          if ((pointer = this.source.indexOf("#")) != -1) {
            this.XPathQuery = source.substring(pointer + 1);
            this.source = source.substring(0, pointer);
            if (this.getLogger().isDebugEnabled())
              this.getLogger().debug("Applying XPath: " + XPathQuery 
                + " to directory " + source);
          }
  
      }
  
      public void compose(ComponentManager manager) {
        try {
          super.compose(manager);
          processor = (XPathProcessor)manager.lookup(XPathProcessor.ROLE);
          parser = (Parser)manager.lookup(Parser.ROLE);
        } catch (Exception e) {
          this.getLogger().error("Could not obtain a required component", e);
        }
      }  
        
  
      /**
       * Adds a single node to the generated document. If the path is a
       * directory, and depth is greater than zero, then recursive calls
       * are made to add nodes for the directory's children. Moreover,
       * if the file is an XML file (ends with .xml), the XPath query
       * is performed and results returned.
       *
       * @param   path
       *      the file/directory to process
       * @param   depth
       *      how deep to scan the directory
       *
       * @throws  SAXException
       *      if an error occurs while constructing nodes
       */
      protected void addPath(File path, int depth)
      throws SAXException {
          if (path.isDirectory()) {
              startNode(DIR_NODE_NAME, path);
              if (depth>0) {
                  File contents[] = path.listFiles();
                  for (int i=0; i<contents.length; i++) {
                      if (isIncluded(contents[i]) && !isExcluded(contents[i])) {
                          addPath(contents[i], depth-1);
                      }
                  }
              }
              endNode(DIR_NODE_NAME);
          } else {
              if (isIncluded(path) && !isExcluded(path)) {
                  startNode(FILE_NODE_NAME, path);
                  if (path.getName().endsWith(".xml") && XPathQuery != null)
                    performXPathQuery(path);
                  endNode(FILE_NODE_NAME);
              }
          }
      }
  
      protected void performXPathQuery(File in) 
        throws SAXException {
         
        doc = null;
        try {
          doc = parser.parseDocument(
                  resolver.resolve(in.toURL().toExternalForm()).getInputSource());  
         } catch (SAXException se) {
           this.getLogger().error("Warning:" + in.getName() 
            + " is not a valid XML file. Ignoring");
         } catch (Exception e) {
           this.getLogger().error("Unable to resolve and parse file" + e);
         }
  
         if (doc != null) {
           NodeList nl = processor.selectNodeList(doc.getDocumentElement(), 
XPathQuery);
          
           final String id = in.getName();
           
           AttributesImpl attributes = new AttributesImpl();
           attributes.addAttribute("", RESULT_DOCID_ATTR, RESULT_DOCID_ATTR,
             CDATA, id);
           attributes.addAttribute("", QUERY_ATTR, QUERY_ATTR, CDATA, 
             XPathQuery);  
      
           super.contentHandler.startElement(URI, RESULT, QRESULT, attributes);
           DOMStreamer ds = new DOMStreamer(super.xmlConsumer);
           for (int i = 0; i < nl.getLength(); i++)
             ds.stream(nl.item(i));
           super.contentHandler.endElement(URI, RESULT, QRESULT);
        } 
        }  
        
        /**
         * Recycle resources
         * 
         */
        
     public void recycle() {
        super.recycle(); 
        this.XPathQuery = null;
        this.attributes = null;
        this.doc = null;
      }
  }
  
  
  

----------------------------------------------------------------------
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