# HG changeset patch # User Sascha L. Teichmann # Date 1325851840 0 # Node ID da9df364157845a262696edecaee9345fa61c7f3 # Parent b20b710aa86f108a2c674ac77b24f1f1f720f08b Send XML messages via HTTP POST around if the FLYS database has changed. flys-aft/trunk@3614 c6561f87-3c4e-4783-a992-168aeb5c3f6f diff -r b20b710aa86f -r da9df3641578 flys-aft/ChangeLog --- 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 + + * 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 * doc/conf.xml: Added demo notification url. diff -r b20b710aa86f -r da9df3641578 flys-aft/src/main/java/de/intevation/aft/Notification.java --- /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 : diff -r b20b710aa86f -r da9df3641578 flys-aft/src/main/java/de/intevation/aft/Sync.java --- 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); } diff -r b20b710aa86f -r da9df3641578 flys-aft/src/main/java/de/intevation/utils/XML.java --- 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 :