X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Fsal-rest-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fnetconf%2Fsal%2Fstreams%2Flisteners%2FNotificationListenerAdapter.java;h=1d32b39e23bb077c59120d7bcd5a78c09db0fe35;hb=ddc71443d58ac78f8a593be88e181310f1e4b9c8;hp=42f0996052e022be82289226aa13bd18fe294878;hpb=1582427eb81ac3250f2db5c041838d11432b45a0;p=netconf.git diff --git a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/streams/listeners/NotificationListenerAdapter.java b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/streams/listeners/NotificationListenerAdapter.java index 42f0996052..1d32b39e23 100644 --- a/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/streams/listeners/NotificationListenerAdapter.java +++ b/restconf/sal-rest-connector/src/main/java/org/opendaylight/netconf/sal/streams/listeners/NotificationListenerAdapter.java @@ -18,11 +18,14 @@ import io.netty.util.internal.ConcurrentSet; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; +import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.util.Collection; import java.util.Date; import java.util.Set; import java.util.concurrent.Executors; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; @@ -33,11 +36,15 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMResult; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; import org.json.JSONObject; import org.json.XML; import org.opendaylight.controller.md.sal.dom.api.DOMNotification; import org.opendaylight.controller.md.sal.dom.api.DOMNotificationListener; import org.opendaylight.netconf.sal.restconf.impl.ControllerContext; +import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException; import org.opendaylight.yangtools.concepts.ListenerRegistration; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier; @@ -55,6 +62,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; +import org.xml.sax.InputSource; /** * {@link NotificationListenerAdapter} is responsible to track events on @@ -74,6 +82,9 @@ public class NotificationListenerAdapter implements DOMNotificationListener { private final SchemaPath path; private final String outputType; + private Date start = null; + private Date stop = null; + private String filter; /** * Set path of listener and stream name, register event bus. @@ -98,7 +109,72 @@ public class NotificationListenerAdapter implements DOMNotificationListener { @Override public void onNotification(final DOMNotification notification) { + final Date now = new Date(); + if (this.stop != null) { + if ((this.start.compareTo(now) < 0) && (this.stop.compareTo(now) > 0)) { + checkFilter(notification); + } + if (this.stop.compareTo(now) < 0) { + try { + this.close(); + } catch (final Exception e) { + throw new RestconfDocumentedException("Problem with unregister listener." + e); + } + } + } else if (this.start != null) { + if (this.start.compareTo(now) < 0) { + this.start = null; + checkFilter(notification); + } + } else { + checkFilter(notification); + } + } + + /** + * Check if is filter used and then prepare and post data do client + * + * @param notification + * - data of notification + */ + private void checkFilter(final DOMNotification notification) { final String xml = prepareXmlFrom(notification); + if (this.filter == null) { + prepareAndPostData(xml); + } else { + try { + if (parseFilterParam(xml)) { + prepareAndPostData(xml); + } + } catch (final Exception e) { + throw new RestconfDocumentedException("Problem while parsing filter.", e); + } + } + } + + /** + * Parse and evaluate filter value by xml + * + * @param xml + * - notification data in xml + * @return true or false - depends on filter expression and data of + * notifiaction + * @throws Exception + */ + private boolean parseFilterParam(final String xml) throws Exception { + final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + final DocumentBuilder builder = factory.newDocumentBuilder(); + final Document docOfXml = builder.parse(new InputSource(new StringReader(xml))); + final XPath xPath = XPathFactory.newInstance().newXPath(); + return (boolean) xPath.compile(this.filter).evaluate(docOfXml, XPathConstants.BOOLEAN); + } + + /** + * Prepare data of notification and data to client + * + * @param xml + */ + private void prepareAndPostData(final String xml) { final Event event = new Event(EventType.NOTIFY); if (this.outputType.equals("JSON")) { final JSONObject jsonObject = XML.toJSONObject(xml); @@ -200,16 +276,17 @@ public class NotificationListenerAdapter implements DOMNotificationListener { private String prepareXmlFrom(final DOMNotification notification) { final SchemaContext schemaContext = ControllerContext.getInstance().getGlobalSchema(); final Document doc = ListenerAdapter.createDocument(); - final Element notificationElement = doc.createElementNS("urn:ietf:params:xml:ns:netconf:notification:1.0", + final Element notificationElement = + doc.createElementNS("urn:ietf:params:xml:ns:netconf:notification:1.0", "notification"); doc.appendChild(notificationElement); final Element eventTimeElement = doc.createElement("eventTime"); eventTimeElement.setTextContent(ListenerAdapter.toRFC3339(new Date())); notificationElement.appendChild(eventTimeElement); - + final String notificationNamespace = notification.getType().getLastComponent().getNamespace().toString(); final Element notificationEventElement = doc.createElementNS( - "urn:opendaylight:params:xml:ns:yang:controller:md:sal:remote", "create-notification-stream"); + notificationNamespace, "event"); addValuesToNotificationEventElement(doc, notificationEventElement, notification, schemaContext); notificationElement.appendChild(notificationEventElement); @@ -243,9 +320,7 @@ public class NotificationListenerAdapter implements DOMNotificationListener { final DOMResult domResult = writeNormalizedNode(body, YangInstanceIdentifier.create(body.getIdentifier()), schemaContext); final Node result = doc.importNode(domResult.getNode().getFirstChild(), true); - final Element dataElement = doc.createElement("notification"); - dataElement.appendChild(result); - element.appendChild(dataElement); + element.appendChild(result); } catch (final IOException e) { LOG.error("Error in writer ", e); } catch (final XMLStreamException e) { @@ -385,6 +460,22 @@ public class NotificationListenerAdapter implements DOMNotificationListener { * Type of the event. */ private enum EventType { - REGISTER, DEREGISTER, NOTIFY; + REGISTER, DEREGISTER, NOTIFY + } + + /** + * Set query parameters for listener + * + * @param start + * - start-time of getting notification + * @param stop + * - stop-time of getting notification + * @param filter + * - indicate which subset of all possible events are of interest + */ + public void setQueryParams(final Date start, final Date stop, final String filter) { + this.start = start; + this.stop = stop; + this.filter = filter; } }