You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by up...@apache.org on 2004/01/13 09:44:05 UTC
cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl XMLDBSource.java
upayavira 2004/01/13 00:44:05
Modified: src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
XMLDBSource.java
Log:
Making XMLDBSource modifiable. Should be useful with Woody binding infrastructure, and can use SourceWritingTransformer to write to DB (as well as XMLDBTransformer)
Revision Changes Path
1.9 +165 -3 cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl/XMLDBSource.java
Index: XMLDBSource.java
===================================================================
RCS file: /home/cvs/cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl/XMLDBSource.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- XMLDBSource.java 5 Dec 2003 00:29:02 -0000 1.8
+++ XMLDBSource.java 13 Jan 2004 08:44:05 -0000 1.9
@@ -62,7 +62,9 @@
import org.apache.cocoon.components.source.helpers.SourceCredential;
import org.apache.cocoon.serialization.Serializer;
import org.apache.cocoon.xml.IncludeXMLConsumer;
+import org.apache.excalibur.source.ModifiableSource;
import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceException;
import org.apache.excalibur.source.SourceValidity;
import org.apache.excalibur.xml.sax.XMLizable;
import org.xml.sax.ContentHandler;
@@ -70,9 +72,11 @@
import org.xml.sax.helpers.AttributesImpl;
import org.xmldb.api.DatabaseManager;
import org.xmldb.api.base.Collection;
+import org.xmldb.api.base.Resource;
import org.xmldb.api.base.ResourceIterator;
import org.xmldb.api.base.ResourceSet;
import org.xmldb.api.base.XMLDBException;
+import org.xmldb.api.modules.CollectionManagementService;
import org.xmldb.api.modules.XMLResource;
import org.xmldb.api.modules.XPathQueryService;
@@ -80,6 +84,8 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.MalformedURLException;
/**
* This class implements the xmldb:// pseudo-protocol and allows to get XML
@@ -90,7 +96,7 @@
* @version CVS $Id$
*/
public class XMLDBSource extends AbstractLogEnabled
- implements Source, XMLizable {
+ implements Source, ModifiableSource, XMLizable {
//
// Static Strings used for XML Collection representation
@@ -161,7 +167,9 @@
/** ServiceManager */
protected ServiceManager manager;
-
+
+ /** XMLDBOutputStream for writing to Modifiable resource */
+ protected XMLDBOutputStream os;
/**
* The constructor.
*
@@ -188,6 +196,7 @@
} else {
this.url = url;
}
+ this.os = null;
}
/**
@@ -481,6 +490,159 @@
if (serializerSelector != null) {
this.manager.release(serializerSelector);
}
+ }
+ }
+ /**
+ * Return an {@link OutputStream} to write to.
+ */
+ public OutputStream getOutputStream() throws IOException, MalformedURLException {
+ if (query != null) {
+ throw new MalformedURLException("Cannot modify a resource that includes an XPATH expression");
+ }
+ this.os = new XMLDBOutputStream();
+ return this.os;
+ }
+
+ private void writeOutputStream(String content) throws SourceException {
+ String name = null;
+ String base = null;
+
+ try {
+ if (this.url.endsWith("/")) {
+ name = "";
+ base = this.url.substring(0, this.url.length() - 1);
+ } else {
+ base = this.url.substring(0, this.url.lastIndexOf("/"));
+ name = this.url.substring(this.url.lastIndexOf("/")+1);
+ }
+ Collection collection = DatabaseManager.getCollection(base);
+
+ if (name.equals("")) {
+ name = collection.createId();
+ }
+ Resource resource = collection.createResource(name, "XMLResource");
+
+ resource.setContent(content);
+ collection.storeResource(resource);
+
+ getLogger().debug("Written to resource " + name);
+ } catch (XMLDBException e) {
+ String message = "Failed to create resource " + name + ": " + e.errorCode;
+ getLogger().debug(message, e);
+ throw new SourceException(message);
+ }
+ }
+
+ /**
+ * Delete the source
+ */
+ public void delete() throws SourceException {
+ String base = null;
+ String name = null;
+ if (this.url.endsWith("/")) {
+ try {
+ // Cut trailing '/'
+ String k = this.url.substring(0, this.url.length() - 1);
+
+ base = k.substring(0, k.lastIndexOf("/"));
+ name = k.substring(k.lastIndexOf("/")+1);
+
+ Collection collection = DatabaseManager.getCollection(base);
+
+ CollectionManagementService service =
+ (CollectionManagementService) collection.getService("CollectionManagementService", "1.0");
+ service.removeCollection(name);
+ } catch (XMLDBException e) {
+ String message = "Failed to remove collection " + name + ": " + e.errorCode;
+ getLogger().error(message, e);
+ throw new SourceException(message);
+ }
+ } else {
+ try {
+ base = this.url.substring(0, this.url.lastIndexOf("/"));
+ name = this.url.substring(this.url.lastIndexOf("/")+1);
+
+ Collection collection = DatabaseManager.getCollection(base);
+
+ Resource resource = collection.getResource(name);
+ if (resource == null) {
+ String message = "Resource " + name + " does not exist";
+ getLogger().debug(message);
+ throw new SourceException(message);
+ } else {
+ collection.removeResource(resource);
+ getLogger().debug("Removed resource: "+ name);
+ }
+ } catch (XMLDBException e) {
+ String message = "Failed to delete resource " + name + ": " + e.errorCode;
+ getLogger().debug(message, e);
+ throw new SourceException(message);
+ }
+ }
+ }
+
+ /**
+ * Can the data sent to an <code>OutputStream</code> returned by
+ * {@link #getOutputStream()} be cancelled ?
+ *
+ * @return true if the stream can be cancelled
+ */
+ public boolean canCancel(OutputStream stream) {
+ return !this.os.isClosed();
+ }
+
+ /**
+ * Cancel the data sent to an <code>OutputStream</code> returned by
+ * {@link #getOutputStream()}.
+ *
+ * <p>After cancelling, the stream should no longer be used.</p>
+ */
+ public void cancel(OutputStream stream) throws IOException {
+ this.os.cancel();
+ this.os = null;
+ }
+
+ public class XMLDBOutputStream extends OutputStream {
+
+ private ByteArrayOutputStream baos;
+ private boolean isClosed;
+ public XMLDBOutputStream() {
+ baos = new ByteArrayOutputStream();
+ isClosed = false;
+ }
+
+ public void write(int b) throws IOException {
+ baos.write(b);
+ }
+
+ public void write(byte b[]) throws IOException {
+ baos.write(b);
+ }
+
+ public void write(byte b[], int off, int len) throws IOException {
+ baos.write(b, off, len);
+ }
+
+ public void close() throws IOException, SourceException {
+ if (!isClosed) {
+ writeOutputStream(baos.toString());
+ baos.close();
+ this.isClosed = true;
+ }
+ }
+
+ public void flush() throws IOException {
+ }
+
+ public int size() {
+ return baos.size();
+ }
+
+ public boolean isClosed() {
+ return this.isClosed;
+ }
+ public void cancel() {
+ this.isClosed = true;
}
}
}
Re: cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
Posted by Upayavira <uv...@upaya.co.uk>.
Ugo Cei wrote:
> It looks like we might have a problem. I copied the loadDocument
> function from woody's binding_example.js and passed it an "xmldb:"
> URI. This is the exception I get when I call
>
> var is = new Packages.org.xml.sax.InputSource(source.getInputStream());
>
> org.apache.cocoon.CascadingIOException: Could not lookup pipeline
> components: org.apache.avalon.framework.service.ServiceException:
> Could not find component (key
> [org.apache.cocoon.serialization.SerializerSelector])
> (Key='org.apache.cocoon.serialization.SerializerSelector')
But that's not in my new code, that is in the unchanged
getInputStream(), which uses an XML serializer to serialize SAX events.
Why it shouldn't be able to get a SerializerSelector I don't know, but
I'm not an Avalon guru.
Regards, Upayavira
Re: cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
Posted by Upayavira <uv...@upaya.co.uk>.
Ugo Cei wrote:
> It looks like we might have a problem. I copied the loadDocument
> function from woody's binding_example.js and passed it an "xmldb:"
> URI. This is the exception I get when I call
>
> var is = new Packages.org.xml.sax.InputSource(source.getInputStream());
>
> org.apache.cocoon.CascadingIOException: Could not lookup pipeline
> components: org.apache.avalon.framework.service.ServiceException:
> Could not find component (key
> [org.apache.cocoon.serialization.SerializerSelector])
> (Key='org.apache.cocoon.serialization.SerializerSelector')
I've just got this now.
Don't know why a source can't get a SerializerSelector when called from
flow. Anyway I propose to change the source to use trax to serialize,
rarher than a serializer. Any objections?
Regards, Upayavira
Re: cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
Posted by Ugo Cei <u....@cbim.it>.
Guido Casper wrote:
> SourceUtil.toDOM() uses the same code, but calls source.toSAX() only if
> it exists (i.e. the source implements XMLizable). If not, SourceUtil
> falls back to using the XMLizer (which in turn calls
> source.getInputStream again). So SourceUtil works with any kind of
> source while your code does only work on sources implementing XMLizable.
Aw, cool! Thank you.
Ugo
Re: cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
Posted by Guido Casper <gc...@s-und-n.de>.
Ugo Cei wrote:
> Guido Casper wrote:
>> I have no idea what the reason might be but maybe you want to try:
>> org.apache.cocoon.components.source.SourceUtil.toDOM(source);
>
> I already found a workaround:
>
> var domBuilder = new Packages.org.apache.cocoon.xml.dom.DOMBuilder();
> source.toSAX(domBuilder);
> return domBuilder.document;
>
> (BTW, what's the difference between my version and yours?)
SourceUtil.toDOM() uses the same code, but calls source.toSAX() only if
it exists (i.e. the source implements XMLizable). If not, SourceUtil
falls back to using the XMLizer (which in turn calls
source.getInputStream again). So SourceUtil works with any kind of
source while your code does only work on sources implementing XMLizable.
Guido
Re: cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
Posted by Ugo Cei <u....@cbim.it>.
Guido Casper wrote:
> I have no idea what the reason might be but maybe you want to try:
> org.apache.cocoon.components.source.SourceUtil.toDOM(source);
I already found a workaround:
var domBuilder = new Packages.org.apache.cocoon.xml.dom.DOMBuilder();
source.toSAX(domBuilder);
return domBuilder.document;
(BTW, what's the difference between my version and yours?)
but I don't have time to dig deeper into the problem ATM and just wanted
to let it be known. Maybe it's just my installation. Can anyone else
confirm it?
Ugo
Re: cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
Posted by Guido Casper <gc...@s-und-n.de>.
Ugo Cei wrote:
> It looks like we might have a problem. I copied the loadDocument
> function from woody's binding_example.js and passed it an "xmldb:"
> URI. This is the exception I get when I call
>
> var is = new
> Packages.org.xml.sax.InputSource(source.getInputStream());
>
> org.apache.cocoon.CascadingIOException: Could not lookup pipeline
> components: org.apache.avalon.framework.service.ServiceException:
> Could not find component (key
> [org.apache.cocoon.serialization.SerializerSelector])
> (Key='org.apache.cocoon.serialization.SerializerSelector')
I have no idea what the reason might be but maybe you want to try:
org.apache.cocoon.components.source.SourceUtil.toDOM(source);
instead.
HTH
Guido
Re: cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
Posted by Ugo Cei <u....@cbim.it>.
It looks like we might have a problem. I copied the loadDocument
function from woody's binding_example.js and passed it an "xmldb:" URI.
This is the exception I get when I call
var is = new Packages.org.xml.sax.InputSource(source.getInputStream());
org.apache.cocoon.CascadingIOException: Could not lookup pipeline
components: org.apache.avalon.framework.service.ServiceException: Could
not find component (key
[org.apache.cocoon.serialization.SerializerSelector])
(Key='org.apache.cocoon.serialization.SerializerSelector')
Ugo
Re: cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
Posted by Upayavira <uv...@upaya.co.uk>.
Ugo Cei wrote:
> upayavira@apache.org wrote:
>
>> upayavira 2004/01/13 00:44:05
>>
>> Modified:
>> src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
>> XMLDBSource.java
>> Log:
>> Making XMLDBSource modifiable. Should be useful with Woody binding
>> infrastructure, and can use SourceWritingTransformer to write to DB
>> (as well as XMLDBTransformer)
>
>
> You are my hero! I'm going to use this in a few minutes :-).
Great. Things to note:
I've currently implemented it so that, if the URL of a source ends with
a / (i.e. refers to a collection), a new document will be inserted into
the collection with a name created by the database, and the URL of the
source will be changed to include the new document name. For this latter
bit, see my trivial recent commit.
Also, it can currently only write at a document level. I'm sure it would
be possible to write using xupdate or some such, but seeing as I don't
know them yet, I'll leave that for someone else or some other time.
Regards, Upayavira
Re: cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
XMLDBSource.java
Posted by Ugo Cei <u....@cbim.it>.
upayavira@apache.org wrote:
> upayavira 2004/01/13 00:44:05
>
> Modified: src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
> XMLDBSource.java
> Log:
> Making XMLDBSource modifiable. Should be useful with Woody binding infrastructure, and can use SourceWritingTransformer to write to DB (as well as XMLDBTransformer)
You are my hero! I'm going to use this in a few minutes :-).
Ugo
Re: cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
Posted by Vadim Gritsenko <va...@reverycodes.com>.
Upayavira wrote:
> Vadim Gritsenko wrote:
>
>> upayavira@apache.org wrote:
>>
>>> upayavira 2004/01/13 00:44:05
>>>
>>> Modified:
>>> src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
>>> XMLDBSource.java
>>> Log:
>>> Making XMLDBSource modifiable. Should be useful with Woody binding
>>> infrastructure, and can use SourceWritingTransformer to write to DB
>>> (as well as XMLDBTransformer)
>>>
>>>
>>
>> The only thing missing is support for binary resources...
>
>
> The places I stole my code from don't seem to support binary resources
> ('cos they use resource.setContent(String)). If you can point me at
> some code that handles them, I'll happily add it.
See org.apache.xindice.tools.command.AddDocument, version 1.11. I think
I have to create separate command line command for the binary resource
and do not mix them together.
Vadim
Re: cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
Posted by Upayavira <uv...@upaya.co.uk>.
Vadim Gritsenko wrote:
> upayavira@apache.org wrote:
>
>> upayavira 2004/01/13 00:44:05
>>
>> Modified:
>> src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
>> XMLDBSource.java
>> Log:
>> Making XMLDBSource modifiable. Should be useful with Woody binding
>> infrastructure, and can use SourceWritingTransformer to write to DB
>> (as well as XMLDBTransformer)
>>
>>
>
> The only thing missing is support for binary resources...
The places I stole my code from don't seem to support binary resources
('cos they use resource.setContent(String)). If you can point me at some
code that handles them, I'll happily add it.
Regards, Upayavira
Re: cvs commit: cocoon-2.1/src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
XMLDBSource.java
Posted by Vadim Gritsenko <va...@reverycodes.com>.
upayavira@apache.org wrote:
>upayavira 2004/01/13 00:44:05
>
> Modified: src/blocks/xmldb/java/org/apache/cocoon/components/source/impl
> XMLDBSource.java
> Log:
> Making XMLDBSource modifiable. Should be useful with Woody binding infrastructure, and can use SourceWritingTransformer to write to DB (as well as XMLDBTransformer)
>
>
The only thing missing is support for binary resources...
Vadim