vgritsenko 01/12/20 19:29:56
Modified: src/org/apache/cocoon/components/source XMLDBSource.java
src/org/apache/cocoon/generation xmldb.sitemap
webapp cocoon.xconf sitemap.xmap
. changes.xml
Added: lib xmldb.jar
Log:
- Enable XML:DB support by default: add xmldb.jar from dbXML1.0b4.
- Add XPath query capability to XML:DB pseudo protocol.
- Override getLastModified: XML:DB is not (yet?) cacheable
- Fix NPE in resourceToSAX
- Add default configuration to XML:DB generators. Will work out-of-the-box with
dbXML on localhost.
- Add XML:DB protocol and generators test pipelines (TODO: examples)
Revision Changes Path
1.1 xml-cocoon2/lib/xmldb.jar
<<Binary file>>
1.2 +224 -157
xml-cocoon2/src/org/apache/cocoon/components/source/XMLDBSource.java
Index: XMLDBSource.java
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/org/apache/cocoon/components/source/XMLDBSource.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- XMLDBSource.java 2001/12/09 17:05:22 1.1
+++ XMLDBSource.java 2001/12/21 03:29:56 1.2
@@ -1,4 +1,3 @@
-
/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
@@ -13,6 +12,7 @@
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.ResourceNotFoundException;
+import org.apache.cocoon.xml.IncludeXMLConsumer;
import org.apache.cocoon.environment.Environment;
import org.apache.cocoon.environment.Source;
import org.apache.cocoon.environment.ModifiableSource;
@@ -20,14 +20,17 @@
import org.apache.cocoon.sitemap.SitemapComponentSelector;
import org.apache.log.Logger;
-import org.xmldb.api.DatabaseManager;
+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.xmldb.api.base.XMLDBException;
+import org.xmldb.api.base.ResourceSet;
+import org.xmldb.api.base.ResourceIterator;
+import org.xmldb.api.modules.XMLResource;
+import org.xmldb.api.modules.XPathQueryService;
import org.xml.sax.InputSource;
import org.xml.sax.ContentHandler;
@@ -46,10 +49,9 @@
* content from an XML:DB enabled XML database.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Gianugo Rabellino</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Vadim Gritsenko</a>
*/
-
-public class XMLDBSource
- extends AbstractSAXSource {
+public class XMLDBSource extends AbstractSAXSource {
/** The Database instance */
protected Database database;
@@ -70,19 +72,41 @@
protected String systemId;
/** Static Strings used for XML Collection representation */
-
+
protected static final String URI = "http://apache.org/cocoon/xmldb/1.0";
+ // FIXME (VG): Should not be this more generic? Say, "xmldb"?
protected static final String PREFIX = "collection";
+
+ /** Root element <collections> */
+ protected static final String COLLECTIONS = "collections";
+ protected static final String QCOLLECTIONS = PREFIX + ":" + COLLECTIONS;
protected static final String RESOURCE_COUNT_ATTR = "resources";
protected static final String COLLECTION_COUNT_ATTR = "collections";
+// protected static final String COLLECTION_BASE_ATTR = "base";
+
+ /** Element <collection> */
protected static final String COLLECTION = "collection";
- protected static final String QCOLLECTION = PREFIX + ":collection";
+ protected static final String QCOLLECTION = PREFIX + ":" + COLLECTION;
+
+ /** Element <resource> */
protected static final String RESOURCE = "resource";
- protected static final String QRESOURCE = PREFIX + ":resource";
+ protected static final String QRESOURCE = PREFIX + ":" + RESOURCE;
protected static final String NAME_ATTR = "name";
- protected static final String CDATA = "CDATA";
+ /** Root element <results> */
+ protected static final String RESULTSET = "results";
+ protected static final String QRESULTSET = PREFIX + ":" + RESULTSET;
+ protected static final String QUERY_ATTR = "query";
+ protected static final String RESULTS_COUNT_ATTR = "resources";
+
+ /** Element <result> */
+ protected static final String RESULT = "result";
+ protected static final String QRESULT = PREFIX + ":" + RESULT;
+ protected static final String RESULT_DOCID_ATTR = "docid";
+ protected static final String RESULT_ID_ATTR = "id";
+ protected static final String CDATA = "CDATA";
+
/**
* The constructor.
*
@@ -90,61 +114,61 @@
* @param url the URL being queried.
* @param driver the XML:DB driver class name.
*/
-
- public XMLDBSource(Environment environment,
+
+ public XMLDBSource(Environment environment,
ComponentManager manager,
Logger logger,
String driver,
String url) {
- super(environment, manager, logger);
- int start;
+ super(environment, manager, logger);
+ int start;
- this.driver = driver;
+ this.driver = driver;
- if ((start = url.indexOf('?')) != -1) {
- this.url = url.substring(0, start);
- this.urlParameters = url.substring(start+1);
- } else {
- this.url = url;
- }
+ 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);
+ if (log.isDebugEnabled()) {
+ this.log.debug("Initializing XML:DB connection");
+ }
- } catch (XMLDBException xde) {
+ try {
- this.log.error("Unable to connect to the XML:DB database");
- throw new ProcessingException("Unable to connect to the XMLDB database"
- + xde.getMessage());
+ 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) {
+ } 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.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;
+ this.connected = true;
}
-
+
/**
* Stream SAX events to a given ContentHandler. If the requested
@@ -152,143 +176,186 @@
*
*/
- public void toSAX(ContentHandler handler)
- throws SAXException, ProcessingException {
+ 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 (!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);
+ if (url.endsWith("/"))
+ this.collectionToSAX(handler);
+ else
+ this.resourceToSAX(handler);
- 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();
+ private void resourceToSAX(ContentHandler handler) throws SAXException,
ProcessingException {
- } catch (XMLDBException xde) {
+ Collection collection;
+ XMLResource xmlResource;
- throw new ProcessingException("Unable to fetch content: " +
- xde.getMessage(), xde);
+ String col = url.substring(0, url.lastIndexOf('/'));
+ String res = url.substring(url.lastIndexOf('/') + 1);
- } catch (NullPointerException npe) {
+ try {
+ collection = DatabaseManager.getCollection(col);
+ if (collection == null) {
+ throw new ResourceNotFoundException("Document " + url + " not
found");
+ }
+
+ xmlResource = (XMLResource) collection.getResource(res);
+ if (xmlResource == null) {
+ throw new ResourceNotFoundException("Document " + url + " not
found");
+ }
+
+ xmlResource.getContentAsSAX(handler);
+ collection.close();
+ } catch (XMLDBException xde) {
+
+ throw new ProcessingException("Unable to fetch content: " +
+ xde.getMessage(), xde);
- this.log.error("The XML:DB driver raised an exception");
- this.log.error("probably the document was not found");
+ } catch (NullPointerException npe) {
- throw new ProcessingException("Null pointer exception while " +
- "retrieving document : " + npe.getMessage());
- }
+ 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 {
+ 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");
- }
+ AttributesImpl attributes = new AttributesImpl();
- 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);
+ try {
+ Collection collection = DatabaseManager.getCollection(url);
+ if (collection == null) {
+ throw new ResourceNotFoundException("Collection " + url +
+ " not found");
+ }
+
+ if (urlParameters != null) {
+ queryToSAX(handler, collection);
+ return;
+ }
+
+ final String ncollections =
Integer.toString(collection.getChildCollectionCount());
+ final String nresources =
Integer.toString(collection.getResourceCount());
+ attributes.addAttribute("", RESOURCE_COUNT_ATTR,
+ RESOURCE_COUNT_ATTR, "CDATA", nresources);
+ attributes.addAttribute("", COLLECTION_COUNT_ATTR,
+ COLLECTION_COUNT_ATTR, "CDATA", ncollections);
+// attributes.addAttribute("", COLLECTION_BASE_ATTR,
+// COLLECTION_BASE_ATTR, "CDATA", url);
+
+ handler.startDocument();
+ handler.startPrefixMapping(PREFIX, URI);
+ handler.startElement(URI, COLLECTIONS, QCOLLECTIONS, attributes);
+
+ // Print child collections
+ String[] collections = collection.listChildCollections();
+ 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
+ String[] resources = collection.listResources();
+ 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, QCOLLECTIONS);
+ handler.endPrefixMapping(PREFIX);
+ handler.endDocument();
+ } catch (XMLDBException xde) {
+ this.log.error("Collection listing failed. " + xde.getMessage());
+ throw new SAXException("Collection listing failed. " +
xde.getMessage());
}
+ }
- // Print child resources
+ public void queryToSAX(ContentHandler handler, Collection collection) throws
SAXException {
- 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);
- }
+ AttributesImpl attributes = new AttributesImpl();
- 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());
- }
-
+ try {
+ XPathQueryService service =
+ (XPathQueryService) collection.getService("XPathQueryService",
"1.0");
+ ResourceSet resultSet = service.query(urlParameters);
+
+ attributes.addAttribute("", QUERY_ATTR, QUERY_ATTR, "CDATA",
urlParameters);
+ attributes.addAttribute("", RESULTS_COUNT_ATTR,
+ RESULTS_COUNT_ATTR, "CDATA",
Long.toString(resultSet.getSize()));
+
+ handler.startDocument();
+ handler.startPrefixMapping(PREFIX, URI);
+ handler.startElement(URI, RESULTSET, QRESULTSET, attributes);
+
+ IncludeXMLConsumer includeHandler = new IncludeXMLConsumer(handler);
+
+ // Print search results
+ ResourceIterator results = resultSet.getIterator();
+ while (results.hasMoreResources()) {
+ XMLResource resource = (XMLResource)results.nextResource();
+
+ final String id = resource.getId();
+ final String documentId = resource.getDocumentId();
+
+ attributes.clear();
+ if (id != null) {
+ attributes.addAttribute("", RESULT_ID_ATTR, RESULT_ID_ATTR,
+ CDATA, id);
+ }
+ if (documentId != null) {
+ attributes.addAttribute("", RESULT_DOCID_ATTR,
RESULT_DOCID_ATTR,
+ CDATA, documentId);
+ }
+ handler.startElement(URI, RESULT, QRESULT, attributes);
+
+ resource.getContentAsSAX(includeHandler);
+
+ handler.endElement(URI, RESULT, RESULT);
+ }
+
+ handler.endElement(URI, RESULTSET, QRESULTSET);
+ handler.endPrefixMapping(PREFIX);
+ handler.endDocument();
+ } catch (XMLDBException xde) {
+ this.log.error("Collection query failed. " + xde.getMessage());
+ throw new SAXException("Collection query failed. " + xde.getMessage());
+ }
}
public void recycle() {
- this.driver = null;
- this.log = null;
- this.manager = null;
- this.url = null;
- this.urlParameters = null;
+ this.driver = null;
+ this.log = null;
+ this.manager = null;
+ this.url = null;
+ this.urlParameters = null;
}
public String getSystemId() {
- return url;
+ return url;
}
+ /**
+ * Modification date is not known.
+ */
+ public long getLastModified() {
+ return 0;
+ }
}
1.2 +2 -2 xml-cocoon2/src/org/apache/cocoon/generation/xmldb.sitemap
Index: xmldb.sitemap
===================================================================
RCS file: /home/cvs/xml-cocoon2/src/org/apache/cocoon/generation/xmldb.sitemap,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- xmldb.sitemap 2001/11/23 09:11:51 1.1
+++ xmldb.sitemap 2001/12/21 03:29:56 1.2
@@ -1,2 +1,2 @@
-category:generators|componentName:xmldb|componentClass:org.apache.cocoon.generation.XMLDBGenerator
-category:generators|componentName:xmldbcollection|componentClass:org.apache.cocoon.generation.XMLDBCollectionGenerator
+category:generators|componentName:xmldb|componentClass:org.apache.cocoon.generation.XMLDBGenerator|configuration:<driver>org.dbxml.client.xmldb.DatabaseImpl</driver><base>xmldb:dbxml:///db/</base>
+category:generators|componentName:xmldbcollection|componentClass:org.apache.cocoon.generation.XMLDBCollectionGenerator|configuration:<driver>org.dbxml.client.xmldb.DatabaseImpl</driver><base>xmldb:dbxml:///db/</base>
1.46 +6 -0 xml-cocoon2/webapp/cocoon.xconf
Index: cocoon.xconf
===================================================================
RCS file: /home/cvs/xml-cocoon2/webapp/cocoon.xconf,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -r1.45 -r1.46
--- cocoon.xconf 2001/12/20 15:15:08 1.45
+++ cocoon.xconf 2001/12/21 03:29:56 1.46
@@ -150,6 +150,12 @@
sitemap components.
-->
<source-handler>
+ <!-- xmldb pseudo protocol -->
+ <protocol name="xmldb"
class="org.apache.cocoon.components.source.XMLDBSourceFactory">
+ <!-- dbXML driver -->
+ <driver type="dbxml" class="org.dbxml.client.xmldb.DatabaseImpl"/>
+ <!-- Add here other XML:DB compliant databases drivers -->
+ </protocol>
</source-handler>
<!-- Program Generator:
1.71 +21 -0 xml-cocoon2/webapp/sitemap.xmap
Index: sitemap.xmap
===================================================================
RCS file: /home/cvs/xml-cocoon2/webapp/sitemap.xmap,v
retrieving revision 1.70
retrieving revision 1.71
diff -u -r1.70 -r1.71
--- sitemap.xmap 2001/12/20 09:37:31 1.70
+++ sitemap.xmap 2001/12/21 03:29:56 1.71
@@ -1027,6 +1027,27 @@
<map:serialize/>
</map:match>
+ <!-- ========================= XML:DB ================================ -->
+ <map:match pattern="xmldb/**">
+ <map:match type="request" pattern="xpath">
+ <map:generate src="xmldb:dbxml://localhost:4080/{../1}?{1}"/>
+ <map:serialize type="xml"/>
+ </map:match>
+
+ <map:generate src="xmldb:dbxml://localhost:4080/{1}"/>
+ <map:serialize type="xml"/>
+ </map:match>
+
+ <map:match pattern="xmldb-generator/db/**/">
+ <map:generate type="xmldbcollection" src="/{1}"/>
+ <map:serialize type="xml"/>
+ </map:match>
+
+ <map:match pattern="xmldb-generator/db/**">
+ <map:generate type="xmldb" src="/{1}"/>
+ <map:serialize type="xml"/>
+ </map:match>
+
<!-- ========================= Server ================================ -->
<map:match pattern="request">
<map:generate type="request"/>
1.62 +9 -1 xml-cocoon2/changes.xml
Index: changes.xml
===================================================================
RCS file: /home/cvs/xml-cocoon2/changes.xml,v
retrieving revision 1.61
retrieving revision 1.62
diff -u -r1.61 -r1.62
--- changes.xml 2001/12/19 21:24:45 1.61
+++ changes.xml 2001/12/21 03:29:56 1.62
@@ -4,7 +4,7 @@
<!--
History of Cocoon changes
- $Id: changes.xml,v 1.61 2001/12/19 21:24:45 vgritsenko Exp $
+ $Id: changes.xml,v 1.62 2001/12/21 03:29:56 vgritsenko Exp $
-->
<changes title="History of Changes">
@@ -29,6 +29,14 @@
</devs>
<release version="@version@" date="@date@">
+ <action dev="VG" type="add">
+ Added ability to use XPath expressions to query XML:DB collections using
+ XML:DB pseudo protocol. URL should be in form:
+ xmldb:dbxml://host:port/db/collection/?/xpath
+ </action>
+ <action dev="VG" type="add">
+ Enabled XML:DB support (generators and pseudo protocol) by default.
+ </action>
<action dev="VG" type="fix" fixes-bug="4239">
JSPEngine returns result in UTF-8 charset.
</action>
----------------------------------------------------------------------
In case of troubles, e-mail: [EMAIL PROTECTED]
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]