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]