gianugo     01/12/09 09:05:22

  Added:       src/org/apache/cocoon/components/source
                        AbstractSAXSource.java XMLDBSource.java
                        XMLDBSourceFactory.java
  Log:
  Added the XML:DB pseudo-protocol.
  
  Revision  Changes    Path
  1.1                  
xml-cocoon2/src/org/apache/cocoon/components/source/AbstractSAXSource.java
  
  Index: AbstractSAXSource.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.components.source;
  
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.cocoon.ProcessingException;
  import org.apache.cocoon.ResourceNotFoundException;
  import org.apache.cocoon.environment.Environment;
  import org.apache.cocoon.environment.Source;
  import org.apache.cocoon.environment.ModifiableSource;
  import org.apache.cocoon.serialization.Serializer;
  import org.apache.cocoon.sitemap.SitemapComponentSelector;
  import org.apache.log.Logger;
  
  import org.xmldb.api.DatabaseManager;   
  import org.xmldb.api.base.Collection;   
  import org.xmldb.api.base.Database;   
  import org.xmldb.api.base.ErrorCodes;   
  import org.xmldb.api.base.Resource;   
  import org.xmldb.api.base.Service;   
  import org.xmldb.api.base.XMLDBException;   
  import org.xmldb.api.modules.XMLResource; 
  
  import org.xml.sax.InputSource;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.SAXException;
  import org.xml.sax.helpers.AttributesImpl;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.ByteArrayInputStream;
  import java.net.MalformedURLException;
  import java.net.URL;
  
  /**
   * This abstract class provides convenience methods to implement
   * a SAX based Source. Implement toSAX() and getSystemId() and
   * optionally override getLastModified() and getContentLength() to
   * obtain a valid Source implementation.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Gianugo Rabellino</a>
   */
  
  public abstract class AbstractSAXSource
    implements Source {
  
      /** The Logger instance */
      protected Logger log;
  
      /** The ComponentManager instance */
      protected ComponentManager manager;
  
      /**
       * The constructor.
       * 
       * @param environment the Cocoon Environment.
       * @param manager an Avalon Component Manager
       * @param logger A LogKit logger
       */
      
      public AbstractSAXSource(Environment environment, 
                         ComponentManager manager,
                         Logger logger) {
        this.log = logger;
        this.manager = manager;
  
      }
  
      /**
       * Get an InputSource for the given URL. Shamelessly stolen
       * from SitemapSource.
       *
       */
      
      public InputStream getInputStream() 
        throws ProcessingException, IOException {
  
          SitemapComponentSelector serializerSelector = null;
          Serializer serializer = null;
          try {
  
              serializerSelector = (SitemapComponentSelector) 
this.manager.lookup(Serializer.ROLE + "Selector");
              serializer = (Serializer)serializerSelector.select("xml");
              ByteArrayOutputStream os = new ByteArrayOutputStream();
              serializer.setOutputStream(os);
  
              this.toSAX(serializer);
  
              return new ByteArrayInputStream(os.toByteArray());
          } catch (ComponentException cme) {
              throw new ProcessingException("could not lookup pipeline components", 
cme);
          } catch (ProcessingException e) {
              throw e;
          } catch (Exception e) {
              throw new ProcessingException("Exception during processing of " + 
this.getSystemId(), e);
          } finally {
              if (serializer != null) serializerSelector.release(serializer);
              if (serializerSelector != null) this.manager.release(serializerSelector);
          }
      } 
  
      /**
       * Get an InputSource for the given URL.
       *
       */
  
      public InputSource getInputSource()
        throws ProcessingException, IOException {
        InputSource is = new InputSource(this.getInputStream());
        is.setSystemId(this.getSystemId());
  
        return is;
      }  
  
      /**
       * Implement this method to obtain SAX events.
       *
       */
  
      public abstract void toSAX(ContentHandler handler) 
        throws SAXException, ProcessingException; 
  
      /**
       * Implement this method to set the unique identifier. 
       *
       */
  
      public abstract String getSystemId();
  
      /**
       * Override this method to set the Content Length
       *
       */
  
      public long getContentLength() {
        return 0;
      }
  
      /**
       * Override this method to set the Last Modification date
       *
       */
  
      public long getLastModified() {
        return -1;
      }
  
  
  }
  
  
  
  1.1                  
xml-cocoon2/src/org/apache/cocoon/components/source/XMLDBSource.java
  
  Index: XMLDBSource.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.components.source;
  
  import org.apache.avalon.framework.component.ComponentException;
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.cocoon.ProcessingException;
  import org.apache.cocoon.ResourceNotFoundException;
  import org.apache.cocoon.environment.Environment;
  import org.apache.cocoon.environment.Source;
  import org.apache.cocoon.environment.ModifiableSource;
  import org.apache.cocoon.serialization.Serializer;
  import org.apache.cocoon.sitemap.SitemapComponentSelector;
  import org.apache.log.Logger;
  
  import org.xmldb.api.DatabaseManager;   
  import org.xmldb.api.base.Collection;   
  import org.xmldb.api.base.Database;   
  import org.xmldb.api.base.ErrorCodes;   
  import org.xmldb.api.base.Resource;   
  import org.xmldb.api.base.Service;   
  import org.xmldb.api.base.XMLDBException;   
  import org.xmldb.api.modules.XMLResource; 
  
  import org.xml.sax.InputSource;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.SAXException;
  import org.xml.sax.helpers.AttributesImpl;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.ByteArrayInputStream;
  import java.net.MalformedURLException;
  import java.net.URL;
  
  /**
   * This class implements the xmldb:// pseudo-protocol and allows to get XML
   * content from an XML:DB enabled XML database.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Gianugo Rabellino</a>
   */
  
  public class XMLDBSource
    extends AbstractSAXSource {
  
      /** The Database instance */
      protected Database database;
  
      /** The driver implementation class */
      protected String driver;
  
      /** The connection status. */
      protected boolean connected = false;
  
      /** The requested URL */
      protected String url;
  
      /** The URL parameters */
      protected String urlParameters = null;
  
      /** The System ID */
      protected String systemId;
  
      /** Static Strings used for XML Collection representation */
      
      protected static final String URI = "http://apache.org/cocoon/xmldb/1.0";;
      protected static final String PREFIX = "collection";
      protected static final String RESOURCE_COUNT_ATTR = "resources";
      protected static final String COLLECTION_COUNT_ATTR  = "collections";
      protected static final String COLLECTION  = "collection";
      protected static final String QCOLLECTION  = PREFIX + ":collection";
      protected static final String RESOURCE  = "resource";
      protected static final String QRESOURCE  = PREFIX + ":resource";
      protected static final String NAME_ATTR  = "name";
      protected static final String CDATA  = "CDATA";
  
  
      /**
       * The constructor.
       * 
       * @param environment the Cocoon Environment.
       * @param url the URL being queried.
       * @param driver the XML:DB driver class name.
       */
      
      public XMLDBSource(Environment environment, 
                         ComponentManager manager,
                         Logger logger,
                         String driver,
                         String url) {
  
        super(environment, manager, logger);                 
        int start;
  
        this.driver = driver;
  
        if ((start = url.indexOf('?')) != -1) {
          this.url = url.substring(0, start);
          this.urlParameters = url.substring(start+1);
        } else {
          this.url = url;
        }
      }
  
      /** 
       * Initialize the XML:DB connection.
       *
       */
  
      public void connect() throws Exception {
  
        if (log.isDebugEnabled()) {
          this.log.debug("Initializing XML:DB connection");
        }
  
        try {
  
          Class c = Class.forName(driver);
          database = (Database)c.newInstance();
          DatabaseManager.registerDatabase(database);
  
        } catch (XMLDBException xde) {
  
          this.log.error("Unable to connect to the XML:DB database");
          throw new ProcessingException("Unable to connect to the XMLDB database" 
            + xde.getMessage());
  
        } catch (Exception e) {
  
          this.log.error("There was a problem setting up the connection");
          this.log.error("Make sure that your driver is available");
          throw new ProcessingException("Problem setting up the connection: " 
            + e.getMessage(), e);
  
        } 
  
        this.connected = true;
      }
   
  
      /**
       * Stream SAX events to a given ContentHandler. If the requested
       * resource is a collection, build an XML view of it. 
       *
       */
  
      public void toSAX(ContentHandler handler) 
        throws SAXException, ProcessingException {
  
        if (!connected) {
          try {
          this.connect();
          } catch (Exception e) {
            this.log.error("Unable to connect to the database", e);  
            throw new ProcessingException("Unable to connect to the database: " +
              e.getMessage());
          }
        }
        if (url.endsWith("/")) 
          this.collectionToSAX(handler);
        else
          this.resourceToSAX(handler);
  
      }  
  
      private void resourceToSAX(ContentHandler handler) 
        throws SAXException, ProcessingException {
  
        Collection collection;
        XMLResource xmlResource;
        
        String col = url.substring(0, url.lastIndexOf('/'));        
        String res = url.substring(url.lastIndexOf('/') + 1);
  
        try {
          collection = DatabaseManager.getCollection(col);
          xmlResource = (XMLResource) collection.getResource(res);
  
          if (xmlResource == null)
            throw new ResourceNotFoundException("Document " + col + "/" + res + 
              " not found");
  
          xmlResource.getContentAsSAX(handler);
  
          collection.close();
  
        } catch (XMLDBException xde) {
  
          throw new ProcessingException("Unable to fetch content: " +
            xde.getMessage(), xde);
  
        } catch (NullPointerException npe) {
  
            this.log.error("The XML:DB driver raised an exception");
            this.log.error("probably the document was not found");
  
            throw new ProcessingException("Null pointer exception while " + 
              "retrieving document : " + npe.getMessage());
        } 
  
      }
  
      private void collectionToSAX(ContentHandler handler) 
        throws SAXException, ProcessingException {
  
        Collection collection;
        AttributesImpl attributes = new AttributesImpl();
        int queryStart;
  
        try {
          collection = DatabaseManager.getCollection(url);
  
          if (collection == null) {
            throw new ResourceNotFoundException("Collection " + url + 
              " not found");
          }
  
          String ncollections;
          String nresources;
          String[] resources;
          String[] collections;
  
          ncollections = Integer.toString(collection.getChildCollectionCount());
          nresources = Integer.toString(collection.getResourceCount());
  
          attributes.clear();
          attributes.addAttribute("", RESOURCE_COUNT_ATTR,
            RESOURCE_COUNT_ATTR, "CDATA", nresources);
          attributes.addAttribute("", COLLECTION_COUNT_ATTR,
            COLLECTION_COUNT_ATTR, "CDATA", ncollections);
  
          collections = collection.listChildCollections();
          resources = collection.listResources();
  
          handler.startDocument();
          handler.startPrefixMapping(PREFIX, URI);
  
          handler.startElement(URI, "collections", 
            "collection:collections", attributes);
  
          // Print child collections
  
          for (int i = 0; i < collections.length; i++) {
            attributes.clear();
            attributes.addAttribute("", NAME_ATTR, NAME_ATTR, CDATA, collections[i]);
            handler.startElement(URI, COLLECTION, 
              QCOLLECTION, attributes);
            handler.endElement(URI, COLLECTION, COLLECTION);
          }
  
          // Print child resources
  
          for (int i = 0; i < resources.length; i++) {
            attributes.clear();
            attributes.addAttribute("", NAME_ATTR, NAME_ATTR, CDATA, resources[i]);
            handler.startElement(URI, RESOURCE, 
              QRESOURCE, attributes);
            handler.endElement(URI, RESOURCE, RESOURCE);
          }
  
          handler.endElement(URI, "collections", 
            "collection:collections");
            
          handler.endPrefixMapping(PREFIX);
          handler.endDocument();
            
        } catch (XMLDBException xde) {
          this.log.error("Collection listing failed" + xde.getMessage());
          throw new SAXException("Collection listing failed" + xde.getMessage());
        }
        
      }
  
      public void recycle() {
        this.driver = null;
        this.log = null;
        this.manager = null;
        this.url = null;
        this.urlParameters = null;
      }
  
      public String getSystemId() {
        return url;
      }
  
  }
  
  
  
  1.1                  
xml-cocoon2/src/org/apache/cocoon/components/source/XMLDBSourceFactory.java
  
  Index: XMLDBSourceFactory.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.components.source;
  
  import org.apache.avalon.framework.component.ComponentManager;
  import org.apache.avalon.framework.component.Composable;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.logger.AbstractLoggable;
  import org.apache.cocoon.ProcessingException;
  import org.apache.cocoon.environment.Environment;
  import org.apache.cocoon.environment.Source;
  import org.apache.cocoon.sitemap.Sitemap;
  
  import java.io.IOException;
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  
  /**
   * This class implements the xmldb:// pseudo-protocol and allows to get XML
   * content from an XML:DB enabled XML database.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Gianugo Rabellino</a>
   */
  
  public final class XMLDBSourceFactory
    extends AbstractLoggable
    implements SourceFactory, Configurable, Composable {
  
  
      /** The driver implementation class */
      protected String driver;
  
      /** The driver implementation class */
      protected ComponentManager m_manager;
  
      /** A Map containing the driver list */
      protected HashMap driverMap;
  
      /**
       * Configure the instance.
       */ 
      public void configure(final Configuration conf) 
        throws ConfigurationException {
  
        if (conf != null) {
  
          driverMap = new HashMap();
  
          Configuration[] xmldbConfigs = conf.getChildren("driver");
  
          for (int i = 0; i < xmldbConfigs.length; i++) {
            driverMap.put(xmldbConfigs[i].getAttribute("type"),
              xmldbConfigs[i].getAttribute("class"));
          }
  
        } else {
          throw new ConfigurationException("XMLDB configuration not found");
        }
  
      }
  
      /**
       * Compose this Composable object. We need to pass on the 
       * ComponentManager to the actual Source.
       */
      
      public void compose(ComponentManager cm) {
        this.m_manager = cm;
      }
  
      /**
       * Resolve the source
       */
      public Source getSource(Environment environment, String location)
        throws ProcessingException, IOException, MalformedURLException {
  
        int start = location.indexOf(':') + 1;
        int end = location.indexOf(':', start);
  
        if (start == -1 || end == -1) {
          if (this.getLogger().isWarnEnabled()) {
          this.getLogger().warn("Mispelled XML:DB URL. " +
            "The syntax is \"xmldb:databasetype://host/collection/resource\""); 
          throw new MalformedURLException("Mispelled XML:DB URL. " +
            "The syntax is \"xmldb:databasetype://host/collection/resource\""); 
          }  
        }    
  
        String type = location.substring(start, end);
  
        driver = (String)driverMap.get(type);
  
        if (driver == null) {
          this.getLogger().error("Unable to find a driver for the \"" +
            type + " \" database type, please check the configuration");
          throw new ProcessingException("Unable to find a driver for the \"" +
            type + " \" database type, please check the configuration");
        }    
  
        return new XMLDBSource(environment, m_manager, this.getLogger(),
          driver, location);
      }
  
      /**
       * Resolve the source
       */
      public Source getSource(Environment environment, URL base, String location)
        throws ProcessingException, IOException, MalformedURLException {
        return getSource(environment, base.toExternalForm() + location);
      }
  }
  
  
  

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