changeset 4095:da9df3641578

Send XML messages via HTTP POST around if the FLYS database has changed. flys-aft/trunk@3614 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Fri, 06 Jan 2012 12:10:40 +0000 (2012-01-06)
parents b20b710aa86f
children 82f5266f881b
files flys-aft/ChangeLog flys-aft/src/main/java/de/intevation/aft/Notification.java flys-aft/src/main/java/de/intevation/aft/Sync.java flys-aft/src/main/java/de/intevation/utils/XML.java
diffstat 4 files changed, 229 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/flys-aft/ChangeLog	Thu Jan 05 18:58:49 2012 +0000
+++ b/flys-aft/ChangeLog	Fri Jan 06 12:10:40 2012 +0000
@@ -1,3 +1,15 @@
+2012-01-06	Sascha L. Teichmann	<sascha.teichmann@inteavtion.de>
+
+	* src/main/java/de/intevation/utils/XML.java: Added code
+	  to send/receive documents from streams.
+
+	* src/main/java/de/intevation/aft/Notification.java: New.
+	  Sends XML documents via HTTP POST to given URLs.
+
+	* src/main/java/de/intevation/aft/Sync.java: Send notifications
+	  if the FLYS database was modified. Useful to invalidate caches
+	  in the artifact server.
+
 2012-01-05	Sascha L. Teichmann	<sascha.teichmann@inteavtion.de>
 
 	* doc/conf.xml: Added demo notification url.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/flys-aft/src/main/java/de/intevation/aft/Notification.java	Fri Jan 06 12:10:40 2012 +0000
@@ -0,0 +1,101 @@
+package de.intevation.aft;
+
+import de.intevation.utils.XML;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.HttpURLConnection;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import org.apache.log4j.Logger;
+
+public class Notification
+{
+    private static Logger log = Logger.getLogger(Notification.class);
+
+    protected Document message;
+
+    public Notification() {
+    }
+
+    public Notification(Document message) {
+        this.message = message;
+    }
+
+    public Notification(Node message) {
+        this(wrap(message));
+    }
+
+    public static Document wrap(Node node) {
+        Document document = XML.newDocument();
+
+        // Send first element as message.
+        // Fall back to root node.
+        Node toImport = node;
+
+        NodeList children = node.getChildNodes();
+        for (int i = 0, N = children.getLength(); i < N; ++i) {
+            Node child = children.item(i);
+            if (child.getNodeType() == Node.ELEMENT_NODE) {
+                toImport = child;
+                break;
+            }
+        }
+
+        toImport = document.importNode(toImport, true);
+        document.appendChild(toImport);
+        document.normalizeDocument();
+        return document;
+    }
+
+    public Document sendPOST(URL url) {
+
+        OutputStream out    = null;
+        InputStream  in     = null;
+        Document     result = null;
+
+        try {
+            URLConnection ucon = url.openConnection();
+
+            if (!(ucon instanceof HttpURLConnection)) {
+                log.warn("'" + url + "' is not an HTTP(S) connection.");
+                return null;
+            }
+
+            HttpURLConnection con = (HttpURLConnection)ucon;
+
+            con.setRequestMethod("POST");
+            con.setDoInput(true);
+            con.setDoOutput(true);
+            con.setUseCaches(false);
+            con.setRequestProperty("Content-Type", "text/xml");
+
+            out = con.getOutputStream();
+            XML.toStream(message, out);
+            out.flush();
+            in = con.getInputStream();
+            result = XML.parseDocument(in);
+        }
+        catch (IOException ioe) {
+            log.error("Sending message to '" + url + "' failed.", ioe);
+        }
+        finally {
+            if (out != null) {
+                try { out.close(); } catch (IOException ioe) {}
+            }
+            if (in != null) {
+                try { in.close(); } catch (IOException ioe) {}
+            }
+        }
+
+        return result;
+    }
+}
+// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :
--- a/flys-aft/src/main/java/de/intevation/aft/Sync.java	Thu Jan 05 18:58:49 2012 +0000
+++ b/flys-aft/src/main/java/de/intevation/aft/Sync.java	Fri Jan 06 12:10:40 2012 +0000
@@ -2,9 +2,14 @@
 
 import java.io.File;
 
+import java.net.URL;
+import java.net.MalformedURLException;
+
 import java.sql.SQLException;
 
 import org.w3c.dom.Document;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Element;
 
 import org.apache.log4j.Logger;
 
@@ -23,12 +28,45 @@
 
     public static final String XPATH_DIPS   = "/sync/dips/file/text()";
     public static final String XPATH_REPAIR = "/sync/dips/repair/text()";
+
     public static final String XPATH_NOTIFICATIONS =
         "/sync/notifications/notification";
 
     public static final String CONFIG_FILE =
         System.getProperty("config.file", "config.xml");
 
+    public static void sendNotifications(Document config) {
+        NodeList notifications = (NodeList)XML.xpath(
+            config, XPATH_NOTIFICATIONS, XPathConstants.NODESET, null, null);
+
+        if (notifications == null) {
+            return;
+        }
+
+        for (int i = 0, N = notifications.getLength(); i < N; ++i) {
+            Element notification = (Element)notifications.item(i);
+            String urlString = notification.getAttribute("url");
+
+            URL url;
+            try {
+                url = new URL(urlString);
+            }
+            catch (MalformedURLException mfue) {
+                log.warn("Invalid URL '" + urlString + "'. Ignored.", mfue);
+                continue;
+            }
+
+            Notification n = new Notification(notification);
+
+            Document result = n.sendPOST(url);
+
+            if (result != null) {
+                log.info("Send notifcation to '" + urlString + "'.");
+                log.info(XML.toString(result));
+            }
+        }
+    }
+
     public static void main(String [] args) {
 
         File configFile = new File(CONFIG_FILE);
@@ -116,6 +154,10 @@
             }
         }
 
+        if (modified) {
+            sendNotifications(config);
+        }
+
         if (exitCode != 0) {
             System.exit(1);
         }
--- a/flys-aft/src/main/java/de/intevation/utils/XML.java	Thu Jan 05 18:58:49 2012 +0000
+++ b/flys-aft/src/main/java/de/intevation/utils/XML.java	Fri Jan 06 12:10:40 2012 +0000
@@ -5,6 +5,8 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.StringWriter;
 
 import org.w3c.dom.Document;
 
@@ -30,7 +32,9 @@
 import javax.xml.transform.TransformerFactory;
 import javax.xml.transform.TransformerConfigurationException;
 import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactoryConfigurationError;
 
+import javax.xml.transform.stream.StreamResult;
 import javax.xml.transform.stream.StreamSource;
 
 import javax.xml.transform.dom.DOMSource;
@@ -72,6 +76,24 @@
     private XML() {
     }
 
+        /**
+     * Creates a new XML document
+     * @return the new XML document ot null if something went wrong during
+     * creation.
+     */
+    public static final Document newDocument() {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+
+        try {
+            return factory.newDocumentBuilder().newDocument();
+        }
+        catch (ParserConfigurationException pce) {
+            log.error(pce.getLocalizedMessage(), pce);
+        }
+        return null;
+    }
+
     /**
      * Loads a XML document namespace aware from a file
      * @param file The file to load.
@@ -254,5 +276,57 @@
 
         return null;
     }
+
+   /**
+     * Streams out an XML document to a given output stream.
+     * @param document The document to be streamed out.
+     * @param out      The output stream to be used.
+     * @return true if operation succeeded else false.
+     */
+    public static boolean toStream(Document document, OutputStream out) {
+        try {
+            Transformer transformer =
+                TransformerFactory.newInstance().newTransformer();
+            DOMSource    source = new DOMSource(document);
+            StreamResult result = new StreamResult(out);
+            transformer.transform(source, result);
+            return true;
+        }
+        catch (TransformerConfigurationException tce) {
+            log.error(tce.getLocalizedMessage(), tce);
+        }
+        catch (TransformerFactoryConfigurationError tfce) {
+            log.error(tfce.getLocalizedMessage(), tfce);
+        }
+        catch (TransformerException te) {
+            log.error(te.getLocalizedMessage(), te);
+        }
+
+        return false;
+    }
+
+    public static String toString(Document document) {
+        try {
+            Transformer transformer =
+                TransformerFactory.newInstance().newTransformer();
+            DOMSource    source = new DOMSource(document);
+            StringWriter out    = new StringWriter();
+            StreamResult result = new StreamResult(out);
+            transformer.transform(source, result);
+            out.flush();
+            return out.toString();
+        }
+        catch (TransformerConfigurationException tce) {
+            log.error(tce.getLocalizedMessage(), tce);
+        }
+        catch (TransformerFactoryConfigurationError tfce) {
+            log.error(tfce.getLocalizedMessage(), tfce);
+        }
+        catch (TransformerException te) {
+            log.error(te.getLocalizedMessage(), te);
+        }
+
+        return null;
+    }
 }
 // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :

http://dive4elements.wald.intevation.org