package org.gcube.informationsystem.collector.impl.utils; import org.apache.axis.encoding.AnyContentType; import org.gcube.common.core.utils.logging.GCUBELog; import org.gcube.informationsystem.collector.impl.utils.MsgParser; import org.globus.wsrf.utils.AnyHelper; import org.w3c.dom.*; import org.xml.sax.InputSource; import org.xml.sax.SAXParseException; import javax.xml.parsers.*; import javax.xml.xpath.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import java.io.StringWriter; import java.io.StringReader; import java.lang.Exception; /** * * @author manuele simi * * @version 1.0 June 2006 * * @link http://www.diligentproject.org * */ public class MsgParser { private Document internalDOM; private String originalMsgString; private String type; // the entry type (profile or generic resource // properties) private XPath path = XPathFactory.newInstance().newXPath(); // object to // evaluate // Xpath // expressions private final String rootElement = "Data"; private final String typeElement = "Type"; private static GCUBELog logger = new GCUBELog(MsgParser.class); public MsgParser(AnyContentType deliveredMsg) throws Exception { try { this.originalMsgString = AnyHelper.toSingleString(deliveredMsg); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); StringReader reader = new StringReader("<" + rootElement + ">" + this.originalMsgString + ""); InputSource source = new InputSource(reader); this.internalDOM = builder.parse(source); // check if the message has been sent in push or pull mode this.checkMsgType(); // gets the entry type this.type = path.evaluate("//" + rootElement + "/child::*[local-name() = '" + typeElement + "']", internalDOM); } catch (ParserConfigurationException pce) { logger.error("", pce); throw new Exception("Parser configuration error"); } catch (SAXParseException spe) { logger.error("", spe); throw new Exception(" SAX parser error"); } catch (XPathExpressionException xpee) { logger.error("", xpee); throw new Exception("XPath evaluation error"); } } /** * Returns the entry type. It can be "Properties" or "Profile" * * @return the entry type */ public String getEntryType() { return this.type; } /** * Returns the entry type if the entry is a profile * * @throws Exception * * @return the entry type */ public String getResourceType() throws Exception { if (this.type.equalsIgnoreCase("Profile")) { logger.warn("The entry does not have a ResourceType"); throw new Exception("Invalid resource (type = Properties)"); } return this.getDILIGENTProperty("DILIGENTResourceType"); } /** * Returns the VO Name included in the entry * * @throws Exception * * @return the VO name */ public String getVOName() throws Exception { return this.getDILIGENTProperty("VO"); } /** * Returns the Service Name included in the entry * * @throws Exception * * @return the service name */ public String getServiceName() throws Exception { return this.getDILIGENTProperty("ServiceName"); } /** * Returns the Service Class included in the entry * * @throws Exception * * @return the service class */ public String getServiceClass() throws Exception { return this.getDILIGENTProperty("ServiceClass"); } /** * Returns the Running Instance ID included in the entry * * @throws Exception * * @return the ID */ public String getRunningInstanceID() throws Exception { return this.getDILIGENTProperty("RunningInstanceID"); } /** * Returns the Service ID included in the entry * * @throws Exception * * @return the service ID */ public String getServiceID() throws Exception { return this.getDILIGENTProperty("ServiceID"); } /** * Returns the DHN ID included in the entry * * @throws Exception * * @return the DHN ID */ public String getDHNID() throws Exception { return this.getDILIGENTProperty("GHN"); } /** * Extracts a given DILIGENT Property * * @throws Exception * * @return the property value */ private String getDILIGENTProperty(String propName) throws Exception { String value = null; try { value = path.evaluate("//" + rootElement + "/child::*[local-name() = '" + propName + "']", internalDOM); } catch (XPathExpressionException xpee) { logger.error("", xpee); throw new Exception("XPath evaluation error"); } return value; } /** * Returns a XML representation of the Entry * * @return the XML string */ public String getEntryAsString() { return "<" + rootElement + ">\n" + this.originalMsgString + "\n"; // return XMLUtils.DocumentToString(this.internalDOM); } /** * Releases the allocated resources * */ public void dispose() { // remove the allocated DOM internalDOM = null; } /** * Checks if the message has been sent by a WS-Notification In that case, * the NewValue is extracted by the msg * */ private void checkMsgType() throws Exception { Boolean isPush = false; String notificationXpath = "/child::*[local-name() = 'value']"; notificationXpath += "/child::*[local-name() = 'ResourcePropertyValueChangeNotification']"; notificationXpath += "/child::*[local-name() = 'NewValue']"; try { isPush = (Boolean) path.evaluate("//" + rootElement + notificationXpath, this.internalDOM, XPathConstants.BOOLEAN); } catch (NullPointerException n) { logger.trace("The delivered message has been sent using the pull mode"); return; } catch (XPathExpressionException xpee) { logger.error("", xpee); } if (isPush) { // replace the originalMsgString and the internalDOM with the // newValue section of the delivered message logger.trace("The delivered message has been sent using the push mode"); // String nodeString = (String) path.evaluate(notificationXpath, // this.internalDOM, XPathConstants.STRING); Node node = (Node) path.evaluate("//" + rootElement + notificationXpath, this.internalDOM, XPathConstants.NODE); Transformer serializer = TransformerFactory.newInstance().newTransformer(); StringWriter sw = new StringWriter(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder domBuilder = factory.newDocumentBuilder(); // create the nre data string NodeList children = node.getChildNodes(); this.originalMsgString = ""; if (children != null) { for (int i = 0; i < children.getLength(); i++) { serializer.transform(new DOMSource(children.item(i)), new StreamResult(sw)); this.originalMsgString += sw.toString(); } } logger.trace("Data string " + this.originalMsgString); // trim the directive this.originalMsgString = this.originalMsgString.substring(this.originalMsgString.indexOf("?>", 1) + 1); logger.trace("Trimmed data string " + this.originalMsgString); // create the new internalDOM StringReader reader = new StringReader("<" + rootElement + ">" + this.originalMsgString + ""); InputSource source = new InputSource(reader); this.internalDOM = domBuilder.parse(source); } else { logger.info("The delivered message has been sent using the pull mode"); } } }