cziegeler 02/05/07 01:17:46
Modified: src/documentation/xdocs/plan to-avalon.xml
src/scratchpad/src/org/apache/cocoon/transformation
SourceWritingTransformer.java
Log:
Start merging SourceWritingTransformer and InsertTransformer
Revision Changes Path
1.3 +8 -8 xml-cocoon2/src/documentation/xdocs/plan/to-avalon.xml
Index: to-avalon.xml
===================================================================
RCS file: /home/cvs/xml-cocoon2/src/documentation/xdocs/plan/to-avalon.xml,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- to-avalon.xml 9 Apr 2002 06:37:55 -0000 1.2
+++ to-avalon.xml 7 May 2002 08:17:46 -0000 1.3
@@ -30,7 +30,7 @@
<li>XMLFragment</li>
<li>Parser (done)</li>
<li>XMLSerializer/XMLDeserializer</li>
- <li>XSLTProcessor</li>
+ <li>XSLTProcessor (done)</li>
</ul>
<p>Everything dealing with Source objects. (This is the part
@@ -38,11 +38,11 @@
</p>
<ul>
- <li>SourceResolver</li>
- <li>SourceHandler</li>
- <li>SourceFactory</li>
- <li>Source</li>
- <li>ModifiableSource</li>
+ <li>SourceResolver (done)</li>
+ <li>SourceHandler (done)</li>
+ <li>SourceFactory (done)</li>
+ <li>Source (done)</li>
+ <li>ModifiableSource (done)</li>
</ul>
<p>List of Implementations:</p>
@@ -50,8 +50,8 @@
<li>AbstractXMLConsumer</li>
<li>JaxpParser, XercesParser (done)</li>
<li>XMLByteStreamCompiler/XMLByteStreamInterpreter</li>
- <li>Everything dealing with Source objects</li>
- <li>XSLTProcessorImpl</li>
+ <li>Everything dealing with Source objects (done)</li>
+ <li>XSLTProcessorImpl (done)</li>
<li><link href="catalog.html">Entity Catalogs </link>
- the entity resolver (done)</li>
</ul>
1.4 +525 -347
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/transformation/SourceWritingTransformer.java
Index: SourceWritingTransformer.java
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/transformation/SourceWritingTransformer.java,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- SourceWritingTransformer.java 22 Mar 2002 13:14:55 -0000 1.3
+++ SourceWritingTransformer.java 7 May 2002 08:17:46 -0000 1.4
@@ -63,16 +63,22 @@
import org.apache.cocoon.serialization.Serializer;
import org.apache.cocoon.caching.CacheValidity;
import org.apache.cocoon.caching.Cacheable;
-import org.apache.cocoon.environment.Source;
import org.apache.cocoon.environment.SourceResolver;
import org.apache.cocoon.environment.WriteableSource;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.ResourceNotFoundException;
+import org.apache.cocoon.webapps.session.connector.ResourceConnector;
+import org.apache.cocoon.webapps.session.transformation.AbstractSessionTransformer;
+import org.apache.cocoon.webapps.session.xml.XMLUtil;
import org.apache.cocoon.xml.XMLConsumer;
+import org.apache.cocoon.xml.XMLUtils;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceException;
+import org.w3c.dom.*;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
-import java.lang.SecurityException;
+import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
@@ -119,11 +125,80 @@
* </page>
* </pre>
*
+ * <P>Inserting of XML fragments:</p>
+ * This implementation allows the inserting of an xml fragment into a
+ * source.
+ *
+ * <pre>
+ * <page xmlns:source="http://apache.org/cocoon/source/1.0">
+ * ...
+ * <source:insert>
+ * <source:source>The SRC</source:source>
+ * <source:path>XPath denoting the position to insert</source:path>
+ * <source:fragment>the xml fragment</source:fragment>
+ * </source:insert>
+ * ...
+ * </page>
+ * </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.
+ * <pre>
+ * <page xmlns:source="http://apache.org/cocoon/source/1.0">
+ * ...
+ * <source:insert>
+ * <source:source>The SRC</source:source>
+ * <source:path>XPath denoting the position to insert</source:path>
+ * <source:fragment>the xml fragment</source:fragment>
+ * <source:replace>XPath denoting a criteria for which node will be
replaced</source:replace>
+ * </source:insert>
+ * ...
+ * </page>
+ * </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>
+ * <page xmlns:source="http://apache.org/cocoon/source/1.0">
+ * ...
+ * <source:insert>
+ * <source:source>sitemap.xmap</source:source>
+ * <source:path>/*[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"]</source:path>
+ * <source:fragment>
+ * <generator name="file" xmln="http://apache.org/cocoon/sitemap/1.0">
+ * <test/>
+ * </generator>
+ * </source:fragment>
+ * <source:replace>*[namespace-uri()="http://apache.org/cocoon/sitemap/1.0"
and local-name()="generator" and attribute::name="file"]</source:replace>
+ * </source:insert>
+ * ...
+ * </page>
+ * </pre>
+ *
+ * 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...
+ *
+ * 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.
+ * 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 <session:reinsert> option can be used to
+ * reinsert a replaced node at a given path in the new fragment.
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Carsten Ziegeler</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Jeremy Quinn</a>
*
*/
-public class SourceWritingTransformer extends AbstractTransformer
- implements Disposable, Configurable, Composable {
+public class SourceWritingTransformer
+ extends AbstractSessionTransformer {
private static String SWT_URI = "http://apache.org/cocoon/source/1.0";
private static String SWT_ELEMENT = "write";
@@ -137,12 +212,33 @@
private static String SWT_ACTION_NEW = "new";
private static String SWT_ACTION_OVER = "overwritten";
+ public static final String INSERT_ELEMENT = "insert";
+ public static final String INSERT_CREATE_ATTRIBUTE = "create";
+ public static final String INSERT_OVERWRITE_ATTRIBUTE = "overwrite";
- /** The <code>SourceResolver</code> */
- protected SourceResolver sourceResolver;
+ public static final String PATH_ELEMENT = "path";
- /** The current <code>ComponentManager</code>. */
- protected ComponentManager manager = null;
+ public static final String FRAGMENT_ELEMENT = "fragment";
+
+ public static final String REPLACE_ELEMENT = "replace";
+
+ public static final String FILE_ELEMENT = "file";
+
+ public static final String REINSERT_ELEMENT = "reinsert";
+
+ /** The current state */
+ private static final int STATE_OUTSIDE = 0;
+ private static final int STATE_INSERT = 1;
+ private static final int STATE_RESOURCE = 2;
+ private static final int STATE_PATH = 3;
+ private static final int STATE_FRAGMENT = 4;
+ private static final int STATE_REPLACE = 5;
+ private static final int STATE_FILE = 6;
+ private static final int STATE_REINSERT = 7;
+ private int state;
+
+ /** The configured serializer name */
+ protected String configuredSerializerName;
/** The ContentHandler instance */
protected XMLConsumer ch; // is XMLConsumer suitable for this
purpose?
@@ -169,38 +265,28 @@
/** Does the file exist, before we try to make it? */
private boolean exists = false;
- /** True when inside <write> element. */
- private boolean processing;
-
- /** the Source. */
+ /** the Source. */
private Source source = null;
- /** the WritableSource. */
+ /** the WritableSource. */
private WriteableSource wsource = null;
-
-
- public void WriteableSourceTransformer() {
- }
-
/**
- * Set the current <code>ComponentManager</code> instance used by this
- * <code>Composable</code>.
+ * Constructor
+ * Set the namespace
*/
- public void compose(ComponentManager manager) throws ComponentException {
- this.manager=manager; // We need this later to get the Serializer, if it is
required
+ public SourceWritingTransformer() {
+ this.namespaceURI = SWT_URI;
}
/**
* Get the current <code>Configuration</code> instance used by this
* <code>Configurable</code>.
*/
- public void configure(Configuration configuration) throws
ConfigurationException {
- try {
- this.serializer_name =
configuration.getChild(SWT_SERIALIZER_ATTRIBUTE).getValue();
- } catch (Exception e) {
- getLogger().debug("Configuration - no serializer yet");
- }
+ public void configure(Configuration configuration)
+ throws ConfigurationException {
+ super.configure( configuration );
+ this.configuredSerializerName =
configuration.getChild(SWT_SERIALIZER_ATTRIBUTE).getValue(null);
}
/**
@@ -209,37 +295,12 @@
*/
public void setup(SourceResolver resolver, Map objectModel, String src,
Parameters par)
throws ProcessingException, SAXException, IOException {
- this.sourceResolver = resolver; // save it for later, when we
know the filepath to save to
- this.serializer_name =
par.getParameter(SWT_SERIALIZER_ATTRIBUTE, this.serializer_name);
- if (this.serializer_name != null)
- getLogger().debug("Setup, using serializer: " +
this.serializer_name);
- }
-
- /**
- * Begin the scope of a prefix-URI Namespace mapping.
- *
- * @param prefix The Namespace prefix being declared.
- * @param uri The Namespace URI the prefix is mapped to.
- */
- public void startPrefixMapping(String prefix, String uri) throws SAXException {
- if (!this.processing) {
- super.startPrefixMapping(prefix,uri);
- } else if (this.ch != null){
- this.ch.startPrefixMapping(prefix, uri);
- }
- }
-
- /**
- * End the scope of a prefix-URI mapping.
- *
- * @param prefix The prefix that was being mapping.
- */
- public void endPrefixMapping(String prefix) throws SAXException {
- if (!this.processing) {
- super.endPrefixMapping(prefix);
- } else if (this.ch != null){
- this.ch.endPrefixMapping(prefix);
- }
+ 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.state = STATE_OUTSIDE;
}
/**
@@ -255,65 +316,121 @@
* @param a The attributes attached to the element. If there are no
* attributes, it shall be an empty Attributes object.
*/
- public void startElement(String uri, String loc, String raw, Attributes a)
- throws SAXException {
- if (!this.processing) {
- if (SWT_URI.equals(uri) && SWT_ELEMENT.equals(loc)) {
- getLogger().debug("start processing
xmlns:source");
- this.failed = false;
- this.message = null;
- this.target = "";
-
- // look for the Source
- String src = a.getValue("",SWT_SRC_ATTRIBUTE);
- try {
- this.message = "The src attribute
could not be resolved";
- this.source =
this.sourceResolver.resolve(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 =
a.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 =
(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;
- } else {
- this.message = "could not get
a ContentHandler";
- this.ch =
(XMLConsumer)wsource.getContentHandler();
- }
- } catch (Exception e) {
- getLogger().warn("failed, " +
this.message, e);
- this.failed = true;
- try {
- this.wsource.cancel(this.ch);
- } catch (Exception e2) {
- getLogger().warn("failed to
cancel: " + this.target, e2);
- this.message += " and failed
to cancel";
- }
- }
- // start the document
- if (!this.failed) {
- this.ch.startDocument();
- }
- this.processing = true;
- getLogger().debug("Processing Started");
- } else {
- super.startElement(uri,loc,raw,a);
- }
- } else if (this.ch != null){
- this.ch.startElement(uri,loc,raw,a);
- }
+ public void startTransformingElement(String uri, String name, String raw,
Attributes attr)
+ throws SAXException, IOException, ProcessingException {
+ if (this.getLogger().isDebugEnabled() == true) {
+ this.getLogger().debug("BEGIN startTransformingElement uri=" + uri +
+ ", name=" + name + ", raw=" + raw + ", attr=" + attr);
+ }
+ // Element: insert
+ if (name.equals(INSERT_ELEMENT)
+ && this.state == STATE_OUTSIDE) {
+ state = STATE_INSERT;
+ if (attr.getValue(INSERT_CREATE_ATTRIBUTE) != null
+ && attr.getValue(INSERT_CREATE_ATTRIBUTE).equals("false")) {
+ stack.push("false");
+ } else {
+ stack.push("true");
+ }
+ if (attr.getValue(INSERT_OVERWRITE_ATTRIBUTE) != null
+ && attr.getValue(INSERT_OVERWRITE_ATTRIBUTE).equals("false")) {
+ stack.push("false");
+ } else {
+ stack.push("true");
+ }
+ stack.push("INSERT");
+
+
+ // Element: file
+ } else if (name.equals(FILE_ELEMENT)
+ && this.state == STATE_INSERT) {
+ state = STATE_FILE;
+ this.startTextRecording();
+
+ // Element: path
+ } else if (name.equals(PATH_ELEMENT)
+ && this.state == STATE_INSERT) {
+ state = STATE_PATH;
+ this.startTextRecording();
+
+ // Element: replace
+ } else if (name.equals(REPLACE_ELEMENT)
+ && this.state == STATE_INSERT) {
+ state = STATE_REPLACE;
+ this.startTextRecording();
+
+ // Element: fragment
+ } else if (name.equals(FRAGMENT_ELEMENT)
+ && this.state == STATE_INSERT) {
+ state = STATE_FRAGMENT;
+ this.startRecording();
+
+ // Element: reinsert
+ } else if (name.equals(REINSERT_ELEMENT)
+ && this.state == STATE_INSERT) {
+ 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)wsource.getContentHandler();
+ }
+ this.addRecorder( this.ch );
+ this.startDocument();
+ this.sendStartPrefixMapping();
+
+ } catch (Exception e) {
+ getLogger().warn("failed, " + this.message, e);
+ this.failed = true;
+ try {
+ 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);
+ }
+
+ if (this.getLogger().isDebugEnabled() == true) {
+ this.getLogger().debug("END startTransformingElement");
+ }
}
@@ -328,239 +445,300 @@
* @param raw The raw XML 1.0 name (with prefix), or the empty string if
* raw names are not available.
*/
- public void endElement(String uri, String loc, String raw)
- throws SAXException {
- if (!this.processing) {
- super.endElement(uri,loc,raw);
- } else {
- if (SWT_URI.equals(uri) && SWT_ELEMENT.equals(loc)){
- if (!this.failed) {
- this.ch.endDocument();
- }
- this.processing = false;
- getLogger().debug("Processing Ended");
- // 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";
- this.wsource.cancel(this.ch);
- } catch (Exception e2) {
- getLogger().warn("failed to
cancel: " + this.target, e2);
- }
- } finally {
- if (this.source != null) {
- this.source.recycle();
- }
- }
- 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.startElement(uri, loc, raw, attrs);
- if (this.message != null && this.failed ==
true) super.characters(this.message.toCharArray(), 0, this.message.length());
- super.endElement(uri, loc, raw);
- getLogger().debug("Source Written");
- } else if (this.ch != null){
- this.ch.endElement(uri, loc, raw);
- }
- }
- }
-
- /**
- * Receive notification of character data.
- *
- * @param c The characters from the XML document.
- * @param start The start position in the array.
- * @param len The number of characters to read from the array.
- */
- public void characters(char c[], int start, int len) throws SAXException {
- if (!this.processing) {
- super.characters(c,start,len);
- } else if (this.ch != null){
- this.ch.characters(c,start,len);
- }
- }
-
- /**
- * Receive notification of ignorable whitespace in element content.
- *
- * @param c The characters from the XML document.
- * @param start The start position in the array.
- * @param len The number of characters to read from the array.
- */
- public void ignorableWhitespace(char c[], int start, int len) throws
SAXException {
- if (!this.processing) {
- super.ignorableWhitespace(c,start,len);
- } else if (this.ch != null){
- this.ch.ignorableWhitespace(c,start,len);
- }
- }
-
- /**
- * Receive notification of a processing instruction.
- *
- * @param target The processing instruction target.
- * @param data The processing instruction data, or null if none was
- * supplied.
- */
- public void processingInstruction(String target, String data) throws
SAXException {
- if (!this.processing) {
- super.processingInstruction(target,data);
- } else if (this.ch != null){
- this.ch.processingInstruction(target,data);
- }
- }
-
- /**
- * Receive notification of a skipped entity.
- *
- * @param name The name of the skipped entity. If it is a parameter
- * entity, the name will begin with '%'.
- */
- public void skippedEntity(String name) throws SAXException {
- if (!this.processing) {
- super.skippedEntity(name);
- } else if (this.ch != null){
- this.ch.skippedEntity(name);
- }
- }
-
- /**
- * Report the start of DTD declarations, if any.
- *
- * @param name The document type name.
- * @param publicId The declared public identifier for the external DTD
- * subset, or null if none was declared.
- * @param systemId The declared system identifier for the external DTD
- * subset, or null if none was declared.
- */
- public void startDTD(String name, String publicId, String
systemId) throws SAXException {
- if (!this.processing)
- super.startDTD(name,publicId,systemId);
- }
-
- /**
- * Report the end of DTD declarations.
- */
- public void endDTD() throws SAXException {
- if (!this.processing)
- super.endDTD();
- }
-
- /**
- * Report the beginning of an entity.
- *
- * @param name The name of the entity. If it is a parameter entity, the
- * name will begin with '%'.
- */
- public void startEntity(String name) throws SAXException {
- if (!this.processing) {
- super.startEntity(name);
- } else if (this.ch != null){
- this.ch.startEntity(name);
- }
- }
-
- /**
- * Report the end of an entity.
- *
- * @param name The name of the entity that is ending.
- */
- public void endEntity(String name) throws SAXException {
- if (!this.processing) {
- super.endEntity(name);
- } else if (this.ch != null){
- this.ch.endEntity(name);
- }
- }
-
- /**
- * Report the start of a CDATA section.
- */
- public void startCDATA() throws SAXException {
- if (!this.processing) {
- super.startCDATA();
- } else if (this.ch != null){
- this.ch.startCDATA();
- }
- }
-
- /**
- * Report the end of a CDATA section.
- */
- public void endCDATA() throws SAXException {
- if (!this.processing) {
- super.endCDATA();
- } else if (this.ch != null){
- this.ch.endCDATA();
- }
- }
-
- /**
- * Report an XML comment anywhere in the document.
- *
- * @param ch An array holding the characters in the comment.
- * @param start The starting position in the array.
- * @param len The number of characters to use from the array.
- */
- public void comment(char ch[], int start, int len) throws SAXException {
- if (!this.processing) {
- super.comment(ch,start,len);
- } else if (this.ch != null){
- this.ch.comment(ch,start,len);
- }
+ public void endTransformingElement(String uri, String name, String raw)
+ throws SAXException, IOException, ProcessingException {
+ if (this.getLogger().isDebugEnabled() == true) {
+ this.getLogger().debug("BEGIN endTransformingElement uri=" + uri +
+ ", name=" + name +
+ ", raw=" + raw);
+ }
+ if (name.equals(INSERT_ELEMENT) == true && this.state == STATE_INSERT) {
+ state = STATE_OUTSIDE;
+
+ // get the information from the stack
+ String tag;
+ String fileName = null;
+ DocumentFragment fragment = null;
+ String path = null;
+ String replacePath = null;
+ String reinsert = null;
+ do {
+ tag = (String)stack.pop();
+ if (tag.equals("PATH") == true) {
+ path = (String)stack.pop();
+ } else if (tag.equals("FILE") == true) {
+ fileName = (String)stack.pop();
+ } else if (tag.equals("FRAGMENT") == true) {
+ fragment = (DocumentFragment)stack.pop();
+ } else if (tag.equals("REPLACE") == true) {
+ replacePath = (String)stack.pop();
+ } else if (tag.equals("REINSERT") == true) {
+ reinsert = (String)stack.pop();
+ }
+ } while (tag.equals("INSERT") == false);
+ final boolean overwrite = stack.pop().equals("true");
+ final boolean create = stack.pop().equals("true");
+
+ /**this.insertFragment(fileName,
+ path,
+ fragment,
+ replacePath,
+ create,
+ overwrite,
+ reinsert);
+ */
+ // Element: file
+ } else if (name.equals(FILE_ELEMENT) == true && this.state == STATE_FILE) {
+ state = STATE_INSERT;
+ stack.push(this.endTextRecording());
+ stack.push("FILE");
+
+ // Element: path
+ } else if (name.equals(PATH_ELEMENT) == true && this.state == STATE_PATH) {
+ state = STATE_INSERT;
+ stack.push(this.endTextRecording());
+ stack.push("PATH");
+
+ // Element: replace
+ } else if (name.equals(REPLACE_ELEMENT) == true && this.state ==
STATE_REPLACE) {
+ state = STATE_INSERT;
+ stack.push(this.endTextRecording());
+ stack.push("REPLACE");
+
+ // Element: fragment
+ } else if (name.equals(FRAGMENT_ELEMENT) == true && this.state ==
STATE_FRAGMENT) {
+ state = STATE_INSERT;
+ stack.push(this.endRecording());
+ stack.push("FRAGMENT");
+
+ // Element: reinsert
+ } else if (name.equals(REINSERT_ELEMENT) == true
+ && this.state == STATE_REINSERT) {
+ state = STATE_INSERT;
+ stack.push(this.endTextRecording());
+ 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";
+ 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.startElement(uri, name, raw, attrs);
+ if (this.message != null && this.failed == true)
super.characters(this.message.toCharArray(), 0, this.message.length());
+ super.endElement(uri, name, raw);
+ getLogger().debug("Source Written");
+ }
+ // default
+ } else {
+ super.endTransformingElement(uri, name, raw);
+ }
+
+ if (this.getLogger().isDebugEnabled() == true) {
+ this.getLogger().debug("END endTransformingElement");
+ }
}
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 {
- this.wsource.cancel(this.ch);
- } catch (Exception e) {
- getLogger().error("failed to cancel in
recycle() method: ContentHandler");
- }
- }
- }
-
- if (isSerializer) this.manager.release((Component)this.ch);
- this.sourceResolver = null;
+ 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 {
+ 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();
+ }
+
+ /**
+ * Insert a fragment into a file.
+ * The file is loaded by the resource connector.
+ *
+ * @param fileName The name of the xml file.
+ * @param path The XPath specifying the node under which the data is inserted
+ * @param fragment The data to be inserted.
+ * @param replacePath Optional XPath relative to <CODE>path</CODE>. This path
+ * can specify a node which will be removed if it exists.
+ * So insertFragment can be used as a replace utility.
+ * @param create If the file does not exists and this is set to
+ * <CODE>false</CODE> nothing is inserted. If it is set
+ * to <CODE>true</CODE> the file is created and the data
+ * is inserted.
+ * @param overwrite If this is set to <CODE>true</CODE> the data is only
+ * inserted if the node specified by the
<CODE>replacePath</CODE>
+ * 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.
+ */
+ public void insertFragment(String fileName,
+ String path,
+ DocumentFragment fragment,
+ String replacePath,
+ boolean create,
+ boolean overwrite,
+ String reinsertPath)
+ throws SAXException, IOException, ProcessingException {
+ // no sync req
+ if (this.getLogger().isDebugEnabled() == true) {
+ this.getLogger().debug("BEGIN insertFragment fileName="+fileName+
+ ", path="+path+
+ ", replace="+replacePath+
+ ", create="+create+
+ ", overwrite="+overwrite+
+ ", resinsert="+reinsertPath+
+ ", fragment="+(fragment == null ? "null" :
XMLUtils.serializeNodeToXML(fragment)));
+ }
+ // test parameter
+ if (fileName == null) {
+ throw new ProcessingException("insertFragment: file name is required.");
+ }
+ if (path == null) {
+ throw new ProcessingException("insertFragment: path is required.");
+ }
+ if (fragment == null) {
+ throw new ProcessingException("insertFragment: fragment is required.");
+ }
+
+ Source fileSource = null;
+ String systemId = null;
+ try {
+ fileSource = this.resolver.resolveURI( fileName );
+ systemId = fileSource.getSystemId();
+ if (systemId.startsWith("file:") == false) {
+ throw new ProcessingException("insertFragment: this is not a file:
" + systemId);
+ }
+ } catch (SourceException se) {
+ throw new ProcessingException("Error during resolving.", se);
+ } finally {
+ if (fileSource != null) this.resolver.release(fileSource);
+ }
+ if (path.startsWith("/") == true) path = path.substring(1);
+
+ File file = new File(systemId.substring(5));
+ DocumentFragment resource = null;
+ if (file.exists() == true) {
+ resource =
this.getResourceConnector().loadXML(ResourceConnector.RESOURCE_TYPE_FILE, null,
+ fileName, null);
+
+ // import the fragment
+ Node importNode = resource.getOwnerDocument().importNode(fragment,
true);
+
+ // get the node
+ Node parent = XMLUtil.selectSingleNode(resource, path);
+
+ // replace?
+ 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);
+ if (reinsertPath != null) {
+ Node insertAt = XMLUtil.getSingleNode(importNode,
reinsertPath);
+ if (insertAt != null) {
+ while (replaceNode.hasChildNodes() == true) {
+
insertAt.appendChild(replaceNode.getFirstChild());
+ }
+ }
+ }
+ }
+ } else {
+ parent.appendChild(importNode);
+ }
+ } catch (javax.xml.transform.TransformerException sax) {
+ throw new ProcessingException("TransformerException: " + sax,
sax);
+ }
+ } else { // no replace
+ parent.appendChild(importNode);
+ }
+ } else {
+ if (create == true) {
+ Document doc = XMLUtil.createDocument();
+ resource = doc.createDocumentFragment();
+ // import the fragment
+ Node importNode = resource.getOwnerDocument().importNode(fragment,
true);
+ // get the node
+ Node parent = XMLUtil.selectSingleNode(resource, path);
+ // add fragment
+ parent.appendChild(importNode);
+ }
+ }
+
+ if (resource != null) {
+ // finally: save resource
+ resource.normalize();
+
this.getResourceConnector().saveXML(ResourceConnector.RESOURCE_TYPE_FILE, null,
+ fileName, null,
+ resource);
+ }
+
+ if (this.getLogger().isDebugEnabled() == true) {
+ this.getLogger().debug("END insertFragment");
+ }
}
- /**
- * dispose
- */
- public void dispose() {
- }
+
}
----------------------------------------------------------------------
In case of troubles, e-mail: [EMAIL PROTECTED]
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]