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