diff options
Diffstat (limited to 'netconf/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/listeners/AbstractQueryParams.java')
-rw-r--r-- | netconf/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/listeners/AbstractQueryParams.java | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/netconf/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/listeners/AbstractQueryParams.java b/netconf/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/listeners/AbstractQueryParams.java new file mode 100644 index 0000000..4697646 --- /dev/null +++ b/netconf/restconf/restconf-nb-bierman02/src/main/java/org/opendaylight/netconf/sal/streams/listeners/AbstractQueryParams.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.netconf.sal.streams.listeners; + +import static java.util.Objects.requireNonNull; + +import com.google.common.annotations.VisibleForTesting; +import java.io.StringReader; +import java.time.Instant; +import java.util.Optional; +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; +import org.opendaylight.restconf.common.errors.RestconfDocumentedException; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; + +/** + * Features of query parameters part of both notifications. + * + */ +abstract class AbstractQueryParams extends AbstractNotificationsData { + // FIXME: BUG-7956: switch to using UntrustedXML + private static final DocumentBuilderFactory DBF; + + static { + final DocumentBuilderFactory f = DocumentBuilderFactory.newInstance(); + f.setCoalescing(true); + f.setExpandEntityReferences(false); + f.setIgnoringElementContentWhitespace(true); + f.setIgnoringComments(true); + f.setXIncludeAware(false); + try { + f.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + f.setFeature("http://xml.org/sax/features/external-general-entities", false); + f.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + } catch (final ParserConfigurationException e) { + throw new ExceptionInInitializerError(e); + } + DBF = f; + } + + // FIXME: these should be final + private Instant start = null; + private Instant stop = null; + private String filter = null; + private boolean leafNodesOnly = false; + private boolean skipNotificationData = false; + + @VisibleForTesting + public final Instant getStart() { + return start; + } + + /** + * 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 + * @param leafNodesOnly + * if true, notifications will contain changes to leaf nodes only + * @param skipNotificationData + * if true, notification will not contain changed data + */ + @SuppressWarnings("checkstyle:hiddenField") + public void setQueryParams(final Instant start, final Optional<Instant> stop, final Optional<String> filter, + final boolean leafNodesOnly, final boolean skipNotificationData) { + this.start = requireNonNull(start); + this.stop = stop.orElse(null); + this.filter = filter.orElse(null); + this.leafNodesOnly = leafNodesOnly; + this.skipNotificationData = skipNotificationData; + } + + /** + * Check whether this query should only notify about leaf node changes. + * + * @return true if this query should only notify about leaf node changes + */ + public boolean getLeafNodesOnly() { + return leafNodesOnly; + } + + /** + * Check whether this query should notify changes without data. + * + * @return true if this query should notify about changes with data + */ + public boolean isSkipNotificationData() { + return skipNotificationData; + } + + @SuppressWarnings("checkstyle:IllegalCatch") + <T extends BaseListenerInterface> boolean checkStartStop(final Instant now, final T listener) { + if (this.stop != null) { + if (this.start.compareTo(now) < 0 && this.stop.compareTo(now) > 0) { + return true; + } + if (this.stop.compareTo(now) < 0) { + try { + listener.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; + return true; + } + } else { + return true; + } + return false; + } + + /** + * Check if is filter used and then prepare and post data do client. + * + * @param xml data of notification + */ + @SuppressWarnings("checkstyle:IllegalCatch") + boolean checkFilter(final String xml) { + if (this.filter == null) { + return true; + } + + try { + return parseFilterParam(xml); + } catch (final Exception e) { + throw new RestconfDocumentedException("Problem while parsing filter.", e); + } + } + + /** + * Parse and evaluate filter value by xml. + * + * @return true or false - depends on filter expression and data of + * notifiaction + * @throws Exception if operation fails + */ + private boolean parseFilterParam(final String xml) throws Exception { + final Document docOfXml = DBF.newDocumentBuilder().parse(new InputSource(new StringReader(xml))); + final XPath xPath = XPathFactory.newInstance().newXPath(); + // FIXME: BUG-7956: xPath.setNamespaceContext(nsContext); + return (boolean) xPath.compile(this.filter).evaluate(docOfXml, XPathConstants.BOOLEAN); + } +} |