X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-rest-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fstreams%2Flisteners%2FListenerAdapter.java;h=925a09337ca3ee1e8fba707020e3c7a19b8e03f6;hb=0e7b83c0739ac579ca6dbf6a3f7992f70eb3000f;hp=6282f37602be8236a737fe3e8ef42852816756bc;hpb=53aff7cd94da139a8329daddbcd773469564d1f4;p=controller.git diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/listeners/ListenerAdapter.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/listeners/ListenerAdapter.java index 6282f37602..925a09337c 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/listeners/ListenerAdapter.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/streams/listeners/ListenerAdapter.java @@ -7,6 +7,12 @@ */ package org.opendaylight.controller.sal.streams.listeners; +import com.google.common.base.Charsets; +import com.google.common.base.Preconditions; +import com.google.common.eventbus.AsyncEventBus; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; + import io.netty.channel.Channel; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import io.netty.util.internal.ConcurrentSet; @@ -23,6 +29,7 @@ import java.util.Map.Entry; import java.util.Random; import java.util.Set; import java.util.concurrent.Executors; +import java.util.regex.Pattern; import javax.activation.UnsupportedDataTypeException; import javax.xml.parsers.DocumentBuilder; @@ -53,19 +60,17 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; -import com.google.common.base.Preconditions; -import com.google.common.eventbus.AsyncEventBus; -import com.google.common.eventbus.EventBus; -import com.google.common.eventbus.Subscribe; - /** * {@link ListenerAdapter} is responsible to track events, which occurred by * changing data in data source. */ public class ListenerAdapter implements DataChangeListener { - private static final Logger logger = LoggerFactory - .getLogger(ListenerAdapter.class); + private static final Logger LOG = LoggerFactory.getLogger(ListenerAdapter.class); + private static final DocumentBuilderFactory DBF = DocumentBuilderFactory.newInstance(); + private static final TransformerFactory FACTORY = TransformerFactory.newInstance(); + private static final Pattern RFC3339_PATTERN = Pattern.compile("(\\d\\d)(\\d\\d)$"); + private final XmlMapper xmlMapper = new XmlMapper(); private final SimpleDateFormat rfc3339 = new SimpleDateFormat( "yyyy-MM-dd'T'hh:mm:ssZ"); @@ -77,6 +82,7 @@ public class ListenerAdapter implements DataChangeListener { private final EventBus eventBus; private final EventBusChangeRecorder eventBusChangeRecorder; + /** * Creates new {@link ListenerAdapter} listener specified by path and stream * name. @@ -86,10 +92,10 @@ public class ListenerAdapter implements DataChangeListener { * @param streamName * The name of the stream. */ - ListenerAdapter(InstanceIdentifier path, String streamName) { + ListenerAdapter(final InstanceIdentifier path, final String streamName) { Preconditions.checkNotNull(path); Preconditions - .checkArgument(streamName != null && !streamName.isEmpty()); + .checkArgument(streamName != null && !streamName.isEmpty()); this.path = path; this.streamName = streamName; eventBus = new AsyncEventBus(Executors.newSingleThreadExecutor()); @@ -99,7 +105,7 @@ public class ListenerAdapter implements DataChangeListener { @Override public void onDataChanged( - DataChangeEvent change) { + final DataChangeEvent change) { if (!change.getCreatedConfigurationData().isEmpty() || !change.getCreatedOperationalData().isEmpty() || !change.getUpdatedConfigurationData().isEmpty() @@ -118,7 +124,7 @@ public class ListenerAdapter implements DataChangeListener { */ private final class EventBusChangeRecorder { @Subscribe - public void recordCustomerChange(Event event) { + public void recordCustomerChange(final Event event) { if (event.getType() == EventType.REGISTER) { Channel subscriber = event.getSubscriber(); if (!subscribers.contains(subscriber)) { @@ -127,16 +133,16 @@ public class ListenerAdapter implements DataChangeListener { } else if (event.getType() == EventType.DEREGISTER) { subscribers.remove(event.getSubscriber()); Notificator - .removeListenerIfNoSubscriberExists(ListenerAdapter.this); + .removeListenerIfNoSubscriberExists(ListenerAdapter.this); } else if (event.getType() == EventType.NOTIFY) { for (Channel subscriber : subscribers) { if (subscriber.isActive()) { - logger.debug("Data are sent to subscriber {}:", + LOG.debug("Data are sent to subscriber {}:", subscriber.remoteAddress()); subscriber.writeAndFlush(new TextWebSocketFrame(event .getData())); } else { - logger.debug( + LOG.debug( "Subscriber {} is removed - channel is not active yet.", subscriber.remoteAddress()); subscribers.remove(subscriber); @@ -161,7 +167,7 @@ public class ListenerAdapter implements DataChangeListener { * @param type * EventType */ - public Event(EventType type) { + public Event(final EventType type) { this.type = type; } @@ -180,7 +186,7 @@ public class ListenerAdapter implements DataChangeListener { * @param subscriber * Channel */ - public void setSubscriber(Channel subscriber) { + public void setSubscriber(final Channel subscriber) { this.subscriber = subscriber; } @@ -199,7 +205,7 @@ public class ListenerAdapter implements DataChangeListener { * @param String * data. */ - public void setData(String data) { + public void setData(final String data) { this.data = data; } @@ -228,7 +234,7 @@ public class ListenerAdapter implements DataChangeListener { * @return Data in printable form. */ private String prepareXmlFrom( - DataChangeEvent change) { + final DataChangeEvent change) { Document doc = createDocument(); Element notificationElement = doc.createElementNS( "urn:ietf:params:xml:ns:netconf:notification:1.0", @@ -248,22 +254,19 @@ public class ListenerAdapter implements DataChangeListener { try { ByteArrayOutputStream out = new ByteArrayOutputStream(); - TransformerFactory tf = TransformerFactory.newInstance(); - Transformer transformer = tf.newTransformer(); - transformer - .setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); + Transformer transformer = FACTORY.newTransformer(); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); - transformer.setOutputProperty( - "{http://xml.apache.org/xslt}indent-amount", "4"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); transformer.transform(new DOMSource(doc), new StreamResult( - new OutputStreamWriter(out, "UTF-8"))); + new OutputStreamWriter(out, Charsets.UTF_8))); byte[] charData = out.toByteArray(); return new String(charData, "UTF-8"); } catch (TransformerException | UnsupportedEncodingException e) { String msg = "Error during transformation of Document into String"; - logger.error(msg, e); + LOG.error(msg, e); return msg; } } @@ -275,8 +278,8 @@ public class ListenerAdapter implements DataChangeListener { * Date * @return Data specified by RFC3339. */ - private String toRFC3339(Date d) { - return rfc3339.format(d).replaceAll("(\\d\\d)(\\d\\d)$", "$1:$2"); + private String toRFC3339(final Date d) { + return RFC3339_PATTERN.matcher(rfc3339.format(d)).replaceAll("$1:$2"); } /** @@ -285,15 +288,13 @@ public class ListenerAdapter implements DataChangeListener { * @return {@link Document} document. */ private Document createDocument() { - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - Document doc = null; + final DocumentBuilder bob; try { - DocumentBuilder bob = dbf.newDocumentBuilder(); - doc = bob.newDocument(); + bob = DBF.newDocumentBuilder(); } catch (ParserConfigurationException e) { return null; } - return doc; + return bob.newDocument(); } /** @@ -306,9 +307,9 @@ public class ListenerAdapter implements DataChangeListener { * @param change * {@link DataChangeEvent} */ - private void addValuesToDataChangedNotificationEventElement(Document doc, - Element dataChangedNotificationEventElement, - DataChangeEvent change) { + private void addValuesToDataChangedNotificationEventElement(final Document doc, + final Element dataChangedNotificationEventElement, + final DataChangeEvent change) { addValuesFromDataToElement(doc, change.getCreatedConfigurationData(), dataChangedNotificationEventElement, Store.CONFIG, Operation.CREATED); @@ -348,9 +349,9 @@ public class ListenerAdapter implements DataChangeListener { * @param operation * {@link Operation} */ - private void addValuesFromDataToElement(Document doc, - Set data, Element element, Store store, - Operation operation) { + private void addValuesFromDataToElement(final Document doc, + final Set data, final Element element, final Store store, + final Operation operation) { if (data == null || data.isEmpty()) { return; } @@ -375,9 +376,9 @@ public class ListenerAdapter implements DataChangeListener { * @param operation * {@link Operation} */ - private void addValuesFromDataToElement(Document doc, - Map data, Element element, - Store store, Operation operation) { + private void addValuesFromDataToElement(final Document doc, + final Map data, final Element element, + final Store store, final Operation operation) { if (data == null || data.isEmpty()) { return; } @@ -403,9 +404,9 @@ public class ListenerAdapter implements DataChangeListener { * {@link Operation} * @return {@link Node} node represented by changed event element. */ - private Node createDataChangeEventElement(Document doc, - InstanceIdentifier path, CompositeNode data, Store store, - Operation operation) { + private Node createDataChangeEventElement(final Document doc, + final InstanceIdentifier path, final CompositeNode data, final Store store, + final Operation operation) { Element dataChangeEventElement = doc.createElement("data-change-event"); Element pathElement = doc.createElement("path"); @@ -440,11 +441,11 @@ public class ListenerAdapter implements DataChangeListener { * {@link CompositeNode} * @return Data in XML format. */ - private Node translateToXml(InstanceIdentifier path, CompositeNode data) { + private Node translateToXml(final InstanceIdentifier path, final CompositeNode data) { DataNodeContainer schemaNode = ControllerContext.getInstance() .getDataNodeContainerFor(path); if (schemaNode == null) { - logger.info( + LOG.info( "Path '{}' contains node with unsupported type (supported type is Container or List) or some node was not found.", path); return null; @@ -453,7 +454,7 @@ public class ListenerAdapter implements DataChangeListener { Document xml = xmlMapper.write(data, schemaNode); return xml.getFirstChild(); } catch (UnsupportedDataTypeException e) { - logger.error( + LOG.error( "Error occured during translation of notification to XML.", e); return null; @@ -468,13 +469,15 @@ public class ListenerAdapter implements DataChangeListener { * @param element * {@link Element} */ - private void addPathAsValueToElement(InstanceIdentifier path, - Element element) { + private void addPathAsValueToElement(final InstanceIdentifier path, + final Element element) { // Map< key = namespace, value = prefix> Map prefixes = new HashMap<>(); InstanceIdentifier instanceIdentifier = path; StringBuilder textContent = new StringBuilder(); - for (PathArgument pathArgument : instanceIdentifier.getPath()) { + + // FIXME: BUG-1281: this is duplicated code from yangtools (BUG-1275) + for (PathArgument pathArgument : instanceIdentifier.getPathArguments()) { textContent.append("/"); writeIdentifierWithNamespacePrefix(element, textContent, pathArgument.getNodeType(), prefixes); @@ -514,8 +517,8 @@ public class ListenerAdapter implements DataChangeListener { * @param prefixes * Map of namespaces and prefixes. */ - private static void writeIdentifierWithNamespacePrefix(Element element, - StringBuilder textContent, QName qName, Map prefixes) { + private static void writeIdentifierWithNamespacePrefix(final Element element, + final StringBuilder textContent, final QName qName, final Map prefixes) { String namespace = qName.getNamespace().toString(); String prefix = prefixes.get(namespace); if (prefix == null) { @@ -541,7 +544,7 @@ public class ListenerAdapter implements DataChangeListener { * Collection of prefixes. * @return New prefix which consists of four random characters . */ - private static String generateNewPrefix(Collection prefixes) { + private static String generateNewPrefix(final Collection prefixes) { StringBuilder result = null; Random random = new Random(); do { @@ -571,7 +574,7 @@ public class ListenerAdapter implements DataChangeListener { * ListenerRegistration */ public void setRegistration( - ListenerRegistration registration) { + final ListenerRegistration registration) { this.registration = registration; } @@ -611,9 +614,9 @@ public class ListenerAdapter implements DataChangeListener { * @param subscriber * Channel */ - public void addSubscriber(Channel subscriber) { + public void addSubscriber(final Channel subscriber) { if (!subscriber.isActive()) { - logger.debug("Channel is not active between websocket server and subscriber {}" + LOG.debug("Channel is not active between websocket server and subscriber {}" + subscriber.remoteAddress()); } Event event = new Event(EventType.REGISTER); @@ -627,8 +630,8 @@ public class ListenerAdapter implements DataChangeListener { * * @param subscriber */ - public void removeSubscriber(Channel subscriber) { - logger.debug("Subscriber {} is removed.", subscriber.remoteAddress()); + public void removeSubscriber(final Channel subscriber) { + LOG.debug("Subscriber {} is removed.", subscriber.remoteAddress()); Event event = new Event(EventType.DEREGISTER); event.setSubscriber(subscriber); eventBus.post(event); @@ -652,7 +655,7 @@ public class ListenerAdapter implements DataChangeListener { private final String value; - private Store(String value) { + private Store(final String value) { this.value = value; } } @@ -666,7 +669,7 @@ public class ListenerAdapter implements DataChangeListener { private final String value; - private Operation(String value) { + private Operation(final String value) { this.value = value; } }