in core/cocoon-pipeline/cocoon-pipeline-components/src/main/java/org/apache/cocoon/transformation/SourceWritingTransformer.java [562:790]
protected void insertFragment(String systemID,
String path,
DocumentFragment fragment,
String replacePath,
boolean create,
boolean overwrite,
String reinsertPath,
String localSerializer,
String tagname)
throws SAXException, IOException, ProcessingException {
// no sync req
if (getLogger().isDebugEnabled()) {
getLogger().debug("Insert fragment. systemID=" + systemID +
", path=" + path +
", replace=" + replacePath +
", create=" + create +
", overwrite=" + overwrite +
", reinsert=" + reinsertPath +
", fragment=" + (fragment == null ? "null" : XMLUtils.serializeNode(fragment)));
}
// test parameter
if (systemID == null) {
throw new ProcessingException("insertFragment: systemID is required.");
}
if (path == null) {
throw new ProcessingException("insertFragment: path is required.");
}
if (path.startsWith("/")) {
path = path.substring(1);
}
if (fragment == null) {
throw new ProcessingException("insertFragment: fragment is required.");
}
// 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 ModifiableSource)) {
throw new ProcessingException("Source '" + systemID + "' is not writeable.");
}
ModifiableSource ws = (ModifiableSource) source;
exists = ws.exists();
target = source.getURI();
// Insert?
if (exists && this.state == STATE_INSERT) {
message = "content inserted at: " + path;
resource = SourceUtil.toDOM(this.manager, source);
// import the fragment
Node importNode = resource.importNode(fragment, true);
// get the node
Node parent = DOMUtil.selectSingleNode(resource, path, this.xpathProcessor);
// replace?
if (replacePath != null) {
try {
Node replaceNode = DOMUtil.getSingleNode(parent, replacePath, this.xpathProcessor);
// now get the parent of this node until it is the parent node for insertion
while (replaceNode != null && !replaceNode.getParentNode().equals(parent)) {
replaceNode = replaceNode.getParentNode();
}
if (replaceNode != null) {
if (overwrite) {
if (parent.getNodeType() == Node.DOCUMENT_NODE) {
// replacing of the document element is not allowed
resource = newDocument();
resource.appendChild(resource.importNode(importNode, true));
parent = resource;
replaceNode = resource.importNode(replaceNode, true);
} else {
parent.replaceChild(importNode, replaceNode);
}
message += ", replacing: " + replacePath;
if (reinsertPath != null) {
Node insertAt = DOMUtil.getSingleNode(parent, reinsertPath, this.xpathProcessor);
if (insertAt != null) {
while (replaceNode.hasChildNodes()) {
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 { // specified replaceNode was not found
parent.appendChild(importNode);
}
} catch (javax.xml.transform.TransformerException sax) {
throw new ProcessingException("TransformerException: " + sax, sax);
}
} else { // no replace path, just do an insert at end
parent.appendChild(importNode);
}
// Create?
} else if (create) {
// Create new document
resource = newDocument();
// Import the fragment
Node importNode = resource.importNode(fragment, true);
if (path.equals("")) {
// Parent node is document itself
NodeList nodes = importNode.getChildNodes();
for (int i = 0; i < nodes.getLength();) {
Node node = nodes.item(i);
switch (node.getNodeType()) {
case Node.ELEMENT_NODE:
// May throw exception if fragment has more than one element
resource.appendChild(node);
break;
case Node.DOCUMENT_TYPE_NODE:
case Node.PROCESSING_INSTRUCTION_NODE:
case Node.COMMENT_NODE:
resource.appendChild(node);
break;
default:
// Ignore all other nodes
i++;
break;
}
}
message = "entire source overwritten";
} else {
// Get the parent node
Node parent = DOMUtil.selectSingleNode(resource, path, this.xpathProcessor);
// Add a fragment
parent.appendChild(importNode);
message = "content appended to: " + path;
}
// Oops: Document does not exist and create is not allowed.
} else {
message = "create not allowed";
resource = null;/**/
}
// Write source
if (resource != null) {
resource.normalize();
// use serializer
if (localSerializer == null) {
localSerializer = this.configuredSerializerName;
}
if (localSerializer != null) {
// Lookup the Serializer
ServiceSelector selector = null;
Serializer serializer = null;
OutputStream oStream = null;
try {
selector = (ServiceSelector)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 (getLogger().isDebugEnabled()) {
getLogger().debug("FAIL (oStream.close) exception"+t, t);
}
throw new ProcessingException("Could not process your document.", t);
} finally {
if (selector != null) {
selector.release(serializer);
this.manager.release(selector);
}
}
}
}
} else {
if (getLogger().isDebugEnabled()) {
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 (getLogger().isDebugEnabled()) {
getLogger().debug("FAIL exception: "+de, de);
}
message = "There was a problem manipulating your document: " + de;
} catch (ServiceException ce) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("FAIL exception: "+ce, ce);
}
message = "There was a problem looking up a component: " + ce;
} catch (SourceException se) {
if (getLogger().isDebugEnabled()) {
getLogger().debug("FAIL exception: "+se, 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;
}
reportResult(localSerializer, tagname, message, target, result, action);
}