2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.restconf.nb.rfc8040.streams.listeners;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.annotations.VisibleForTesting;
13 import java.io.StringReader;
14 import java.time.Instant;
15 import javax.xml.XMLConstants;
16 import javax.xml.parsers.DocumentBuilderFactory;
17 import javax.xml.parsers.ParserConfigurationException;
18 import javax.xml.xpath.XPath;
19 import javax.xml.xpath.XPathConstants;
20 import javax.xml.xpath.XPathFactory;
21 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
22 import org.w3c.dom.Document;
23 import org.xml.sax.InputSource;
26 * Features of query parameters part of both notifications.
28 abstract class AbstractQueryParams extends AbstractNotificationsData {
29 // FIXME: BUG-7956: switch to using UntrustedXML
30 private static final DocumentBuilderFactory DBF;
33 final DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
34 f.setCoalescing(true);
35 f.setExpandEntityReferences(false);
36 f.setIgnoringElementContentWhitespace(true);
37 f.setIgnoringComments(true);
38 f.setXIncludeAware(false);
40 f.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
41 f.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
42 f.setFeature("http://xml.org/sax/features/external-general-entities", false);
43 f.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
44 } catch (final ParserConfigurationException e) {
45 throw new ExceptionInInitializerError(e);
50 // FIXME: these should be final
51 private Instant startTime = null;
52 private Instant stopTime = null;
53 private String filter = null;
54 private boolean leafNodesOnly = false;
55 private boolean skipNotificationData = false;
58 public final Instant getStart() {
63 * Set query parameters for listener.
65 * @param startTime Start-time of getting notification.
66 * @param stopTime Stop-time of getting notification.
67 * @param filter Indicates which subset of all possible events are of interest.
68 * @param leafNodesOnly If TRUE, notifications will contain changes of leaf nodes only.
70 @SuppressWarnings("checkstyle:hiddenField")
71 public void setQueryParams(final Instant startTime, final Instant stopTime, final String filter,
72 final boolean leafNodesOnly, final boolean skipNotificationData) {
73 this.startTime = requireNonNull(startTime);
74 this.stopTime = stopTime;
76 this.leafNodesOnly = leafNodesOnly;
77 this.skipNotificationData = skipNotificationData;
81 * Check whether this query should only notify about leaf node changes.
83 * @return true if this query should only notify about leaf node changes
85 boolean getLeafNodesOnly() {
90 * Check whether this query should notify changes without data.
92 * @return true if this query should notify about changes with data
94 public boolean isSkipNotificationData() {
95 return skipNotificationData;
98 @SuppressWarnings("checkstyle:IllegalCatch")
99 <T extends BaseListenerInterface> boolean checkStartStop(final Instant now, final T listener) {
100 if (stopTime != null) {
101 if (startTime.compareTo(now) < 0 && stopTime.compareTo(now) > 0) {
104 if (stopTime.compareTo(now) < 0) {
107 } catch (final Exception e) {
108 throw new RestconfDocumentedException("Problem with unregister listener." + e);
111 } else if (startTime != null) {
112 if (startTime.compareTo(now) < 0) {
123 * Check if is filter used and then prepare and post data do client.
125 * @param xml XML data of notification.
127 @SuppressWarnings("checkstyle:IllegalCatch")
128 // FIXME: this method is never called, have we lost functionality compared to bierman02?
129 boolean checkFilter(final String xml) {
130 if (filter == null) {
134 return parseFilterParam(xml);
135 } catch (final Exception e) {
136 throw new RestconfDocumentedException("Problem while parsing filter.", e);
141 * Parse and evaluate filter statement by XML format.
143 * @return {@code true} or {@code false} depending on filter expression and data of notification.
144 * @throws Exception If operation fails.
146 private boolean parseFilterParam(final String xml) throws Exception {
147 final Document docOfXml = DBF.newDocumentBuilder().parse(new InputSource(new StringReader(xml)));
148 final XPath xPath = XPathFactory.newInstance().newXPath();
149 // FIXME: BUG-7956: xPath.setNamespaceContext(nsContext);
150 return (boolean) xPath.compile(filter).evaluate(docOfXml, XPathConstants.BOOLEAN);