webwork/src/main/webwork/config XMLActionConfiguration.java,1.19,1.20

[email protected] Sun, 03 Apr 2005 18:02:07 -0700
Newsgroups gmane.comp.java.open-symphony.cvs
Message-ID <[email protected]>
Update of /cvsroot/opensymphony/webwork/src/main/webwork/config
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv13536/src/main/webwork/config

Modified Files:
	XMLActionConfiguration.java 
Log Message:
Added support for included actions files. Syntax is: <include path="foo.xml" /> for including files relative to the current file
OR <include resource="com/foo/bar.xml" /> for including xml files in the classpath of the app
Fixed WW-762

Index: XMLActionConfiguration.java
===================================================================
RCS file: /cvsroot/opensymphony/webwork/src/main/webwork/config/XMLActionConfiguration.java,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- XMLActionConfiguration.java	17 Jan 2005 05:10:37 -0000	1.19
+++ XMLActionConfiguration.java	4 Apr 2005 01:01:54 -0000	1.20
@@ -8,8 +8,7 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.w3c.dom.DOMException;
-import org.w3c.dom.Document;
+import org.w3c.dom.*;
 import org.xml.sax.SAXException;
 import webwork.config.util.XMLConfigurationReader;
 import webwork.util.ClassLoaderUtils;
@@ -21,6 +20,8 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Iterator;
+import java.util.List;
+import java.util.ArrayList;
 
 /**
  * Access view configuration from an XML file.
@@ -35,7 +36,7 @@
 {
    // Attributes ----------------------------------------------------
    private XMLConfigurationReader configurationReader;
-   Log log = LogFactory.getLog(getClass());
+   private static final Log log = LogFactory.getLog(XMLActionConfiguration.class);
    private File file;
    private long lastModified;
 
@@ -46,12 +47,12 @@
      URL fileUrl = ClassLoaderUtils.getResource(aName+".xml", XMLActionConfiguration.class);
      if (fileUrl == null)
         throw new IllegalArgumentException("No such XML resource:"+aName+".xml");
-     configurationReader = getMappingsFromResource(fileUrl);
      file = new File(fileUrl.getFile());
      if(!file.exists() || !file.canRead())
      {
        file = null;
      }
+     configurationReader = getMappingsFromResource(fileUrl);
      if(file!=null)
        lastModified = file.lastModified();
    }
@@ -60,27 +61,13 @@
    {
       try
       {
-         DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-
-         // Parse document
-         Document document = factory.newDocumentBuilder().parse(url.toString());
+        Document document = getDocument(url);
 
-         log.debug("Found XML view configuration "+url);
+        log.debug("Found XML view configuration "+url);
 
+         resolveIncludes(url, document);
          return new XMLConfigurationReader(document.getDocumentElement());
 
-      } catch (SAXException e)
-      {
-         log.error("SAX exception", e);
-         throw new IllegalArgumentException("Could not parse XML action configuration");
-      } catch (IOException e)
-      {
-         log.error("IO exception", e);
-         throw new IllegalArgumentException("Could not load XML action configuration");
-      } catch (ParserConfigurationException e)
-      {
-         log.error("Parser conf exception", e);
-         throw new IllegalArgumentException("Could not load XML action configuration");
       } catch (DOMException e)
       {
          log.error("DOM exception", e);
@@ -88,7 +75,106 @@
       }
    }
 
+  private Document getDocument(URL url)
+  {
+    try
+      {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        Document document = factory.newDocumentBuilder().parse(url.openStream());
+        return document;
+      }
+      catch(SAXException e)
+      {
+        log.error("SAX exception in " + url, e);
+        throw new IllegalArgumentException("Could not parse XML action configuration: " + e);
+      }
+      catch(IOException e)
+      {
+        log.error("IO exception in " + url, e);
+        throw new IllegalArgumentException("Could not load XML action configuration");
+      }
+      catch(ParserConfigurationException e)
+      {
+        log.error("Parser conf exception", e);
+        throw new IllegalArgumentException("Could not load XML action configuration");
+      }
+  }
+
+  private void resolveIncludes(URL parent, Document doc)
+  {
+    NodeList includes = doc.getDocumentElement().getElementsByTagName("include");
+    List elements = new ArrayList(includes.getLength());
+    for(int i = 0; i < includes.getLength(); i++)
+    {
+      Element element = (Element)includes.item(i);
+      elements.add(element);
+    }
 
+    for(int i = 0; i < elements.size(); i++)
+    {
+      Element element = (Element)elements.get(i);
+      String path = element.getAttribute("resource");
+      URL url = null;
+      if(path != null && path.length() > 0)
+      {
+        url = ClassLoaderUtils.getResource(path, getClass());
+      }
+      else
+      {
+        path = element.getAttribute("path");
+        if(path != null && path.length() > 0)
+        {
+          //hrm, disallow absolute includes? security risk?
+          if(path.charAt(0) == '/')
+          {
+            try
+            {
+              url = new File(path).toURL();
+            }
+            catch(MalformedURLException e)
+            {
+              //can't happen
+            }
+          }
+          else
+          {
+            try
+            {
+              File parentFile = new File(parent.getFile());
+              if(!parentFile.canRead() || !parentFile.exists())
+              {
+                log.warn("parentFile '" + parent + "' cannot be resolved so ignoring specified path include '" + path + "'");
+              }
+              url = new File(parentFile.getParentFile(), path).toURL();
+            }
+            catch(MalformedURLException e)
+            {
+              //can't happen
+            }
+          }
+        }
+      }
+      if(url != null)
+      {
+        Document included = getDocument(url);
+        resolveIncludes(url, included);
+        DocumentFragment fragment = doc.createDocumentFragment();
+        NodeList includedContents = included.getDocumentElement().getChildNodes();
+        int includedSize = includedContents.getLength();
+        for(int j = 0; j < includedSize; j++)
+        {
+          Node imported = doc.importNode(includedContents.item(j), true);
+          fragment.appendChild(imported);
+        }
+        element.getParentNode().replaceChild(fragment, element);
+      }
+      else
+      {
+        log.warn("Included url '" + path + "' not found");
+      }
+    }
+  }
+  
     /**
     * Get a named setting. Note extension is stripped and replaced with extension defined
     * in property file. This is done here because of the recursive dependency if the constructor



-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click