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]