From: Martin Bobak Date: Wed, 30 Oct 2013 10:19:12 +0000 (+0100) Subject: - Added exi capability utilities, handlers and necessary modifications X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~457^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=a474fa0e090124ba715dc4251944dd8532c90491 - Added exi capability utilities, handlers and necessary modifications - Exi parameters decomposition - Introduced HandlerManipulator class in netconf-api to be used for handlers management on channel pipeline - Exi encoding/decoding test added - exi returns NetconfMessage - added DOM attributes - exi encode decode test to expect NetconfMessage instead of Document - XmlElement.getName() returns localName first and tagName if localName not present, incorporated notes from Robert - NetconfSession implements all common methods - added copyright where needed - ProtocolMessageEncoder/Decoder stored in session and replaced with Exi enc/dec - exi encoder/decoder interface become comaptible with ProtocoleMessageEncoder/Decoder and no longer needs to be taken care of this handlers - created thirdParty bundle for exi - incorporation of Maros's notes Author: Martin Bobak Signed-off-by: Martin Bobak Change-Id: If9f20cef34ec05495eb212f6a584dd65a401dc0a Signed-off-by: Martin Bobak --- diff --git a/opendaylight/commons/opendaylight/pom.xml b/opendaylight/commons/opendaylight/pom.xml index 8ff25c35de..862f809df2 100644 --- a/opendaylight/commons/opendaylight/pom.xml +++ b/opendaylight/commons/opendaylight/pom.xml @@ -101,6 +101,7 @@ 1.7 1.3.1 + 0.9.2 @@ -607,6 +608,11 @@ org.openflow.openflowj 1.0.2 + + org.opendaylight.controller.thirdparty + exificient + ${exi.version} + org.opendaylight.controller.thirdparty com.sun.jersey.jersey-servlet diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index a0d7162b3f..1ebab9b03a 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -230,10 +230,23 @@ config-persister-impl ${netconf.version} - + + org.opendaylight.controller.thirdparty + exificient + ${exi.version} + + + org.apache.servicemix.bundles + org.apache.servicemix.bundles.xerces + 2.11.0_1 + + + org.eclipse.birt.runtime.3_7_1 + org.apache.xml.resolver + 1.2.0 + - org.opendaylight.controller.samples sample-toaster diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java index 8497edbd26..ce0036f9af 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java @@ -8,8 +8,11 @@ package org.opendaylight.controller.netconf.confignetconfconnector.osgi; -import com.google.common.base.Optional; -import com.google.common.collect.Sets; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + import org.opendaylight.controller.config.util.ConfigRegistryJMXClient; import org.opendaylight.controller.config.yang.store.api.YangStoreException; import org.opendaylight.controller.config.yang.store.api.YangStoreService; @@ -22,10 +25,8 @@ import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationService; import org.opendaylight.yangtools.yang.model.api.Module; -import java.util.Collection; -import java.util.Collections; -import java.util.Map; -import java.util.Set; +import com.google.common.base.Optional; +import com.google.common.collect.Sets; /** * Manages life cycle of {@link YangStoreSnapshot}. diff --git a/opendaylight/netconf/netconf-api/pom.xml b/opendaylight/netconf/netconf-api/pom.xml index 3c6209485d..902cf2a863 100644 --- a/opendaylight/netconf/netconf-api/pom.xml +++ b/opendaylight/netconf/netconf-api/pom.xml @@ -38,7 +38,10 @@ javax.management, org.opendaylight.controller.config.api.jmx, org.opendaylight.protocol.framework, - org.w3c.dom + io.netty.channel, + io.netty.util.concurrent, + org.w3c.dom, + org.slf4j org.opendaylight.controller.netconf.api, @@ -46,7 +49,7 @@ - + diff --git a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java index 49ca0c0106..e2a2d832c7 100644 --- a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java +++ b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java @@ -12,7 +12,8 @@ import org.w3c.dom.Document; public interface NetconfOperationRouter extends AutoCloseable { - Document onNetconfMessage(Document message) throws NetconfDocumentedException; + Document onNetconfMessage(Document message, NetconfSession session) + throws NetconfDocumentedException; @Override void close(); diff --git a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfSession.java b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfSession.java index a61d6938f6..8b761a85b2 100644 --- a/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfSession.java +++ b/opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfSession.java @@ -5,12 +5,141 @@ * 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.controller.netconf.api; +import io.netty.channel.Channel; +import io.netty.channel.ChannelHandler; + +import java.io.IOException; +import java.util.Map; + import org.opendaylight.protocol.framework.AbstractProtocolSession; +import org.opendaylight.protocol.framework.ProtocolMessageDecoder; +import org.opendaylight.protocol.framework.ProtocolMessageEncoder; +import org.opendaylight.protocol.framework.SessionListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class NetconfSession extends AbstractProtocolSession { - public abstract void sendMessage(NetconfMessage netconfMessage); + private ChannelHandler exiEncoder; + private String exiEncoderName; + private String removeAfterMessageSentname; + private String pmeName,pmdName; + private final Channel channel; + private final SessionListener sessionListener; + private final long sessionId; + private boolean up = false; + private static final Logger logger = LoggerFactory.getLogger(NetconfSession.class); + private static final int T = 0; + + protected NetconfSession(SessionListener sessionListener, Channel channel, long sessionId) { + this.sessionListener = sessionListener; + this.channel = channel; + this.sessionId = sessionId; + logger.debug("Session {} created", toString()); + + ChannelHandler pmd = channel.pipeline().get(ProtocolMessageDecoder.class); + ChannelHandler pme = channel.pipeline().get(ProtocolMessageEncoder.class); + + for (Map.Entry entry:channel.pipeline().toMap().entrySet()){ + if (entry.getValue().equals(pmd)){ + pmdName = entry.getKey(); + } + if (entry.getValue().equals(pme)){ + pmeName = entry.getKey(); + } + } + } + @Override + public void close() { + channel.close(); + sessionListener.onSessionTerminated(this, new NetconfTerminationReason("Session closed")); + } + + @Override + protected void handleMessage(NetconfMessage netconfMessage) { + logger.debug("handlign incomming message"); + sessionListener.onMessage(this, netconfMessage); + } + + public void sendMessage(NetconfMessage netconfMessage) { + channel.writeAndFlush(netconfMessage); + if (exiEncoder!=null){ + if (channel.pipeline().get(exiEncoderName)== null){ + channel.pipeline().addBefore(pmeName, exiEncoderName, exiEncoder); + } + } + if (removeAfterMessageSentname!=null){ + channel.pipeline().remove(removeAfterMessageSentname); + removeAfterMessageSentname = null; + } + } + + @Override + protected void endOfInput() { + logger.debug("Session {} end of input detected while session was in state {}", toString(), isUp() ? "up" + : "initialized"); + if (isUp()) { + this.sessionListener.onSessionDown(this, new IOException("End of input detected. Close the session.")); + } + } + + @Override + protected void sessionUp() { + logger.debug("Session {} up", toString()); + sessionListener.onSessionUp(this); + this.up = true; + } + + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("ServerNetconfSession{"); + sb.append("sessionId=").append(sessionId); + sb.append('}'); + return sb.toString(); + } + + public boolean isUp() { + return up; + } + + public long getSessionId() { + return sessionId; + } + + public T remove(Class handlerType) { + return channel.pipeline().remove(handlerType); + } + + public T getHandler(Class handlerType) { + return channel.pipeline().get(handlerType); + } + + public void addFirst(ChannelHandler handler, String name){ + channel.pipeline().addFirst(name, handler); + } + public void addLast(ChannelHandler handler, String name){ + channel.pipeline().addLast(name, handler); + } + + public void addExiDecoder(String name,ChannelHandler handler){ + if (channel.pipeline().get(name)== null){ + channel.pipeline().addBefore(pmdName, name, handler); + } + } + public void addExiEncoderAfterMessageSent(String name, ChannelHandler handler){ + this.exiEncoder = handler; + this.exiEncoderName = name; + } + + public void addExiEncoder(String name, ChannelHandler handler){ + channel.pipeline().addBefore(pmeName, name, handler); + } + + public void removeAfterMessageSent(String handlerName){ + this.removeAfterMessageSentname = handlerName; + } + } + diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java index cc8d987a68..61a9a9b954 100644 --- a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java @@ -8,16 +8,8 @@ package org.opendaylight.controller.netconf.client; -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GlobalEventExecutor; -import org.opendaylight.controller.netconf.api.NetconfMessage; -import org.opendaylight.protocol.framework.NeverReconnectStrategy; -import org.opendaylight.protocol.framework.ReconnectStrategy; -import org.opendaylight.protocol.framework.TimedReconnectStrategy; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.Closeable; import java.io.IOException; @@ -26,6 +18,16 @@ import java.util.Set; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; +import org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.protocol.framework.NeverReconnectStrategy; +import org.opendaylight.protocol.framework.ReconnectStrategy; +import org.opendaylight.protocol.framework.TimedReconnectStrategy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Sets; + public class NetconfClient implements Closeable { private static final Logger logger = LoggerFactory.getLogger(NetconfClient.class); @@ -121,4 +123,8 @@ public class NetconfClient implements Closeable { Preconditions.checkState(clientSession != null, "Client was not initialized successfully"); return Sets.newHashSet(clientSession.getServerCapabilities()); } + + public NetconfClientSession getClientSession() { + return clientSession; + } } diff --git a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSession.java b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSession.java index f0180cf78d..11c7f3061f 100644 --- a/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSession.java +++ b/opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSession.java @@ -9,87 +9,28 @@ package org.opendaylight.controller.netconf.client; import io.netty.channel.Channel; -import org.opendaylight.controller.netconf.api.NetconfMessage; + +import java.util.Collection; + import org.opendaylight.controller.netconf.api.NetconfSession; -import org.opendaylight.controller.netconf.api.NetconfTerminationReason; -import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.opendaylight.protocol.framework.SessionListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; -import java.util.Collection; - public class NetconfClientSession extends NetconfSession { - private final SessionListener sessionListener; - private final long sessionId; - private final Channel channel; - private static final Logger logger = LoggerFactory.getLogger(NetconfClientSession.class); private final Collection capabilities; - private boolean up; public NetconfClientSession(SessionListener sessionListener, Channel channel, long sessionId, Collection capabilities) { - this.sessionListener = sessionListener; - this.channel = channel; - this.sessionId = sessionId; + super(sessionListener,channel,sessionId); this.capabilities = capabilities; logger.debug("Client Session {} created", toString()); } - @Override - public void close() { - channel.close(); - sessionListener.onSessionTerminated(this, new NetconfTerminationReason("Client Session closed")); - } - - @Override - protected void handleMessage(NetconfMessage netconfMessage) { - logger.debug("Client Session {} received message {}", toString(), - XmlUtil.toString(netconfMessage.getDocument())); - sessionListener.onMessage(this, netconfMessage); - } - - @Override - public void sendMessage(NetconfMessage netconfMessage) { - channel.writeAndFlush(netconfMessage); - } - - @Override - protected void endOfInput() { - logger.debug("Client Session {} end of input detected while session was in state {}", toString(), isUp() ? "up" - : "initialized"); - if (isUp()) { - this.sessionListener.onSessionDown(this, new IOException("End of input detected. Close the session.")); - } - } - - @Override - protected void sessionUp() { - logger.debug("Client Session {} up", toString()); - sessionListener.onSessionUp(this); - this.up = true; - } - - @Override - public String toString() { - final StringBuffer sb = new StringBuffer("ClientNetconfSession{"); - sb.append("sessionId=").append(sessionId); - sb.append('}'); - return sb.toString(); - } - - public boolean isUp() { - return up; - } - - public long getSessionId() { - return sessionId; - } - public Collection getServerCapabilities() { return capabilities; } + } diff --git a/opendaylight/netconf/netconf-client/src/main/resources/client_hello.xml b/opendaylight/netconf/netconf-client/src/main/resources/client_hello.xml index 1d85b688e5..221953e56e 100644 --- a/opendaylight/netconf/netconf-client/src/main/resources/client_hello.xml +++ b/opendaylight/netconf/netconf-client/src/main/resources/client_hello.xml @@ -1,5 +1,6 @@ urn:ietf:params:netconf:base:1.0 + urn:ietf:params:netconf:capability:exi:1.0 \ No newline at end of file diff --git a/opendaylight/netconf/netconf-impl/pom.xml b/opendaylight/netconf/netconf-impl/pom.xml index c355cb0638..1bd3a78326 100644 --- a/opendaylight/netconf/netconf-impl/pom.xml +++ b/opendaylight/netconf/netconf-impl/pom.xml @@ -54,7 +54,6 @@ org.slf4j slf4j-api - org.opendaylight.bgpcep @@ -106,6 +105,8 @@ io.netty.channel.socket, io.netty.util, io.netty.util.concurrent, + io.netty.buffer, + io.netty.handler.codec, javax.management, javax.net.ssl, javax.xml.namespace, @@ -117,6 +118,7 @@ org.opendaylight.controller.netconf.util.mapping, org.opendaylight.controller.netconf.util.osgi, org.opendaylight.controller.netconf.util.xml, + org.opendaylight.controller.netconf.util.handler, org.opendaylight.protocol.framework, org.osgi.framework, org.osgi.util.tracker, @@ -124,7 +126,8 @@ org.w3c.dom, org.xml.sax, org.opendaylight.controller.netconf.util.messages, - org.opendaylight.controller.config.stat + org.opendaylight.controller.config.stat, + com.siemens.ct.exi.exceptions diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java index 1ae3fabbb9..a4d7e74723 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java @@ -9,77 +9,18 @@ package org.opendaylight.controller.netconf.impl; import io.netty.channel.Channel; -import org.opendaylight.controller.netconf.api.NetconfMessage; + import org.opendaylight.controller.netconf.api.NetconfSession; -import org.opendaylight.controller.netconf.api.NetconfTerminationReason; -import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.opendaylight.protocol.framework.SessionListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; - public class NetconfServerSession extends NetconfSession { - private final SessionListener sessionListener; - private final Channel channel; - private static final Logger logger = LoggerFactory.getLogger(NetconfServerSession.class); - private final long sessionId; - private boolean up = false; public NetconfServerSession(SessionListener sessionListener, Channel channel, long sessionId) { - this.sessionListener = sessionListener; - this.channel = channel; - this.sessionId = sessionId; + super(sessionListener,channel,sessionId); logger.debug("Session {} created", toString()); } - - @Override - public void close() { - channel.close(); - sessionListener.onSessionTerminated(this, new NetconfTerminationReason("Session closed")); - } - - @Override - protected void handleMessage(NetconfMessage netconfMessage) { - logger.debug("Session {} received message {}", toString(), XmlUtil.toString(netconfMessage.getDocument())); - sessionListener.onMessage(this, netconfMessage); - } - - public void sendMessage(NetconfMessage netconfMessage) { - channel.writeAndFlush(netconfMessage); - } - - @Override - protected void endOfInput() { - logger.debug("Session {} end of input detected while session was in state {}", toString(), isUp() ? "up" - : "initialized"); - if (isUp()) { - this.sessionListener.onSessionDown(this, new IOException("End of input detected. Close the session.")); - } - } - - @Override - protected void sessionUp() { - logger.debug("Session {} up", toString()); - sessionListener.onSessionUp(this); - this.up = true; - } - - @Override - public String toString() { - final StringBuffer sb = new StringBuffer("ServerNetconfSession{"); - sb.append("sessionId=").append(sessionId); - sb.append('}'); - return sb.toString(); - } - - public boolean isUp() { - return up; - } - - public long getSessionId() { - return sessionId; - } } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java index 4f71ab9bb5..686adcad85 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java @@ -8,10 +8,11 @@ package org.opendaylight.controller.netconf.impl; -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableMap; +import static com.google.common.base.Preconditions.checkState; + import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.controller.netconf.api.NetconfSession; import org.opendaylight.controller.netconf.api.NetconfTerminationReason; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationRouterImpl; import org.opendaylight.controller.netconf.util.messages.SendErrorExceptionUtil; @@ -24,7 +25,8 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Node; -import static com.google.common.base.Preconditions.checkState; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; public class NetconfServerSessionListener implements SessionListener { @@ -66,7 +68,8 @@ public class NetconfServerSessionListener implements Preconditions.checkState(operationRouter != null, "Cannot handle message, session up was not yet received"); // FIXME: there is no validation since the document may contain yang // schemas - final NetconfMessage message = processDocument(netconfMessage); + final NetconfMessage message = processDocument(netconfMessage, + session); logger.debug("Respondign with message {}", XmlUtil.toString(message.getDocument())); session.sendMessage(message); @@ -89,16 +92,18 @@ public class NetconfServerSessionListener implements logger.info("Session {} closed successfully", session.getSessionId()); } - private NetconfMessage processDocument(final NetconfMessage netconfMessage) throws NetconfDocumentedException { + private NetconfMessage processDocument(final NetconfMessage netconfMessage, + NetconfSession session) throws NetconfDocumentedException { final Document incommingDocument = netconfMessage.getDocument(); final Node rootNode = incommingDocument.getDocumentElement(); - if (rootNode.getNodeName().equals(XmlNetconfConstants.RPC_KEY)) { + if (rootNode.getLocalName().equals(XmlNetconfConstants.RPC_KEY)) { final String messageId = rootNode.getAttributes().getNamedItem(MESSAGE_ID).getTextContent(); checkState(messageId != null); final Document responseDocument = XmlUtil.newDocument(); - Document rpcReply = operationRouter.onNetconfMessage(incommingDocument); + Document rpcReply = operationRouter.onNetconfMessage( + incommingDocument, session); responseDocument.appendChild(responseDocument.importNode(rpcReply.getDocumentElement(), true)); return new NetconfMessage(responseDocument); } else { diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java index eea6dc19da..70ddf299fd 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java @@ -23,7 +23,8 @@ public class NetconfServerSessionListenerFactory implements SessionListenerFacto private final SessionIdProvider idProvider; public NetconfServerSessionListenerFactory(NetconfOperationServiceFactoryListener factoriesListener, - DefaultCommitNotificationProducer commitNotifier, SessionIdProvider idProvider) { + DefaultCommitNotificationProducer commitNotifier, + SessionIdProvider idProvider) { this.factoriesListener = factoriesListener; this.commitNotifier = commitNotifier; this.idProvider = idProvider; @@ -36,8 +37,9 @@ public class NetconfServerSessionListenerFactory implements SessionListenerFacto CapabilityProvider capabilityProvider = new CapabilityProviderImpl(netconfOperationServiceSnapshot); - NetconfOperationRouterImpl operationRouter = new NetconfOperationRouterImpl(netconfOperationServiceSnapshot, - capabilityProvider, commitNotifier); + NetconfOperationRouterImpl operationRouter = new NetconfOperationRouterImpl( + netconfOperationServiceSnapshot, capabilityProvider, + commitNotifier); return new NetconfServerSessionListener(operationRouter); } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiDecoderHandler.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiDecoderHandler.java new file mode 100644 index 0000000000..721c0c28be --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiDecoderHandler.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 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.controller.netconf.impl.mapping; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + +import java.util.List; + +import org.opendaylight.controller.netconf.util.xml.ExiParameters; +import org.opendaylight.controller.netconf.util.xml.ExiUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ExiDecoderHandler extends ByteToMessageDecoder { + + public static final String HANDLER_NAME; + + static { + HANDLER_NAME = "exiDecoder"; + } + + private final static Logger logger = LoggerFactory + .getLogger(ExiDecoderHandler.class); + + private ExiParameters parameters; + + public ExiDecoderHandler(ExiParameters parameters) { + this.parameters = parameters; + } + + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, + List out) { + try { + ExiUtil.decode(in, out, this.parameters); + } catch (Exception e) { + throw new IllegalStateException("Unable to decode exi message."); + } + } + +} diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiEncoderHandler.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiEncoderHandler.java new file mode 100644 index 0000000000..e7a5917d6c --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiEncoderHandler.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 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.controller.netconf.impl.mapping; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.MessageToByteEncoder; + +import org.opendaylight.controller.netconf.util.xml.ExiParameters; +import org.opendaylight.controller.netconf.util.xml.ExiUtil; + +public class ExiEncoderHandler extends MessageToByteEncoder { + + public static final String HANDLER_NAME; + static { + HANDLER_NAME = "exiEncoder"; + } + + private ExiParameters parameters; + + public ExiEncoderHandler(ExiParameters parameters) { + this.parameters = parameters; + } + + @Override + protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) + throws Exception { + try { + ExiUtil.encode(msg, out, this.parameters); + } catch (Exception e) { + throw new IllegalStateException("Unable to encode exi message."); + } + } +} diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java index 1438515f04..3623ef5032 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java @@ -10,6 +10,8 @@ package org.opendaylight.controller.netconf.impl.mapping.operations; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfOperationRouter; +import org.opendaylight.controller.netconf.api.NetconfSession; +import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation; import org.opendaylight.controller.netconf.util.xml.XmlElement; @@ -17,8 +19,9 @@ import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; import org.w3c.dom.Document; import org.w3c.dom.Element; -public class DefaultCloseSession extends AbstractNetconfOperation { +public class DefaultCloseSession extends AbstractNetconfOperation implements DefaultNetconfOperation { public static final String CLOSE_SESSION = "close-session"; + private NetconfSession netconfSession; public DefaultCloseSession(String netconfSessionIdForReporting) { super(netconfSessionIdForReporting); @@ -45,4 +48,13 @@ public class DefaultCloseSession extends AbstractNetconfOperation { opRouter.close(); return document.createElement(XmlNetconfConstants.OK); } + + @Override + public void setNetconfSession(NetconfSession s) { + this.netconfSession = s; + } + + public NetconfSession getNetconfSession() { + return netconfSession; + } } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java index 8637c0dd74..9069e87a93 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java @@ -8,7 +8,9 @@ package org.opendaylight.controller.netconf.impl.mapping.operations; -import com.google.common.collect.Maps; +import java.io.InputStream; +import java.util.Map; + import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfOperationRouter; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; @@ -24,8 +26,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import java.io.InputStream; -import java.util.Map; +import com.google.common.collect.Maps; public class DefaultCommit implements NetconfOperationFilter { @@ -78,13 +79,13 @@ public class DefaultCommit implements NetconfOperationFilter { } @Override - public int getSoringOrder() { + public int getSortingOrder() { return 0; } @Override public int compareTo(NetconfOperationFilter o) { - return Integer.compare(getSoringOrder(), o.getSoringOrder()); + return Integer.compare(getSortingOrder(), o.getSortingOrder()); } private boolean canHandle(OperationNameAndNamespace operationNameAndNamespace) { @@ -117,7 +118,8 @@ public class DefaultCommit implements NetconfOperationFilter { } private Element getConfigSnapshot(NetconfOperationRouter opRouter) throws NetconfDocumentedException { - final Document responseDocument = opRouter.onNetconfMessage(getConfigMessage); + final Document responseDocument = opRouter.onNetconfMessage( + getConfigMessage, null); XmlElement dataElement; try { diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java index 3e65ed8842..77042855e6 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java @@ -8,11 +8,14 @@ package org.opendaylight.controller.netconf.impl.mapping.operations; -import com.google.common.base.Optional; -import com.google.common.collect.Maps; +import java.util.HashMap; +import java.util.Map; + import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfOperationRouter; +import org.opendaylight.controller.netconf.api.NetconfSession; import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; +import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation; import org.opendaylight.controller.netconf.util.xml.XmlElement; @@ -23,12 +26,13 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.w3c.dom.Element; -import java.util.HashMap; -import java.util.Map; +import com.google.common.base.Optional; +import com.google.common.collect.Maps; -public final class DefaultGetSchema extends AbstractNetconfOperation { +public final class DefaultGetSchema extends AbstractNetconfOperation implements DefaultNetconfOperation { private final CapabilityProvider cap; + private NetconfSession netconfSession; private static final Logger logger = LoggerFactory.getLogger(DefaultGetSchema.class); @@ -116,4 +120,12 @@ public final class DefaultGetSchema extends AbstractNetconfOperation { } } + + public void setNetconfSession(NetconfSession s) { + this.netconfSession = s; + } + + public NetconfSession getNetconfSession() { + return netconfSession; + } } diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java new file mode 100644 index 0000000000..8f08688f59 --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2013 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.controller.netconf.impl.mapping.operations; + +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.NetconfOperationRouter; +import org.opendaylight.controller.netconf.api.NetconfSession; +import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler; +import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler; +import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation; +import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; +import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation; +import org.opendaylight.controller.netconf.util.xml.ExiParameters; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import com.siemens.ct.exi.exceptions.EXIException; + +public class DefaultStartExi extends AbstractNetconfOperation implements DefaultNetconfOperation { + + public static final String START_EXI = "start-exi"; + + private static NetconfSession netconfSession; + + private static final Logger logger = LoggerFactory.getLogger(DefaultStartExi.class); + + public DefaultStartExi(String netconfSessionIdForReporting) { + super(netconfSessionIdForReporting); + } + + @Override + protected HandlingPriority canHandle(String operationName, + String netconfOperationNamespace) { + if (operationName.equals(START_EXI) == false) + return HandlingPriority.CANNOT_HANDLE; + if (netconfOperationNamespace + .equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false) + return HandlingPriority.CANNOT_HANDLE; + + return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY; + } + + @Override + protected Element handle(Document document, XmlElement operationElement, + NetconfOperationRouter opRouter) throws NetconfDocumentedException { + + + Element getSchemaResult = document + .createElement(XmlNetconfConstants.OK); + XmlUtil.addNamespaceAttr(getSchemaResult, + XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); + + + try { + ExiParameters exiParams = new ExiParameters(); + exiParams.setParametersFromXmlElement(operationElement); + + netconfSession.addExiDecoder(ExiDecoderHandler.HANDLER_NAME, new ExiDecoderHandler(exiParams)); + netconfSession.addExiEncoderAfterMessageSent(ExiEncoderHandler.HANDLER_NAME,new ExiEncoderHandler(exiParams)); + + } catch (EXIException e) { + getSchemaResult = document + .createElement(XmlNetconfConstants.RPC_ERROR); + } + + logger.info("{} operation successful", START_EXI); + logger.debug("received start-exi message {} ", XmlUtil.toString(document)); + return getSchemaResult; + + } + + @Override + public void setNetconfSession(NetconfSession s) { + netconfSession = s; + } + + public NetconfSession getNetconfSession() { + return netconfSession; + } + + +} diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java new file mode 100644 index 0000000000..98a7205682 --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2013 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.controller.netconf.impl.mapping.operations; + +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.api.NetconfOperationRouter; +import org.opendaylight.controller.netconf.api.NetconfSession; +import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler; +import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler; +import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation; +import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; +import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation; +import org.opendaylight.controller.netconf.util.xml.XmlElement; +import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants; +import org.opendaylight.controller.netconf.util.xml.XmlUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class DefaultStopExi extends AbstractNetconfOperation implements DefaultNetconfOperation { + + public static final String STOP_EXI = "stop-exi"; + private NetconfSession netconfSession; + + private static final Logger logger = LoggerFactory + .getLogger(DefaultStartExi.class); + + public DefaultStopExi(String netconfSessionIdForReporting) { + super(netconfSessionIdForReporting); + } + + @Override + protected HandlingPriority canHandle(String operationName, + String netconfOperationNamespace) { + if (operationName.equals(STOP_EXI) == false) + return HandlingPriority.CANNOT_HANDLE; + if (netconfOperationNamespace + .equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false) + return HandlingPriority.CANNOT_HANDLE; + + return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY; + } + + @Override + protected Element handle(Document document, XmlElement operationElement, + NetconfOperationRouter opRouter) throws NetconfDocumentedException { + + netconfSession.remove(ExiDecoderHandler.class); + netconfSession.removeAfterMessageSent(ExiEncoderHandler.HANDLER_NAME); + + Element getSchemaResult = document.createElement(XmlNetconfConstants.OK); + XmlUtil.addNamespaceAttr(getSchemaResult, + XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0); + logger.info("{} operation successful", STOP_EXI); + logger.debug("received stop-exi message {} ", XmlUtil.toString(document)); + return getSchemaResult; + } + + @Override + public void setNetconfSession(NetconfSession s) { + this.netconfSession = s; + } + + public NetconfSession getNetconfSession() { + return netconfSession; + } +} \ No newline at end of file diff --git a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java index a9bea344c9..3dd6e6803b 100644 --- a/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java +++ b/opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java @@ -7,16 +7,25 @@ */ package org.opendaylight.controller.netconf.impl.osgi; -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; + import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfOperationRouter; +import org.opendaylight.controller.netconf.api.NetconfSession; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; import org.opendaylight.controller.netconf.impl.mapping.CapabilityProvider; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCloseSession; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultCommit; import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultGetSchema; +import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStartExi; +import org.opendaylight.controller.netconf.impl.mapping.operations.DefaultStopExi; +import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.mapping.api.NetconfOperation; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationFilter; @@ -27,13 +36,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; +import com.google.common.base.Preconditions; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; public class NetconfOperationRouterImpl implements NetconfOperationRouter { @@ -46,8 +51,10 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { private final CapabilityProvider capabilityProvider; + public NetconfOperationRouterImpl(NetconfOperationServiceSnapshot netconfOperationServiceSnapshot, - CapabilityProvider capabilityProvider, DefaultCommitNotificationProducer commitNotifier) { + CapabilityProvider capabilityProvider, + DefaultCommitNotificationProducer commitNotifier) { this.netconfOperationServiceSnapshot = netconfOperationServiceSnapshot; @@ -58,6 +65,12 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { .getNetconfSessionIdForReporting())); defaultNetconfOperations.add(new DefaultCloseSession(netconfOperationServiceSnapshot .getNetconfSessionIdForReporting())); + defaultNetconfOperations.add(new DefaultStartExi( + netconfOperationServiceSnapshot + .getNetconfSessionIdForReporting())); + defaultNetconfOperations.add(new DefaultStopExi( + netconfOperationServiceSnapshot + .getNetconfSessionIdForReporting())); allNetconfOperations = getAllNetconfOperations(defaultNetconfOperations, netconfOperationServiceSnapshot); @@ -101,8 +114,10 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { } @Override - public synchronized Document onNetconfMessage(Document message) throws NetconfDocumentedException { - NetconfOperationExecution netconfOperationExecution = getNetconfOperationWithHighestPriority(message); + public synchronized Document onNetconfMessage(Document message, + NetconfSession session) throws NetconfDocumentedException { + NetconfOperationExecution netconfOperationExecution = getNetconfOperationWithHighestPriority( + message, session); logger.debug("Forwarding netconf message {} to {}", XmlUtil.toString(message), netconfOperationExecution.operationWithHighestPriority); @@ -125,10 +140,12 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { return chain.getFirst().execute(message, this); } - private NetconfOperationExecution getNetconfOperationWithHighestPriority(Document message) { + private NetconfOperationExecution getNetconfOperationWithHighestPriority( + Document message, NetconfSession session) { // TODO test - TreeMap> sortedPriority = getSortedNetconfOperationsWithCanHandle(message); + TreeMap> sortedPriority = getSortedNetconfOperationsWithCanHandle( + message, session); Preconditions.checkState(sortedPriority.isEmpty() == false, "No %s available to handle message %s", NetconfOperation.class.getName(), XmlUtil.toString(message)); @@ -143,12 +160,16 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { return new NetconfOperationExecution(sortedPriority, highestFoundPriority); } - private TreeMap> getSortedNetconfOperationsWithCanHandle(Document message) { + private TreeMap> getSortedNetconfOperationsWithCanHandle( + Document message, NetconfSession session) { TreeMap> sortedPriority = Maps.newTreeMap(); for (NetconfOperation netconfOperation : allNetconfOperations) { final HandlingPriority handlingPriority = netconfOperation.canHandle(message); - + if (netconfOperation instanceof DefaultNetconfOperation) { + ((DefaultNetconfOperation) netconfOperation) + .setNetconfSession(session); + } if (handlingPriority.equals(HandlingPriority.CANNOT_HANDLE) == false) { Set netconfOperations = sortedPriority.get(handlingPriority); netconfOperations = checkIfNoOperationsOnPriority(sortedPriority, handlingPriority, netconfOperations); @@ -197,4 +218,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter { return "NetconfOperationRouterImpl{" + "netconfOperationServiceSnapshot=" + netconfOperationServiceSnapshot + '}'; } + + + } diff --git a/opendaylight/netconf/netconf-impl/src/main/resources/server_hello.xml b/opendaylight/netconf/netconf-impl/src/main/resources/server_hello.xml index 6a3f911cd4..eb4b4b9225 100644 --- a/opendaylight/netconf/netconf-impl/src/main/resources/server_hello.xml +++ b/opendaylight/netconf/netconf-impl/src/main/resources/server_hello.xml @@ -2,6 +2,7 @@ urn:ietf:params:netconf:base:1.0 + urn:ietf:params:netconf:capability:exi:1.0 1 diff --git a/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ExiEncodeDecodeTest.java b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ExiEncodeDecodeTest.java new file mode 100644 index 0000000000..6b0316b6fc --- /dev/null +++ b/opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ExiEncodeDecodeTest.java @@ -0,0 +1,44 @@ +package org.opendaylight.controller.netconf.impl; + +import static junit.framework.Assert.assertNotNull; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.opendaylight.controller.netconf.api.NetconfMessage; +import org.opendaylight.controller.netconf.util.test.XmlFileLoader; +import org.opendaylight.controller.netconf.util.xml.ExiParameters; +import org.opendaylight.controller.netconf.util.xml.ExiUtil; +import org.opendaylight.controller.netconf.util.xml.XmlElement; + + + +public class ExiEncodeDecodeTest { + @Test + public void encodeExi() throws Exception{ + + String startExiString = XmlFileLoader.xmlFileToString("netconfMessages/startExi.xml"); + assertNotNull(startExiString); + + NetconfMessage startExiMessage = XmlFileLoader.xmlFileToNetconfMessage(("netconfMessages/startExi.xml")); + assertNotNull(startExiMessage); + + ExiParameters exiParams = new ExiParameters(); + exiParams.setParametersFromXmlElement(XmlElement.fromDomElement(startExiMessage.getDocument().getDocumentElement())); + assertNotNull(exiParams); + + ByteBuf encodedBuf = Unpooled.buffer(); + ByteBuf sourceBuf = Unpooled.copiedBuffer(startExiString.getBytes()); + ExiUtil.encode(sourceBuf, encodedBuf, exiParams); + + List newOut = new ArrayList(); + ExiUtil.decode(encodedBuf, newOut, exiParams); + + ByteBuf decodedBuf = (ByteBuf)newOut.get(0); + String decodedString = new String(decodedBuf.array(),"UTF-8"); + assertNotNull(decodedString); + } +} diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java index 1512d54105..e9fe857bca 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java @@ -44,9 +44,12 @@ import org.opendaylight.controller.netconf.impl.NetconfServerDispatcher; import org.opendaylight.controller.netconf.impl.NetconfServerSessionListenerFactory; import org.opendaylight.controller.netconf.impl.NetconfServerSessionNegotiatorFactory; import org.opendaylight.controller.netconf.impl.SessionIdProvider; +import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler; +import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler; import org.opendaylight.controller.netconf.impl.osgi.NetconfOperationServiceFactoryListenerImpl; import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler; import org.opendaylight.controller.netconf.util.test.XmlFileLoader; +import org.opendaylight.controller.netconf.util.xml.ExiParameters; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; @@ -80,9 +83,11 @@ public class NetconfITTest extends AbstractConfigTest { // private static final Logger logger = // LoggerFactory.getLogger(NetconfITTest.class); // + private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023); - private NetconfMessage getConfig, getConfigCandidate, editConfig, closeSession; + private NetconfMessage getConfig, getConfigCandidate, editConfig, + closeSession, startExi, stopExi; private DefaultCommitNotificationProducer commitNot; private NetconfServerDispatcher dispatch; @@ -132,6 +137,10 @@ public class NetconfITTest extends AbstractConfigTest { this.editConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/edit_config.xml"); this.getConfig = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig.xml"); this.getConfigCandidate = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/getConfig_candidate.xml"); + this.startExi = XmlFileLoader + .xmlFileToNetconfMessage("netconfMessages/startExi.xml"); + this.stopExi = XmlFileLoader + .xmlFileToNetconfMessage("netconfMessages/stopExi.xml"); this.closeSession = XmlFileLoader.xmlFileToNetconfMessage("netconfMessages/closeSession.xml"); } @@ -270,6 +279,7 @@ public class NetconfITTest extends AbstractConfigTest { final Element rpcReply = message.getDocument().getDocumentElement(); final XmlElement resultElement = XmlElement.fromDomElement(rpcReply).getOnlyChildElement(); assertEquals("result", resultElement.getName()); + final String namespace = resultElement.getNamespaceAttribute(); assertEquals(expectedNamespace, namespace); } @@ -298,15 +308,44 @@ public class NetconfITTest extends AbstractConfigTest { }); } + @Test +// @Ignore + public void testStartExi() throws Exception { + try (NetconfClient netconfClient = createSession(tcpAddress, "1")) { + + + Document rpcReply = netconfClient.sendMessage(this.startExi) + .getDocument(); + assertIsOK(rpcReply); + + ExiParameters exiParams = new ExiParameters(); + exiParams.setParametersFromXmlElement(XmlElement.fromDomDocument(this.startExi.getDocument())); + + netconfClient.getClientSession().addExiDecoder(ExiDecoderHandler.HANDLER_NAME, new ExiDecoderHandler(exiParams)); + netconfClient.getClientSession().addExiEncoder(ExiEncoderHandler.HANDLER_NAME, new ExiEncoderHandler(exiParams)); + + rpcReply = netconfClient.sendMessage(this.editConfig) + .getDocument(); + assertIsOK(rpcReply); + + rpcReply = netconfClient.sendMessage(this.stopExi) + .getDocument(); + assertIsOK(rpcReply); + + } + } + @Test public void testCloseSession() throws Exception { try (NetconfClient netconfClient = createSession(tcpAddress, "1")) { // edit config - Document rpcReply = netconfClient.sendMessage(this.editConfig).getDocument(); + Document rpcReply = netconfClient.sendMessage(this.editConfig) + .getDocument(); assertIsOK(rpcReply); - rpcReply = netconfClient.sendMessage(this.closeSession).getDocument(); + rpcReply = netconfClient.sendMessage(this.closeSession) + .getDocument(); assertIsOK(rpcReply); } @@ -336,7 +375,7 @@ public class NetconfITTest extends AbstractConfigTest { } private void assertIsOK(final Document rpcReply) { - assertEquals("rpc-reply", rpcReply.getDocumentElement().getTagName()); + assertEquals("rpc-reply", rpcReply.getDocumentElement().getLocalName()); assertEquals("ok", XmlElement.fromDomDocument(rpcReply).getOnlyChildElement().getName()); } @@ -398,9 +437,7 @@ public class NetconfITTest extends AbstractConfigTest { private NetconfClient createSession(final InetSocketAddress address, final String expected) throws Exception { final NetconfClient netconfClient = new NetconfClient("test " + address.toString(), address, 5000, NETCONF_CLIENT_DISPATCHER); - assertEquals(expected, Long.toString(netconfClient.getSessionId())); - return netconfClient; } diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/DefaultNetconfOperation.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/DefaultNetconfOperation.java new file mode 100644 index 0000000000..f6f05f6bde --- /dev/null +++ b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/DefaultNetconfOperation.java @@ -0,0 +1,7 @@ +package org.opendaylight.controller.netconf.mapping.api; + +import org.opendaylight.controller.netconf.api.NetconfSession; + +public interface DefaultNetconfOperation { + void setNetconfSession(NetconfSession s); +} diff --git a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java index 22a730726d..c9e04e3dcd 100644 --- a/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java +++ b/opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java @@ -21,6 +21,6 @@ public interface NetconfOperationFilter extends Comparablenetty-handler ${netconf.netty.version} + + com.siemens.ct.exi + exificient + org.opendaylight.controller.thirdparty ganymed @@ -71,6 +75,7 @@ org.opendaylight.controller.netconf.util.osgi, org.opendaylight.controller.netconf.util.mapping, org.opendaylight.controller.netconf.util.messages, + org.opendaylight.controller.netconf.util.handler, org.opendaylight.controller.config.stat, @@ -93,6 +98,7 @@ javax.xml.transform.stream, javax.xml.validation, javax.xml.xpath, + javax.xml.transform.sax, org.opendaylight.controller.netconf.api, org.opendaylight.controller.netconf.mapping.api, org.opendaylight.protocol.framework, @@ -101,6 +107,13 @@ org.slf4j, org.w3c.dom, org.xml.sax, + com.siemens.ct.exi, + com.siemens.ct.exi.api.sax, + com.siemens.ct.exi.grammars, + com.siemens.ct.exi.helpers, + com.siemens.ct.exi.exceptions, + com.siemens.ct.exi.api.dom, + org.xml.sax.helpers, diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageAggregator.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageAggregator.java index 868ddbd99c..b67f48f5fc 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageAggregator.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageAggregator.java @@ -8,6 +8,10 @@ package org.opendaylight.controller.netconf.util.handler; +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.handler.codec.ByteToMessageDecoder; + import java.util.List; import org.opendaylight.controller.netconf.util.messages.FramingMechanism; @@ -15,10 +19,6 @@ import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.ByteToMessageDecoder; - public class NetconfMessageAggregator extends ByteToMessageDecoder { private final static Logger logger = LoggerFactory.getLogger(NetconfMessageAggregator.class); @@ -35,7 +35,7 @@ public class NetconfMessageAggregator extends ByteToMessageDecoder { protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception { int index = indexOfSequence(in, eom); if (index == -1) { - logger.debug("Message is not complete, read agian."); + logger.debug("Message is not complete, read again."); ctx.read(); } else { ByteBuf msg = in.readBytes(index); diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java index 5850e64a05..86081b7f81 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java @@ -8,8 +8,6 @@ package org.opendaylight.controller.netconf.util.mapping; -import java.util.Map; - import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.NetconfOperationRouter; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; @@ -20,6 +18,9 @@ import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import java.util.Map; public abstract class AbstractNetconfOperation implements NetconfOperation { private final String netconfSessionIdForReporting; @@ -76,15 +77,23 @@ public abstract class AbstractNetconfOperation implements NetconfOperation { Map attributes = requestElement.getAttributes(); Element response = handle(document, operationElement, opRouter); - Element rpcReply = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, XmlNetconfConstants.RPC_REPLY_KEY); - rpcReply.appendChild(response); - for (String attrName : attributes.keySet()) { - rpcReply.setAttribute(attrName, attributes.get(attrName).getNodeValue()); + if(XmlElement.fromDomElement(response).hasNamespace()) { + rpcReply.appendChild(response); + } else { + Element responseNS = document.createElementNS(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0, response.getNodeName()); + NodeList list = response.getChildNodes(); + while(list.getLength()!=0) { + responseNS.appendChild(list.item(0)); + } + rpcReply.appendChild(responseNS); } + for (String attrName : attributes.keySet()) { + rpcReply.setAttributeNode((Attr) document.importNode(attributes.get(attrName), true)); + } document.appendChild(rpcReply); return document; } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiParameters.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiParameters.java new file mode 100644 index 0000000000..63dfcde0c6 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiParameters.java @@ -0,0 +1,128 @@ +package org.opendaylight.controller.netconf.util.xml; + +import com.siemens.ct.exi.CodingMode; +import com.siemens.ct.exi.FidelityOptions; +import com.siemens.ct.exi.GrammarFactory; +import com.siemens.ct.exi.exceptions.EXIException; +import com.siemens.ct.exi.grammars.Grammars; + +public class ExiParameters { + + private static final String EXI_PARAMETER_ALIGNMENT = "alignment"; + private static final String EXI_PARAMETER_BYTE_ALIGNED = "byte-aligned"; + private static final String EXI_PARAMETER_COMPRESSED = "compressed"; + + private static final String EXI_PARAMETER_FIDELITY = "fidelity"; + private static final String EXI_FIDELITY_DTD = "dtd"; + private static final String EXI_FIDELITY_LEXICAL_VALUES = "lexical-values"; + private static final String EXI_FIDELITY_COMMENTS = "comments"; + private static final String EXI_FIDELITY_PIS = "pis"; + private static final String EXI_FIDELITY_PREFIXES = "prefixes"; + + private static final String EXI_PARAMETER_SCHEMA = "schema"; + private static final String EXI_PARAMETER_SCHEMA_NONE = "none"; + private static final String EXI_PARAMETER_SCHEMA_BUILT_IN = "builtin"; + private static final String EXI_PARAMETER_SCHEMA_BASE_1_1 = "base:1.1"; + + private static final String NETCONF_XSD_LOCATION = ""; + + private FidelityOptions fidelityOptions; + private Grammars grammars; + private CodingMode codingMode = CodingMode.BIT_PACKED; + + public void setParametersFromXmlElement(XmlElement operationElement) + throws EXIException { + + if (operationElement.getElementsByTagName(EXI_PARAMETER_ALIGNMENT) + .getLength() > 0) { + + if (operationElement.getElementsByTagName( + EXI_PARAMETER_BYTE_ALIGNED) + .getLength() > 0) { + this.codingMode = CodingMode.BYTE_PACKED; + } + + if (operationElement.getElementsByTagName( + EXI_PARAMETER_BYTE_ALIGNED).getLength() > 0) { + this.codingMode = CodingMode.BYTE_PACKED; + } + if (operationElement.getElementsByTagName(EXI_PARAMETER_COMPRESSED) + .getLength() > 0) { + this.codingMode = CodingMode.COMPRESSION; + } + } + + if (operationElement.getElementsByTagName(EXI_PARAMETER_FIDELITY) + .getLength() > 0) { + + this.fidelityOptions = FidelityOptions.createDefault(); + + if (operationElement.getElementsByTagName(EXI_FIDELITY_DTD) + .getLength() > 0) { + this.fidelityOptions.setFidelity(FidelityOptions.FEATURE_DTD, + true); + } + if (operationElement.getElementsByTagName( + EXI_FIDELITY_LEXICAL_VALUES) + .getLength() > 0) { + this.fidelityOptions.setFidelity( + FidelityOptions.FEATURE_LEXICAL_VALUE, true); + } + + if (operationElement.getElementsByTagName(EXI_FIDELITY_COMMENTS) + .getLength() > 0) { + this.fidelityOptions.setFidelity( + FidelityOptions.FEATURE_COMMENT, true); + } + + if (operationElement.getElementsByTagName(EXI_FIDELITY_PIS) + .getLength() > 0) { + this.fidelityOptions.setFidelity(FidelityOptions.FEATURE_PI, + true); + } + + if (operationElement.getElementsByTagName(EXI_FIDELITY_PREFIXES) + .getLength() > 0) { + this.fidelityOptions.setFidelity( + FidelityOptions.FEATURE_PREFIX, true); + } + + } + + if (operationElement.getElementsByTagName(EXI_PARAMETER_SCHEMA) + .getLength() > 0) { + + GrammarFactory grammarFactory = GrammarFactory.newInstance(); + if (operationElement + .getElementsByTagName(EXI_PARAMETER_SCHEMA_NONE) + .getLength() > 0) { + this.grammars = grammarFactory.createSchemaLessGrammars(); + } + + if (operationElement.getElementsByTagName( + EXI_PARAMETER_SCHEMA_BUILT_IN).getLength() > 0) { + this.grammars = grammarFactory.createXSDTypesOnlyGrammars(); + } + + if (operationElement.getElementsByTagName( + EXI_PARAMETER_SCHEMA_BASE_1_1).getLength() > 0) { + this.grammars = grammarFactory + .createGrammars(NETCONF_XSD_LOCATION); + } + + } + } + + public FidelityOptions getFidelityOptions() { + return fidelityOptions; + } + + public Grammars getGrammars() { + return grammars; + } + + public CodingMode getCodingMode() { + return codingMode; + } + +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiUtil.java new file mode 100644 index 0000000000..8baa68e494 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiUtil.java @@ -0,0 +1,91 @@ +package org.opendaylight.controller.netconf.util.xml; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.EmptyByteBuf; +import io.netty.buffer.Unpooled; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.List; + +import javax.xml.parsers.ParserConfigurationException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.SAXException; + +import com.siemens.ct.exi.EXIFactory; +import com.siemens.ct.exi.api.dom.DOMBuilder; +import com.siemens.ct.exi.api.dom.DOMWriter; +import com.siemens.ct.exi.exceptions.EXIException; +import com.siemens.ct.exi.helpers.DefaultEXIFactory; + +public class ExiUtil { + + private final static Logger logger = LoggerFactory.getLogger(ExiUtil.class); + + + + public static void encode(final Object msg, final ByteBuf out, + ExiParameters parameters) + throws EXIException, IOException, SAXException { + final byte[] bytes = toExi(msg, parameters); + out.writeBytes(bytes); + } + + public static void decode(ByteBuf in, List out, + ExiParameters parameters) throws ParserConfigurationException, EXIException, IOException + { + if (in instanceof EmptyByteBuf){ + return; + } + + EXIFactory exiFactory = DefaultEXIFactory.newInstance(); + if (parameters.getGrammars() != null) { + exiFactory.setGrammars(parameters.getGrammars()); + } + + if (parameters.getFidelityOptions() != null) { + exiFactory.setFidelityOptions(parameters.getFidelityOptions()); + } + + exiFactory.setCodingMode(parameters.getCodingMode()); + try (ByteArrayInputStream exiIS = new ByteArrayInputStream(((ByteBuf)in).readBytes(((ByteBuf)in).readableBytes()).array())){ + DOMBuilder domBuilder = new DOMBuilder(exiFactory); + ByteBuf result = Unpooled.copiedBuffer(XmlUtil.toString(domBuilder.parse(exiIS)).getBytes()); + exiIS.close(); + out.add(result); + } + } + + private static byte[] toExi(Object msg, ExiParameters parameters) throws EXIException, IOException, + SAXException { + + if (!(msg instanceof ByteBuf)){ + return Unpooled.EMPTY_BUFFER.array(); + } + + EXIFactory exiFactory = DefaultEXIFactory.newInstance(); + if (parameters.getGrammars() != null) { + exiFactory.setGrammars(parameters.getGrammars()); + } + + if (parameters.getFidelityOptions() != null) { + exiFactory.setFidelityOptions(parameters.getFidelityOptions()); + } + + Document doc = XmlUtil.readXmlToDocument(new String( ((ByteBuf)msg).readBytes(((ByteBuf)msg).readableBytes()).array(),"UTF-8")); + exiFactory.setCodingMode(parameters.getCodingMode()); + + try (ByteArrayOutputStream exiOS = new ByteArrayOutputStream()){ + DOMWriter domWriter = new DOMWriter(exiFactory); + domWriter.setOutput(exiOS); + domWriter.encode(doc) ; + exiOS.close(); + return exiOS.toByteArray(); + } + } + +} diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java index 7cb0bb0285..c37b4abc62 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java @@ -103,6 +103,9 @@ public class XmlElement { } public String getName() { + if (element.getLocalName()!=null && !element.getLocalName().equals("")){ + return element.getLocalName(); + } return element.getTagName(); } @@ -114,6 +117,10 @@ public class XmlElement { return element.getAttributeNS(namespace, attributeName); } + public NodeList getElementsByTagName(String name) { + return element.getElementsByTagName(name); + } + public void appendChild(Element element) { this.element.appendChild(element); // Element newElement = (Element) element.cloneNode(true); @@ -273,8 +280,8 @@ public class XmlElement { public String getNamespaceAttribute() { String attribute = element.getAttribute(XmlUtil.XMLNS_ATTRIBUTE_KEY); - Preconditions.checkState(attribute != null && !attribute.equals(""), "Element %s must specify a %s attribute", - toString(), XmlUtil.XMLNS_ATTRIBUTE_KEY); + Preconditions.checkState(attribute != null && !attribute.equals(""), "Element %s must specify namespace", + toString()); return attribute; } @@ -369,6 +376,20 @@ public class XmlElement { return element.hashCode(); } + public boolean hasNamespace() { + try { + getNamespaceAttribute(); + } catch (IllegalStateException e) { + try { + getNamespace(); + } catch (IllegalStateException e1) { + return false; + } + return true; + } + return true; + } + private static interface ElementFilteringStrategy { boolean accept(Element e); } diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java index 0791812910..3e862faa7b 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java @@ -35,6 +35,7 @@ public class XmlNetconfConstants { // public static final String RFC4741_TARGET_NAMESPACE = "urn:ietf:params:xml:ns:netconf:base:1.0"; public static final String URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0 = "urn:ietf:params:xml:ns:netconf:base:1.0"; + public static final String URN_IETF_PARAMS_XML_NS_YANG_IETF_NETCONF_MONITORING = "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"; // TODO where to store namespace of config ? public static final String URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG = "urn:opendaylight:params:xml:ns:yang:controller:config"; diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java index 298038996e..5e3a7ac54f 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java @@ -8,11 +8,12 @@ package org.opendaylight.controller.netconf.util.xml; -import com.google.common.base.Charsets; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.xml.sax.SAXException; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; import javax.xml.XMLConstants; import javax.xml.namespace.QName; @@ -32,12 +33,13 @@ import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.StringWriter; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.SAXException; + +import com.google.common.base.Charsets; public class XmlUtil { @@ -79,7 +81,6 @@ public class XmlUtil { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); factory.setCoalescing(true); - // factory.setValidating(true); factory.setIgnoringElementContentWhitespace(true); factory.setIgnoringComments(true); return factory; diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java index 8b60719ebe..28cb4d8194 100644 --- a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java +++ b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java @@ -8,20 +8,22 @@ package org.opendaylight.controller.netconf.util.test; -import com.google.common.base.Charsets; -import com.google.common.base.Preconditions; -import com.google.common.io.CharStreams; -import com.google.common.io.InputSupplier; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import javax.xml.parsers.ParserConfigurationException; + import org.opendaylight.controller.netconf.api.NetconfMessage; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.xml.sax.SAXException; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import com.google.common.base.Charsets; +import com.google.common.base.Preconditions; +import com.google.common.io.CharStreams; +import com.google.common.io.InputSupplier; public class XmlFileLoader { diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml new file mode 100644 index 0000000000..6b9e9452e8 --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml @@ -0,0 +1,9 @@ + + +pre-compression + + + + + + \ No newline at end of file diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml new file mode 100644 index 0000000000..4168d21aba --- /dev/null +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/opendaylight/netconf/pom.xml b/opendaylight/netconf/pom.xml index 5447f7f5d0..5efff5d9a0 100644 --- a/opendaylight/netconf/pom.xml +++ b/opendaylight/netconf/pom.xml @@ -27,6 +27,7 @@ netconf-mapping-api netconf-client ../../third-party/ganymed + ../../third-party/com.siemens.ct.exi @@ -46,6 +47,7 @@ 2.3.7 1.7.2 4.0.10.Final + 0.9.2 @@ -182,6 +184,11 @@ logback-config ${config.version} + + com.siemens.ct.exi + exificient + ${ct.exi.version} + diff --git a/third-party/com.siemens.ct.exi/pom.xml b/third-party/com.siemens.ct.exi/pom.xml new file mode 100644 index 0000000000..237222cd8c --- /dev/null +++ b/third-party/com.siemens.ct.exi/pom.xml @@ -0,0 +1,69 @@ + + + + + org.opendaylight.controller + commons.thirdparty + 1.1.1-SNAPSHOT + ../commons/thirdparty + + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main + HEAD + + + 4.0.0 + org.opendaylight.controller.thirdparty + exificient + 0.9.2 + bundle + + + + org.apache.felix + maven-bundle-plugin + 2.3.6 + true + + + *;scope=!provided;type=!pom;inline=false + false + + com.siemens.ct.exi.*, + + + javax.xml.namespace, + javax.xml.parsers, + javax.xml.stream, + javax.xml.stream.events, + javax.xml.transform.sax, + org.apache.xerces.impl.xs, + org.apache.xerces.impl.xs.models, + org.apache.xerces.xni, + org.apache.xerces.xni.grammars, + org.apache.xerces.xni.parser, + org.apache.xerces.xs, + org.w3c.dom, + org.xml.sax, + org.xml.sax.ext, + org.xml.sax.helpers + + + ${project.basedir}/META-INF + + + + + + + + + com.siemens.ct.exi + exificient + 0.9.2 + + + +