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]