jeremy      2002/07/01 01:53:39

  Modified:    src/java/org/apache/cocoon/transformation
                        SourceWritingTransformer.java
  Log:
  unified the tags style, response and implementation of source:write and 
source:insert tags
  
  Revision  Changes    Path
  1.5       +326 -304  
xml-cocoon2/src/java/org/apache/cocoon/transformation/SourceWritingTransformer.java
  
  Index: SourceWritingTransformer.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/java/org/apache/cocoon/transformation/SourceWritingTransformer.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SourceWritingTransformer.java     28 Jun 2002 07:14:36 -0000      1.4
  +++ SourceWritingTransformer.java     1 Jul 2002 08:53:39 -0000       1.5
  @@ -86,7 +86,8 @@
   import java.util.Properties;
   
   /**
  - * This transformer allows you to output to a WritableSource.
  +/**
  + * This transformer allows you to output to a WriteableSource.
    *
    * <p>Definition:</p>
    * <pre>
  @@ -98,67 +99,111 @@
    * <p>Invocation:</p>
    * <pre>
    * &lt;map:transform type="tofile"&gt;
  - *   &lt;map:parameter name="serializer" value="xml"/&gt;
  + *   &lt;map:parameter name="serializer" value="xml"/&gt;   &lt;!-- you can 
optionally override the serializer here --&gt;
    * &lt;/map:transform&gt;
    * </pre>
    *
  - * <p>Input XML document example:</p>
  + * <p>The Tags:</p>
    * <pre>
  - * &lt;page xmlns:source="http://apache.org/cocoon/source/1.0"&gt;
  + * &lt;source:write create="[true]|false"&gt; - replaces the entire content of an 
existing asset, if @create is 'true' (default), a new asset will be created if one 
does not already exist.
  + *     &lt;source:source&gt;The System ID of the asset to be written 
to&lt;/source:source&gt; - eg: "docs/blah.xml" or "context://blah.xml" etc.
  + *     &lt;source:path&gt;[Optional] XPath to specify how your content is 
wrapped&lt;/source:path&gt; - eg: "doc" (your content is placed inside a &lt;doc/&gt; 
root tag). NOTE: if this value is omitted, your content MUST have only ONE top-level 
node.
  + *     &lt;source:fragment&gt;The XML Fragment to be 
written&lt;/source:fragment&gt; - eg: "&lt;foo&gt;&lt;bar 
id="dogcow"/&gt;&lt;/foo&gt;" or "&lt;foo/&gt;&lt;bar&gt;&lt;dogcow/&gt;&lt;bar/&gt;" 
etc. NOTE: the second example type, can only be used when the &lt;source:path/&gt; tag 
has been specified.
  + * &lt;source:write&gt;
  + * 
  + * &lt;source:insert create="[true]|false" overwrite="[true]|false"&gt; - inserts 
content into an existing asset, if @create is 'true' (default), a new asset will be 
created if one does not already exist. If @overwrite is set to 'true' the data is only 
inserted if the node specified by the 'replacePath' does not exists.
  + *     &lt;source:source&gt;The System ID of the asset to be written 
to&lt;/source:source&gt; - eg: "docs/blah.xml" or "context://blah.xml" etc.
  + *     &lt;source:path&gt;XPath specifying the node into which the content is 
inserted&lt;/source:path&gt; - eg: "doc" (your content is appended as the last child 
of the &lt;doc/&gt; root tag), or "doc/section[3]". NOTE: this tag is required in 
&lt;source:insert/&gt; unlike &lt;source:write/&gt; where it is optional.
  + *     &lt;source:replace&gt;[Optional] XPath (relative to &lt;source:path/&gt;) to 
the node that is replaced by your new content&lt;/source:replace&gt; - eg: 
"foo/bar/dogcow/@status='cut'" (is equivalent to this in XSLT: 
select="foo[bar/dogcow/@status='cut']").
  + *     &lt;source:reinsert&gt;[Optional] The XPath (relative to 
&lt;source:replace/&gt;) to backup the overwritten node to&lt;/source:reinsert&gt; - 
eg: "foo/versions" or "/doc/versions/foo". NOTE: If specified and a node is replaced, 
all children of this replaced node will be reinserted at the given path.
  + *     &lt;source:fragment&gt;The XML Fragment to be 
written&lt;/source:fragment&gt; - eg: "&lt;foo&gt;&lt;bar 
id="dogcow"/&gt;&lt;/foo&gt;" or "&lt;foo/&gt;&lt;bar&gt;&lt;dogcow/&gt;&lt;bar/&gt;" 
etc. 
  + * &lt;source:insert&gt;
  + * </pre>
  + *
  + *
  + * <p>Input XML document example (write):</p>
  + * <pre>
  + * &lt;page&gt;
    *   ...
  - *   &lt;source:write src="context://doc/editable/my.xml"&gt;
  - *     &lt;page&gt;
  - *       XML Object body
  - *     &lt;/page&gt;
  + *   &lt;source:write xmlns:source="http://apache.org/cocoon/source/1.0"&gt;
  + *     &lt;source:source&gt;context://doc/editable/my.xml&lt;/source:source&gt;     
 
  + *     &lt;source:fragment&gt;&lt;page&gt;
  + *       &lt;title&gt;Hello World&lt;/title&gt;
  + *       &lt;content&gt;
  + *         &lt;p&gt;This is my first paragraph.&lt;/p&gt;
  + *       &lt;/content&gt;
  + *     &lt;/page&gt;&lt;/source:fragment&gt;
    *   &lt;/source:write&gt;
    *   ...
    * &lt;/page&gt;
    * </pre>
    *
  - * <p>Output XML document example:</p>
  + * <p>Input XML document example (insert at end):</p>
    * <pre>
  - * &lt;page xmlns:source="http://apache.org/cocoon/source/1.0"&gt;
  + * &lt;page&gt;
    *   ...
  - *   &lt;source:write src="/source/specific/path/to/context/doc/editable/my.xml" 
result="success|failure" action="new"&gt;
  - *           source specific error message
  - *   &lt;/source:write&gt;
  + *   &lt;source:insert xmlns:source="http://apache.org/cocoon/source/1.0"&gt;
  + *     &lt;source:source&gt;context://doc/editable/my.xml&lt;/source:source&gt;     
 
  + *     &lt;source:path&gt;page/content&lt;/source:path&gt;      
  + *     &lt;source:fragment&gt;
  + *       &lt;p&gt;This paragraph gets &lt;emp&gt;inserted&lt;/emp&gt;.&lt;/p&gt;
  + *       &lt;p&gt;With this one, at the end of the content.&lt;/p&gt;
  + *     &lt;/source:fragment&gt;
  + *   &lt;/source:insert&gt;
    *   ...
    * &lt;/page&gt;
    * </pre>
    *
  - * <P>Inserting of XML fragments:</p>
  - * This implementation allows the inserting of an xml fragment into a
  - * source.
  + * <p>Input XML document example (insert at beginning):</p>
  + * <pre>
  + * &lt;page&gt;
  + *   ...
  + *   &lt;source:insert&gt;
  + *     &lt;source:source&gt;context://doc/editable/my.xml&lt;/source:source&gt;
  + *     &lt;source:path&gt;page&lt;/source:path&gt;
  + *     &lt;source:replace&gt;content&lt;/source:replace&gt;
  + *     &lt;source:reinsert&gt;content&lt;/source:reinsert&gt;
  + *     &lt;source:fragment&gt;
  + *       &lt;content&gt;
  + *         &lt;p&gt;This new paragraph gets inserted &lt;emp&gt;before&lt;/emp&gt; 
the other ones.&lt;/p&gt;
  + *       &lt;/content&gt;
  + *     &lt;/source:fragment&gt;
  + *    &lt;source:insert&gt;
  + *   ...
  + * &lt;/page&gt;
  + * </pre>
    *
  + * <p>Input XML document example (replace):</p>
    * <pre>
  - * &lt;page xmlns:source="http://apache.org/cocoon/source/1.0"&gt;
  + * &lt;page&gt;
    *   ...
  - * &lt;source:insert&gt;
  - *   &lt;source:source&gt;The SRC&lt;/source:source&gt;
  - *   &lt;source:path&gt;XPath denoting the position to insert&lt;/source:path&gt;
  - *   &lt;source:fragment&gt;the xml fragment&lt;/source:fragment&gt;
  - * &lt;/source:insert&gt;
  + *   &lt;source:insert xmlns:source="http://apache.org/cocoon/source/1.0"&gt;
  + *     &lt;source:source&gt;context://doc/editable/my.xml"&lt;/source:source&gt;    
  
  + *     &lt;source:path&gt;page/content&lt;/source:path&gt;      
  + *     &lt;source:replace&gt;p[1]&lt;/source:replace&gt;      
  + *     &lt;source:fragment&gt;
  + *       &lt;p&gt;This paragraph &lt;emp&gt;replaces&lt;/emp&gt; the first 
paragraph.&lt;/p&gt;
  + *     &lt;/source:fragment&gt;
  + *   &lt;/source:insert&gt;
    *   ...
    * &lt;/page&gt;
    * </pre>
    *
  - * By default, the fragment is always inserted (added). It is possible to specify
  - * a node (by an XPath) which will be replaced if it exists.
  + * <p>Output XML document example:</p>
    * <pre>
  - * &lt;page xmlns:source="http://apache.org/cocoon/source/1.0"&gt;
  + * &lt;page&gt;
    *   ...
  - * &lt;source:insert&gt;
  - *   &lt;source:source&gt;The SRC&lt;/source:source&gt;
  - *   &lt;source:path&gt;XPath denoting the position to insert&lt;/source:path&gt;
  - *   &lt;source:fragment&gt;the xml fragment&lt;/source:fragment&gt;
  - *   &lt;source:replace&gt;XPath denoting a criteria for which node will be 
replaced&lt;/source:replace>
  - * &lt;/source:insert&gt;
  + *   &lt;sourceResult xmlns:source="http://apache.org/cocoon/source/1.0"&gt;
  + *     &lt;action&gt;new|overwritten|none&lt;/action&gt;
  + *     &lt;behaviour&gt;write|insert&lt;behaviour&gt;
  + *     &lt;execution&gt;success|failure&lt;/execution&gt;
  + *     &lt;serializer&gt;xml&lt;/serializer&gt;
  + *     
&lt;source&gt;file:/source/specific/path/to/context/doc/editable/my.xml&lt;/source&gt;
  + *   &lt;/sourceResult&gt;
    *   ...
    * &lt;/page&gt;
    * </pre>
    *
  - * The information for <code>replace</code> has to be relative to path, but can
  - *  specify a subnode of the node the be replaced.
    *
    * The XPath specification is very complicated. So here is an example for the 
sitemap:
    * <pre>
  @@ -168,9 +213,9 @@
    *   &lt;source:source&gt;sitemap.xmap&lt;/source:source&gt;
    *   &lt;source:path&gt;/*[namespace-uri()="http://apache.org/cocoon/sitemap/1.0"; 
and local-name()="sitemap"]/*[namespace-uri()="http://apache.org/cocoon/sitemap/1.0"; 
and 
local-name()="components"]/*[namespace-uri()="http://apache.org/cocoon/sitemap/1.0"; 
and local-name()="generators"]&lt;/source:path&gt;
    *   &lt;source:fragment&gt;
  - *           <generator name="file" xmln="http://apache.org/cocoon/sitemap/1.0";>
  - *                   <test/>
  - *           </generator>
  + *           &lt;generator name="file" 
xmln="http://apache.org/cocoon/sitemap/1.0"&gt;
  + *                   &lt;test/&gt;
  + *           &lt;/generator&gt;
    *   &lt;/source:fragment&gt;
    *   &lt;source:replace&gt;*[namespace-uri()="http://apache.org/cocoon/sitemap/1.0"; 
and local-name()="generator" and attribute::name="file"]&lt;/source:replace&gt;
    * &lt;/source:insert&gt;
  @@ -178,23 +223,35 @@
    * &lt;/page&gt;
    * </pre>
    *
  - * This insert replaces (if it exists) the file generator definition with a new one.
  + * <p>This insert replaces (if it exists) the file generator definition with a new 
one.
    * As the sitemap uses namespaces the XPath for the generator is rather complicated.
    * Due to this it is necessary that the node specified by path exists if namespaces
  - * are used! Otherwise a node with the name * would be created...
  + * are used! Otherwise a node with the name * would be created...</p>
    *
  - *  The create attribute of insert. If this is set
  + *  <p>The create attribute of insert. If this is set
    *  to true (default is true), the file is created if it does not exists.
    *  If it is set to false, it is not created, making insert a real insert.
  - *  create is only usable for files!
  - *  In addition the overwrite attribute is used to check if replacing is allowed.
  + *  create is only usable for files!</p>
  + *  <p>In addition the overwrite attribute is used to check if replacing is allowed.
    *  If overwrite is true (the default) the node is replaced. If it is false
  - *  the node is not inserted if the replace node is available.
  + *  the node is not inserted if the replace node is available.</p>
    *
  - * The &lt;session:reinsert&gt; option can be used to
  + *  <p>[JQ] - the way I understand this, looking at the code: 
  + *  <pre>
  + *   if 'replace' is not specified, your 'fragment' is appended as a child of 
'path'.
  + *   if 'replace' is specified and it exists and 'overwrite' is true, your 
'fragment' is inserted in 'path', before 'replace' and then 'replace' is deleted.
  + *   if 'replace' is specified and it exists and 'overwrite' is false, no action 
occurs.
  + *   if 'replace' is specified and it does not exist and 'overwrite' is true, your 
'fragment' is appended as a child of 'path'.
  + *   if 'replace' is specified and it does not exist and 'overwrite' is false, your 
'fragment' is appended as a child of 'path'.
  + *   if 'reinsert' is specified and it does not exist, no action occurs.
  + *  </pre></p>
  + *
  + * The &lt;source:reinsert&gt; option can be used to
    * reinsert a replaced node at a given path in the new fragment.
    *
  + *
    * TODO: Use the serializer instead of the XMLUtils for inserting of fragments
  + * TODO: Add a &lt;source:before/&gt; tag.
    *
    * @author <a href="mailto:[EMAIL PROTECTED]";>Carsten Ziegeler</a>
    * @author <a href="mailto:[EMAIL PROTECTED]";>Jeremy Quinn</a>
  @@ -203,32 +260,34 @@
   public class SourceWritingTransformer
       extends AbstractSAXTransformer {
   
  -    private static String SWT_URI = "http://apache.org/cocoon/source/1.0";;
  -    private static String SWT_ELEMENT = "write";
  -    private static String SWT_RESULT_ATTRIBUTE= "result";
  -    private static String SWT_SRC_ATTRIBUTE = "src";
  -    private static String SWT_ACTION_ATTRIBUTE = "action";
  -    private static String SWT_SERIALIZER_ATTRIBUTE = "serializer";
  -    private static String SWT_RESULT_FAILED = "failed";
  -    private static String SWT_RESULT_SUCCESS = "success";
  -    private static String SWT_ACTION_NONE = "none";
  -    private static String SWT_ACTION_NEW = "new";
  -    private static String SWT_ACTION_OVER = "overwritten";
  -
  +    public static final String SWT_URI = "http://apache.org/cocoon/source/1.0";;
  +    public static final String DEFAULT_SERIALIZER = "xml";
  +    
  +             /** incoming elements */
  +    public static final String WRITE_ELEMENT = "write";
       public static final String INSERT_ELEMENT = "insert";
  -    public static final String INSERT_CREATE_ATTRIBUTE = "create";
  -    public static final String INSERT_OVERWRITE_ATTRIBUTE = "overwrite";
  -
       public static final String PATH_ELEMENT = "path";
  -
       public static final String FRAGMENT_ELEMENT = "fragment";
  -
       public static final String REPLACE_ELEMENT = "replace";
  -
       public static final String SOURCE_ELEMENT = "source";
  -
       public static final String REINSERT_ELEMENT = "reinsert";
  -
  +    /** outgoing elements */
  +    public static final String RESULT_ELEMENT = "sourceResult";
  +    public static final String EXECUTION_ELEMENT = "execution";
  +    public static final String BEHAVIOUR_ELEMENT = "behaviour";
  +    public static final String ACTION_ELEMENT = "action";
  +    public static final String MESSAGE_ELEMENT = "message";
  +    public static final String SERIALIZER_ELEMENT = "serializer";
  +             /** main (write or insert) tag attributes */
  +    public static final String SERIALIZER_ATTRIBUTE = "serializer";
  +    public static final String CREATE_ATTRIBUTE = "create";
  +    public static final String OVERWRITE_ATTRIBUTE = "overwrite";
  +             /** results */
  +    public static final String RESULT_FAILED = "failed";
  +    public static final String RESULT_SUCCESS = "success";
  +    public static final String ACTION_NONE = "none";
  +    public static final String ACTION_NEW = "new";
  +    public static final String ACTION_OVER = "overwritten";
       /** The current state */
       private static final int STATE_OUTSIDE  = 0;
       private static final int STATE_INSERT   = 1;
  @@ -238,41 +297,13 @@
       private static final int STATE_REPLACE  = 5;
       private static final int STATE_FILE     = 6;
       private static final int STATE_REINSERT = 7;
  +    private static final int STATE_WRITE    = 8;
       private int state;
  +    private int parent_state;
   
       /** The configured serializer name */
       protected String configuredSerializerName;
   
  -    /** The ContentHandler instance */
  -    protected XMLConsumer ch;                   // is XMLConsumer suitable for this 
purpose?
  -
  -
  -    /** Are we using a Serializer? */
  -    private boolean isSerializer = false;
  -
  -    /** Current Serializer name. */
  -    private String serializer_name = null;
  -
  -    /** Current target name. */
  -    private String target = null;
  -
  -    /** Current OutputStream. */
  -    private OutputStream os = null;
  -
  -    /** Current status of outputting the file. */
  -    private boolean failed = true;
  -
  -    /** Current error message. */
  -    private String message = null;
  -
  -    /** Does the file exist, before we try to make it? */
  -    private boolean exists = false;
  -
  -    /** the Source. */
  -    private Source source = null;
  -
  -        /** the WritableSource. */
  -    private WriteableSource wsource = null;
   
       /**
        * Constructor
  @@ -289,7 +320,7 @@
       public void configure(Configuration configuration)
       throws ConfigurationException {
           super.configure( configuration );
  -        this.configuredSerializerName = 
configuration.getChild(SWT_SERIALIZER_ATTRIBUTE).getValue("xml");
  +        this.configuredSerializerName = 
configuration.getChild(SERIALIZER_ATTRIBUTE).getValue(DEFAULT_SERIALIZER);
       }
   
       /**
  @@ -299,10 +330,7 @@
       public void setup(SourceResolver resolver, Map objectModel, String src, 
Parameters par)
       throws ProcessingException, SAXException, IOException {
           super.setup(resolver, objectModel, src, par);
  -        this.serializer_name = par.getParameter(SWT_SERIALIZER_ATTRIBUTE, 
this.configuredSerializerName);
  -        if (this.serializer_name != null && this.getLogger().isDebugEnabled() ) {
  -            this.getLogger().debug("Setup, using serializer: " + 
this.serializer_name);
  -        }
  +        this.configuredSerializerName = par.getParameter(SERIALIZER_ATTRIBUTE, 
this.configuredSerializerName);
           this.state = STATE_OUTSIDE;
       }
   
  @@ -329,30 +357,51 @@
           if (name.equals(INSERT_ELEMENT)
               && this.state == STATE_OUTSIDE) {
               this.state = STATE_INSERT;
  -            if (attr.getValue(INSERT_CREATE_ATTRIBUTE) != null
  -                && attr.getValue(INSERT_CREATE_ATTRIBUTE).equals("false")) {
  +            this.parent_state = STATE_INSERT;
  +            if (attr.getValue(CREATE_ATTRIBUTE) != null
  +                && attr.getValue(CREATE_ATTRIBUTE).equals("false")) {
                   this.stack.push("false");
               } else {
                   this.stack.push("true");
               }
  -            if (attr.getValue(INSERT_OVERWRITE_ATTRIBUTE) != null
  -                && attr.getValue(INSERT_OVERWRITE_ATTRIBUTE).equals("false")) {
  +            if (attr.getValue(OVERWRITE_ATTRIBUTE) != null
  +                && attr.getValue(OVERWRITE_ATTRIBUTE).equals("false")) {
                   this.stack.push("false");
               } else {
                   this.stack.push("true");
               }
  +            this.stack.push(attr.getValue(SERIALIZER_ATTRIBUTE));
               this.stack.push("INSERT");
   
  +        // Element: write
  +        } else if (name.equals(WRITE_ELEMENT)
  +            && this.state == STATE_OUTSIDE) {
  +            this.state = STATE_WRITE;
  +            this.parent_state = STATE_WRITE;
  +            if (attr.getValue(CREATE_ATTRIBUTE) != null
  +                && attr.getValue(CREATE_ATTRIBUTE).equals("false")) {
  +                this.stack.push("false");
  +            } else {
  +                this.stack.push("true"); // default value
  +            }
  +            if (attr.getValue(OVERWRITE_ATTRIBUTE) != null
  +                && attr.getValue(OVERWRITE_ATTRIBUTE).equals("false")) {
  +                this.stack.push("false");
  +            } else {
  +                this.stack.push("true"); // default value
  +            }
  +            this.stack.push(attr.getValue(SERIALIZER_ATTRIBUTE));
  +            this.stack.push("WRITE");
   
           // Element: file
           } else if (name.equals(SOURCE_ELEMENT)
  -                   && this.state == STATE_INSERT) {
  +                   && (this.state == STATE_INSERT || this.state == STATE_WRITE)) {
               this.state = STATE_FILE;
               this.startTextRecording();
   
           // Element: path
           } else if (name.equals(PATH_ELEMENT)
  -                   && this.state == STATE_INSERT) {
  +                   && (this.state == STATE_INSERT || this.state == STATE_WRITE)) {
               this.state = STATE_PATH;
               this.startTextRecording();
   
  @@ -364,7 +413,7 @@
   
           // Element: fragment
           } else if (name.equals(FRAGMENT_ELEMENT)
  -                   && this.state == STATE_INSERT) {
  +                   &&  (this.state == STATE_INSERT || this.state == STATE_WRITE)) {
               this.state = STATE_FRAGMENT;
               this.startRecording();
   
  @@ -374,63 +423,6 @@
               this.state = STATE_REINSERT;
               this.startTextRecording();
   
  -        } else if (name.equals(SWT_ELEMENT)) {
  -            this.failed = false;
  -            this.message = null;
  -            this.target = "";
  -
  -            // look for the Source
  -            String src = attr.getValue("",SWT_SRC_ATTRIBUTE);
  -            try {
  -                this.message = "The src attribute could not be resolved";
  -                this.source = this.resolver.resolveURI(src);
  -                this.target = this.source.getSystemId();
  -
  -                this.message = "The src attribute doesn't resolve to a writeable 
source";
  -                this.wsource = (WriteableSource)this.source;
  -                this.exists = this.wsource.exists();
  -
  -                // has a Serializer been specified?
  -                String local_serializer = 
attr.getValue("",SWT_SERIALIZER_ATTRIBUTE);
  -                if (local_serializer != null) this.serializer_name = 
local_serializer;
  -                if (this.serializer_name != null) {
  -                    // Lookup the Serializer
  -                    this.message = "that Serializer does not exist";
  -                    ComponentSelector selector = null;
  -                    try {
  -                        selector = 
(ComponentSelector)manager.lookup(Serializer.ROLE + "Selector");
  -                        this.ch = (Serializer)selector.select(this.serializer_name);
  -                        this.message = "Could not open the source for writing";
  -                        this.os = this.wsource.getOutputStream();
  -                        this.message = "could not write the file";
  -                        ((Serializer)this.ch).setOutputStream(this.os);             
         // Is there a way to avoid this casting?
  -                        this.isSerializer = true;
  -                    } finally {
  -                        this.manager.release( selector );
  -                    }
  -                } else {
  -                    this.message = "could not get a ContentHandler";
  -                    this.ch = 
(XMLConsumer)((WriteableSAXSource)wsource).getContentHandler();
  -                }
  -                this.addRecorder( this.ch );
  -                this.startDocument();
  -                this.sendStartPrefixMapping();
  -
  -            } catch (Exception e) {
  -                getLogger().warn("failed, " + this.message, e);
  -                this.failed = true;
  -                try {
  -                    if (this.isSerializer) {
  -                        this.wsource.cancel(this.os);
  -                    } else {
  -                        ((WriteableSAXSource)this.wsource).cancel(this.ch);
  -                    }
  -                } catch (Exception e2) {
  -                    getLogger().warn("failed to cancel: " + this.target, e2);
  -                    this.message += " and failed to cancel";
  -                }
  -            }
  -        // default
           } else {
               super.startTransformingElement(uri, name, raw, attr);
           }
  @@ -460,7 +452,6 @@
                                 ", raw=" + raw);
           }
           if (name.equals(INSERT_ELEMENT) == true && this.state == STATE_INSERT) {
  -            this.state = STATE_OUTSIDE;
   
               // get the information from the stack
               String tag;
  @@ -483,10 +474,45 @@
                       reinsert = (String)this.stack.pop();
                   }
               } while (tag.equals("INSERT") == false);
  +            final String localSerializer = (String)this.stack.pop();
  +            final boolean overwrite = this.stack.pop().equals("true");
  +            final boolean create = this.stack.pop().equals("true");
  +
  +            this.insertFragment(fileName,
  +                                    path,
  +                                    fragment,
  +                                    replacePath,
  +                                    create,
  +                                    overwrite,
  +                                    reinsert,
  +                                    localSerializer,
  +                                    name);
  +
  +            this.state = STATE_OUTSIDE;
  +            
  +        } else if (name.equals(WRITE_ELEMENT) == true && this.state == STATE_WRITE) 
{
  +
  +            // get the information from the stack
  +            String tag;
  +            String     fileName        = null;
  +            DocumentFragment fragment  = null;
  +            String     path            = "/"; // source:write's path can be empty
  +            String     replacePath     = null;
  +            String     reinsert        = null;
  +            do {
  +                tag = (String)this.stack.pop();
  +                if (tag.equals("PATH") == true) {
  +                    path = (String)this.stack.pop();
  +                } else if (tag.equals("FILE") == true) {
  +                    fileName = (String)this.stack.pop();
  +                } else if (tag.equals("FRAGMENT") == true) {
  +                    fragment = (DocumentFragment)this.stack.pop();
  +                } 
  +            } while (tag.equals("WRITE") == false);
  +            final String localSerializer = (String)this.stack.pop();
               final boolean overwrite = this.stack.pop().equals("true");
               final boolean create = this.stack.pop().equals("true");
   
  -            // FIXME (CZ) : Overriding of serializer is not implemented yet!
               this.insertFragment(fileName,
                                       path,
                                       fragment,
  @@ -494,97 +520,41 @@
                                       create,
                                       overwrite,
                                       reinsert,
  -                                    null);
  +                                    localSerializer,
  +                                    name);
  +                                    
  +            this.state = STATE_OUTSIDE;
   
           // Element: file
           } else if (name.equals(SOURCE_ELEMENT) == true && this.state == STATE_FILE) 
{
  -            this.state = STATE_INSERT;
  +            this.state = this.parent_state;
               this.stack.push(this.endTextRecording());
               this.stack.push("FILE");
   
           // Element: path
           } else if (name.equals(PATH_ELEMENT) == true && this.state == STATE_PATH) {
  -            this.state = STATE_INSERT;
  +            this.state = this.parent_state;
               this.stack.push(this.endTextRecording());
               this.stack.push("PATH");
   
           // Element: replace
           } else if (name.equals(REPLACE_ELEMENT) == true && this.state == 
STATE_REPLACE) {
  -            this.state = STATE_INSERT;
  +            this.state = this.parent_state;
               this.stack.push(this.endTextRecording());
               this.stack.push("REPLACE");
   
           // Element: fragment
           } else if (name.equals(FRAGMENT_ELEMENT) == true && this.state == 
STATE_FRAGMENT) {
  -            this.state = STATE_INSERT;
  +            this.state = this.parent_state;
               this.stack.push(this.endRecording());
               this.stack.push("FRAGMENT");
   
           // Element: reinsert
  -        } else if (name.equals(REINSERT_ELEMENT) == true
  -                   && this.state == STATE_REINSERT) {
  -            this.state = STATE_INSERT;
  +        } else if (name.equals(REINSERT_ELEMENT) == true && this.state == 
STATE_REINSERT) {
  +            this.state = this.parent_state;
               this.stack.push(this.endTextRecording());
               this.stack.push("REINSERT");
   
  -        } else if (name.equals(SWT_ELEMENT)) {
  -            if (!this.failed) {
  -                this.sendEndPrefixMapping();
  -                this.endDocument();
  -                this.removeRecorder();
  -                // close the OutputStream
  -                try {
  -                    if (this.os != null) {
  -                        this.os.close();
  -                        this.os = null;
  -                    }
  -
  -                } catch(Exception e) {
  -                    getLogger().warn("Failed to close source", e);
  -                    this.message = "Failed to close source";
  -                    this.failed = true;
  -                    try {
  -                        this.message = "Failed to cancel source";
  -                        if (this.isSerializer) {
  -                            this.wsource.cancel(this.os);
  -                        } else {
  -                            ((WriteableSAXSource)this.wsource).cancel(this.ch);
  -                        }
  -                    } catch (Exception e2) {
  -                        getLogger().warn("failed to cancel: " + this.target, e2);
  -                    }
  -                } finally {
  -                    if (this.source != null) {
  -                        this.resolver.release( this.source );
  -                        this.source = null;
  -                    }
  -                }
  -                if (!this.failed) {
  -                    this.wsource = null;
  -                }
  -
  -                // Report result
  -                String result = (this.failed) ? SWT_RESULT_FAILED : 
SWT_RESULT_SUCCESS;
  -                String action = SWT_ACTION_NONE;
  -                if (!this.failed){
  -                    if (this.exists) {
  -                        action = SWT_ACTION_OVER;
  -                    } else {
  -                        action = SWT_ACTION_NEW;
  -                    }
  -                }
  -                AttributesImpl attrs = new AttributesImpl();
  -                attrs.addAttribute(null, SWT_SRC_ATTRIBUTE, SWT_SRC_ATTRIBUTE, 
"CDATA", this.target);
  -                attrs.addAttribute(null, SWT_ACTION_ATTRIBUTE, 
SWT_ACTION_ATTRIBUTE, "CDATA", action);
  -                attrs.addAttribute(null, SWT_RESULT_ATTRIBUTE, 
SWT_RESULT_ATTRIBUTE, "CDATA", result);
  -                if (this.serializer_name != null) attrs.addAttribute(null, 
SWT_SERIALIZER_ATTRIBUTE, SWT_SERIALIZER_ATTRIBUTE, "CDATA", this.serializer_name);
  -                super.contentHandler.startElement(uri, name, raw, attrs);
  -                if (this.message != null && this.failed == true) 
super.characters(this.message.toCharArray(), 0, this.message.length());
  -                super.contentHandler.endElement(uri, name, raw);
  -                if (this.getLogger().isDebugEnabled()) {
  -                    this.getLogger().debug("Source Written");
  -                }
  -            }
           // default
           } else {
               super.endTransformingElement(uri, name, raw);
  @@ -596,29 +566,6 @@
       }
   
       public void recycle() {
  -        if (this.wsource != null) {
  -            getLogger().error("cancelled by recycle() method");
  -            if (this.os != null) {
  -                try {
  -                    this.wsource.cancel(this.os);
  -                } catch (Exception e) {
  -                    getLogger().error("failed to cancel in recycle() method: 
OutputStream");
  -                }
  -            } else if (this.ch != null) {
  -                try {
  -                    ((WriteableSAXSource)this.wsource).cancel(this.ch);
  -                } catch (Exception e) {
  -                    getLogger().error("failed to cancel in recycle() method: 
ContentHandler");
  -                }
  -            }
  -        }
  -        if (this.source != null) {
  -            this.resolver.release( this.source );
  -            this.source = null;
  -        }
  -
  -        if (isSerializer) this.manager.release((Component)this.ch);
  -        this.ch = null;
           super.recycle();
       }
   
  @@ -641,7 +588,8 @@
        *                    does not exists.
        * @param reinsertPath If specified and a node is replaced , all children of
        *                     this replaced node will be reinserted at the given path.
  -     * @param serializer  The serializer used to serialize the XML
  +     * @param localSerializer  The serializer used to serialize the XML
  +     * @param tagname     The name of the tag that triggered me 'insert' or 'write'
        */
       protected void insertFragment(String systemID,
                                     String path,
  @@ -650,7 +598,8 @@
                                     boolean create,
                                     boolean overwrite,
                                     String  reinsertPath,
  -                                  String  localSerializer)
  +                                  String  localSerializer,
  +                                  String  tagname)
       throws SAXException, IOException, ProcessingException {
           // no sync req
           if (this.getLogger().isDebugEnabled() == true) {
  @@ -677,18 +626,23 @@
           // first: read the source as a DOM
           Source source = null;
           Document resource = null;
  +        boolean failed = true;
  +        boolean exists = false;
  +        String message = "";
  +        String target = systemID;
           try {
               source = this.resolver.resolveURI( systemID );
               if ( ! (source instanceof WriteableSource)) {
                   throw new ProcessingException("Source '"+systemID+"' is not 
writeable.");
               }
               WriteableSource ws = (WriteableSource)source;
  -            if ( ws.exists() ) {
  -
  +            exists = ws.exists();
  +            target = source.getSystemId();
  +            if ( exists == true && this.state == STATE_INSERT ) {
  +                                                             message = "content 
inserted at: " + path;
                   resource = SourceUtil.toDOM( source, this.manager );
                   // import the fragment
                   Node importNode = resource.importNode(fragment, true);
  -
                   // get the node
                   Node parent = XMLUtil.selectSingleNode(resource, path);
   
  @@ -696,96 +650,164 @@
                   if (replacePath != null) {
                       try {
                           Node replaceNode = XMLUtil.getSingleNode(parent, 
replacePath);
  -
                           // now get the parent of this node until it is the parent 
node for insertion
                           while (replaceNode != null && 
replaceNode.getParentNode().equals(parent) == false) {
                              replaceNode = replaceNode.getParentNode();
                           }
                           if (replaceNode != null) {
                               if (overwrite == true) {
  -                                parent.replaceChild(importNode, replaceNode);
  +                                                                             
parent.replaceChild(importNode, replaceNode);
  +                                                                                    
                                         message += ", replacing: " + replacePath;
                                   if (reinsertPath != null) {
                                       Node insertAt = 
XMLUtil.getSingleNode(importNode, reinsertPath);
                                       if (insertAt != null) {
                                           while (replaceNode.hasChildNodes() == true) 
{
                                               
insertAt.appendChild(replaceNode.getFirstChild());
                                           }
  +                                    } else { // reinsert point null
  +                                                                                    
                                                                 message = "replace 
failed, could not find your reinsert path: " + reinsertPath;
  +                                                                                    
                                                                 resource = null;
                                       }
                                   }
  +                            } else { // overwrite was false
  +                             message = "replace failed, no overwrite allowed.";
  +                             resource = null;/**/
                               }
  -                        } else {
  +                        } else { // specified replaceNode was not found
                               parent.appendChild(importNode);
                           }
                       } catch (javax.xml.transform.TransformerException sax) {
                           throw new ProcessingException("TransformerException: " + 
sax, sax);
                       }
  -                } else { // no replace
  +                } else { // no replace path, just do an insert at end
                       parent.appendChild(importNode);
                   }
               } else if (create == true) {
  -
  -                Parser parser = (Parser)this.manager.lookup(Parser.ROLE);
  -                try {
  -                    resource = parser.createDocument();
  -                } finally {
  -                    this.manager.release( parser );
  -                }
  -
  -                // import the fragment
  -                Node importNode = resource.importNode(fragment, true);
  -                // get the node
  -                Node parent = XMLUtil.selectSingleNode(resource, path);
  -                // add fragment
  -                parent.appendChild(importNode);
  +                                                             Parser parser = 
(Parser)this.manager.lookup(Parser.ROLE);
  +                                                             try {
  +                                                                             
resource = parser.createDocument();
  +                                                             } finally {
  +                                                                             
this.manager.release( parser );
  +                                                             }
  +                                                             // import the fragment
  +                                                             Node importNode = 
resource.importNode(fragment, true);
  +                                                             if ( path.equals("") ) 
{  // this is allowed in write
  +                                                                     
resource.appendChild(importNode);
  +                                                                     message = 
"entire source overwritten";
  +                                                                     
  +                                                             } else {
  +                                                                     // get the node
  +                                                                     Node parent = 
XMLUtil.selectSingleNode(resource, path);
  +                                                                     // add fragment
  +                                                                     
parent.appendChild(importNode);
  +                                                                     message = 
"content appended to: " + path;
  +                                                             }
  +            } else {
  +                                                     message = "create not allowed";
  +             resource = null;/**/
               }
   
               // write source
               if ( resource != null) {
                   resource.normalize();
  -
                   if (source instanceof WriteableSAXSource) {
                       ContentHandler contentHandler = 
((WriteableSAXSource)ws).getContentHandler();
                       DOMStreamer streamer = new DOMStreamer(contentHandler);
                       streamer.stream(resource);
  +                    localSerializer = "null";
  +                    failed = false;
                   } else {
                       // use serializer
                       if (localSerializer == null) localSerializer = 
this.configuredSerializerName;
                       if (localSerializer != null) {
  -                        // Lookup the Serializer
  -                        ComponentSelector selector = null;
  -                        Serializer serializer = null;
  -                        OutputStream oStream = null;
  -                        try {
  -                            selector = 
(ComponentSelector)manager.lookup(Serializer.ROLE + "Selector");
  -                            serializer = 
(Serializer)selector.select(localSerializer);
  -                            oStream = ws.getOutputStream();
  -                            serializer.setOutputStream(oStream);
  -                            DOMStreamer streamer = new DOMStreamer(serializer);
  -                            streamer.stream(resource);
  -                        } finally {
  -                            if (oStream != null) {
  -                                try {
  -                                    oStream.flush();
  -                                    oStream.close();
  -                                } catch (Exception ignore) {}
  -                            }
  -                            if ( selector != null ) {
  -                                selector.release( serializer );
  -                                this.manager.release( selector );
  -                            }
  -                        }
  +                                                                                    
 // Lookup the Serializer
  +                                                                                    
 ComponentSelector selector = null;
  +                                                                                    
 Serializer serializer = null;
  +                                                                                    
 OutputStream oStream = null;
  +                                                                                    
 try {
  +                                                                                    
         selector = (ComponentSelector)manager.lookup(Serializer.ROLE + "Selector");
  +                                                                                    
         serializer = (Serializer)selector.select(localSerializer);
  +                                                                                    
         oStream = ws.getOutputStream();
  +                                                                                    
         serializer.setOutputStream(oStream);
  +                                                                                    
         DOMStreamer streamer = new DOMStreamer(serializer);
  +                                                                                    
         streamer.stream(resource);
  +                                                                                    
 } finally {
  +                                                                                    
         if (oStream != null) {
  +                                                                                    
                 oStream.flush();
  +                                                                                    
                 try {
  +                                                                                    
                         oStream.close();
  +                                                                                    
                         failed = false;
  +                                                                                    
                 } catch (Throwable t) {
  +                                                                                    
                         if (this.getLogger().isDebugEnabled() == true) {
  +                                                                                    
                                 this.getLogger().debug("FAIL (oStream.close) 
exception"+t);
  +                                                                                    
                                 throw new ProcessingException("Could not process your 
document.", t);
  +                                                                                    
                         }
  +                                                                                    
                 } finally {
  +                                                                                    
                         if ( selector != null ) {
  +                                                                                    
                                         selector.release( serializer );
  +                                                                                    
                                         this.manager.release( selector ); 
  +                                                                                    
                         }
  +                                                                                    
                 }
  +                                                                                    
         }
  +                                                                                    
 }
                       } else {
  -                        throw new ProcessingException("No serializer specified for 
writing to source " + systemID);
  +                                                                                    
 if (this.getLogger().isDebugEnabled() == true) {
  +                                                                                    
         this.getLogger().debug("ERROR no serializer");
  +                                                                                    
 }
  +                                                                                    
 //throw new ProcessingException("No serializer specified for writing to source " + 
systemID);
  +                                                                                    
 message = "That source requires a serializer, please add the appropirate tag to your 
code.";
                       }
                   }
  -            }
  +                                             }
  +        } catch (DOMException de) {
  +                                             if (this.getLogger().isDebugEnabled() 
== true) {
  +                                                             
this.getLogger().debug("FAIL exception: "+de);
  +                                             }
  +            //throw new ProcessingException("Could not process your document.", de);
  +            message = "There was a problem manipulating your document: " + de;
           } catch (ComponentException ce) {
  -            throw new ProcessingException("Unable to lookup component.", ce);
  +                                             if (this.getLogger().isDebugEnabled() 
== true) {
  +                                                             
this.getLogger().debug("FAIL exception: "+ce);
  +                                             }
  +            //throw new ProcessingException("Unable to lookup component.", ce);
  +            message = "There was a problem looking up a component: " + ce;
           } catch (SourceException se) {
  -            throw SourceUtil.handle("Error during resolving "+systemID, se);
  +                                             if (this.getLogger().isDebugEnabled() 
== true) {
  +                                                             
this.getLogger().debug("FAIL exception: "+se);
  +                                             }
  +            //throw new ProcessingException("Error during resolving "+systemID, se);
  +            message = "There was a problem resolving that source: [" + systemID + 
"] : " + se;
           } finally {
               this.resolver.release( source );
           }
  +        
  +                             // Report result
  +                             String result = (failed) ? RESULT_FAILED : 
RESULT_SUCCESS;
  +                             String action = ACTION_NONE;
  +                             if (!failed) { action = (exists) ? ACTION_OVER : 
ACTION_NEW; }
  +
  +                             sendStartElementEvent(RESULT_ELEMENT);
  +                                     sendStartElementEvent(EXECUTION_ELEMENT);
  +                                             sendTextEvent(result);
  +                                     sendEndElementEvent(EXECUTION_ELEMENT);
  +                                     sendStartElementEvent(MESSAGE_ELEMENT);
  +                                             sendTextEvent(message);
  +                                     sendEndElementEvent(MESSAGE_ELEMENT);
  +                                     sendStartElementEvent(BEHAVIOUR_ELEMENT);
  +                                             sendTextEvent(tagname);
  +                                     sendEndElementEvent(BEHAVIOUR_ELEMENT);
  +                                     sendStartElementEvent(ACTION_ELEMENT);
  +                                             sendTextEvent(action);
  +                                     sendEndElementEvent(ACTION_ELEMENT);
  +                                     sendStartElementEvent(SOURCE_ELEMENT);
  +                                             sendTextEvent(target);
  +                                     sendEndElementEvent(SOURCE_ELEMENT);
  +                                     if (localSerializer != null) {
  +                                             
sendStartElementEvent(SERIALIZER_ELEMENT);
  +                                                     sendTextEvent(localSerializer);
  +                                             
sendEndElementEvent(SERIALIZER_ELEMENT);
  +                                     }
  +                             sendEndElementEvent(RESULT_ELEMENT);
   
           if (this.getLogger().isDebugEnabled() == true) {
               this.getLogger().debug("END insertFragment");
  
  
  

----------------------------------------------------------------------
In case of troubles, e-mail:     [EMAIL PROTECTED]
To unsubscribe, e-mail:          [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to