You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by re...@apache.org on 2004/11/14 18:12:04 UTC

svn commit: rev 65607 - in cocoon/whiteboard/block-deployer: src/impl/org/apache/cocoon/blockdeployer/utils src/impl/org/apache/cocoon/blockdeployer/utils/xpatch test/junit/org/apache/cocoon/blockdeployer/utils/xpatch test/xpatch

Author: reinhard
Date: Sun Nov 14 09:12:03 2004
New Revision: 65607

Added:
   cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/XPatchLogger.java
   cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/
   cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/DocumentCache.java
   cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/NullPropertyResolver.java
   cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/PropertyResolver.java
   cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/XPatch.java
   cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/XPatchLoggerFacade.java
   cocoon/whiteboard/block-deployer/test/junit/org/apache/cocoon/blockdeployer/utils/xpatch/
   cocoon/whiteboard/block-deployer/test/junit/org/apache/cocoon/blockdeployer/utils/xpatch/XPatchTest.java
   cocoon/whiteboard/block-deployer/test/xpatch/
   cocoon/whiteboard/block-deployer/test/xpatch/zip-source.xconf
   cocoon/whiteboard/block-deployer/test/xpatch/zip-source_cocoon.xconf
Log:
Refactoring of XPatch to make it independant of Ant

Added: cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/XPatchLogger.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/XPatchLogger.java	Sun Nov 14 09:12:03 2004
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.blockdeployer.utils;
+
+import org.apache.cocoon.blockdeployer.logging.LoggerFacade;
+import org.apache.cocoon.blockdeployer.utils.xpatch.XPatchLoggerFacade;
+
+/**
+ * @since 0.1
+ */
+public class XPatchLogger implements XPatchLoggerFacade {
+
+    private LoggerFacade logger;
+
+	public XPatchLogger(LoggerFacade logger) {
+    	this.logger = logger;
+    }
+    
+	public void error(Class clazz, String error) {
+        this.logger.error(clazz, error);
+	}
+
+	public void info(Class clazz, String info) {
+        this.logger.info(clazz, info);
+	}
+
+	public void debug(Class clazz, String debug) {
+        this.logger.debug(clazz, debug);
+	}
+
+}

Added: cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/DocumentCache.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/DocumentCache.java	Sun Nov 14 09:12:03 2004
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.blockdeployer.utils.xpatch;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.cocoon.blockdeployer.logging.LoggerFacade;
+import org.w3c.dom.Document;
+import org.w3c.dom.DocumentType;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 0.1
+ */
+public final class DocumentCache {
+
+    /** Cache the read configuration files (Documents) */
+    private static Map fileCache = new HashMap();
+    
+    /** The document builder */
+    private static DocumentBuilder builder;
+    private static Transformer transformer;
+
+    /**
+     * Initialize internal instance of XMLCatalog
+     */
+    static {
+        try {
+            DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+            builderFactory.setValidating(false);
+            builderFactory.setExpandEntityReferences(false);
+            builderFactory.setNamespaceAware(false);
+            builderFactory.setAttribute(
+               "http://apache.org/xml/features/nonvalidating/load-external-dtd",
+               Boolean.FALSE);
+            builder = builderFactory.newDocumentBuilder();
+            transformer = TransformerFactory.newInstance().newTransformer();
+        } catch (TransformerException e) {
+            throw new RuntimeException("TransformerException: "+e);
+        } catch (ParserConfigurationException e) {
+            throw new RuntimeException("ParserConfigurationException: "+e);
+        }  
+    }
+
+    public static Document getDocument(File file, XPatchLoggerFacade logger) 
+    throws SAXException, IOException {
+        if(logger == null) {
+        	throw new NullPointerException("Logger is null");
+        }
+        final String fileName = file.toURL().toExternalForm();
+        Document document = (Document)fileCache.get(fileName);
+        if ( document != null ) {
+        	logger.debug(DocumentCache.class, "Using file from cache: " + fileName);
+            fileCache.remove(fileName);
+        } else {
+            try {
+                // load xml
+                logger.debug(DocumentCache.class, "Reading: " + fileName);
+                document = builder.parse(fileName);
+            } catch (IOException e) {
+                throw new RuntimeException("IOException: "+e);
+            }                
+        }
+        return document;
+    }
+    
+    public static Document getDocument(String string, String systemURI) {
+        try {
+            final InputSource is = new InputSource(new StringReader(string));
+            if ( systemURI != null ) {
+                is.setSystemId(systemURI);
+            }
+            return builder.parse(is);
+        } catch (Exception e) {
+            throw new RuntimeException("Unable to parse string.", e);
+        }
+    }
+    
+    public static void storeDocument(File file, Document document, LoggerFacade logger) 
+    throws IOException {
+        if(logger==null) {
+        	throw new NullPointerException("Logger is null.");
+        }
+        logger.debug(DocumentCache.class, "Storing file in cache: " + file);
+        final String fileName = file.toURL().toExternalForm();
+        fileCache.put(fileName, document);
+    }
+
+    public static void writeDocument(File file, Document document, LoggerFacade logger) {
+        if(logger == null) {
+            throw new NullPointerException("Logger is null.");
+        }        
+        logger.debug(DocumentCache.class, "Writing: " + file);
+        
+        // Set the DOCTYPE output option on the transformer 
+        // if we have any DOCTYPE declaration in the input xml document
+        final DocumentType doctype = document.getDoctype();
+        Properties props = new Properties();
+        if (null != doctype) {
+            if (null != doctype.getPublicId()) {
+                props.put(OutputKeys.DOCTYPE_PUBLIC, doctype.getPublicId());
+            }
+            if (null != doctype.getSystemId()) {
+                props.put(OutputKeys.DOCTYPE_SYSTEM, doctype.getSystemId());
+            }
+        }
+        transformer.setOutputProperties(props);
+        
+        try {
+            transformer.transform(new DOMSource(document),
+                                  new StreamResult(file));
+        } catch (TransformerException e) {
+            throw new RuntimeException("TransformerException: " + e);
+        }
+    }
+}

Added: cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/NullPropertyResolver.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/NullPropertyResolver.java	Sun Nov 14 09:12:03 2004
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.blockdeployer.utils.xpatch;
+
+/**
+ * @since 0.1
+ */
+public class NullPropertyResolver implements PropertyResolver {
+
+	public String replaceProperties(String property) {
+		return property;
+	}
+
+	public String getProperty(String ifProp) {
+		return "";
+	}
+
+}

Added: cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/PropertyResolver.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/PropertyResolver.java	Sun Nov 14 09:12:03 2004
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.blockdeployer.utils.xpatch;
+
+/**
+ * @since 0.1
+ */
+public interface PropertyResolver {
+
+    public String replaceProperties(String property);
+
+	public String getProperty(String ifProp);
+    
+}

Added: cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/XPatch.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/XPatch.java	Sun Nov 14 09:12:03 2004
@@ -0,0 +1,312 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.blockdeployer.utils.xpatch;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.xml.transform.TransformerException;
+
+import org.apache.xpath.XPathAPI;
+import org.w3c.dom.Attr;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+
+/**
+ * Patch Cocoon XML configuration files (.xconf, .xmap, ...)
+ * 
+ * Refactoring of 
+ * @since 0.1
+ */
+public class XPatch {
+    private boolean addComments = true;
+    private static final String NL = System.getProperty("line.separator");
+    private static final String FSEP = System.getProperty("file.separator");
+	private PropertyResolver propertyResolver;
+	private XPatchLoggerFacade logger;
+	private String startCommentText = null;
+	private String endCommentText = null;
+    
+    /*
+     * FIXME change LoggerFacade to XPatchLogger to make it easier to use in Cocoon 2.1
+     */
+    public XPatch(PropertyResolver propertyResolver, XPatchLoggerFacade logger) {
+    	if(logger == null) {
+    		throw new NullPointerException("Logger mustn't be null.");
+        }
+        this.logger = logger;
+        if(propertyResolver == null) {
+        	throw new NullPointerException("PropertyResolver mustn't be null.");
+        }
+        this.propertyResolver = propertyResolver;
+    }
+    
+    public void setAddComments(Boolean addComments) {
+        this.addComments = addComments.booleanValue();
+    }
+    
+    public void setStartCommentText(String text) {
+    	this.startCommentText = text;
+    }
+    
+    public void setEndCommentText(String text) {
+    	this.endCommentText = text;
+    }
+    
+    public String getStartCommentText(String confName) {
+        String defaultText = "..... Start configuration from '" + confName + "'";
+    	if(this.startCommentText == null) {
+    		return defaultText;
+        }
+        return defaultText + "\n" + this.startCommentText;
+    }
+    
+    public String getEndCommentText(String confName) {
+        String defaultText = "..... End configuration from '" + confName + "'";
+        if(this.endCommentText == null) {
+            return defaultText;
+        }
+        return defaultText + "\n" + this.endCommentText;        
+    }
+    
+	public boolean patch(final Document configuration, final File patchFile)
+			throws TransformerException, IOException, DOMException,
+			SAXException {
+
+        // FIXME should be refactored and set externally (this object shouldn't know about where the documents are cached)
+		Document component = DocumentCache.getDocument(patchFile, this.logger);
+		String filename = patchFile.toString();
+
+		// Check to see if Document is an xconf-tool document
+		Element elem = component.getDocumentElement();
+
+		String extension = filename.lastIndexOf(".") > 0 ? filename
+				.substring(filename.lastIndexOf(".") + 1) : "";
+		String basename = basename(filename);
+
+		if (!elem.getTagName().equals(extension)) {
+			this.logger.info(XPatch.class, "Skipping non xconf-tool file: " + filename);
+			return false;
+		}
+
+		String replacePropertiesStr = elem.getAttribute("replace-properties");
+
+		boolean replaceProperties = !("no"
+				.equalsIgnoreCase(replacePropertiesStr) || "false"
+				.equalsIgnoreCase(replacePropertiesStr));
+
+		// Get 'root' node were 'component' will be inserted into
+		String xpath = getAttribute(elem, "xpath", replaceProperties);
+
+		NodeList nodes = XPathAPI.selectNodeList(configuration, xpath);
+
+		// Suspend, because the xpath returned not one node
+		if (nodes.getLength() != 1) {
+			this.logger.debug(XPatch.class, "Suspending: " + filename);
+			return false;
+		}
+		Node root = nodes.item(0);
+
+		// Test that 'root' node satisfies 'component' insertion criteria
+		String testPath = getAttribute(elem, "unless-path", replaceProperties);
+		if (testPath == null || testPath.length() == 0) {
+			// only look for old "unless" attr if unless-path is not present
+			testPath = getAttribute(elem, "unless", replaceProperties);
+		}
+		// Is if-path needed?
+		String ifProp = getAttribute(elem, "if-prop", replaceProperties);
+		boolean ifValue = false;
+
+		if (ifProp != null && !ifProp.equals("")) {
+			ifValue = Boolean.valueOf(this.propertyResolver.getProperty(ifProp))
+					.booleanValue();
+		}
+
+		if (ifProp != null && ifProp.length() > 0 && !ifValue) {
+			this.logger.debug(XPatch.class, "Skipping: " + filename);
+			return false;
+		} else if (testPath != null && testPath.length() > 0
+				&& XPathAPI.selectNodeList(root, testPath).getLength() != 0) {
+			this.logger.debug(XPatch.class, "Skipping: " + filename);
+			return false;
+		} else {
+			// Test if component wants us to remove a list of nodes first
+			xpath = getAttribute(elem, "remove", replaceProperties);
+
+			if (xpath != null && xpath.length() > 0) {
+				nodes = XPathAPI.selectNodeList(configuration, xpath);
+
+				for (int i = 0, length = nodes.getLength(); i < length; i++) {
+					Node node = nodes.item(i);
+					Node parent = node.getParentNode();
+
+					parent.removeChild(node);
+				}
+			}
+
+			// Test for an attribute that needs to be added to an element
+			String name = getAttribute(elem, "add-attribute", replaceProperties);
+			String value = getAttribute(elem, "value", replaceProperties);
+
+			if (name != null && name.length() > 0) {
+				if (value == null) {
+					throw new IOException(
+							"No attribute value specified for 'add-attribute' "
+									+ xpath);
+				}
+				if (root instanceof Element) {
+					((Element) root).setAttribute(name, value);
+				}
+			}
+
+			// Override addComments from ant task if specified as an attribute
+			String addCommentsAttr = getAttribute(elem, "add-comments",
+					replaceProperties);
+			if ((addCommentsAttr != null) && (addCommentsAttr.length() > 0)) {
+				setAddComments(new Boolean(addCommentsAttr));
+			}
+
+			// Allow multiple attributes to be added or modified
+			if (root instanceof Element) {
+				NamedNodeMap attrMap = elem.getAttributes();
+				for (int i = 0; i < attrMap.getLength(); ++i) {
+					Attr attr = (Attr) attrMap.item(i);
+					final String addAttr = "add-attribute-";
+					if (attr.getName().startsWith(addAttr)) {
+						String key = attr.getName().substring(addAttr.length());
+						((Element) root).setAttribute(key, attr.getValue());
+					}
+				}
+			}
+
+			// Test if 'component' provides desired insertion point
+			xpath = getAttribute(elem, "insert-before", replaceProperties);
+			Node before = null;
+
+			if (xpath != null && xpath.length() > 0) {
+				nodes = XPathAPI.selectNodeList(root, xpath);
+				if (nodes.getLength() == 0) {
+					this.logger.error(XPatch.class, "Error in: " + filename);
+					throw new IOException("XPath (" + xpath
+							+ ") returned zero nodes");
+				}
+				before = nodes.item(0);
+			} else {
+				xpath = getAttribute(elem, "insert-after", replaceProperties);
+				if (xpath != null && xpath.length() > 0) {
+					nodes = XPathAPI.selectNodeList(root, xpath);
+					if (nodes.getLength() == 0) {
+						this.logger.error(XPatch.class, "Error in: " + filename);
+						throw new IOException("XPath (" + xpath
+								+ ") zero nodes.");
+					}
+					before = nodes.item(nodes.getLength() - 1).getNextSibling();
+				}
+			}
+
+			// Add 'component' data into 'root' node
+			this.logger.debug(XPatch.class, "Processing: " + filename);
+			NodeList componentNodes = component.getDocumentElement()
+					.getChildNodes();
+
+			if (this.addComments) {
+				root.appendChild(configuration.createComment(this.getStartCommentText(basename)));
+				root.appendChild(configuration.createTextNode(NL));
+			}
+			for (int i = 0; i < componentNodes.getLength(); i++) {
+				Node node = configuration.importNode(componentNodes.item(i),
+						true);
+
+				// FIXME
+                // if (replaceProperties) {
+				//	replaceProperties(node);
+				// }
+				if (before == null) {
+					root.appendChild(node);
+				} else {
+					root.insertBefore(node, before);
+				}
+			}
+			if (this.addComments) {
+				root.appendChild(configuration.createComment(this.getEndCommentText(basename)));
+				root.appendChild(configuration.createTextNode(NL));
+			}
+			return true;
+		}
+	}
+
+	private String getAttribute(Element elem, String attrName,
+			boolean replaceProperties) {
+		String attr = elem.getAttribute(attrName);
+		if (attr == null) {
+			return null;
+		} else if (replaceProperties) {
+			return this.propertyResolver.replaceProperties(attr);
+		} 
+        else {
+			return attr;
+		}
+	}
+
+	private void replaceProperties(Node n) throws DOMException {
+		NamedNodeMap attrs = n.getAttributes();
+		if (attrs != null) {
+			for (int i = 0; i < attrs.getLength(); i++) {
+				Node attr = attrs.item(i);
+				attr.setNodeValue(this.propertyResolver.replaceProperties(
+						attr.getNodeValue()));
+			}
+		}
+		switch (n.getNodeType()) {
+		case Node.ATTRIBUTE_NODE:
+		case Node.CDATA_SECTION_NODE:
+		case Node.TEXT_NODE: {
+			n.setNodeValue(this.propertyResolver.replaceProperties(n.getNodeValue()));
+			break;
+		}
+		case Node.DOCUMENT_NODE:
+		case Node.DOCUMENT_FRAGMENT_NODE:
+		case Node.ELEMENT_NODE: {
+			Node child = n.getFirstChild();
+			while (child != null) {
+				replaceProperties(child);
+				child = child.getNextSibling();
+			}
+			break;
+		}
+		default: {
+			// ignore all other node types
+		}
+		}
+	}
+
+    private String basename(String fileName) {
+        int start = fileName.lastIndexOf(FSEP) + 1; // last '/'
+        int end = fileName.lastIndexOf(".");        // last '.'
+
+        if (end == 0) {
+            end = fileName.length();
+        }
+        return fileName.substring(start, end);
+    }    
+
+}
\ No newline at end of file

Added: cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/XPatchLoggerFacade.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/block-deployer/src/impl/org/apache/cocoon/blockdeployer/utils/xpatch/XPatchLoggerFacade.java	Sun Nov 14 09:12:03 2004
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.blockdeployer.utils.xpatch;
+
+/**
+ * @since 0.1
+ */
+public interface XPatchLoggerFacade {
+    
+    public void error(Class clazz, String error);
+    
+    public void info(Class clazz, String info);
+    
+    public void debug(Class clazz, String debug);
+
+}

Added: cocoon/whiteboard/block-deployer/test/junit/org/apache/cocoon/blockdeployer/utils/xpatch/XPatchTest.java
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/block-deployer/test/junit/org/apache/cocoon/blockdeployer/utils/xpatch/XPatchTest.java	Sun Nov 14 09:12:03 2004
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.cocoon.blockdeployer.utils.xpatch;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+
+import org.apache.cocoon.blockdeployer.LogEnabledTestCase;
+import org.apache.cocoon.blockdeployer.utils.XPatchLogger;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.w3c.dom.DOMException;
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 0.1
+ */
+public class XPatchTest extends LogEnabledTestCase {
+    
+    public void testXConfPatching() throws DOMException, TransformerException, IOException, SAXException, ParserConfigurationException {
+        XPatch xpatch = new XPatch(new NullPropertyResolver(), new XPatchLogger(this.logger));
+        
+        File confFile = new File("./test/xpatch/zip-source_cocoon.xconf");
+        File patchFile = new File("./test/xpatch/zip-source.xconf");
+        
+        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+        builderFactory.setValidating(false);
+        builderFactory.setExpandEntityReferences(false);
+        builderFactory.setNamespaceAware(false);
+        
+        DocumentBuilder builder = builderFactory.newDocumentBuilder();        
+        Document doc = builder.parse(confFile);
+        xpatch.patch(doc, patchFile);
+
+        FileOutputStream fos = new FileOutputStream(new File("rpo.xml"));
+        OutputFormat of = new OutputFormat("XML","UTF-8",true);
+        of.setIndent(1);
+        of.setIndenting(true);
+        XMLSerializer serializer = new XMLSerializer(fos,of);
+
+        serializer.asDOMSerializer();
+        serializer.serialize( doc.getDocumentElement() );
+        fos.close();            
+    }
+
+}

Added: cocoon/whiteboard/block-deployer/test/xpatch/zip-source.xconf
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/block-deployer/test/xpatch/zip-source.xconf	Sun Nov 14 09:12:03 2004
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 The Apache Software Foundation
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<xconf xpath="/cocoon/source-factories" unless="component-instance[@name='zip']">
+    
+    <!-- zip pseudo protocol -->
+    <component-instance class="org.apache.cocoon.components.source.impl.ZipSourceFactory" name="zip"/>
+    
+</xconf>

Added: cocoon/whiteboard/block-deployer/test/xpatch/zip-source_cocoon.xconf
==============================================================================
--- (empty file)
+++ cocoon/whiteboard/block-deployer/test/xpatch/zip-source_cocoon.xconf	Sun Nov 14 09:12:03 2004
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<!--
+  Copyright 1999-2004 The Apache Software Foundation
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<cocoon>
+	<source-factories/>
+</cocoon>	
\ No newline at end of file