- Added exi capability utilities, handlers and necessary modifications 07/2407/12
authorMartin Bobak <mbobak@cisco.com>
Wed, 30 Oct 2013 10:19:12 +0000 (11:19 +0100)
committerMartin Bobak <mbobak@cisco.com>
Fri, 8 Nov 2013 10:03:26 +0000 (11:03 +0100)
- 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 <mbobak@cisco.com>
Signed-off-by: Martin Bobak <mbobak@cisco.com>
Change-Id: If9f20cef34ec05495eb212f6a584dd65a401dc0a
Signed-off-by: Martin Bobak <mbobak@cisco.com>
39 files changed:
opendaylight/commons/opendaylight/pom.xml
opendaylight/distribution/opendaylight/pom.xml
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/NetconfOperationServiceImpl.java
opendaylight/netconf/netconf-api/pom.xml
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfSession.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSession.java
opendaylight/netconf/netconf-client/src/main/resources/client_hello.xml
opendaylight/netconf/netconf-impl/pom.xml
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiDecoderHandler.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/ExiEncoderHandler.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCommit.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultGetSchema.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStartExi.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultStopExi.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java
opendaylight/netconf/netconf-impl/src/main/resources/server_hello.xml
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ExiEncodeDecodeTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/DefaultNetconfOperation.java [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationFilter.java
opendaylight/netconf/netconf-util/pom.xml
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageAggregator.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/mapping/AbstractNetconfOperation.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiParameters.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/ExiUtil.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlNetconfConstants.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlUtil.java
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/test/XmlFileLoader.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/startExi.xml [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/stopExi.xml [new file with mode: 0644]
opendaylight/netconf/pom.xml
third-party/com.siemens.ct.exi/pom.xml [new file with mode: 0644]

index 8ff25c3..862f809 100644 (file)
     <java.version.target>1.7</java.version.target>
     <!-- enforcer version -->
     <enforcer.version>1.3.1</enforcer.version>
+    <exi.version>0.9.2</exi.version>
   </properties>
 
   <dependencyManagement>
         <artifactId>org.openflow.openflowj</artifactId>
         <version>1.0.2</version>
       </dependency>
+      <dependency>
+        <groupId>org.opendaylight.controller.thirdparty</groupId>
+        <artifactId>exificient</artifactId>
+        <version>${exi.version}</version>
+      </dependency>
       <dependency>
         <groupId>org.opendaylight.controller.thirdparty</groupId>
         <artifactId>com.sun.jersey.jersey-servlet</artifactId>
index a0d7162..1ebab9b 100644 (file)
           <artifactId>config-persister-impl</artifactId>
           <version>${netconf.version}</version>
         </dependency>
-
+        <dependency>
+          <groupId>org.opendaylight.controller.thirdparty</groupId>
+          <artifactId>exificient</artifactId>
+          <version>${exi.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.servicemix.bundles</groupId>
+            <artifactId>org.apache.servicemix.bundles.xerces</artifactId>
+            <version>2.11.0_1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.birt.runtime.3_7_1</groupId>
+            <artifactId>org.apache.xml.resolver</artifactId>
+            <version>1.2.0</version>
+        </dependency>
 
           <!-- toaster example I'm pretty sure we should trim -->
-
          <dependency>
           <groupId>org.opendaylight.controller.samples</groupId>
           <artifactId>sample-toaster</artifactId>
index 8497edb..ce0036f 100644 (file)
@@ -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}.
index 3c62094..902cf2a 100644 (file)
                             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
                         </Import-Package>
                         <Export-Package>
                             org.opendaylight.controller.netconf.api,
@@ -46,7 +49,7 @@
                         </Export-Package>
                     </instructions>
                 </configuration>
-            </plugin>
+             </plugin>
         </plugins>
     </build>
 
index 49ca0c0..e2a2d83 100644 (file)
@@ -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();
index a61d693..8b761a8 100644 (file)
  * 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<NetconfMessage> {
 
-    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<String, ChannelHandler> 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 extends ChannelHandler> T remove(Class<T> handlerType) {
+        return channel.pipeline().remove(handlerType);
+    }
+
+    public <T extends ChannelHandler> T getHandler(Class<T> 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;
+    }
+
 }
+
index cc8d987..61a9a9b 100644 (file)
@@ -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;
+    }
 }
index f0180cf..11c7f30 100644 (file)
@@ -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<String> capabilities;
-    private boolean up;
 
     public NetconfClientSession(SessionListener sessionListener, Channel channel, long sessionId,
             Collection<String> 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<String> getServerCapabilities() {
         return capabilities;
     }
+
 }
index 1d85b68..221953e 100644 (file)
@@ -1,5 +1,6 @@
 <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <capabilities>
         <capability>urn:ietf:params:netconf:base:1.0</capability>
+        <capability>urn:ietf:params:netconf:capability:exi:1.0</capability>
     </capabilities>
 </hello>
\ No newline at end of file
index c355cb0..1bd3a78 100644 (file)
@@ -54,7 +54,6 @@
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
         </dependency>
-
         <!-- test dependencies -->
         <dependency>
             <groupId>org.opendaylight.bgpcep</groupId>
                             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,
                             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,
                             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
                         </Import-Package>
                     </instructions>
                 </configuration>
index 1ae3fab..a4d7e74 100644 (file)
@@ -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;
-    }
 }
index 4f71ab9..686adca 100644 (file)
@@ -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<NetconfMessage, NetconfServerSession, NetconfTerminationReason> {
@@ -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 {
index eea6dc1..70ddf29 100644 (file)
@@ -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 (file)
index 0000000..721c0c2
--- /dev/null
@@ -0,0 +1,48 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.channel.ChannelHandlerContext;\r
+import io.netty.handler.codec.ByteToMessageDecoder;\r
+\r
+import java.util.List;\r
+\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.ExiUtil;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+public class ExiDecoderHandler extends ByteToMessageDecoder {\r
+\r
+    public static final String HANDLER_NAME;\r
+\r
+    static {\r
+        HANDLER_NAME = "exiDecoder";\r
+    }\r
+\r
+    private final static Logger logger = LoggerFactory\r
+            .getLogger(ExiDecoderHandler.class);\r
+\r
+    private ExiParameters parameters;\r
+\r
+    public ExiDecoderHandler(ExiParameters parameters) {\r
+        this.parameters = parameters;\r
+    }\r
+\r
+    @Override\r
+    protected void decode(ChannelHandlerContext ctx, ByteBuf in,\r
+            List<Object> out) {\r
+        try {\r
+            ExiUtil.decode(in, out, this.parameters);\r
+        } catch (Exception e) {\r
+            throw new IllegalStateException("Unable to decode exi message.");\r
+        }\r
+    }\r
+\r
+}\r
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 (file)
index 0000000..e7a5917
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.channel.ChannelHandlerContext;\r
+import io.netty.handler.codec.MessageToByteEncoder;\r
+\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.ExiUtil;\r
+\r
+public class ExiEncoderHandler extends MessageToByteEncoder<Object> {\r
+\r
+    public static final String HANDLER_NAME;\r
+    static {\r
+        HANDLER_NAME = "exiEncoder";\r
+    }\r
+\r
+    private ExiParameters parameters;\r
+\r
+    public ExiEncoderHandler(ExiParameters parameters) {\r
+        this.parameters = parameters;\r
+    }\r
+\r
+    @Override\r
+    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out)\r
+            throws Exception {\r
+        try {\r
+            ExiUtil.encode(msg, out, this.parameters);\r
+        } catch (Exception e) {\r
+            throw new IllegalStateException("Unable to encode exi message.");\r
+        }\r
+    }\r
+}\r
index 1438515..3623ef5 100644 (file)
@@ -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;
+    }
 }
index 8637c0d..9069e87 100644 (file)
@@ -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 {
index 3e65ed8..7704285 100644 (file)
@@ -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 (file)
index 0000000..8f08688
--- /dev/null
@@ -0,0 +1,92 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping.operations;\r
+\r
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;\r
+import org.opendaylight.controller.netconf.api.NetconfOperationRouter;\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler;\r
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;\r
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;\r
+import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+import com.siemens.ct.exi.exceptions.EXIException;\r
+\r
+public class DefaultStartExi extends AbstractNetconfOperation implements DefaultNetconfOperation {\r
+\r
+    public static final String START_EXI = "start-exi";\r
+\r
+    private static NetconfSession netconfSession;\r
+\r
+    private static final Logger logger = LoggerFactory.getLogger(DefaultStartExi.class);\r
+\r
+    public DefaultStartExi(String netconfSessionIdForReporting) {\r
+        super(netconfSessionIdForReporting);\r
+    }\r
+\r
+    @Override\r
+    protected HandlingPriority canHandle(String operationName,\r
+            String netconfOperationNamespace) {\r
+        if (operationName.equals(START_EXI) == false)\r
+            return HandlingPriority.CANNOT_HANDLE;\r
+        if (netconfOperationNamespace\r
+                .equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false)\r
+            return HandlingPriority.CANNOT_HANDLE;\r
+\r
+        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;\r
+    }\r
+\r
+    @Override\r
+    protected Element handle(Document document, XmlElement operationElement,\r
+            NetconfOperationRouter opRouter) throws NetconfDocumentedException {\r
+\r
+\r
+        Element getSchemaResult = document\r
+                .createElement(XmlNetconfConstants.OK);\r
+        XmlUtil.addNamespaceAttr(getSchemaResult,\r
+                XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);\r
+\r
+\r
+        try {\r
+            ExiParameters exiParams = new ExiParameters();\r
+            exiParams.setParametersFromXmlElement(operationElement);\r
+\r
+            netconfSession.addExiDecoder(ExiDecoderHandler.HANDLER_NAME, new ExiDecoderHandler(exiParams));\r
+            netconfSession.addExiEncoderAfterMessageSent(ExiEncoderHandler.HANDLER_NAME,new ExiEncoderHandler(exiParams));\r
+\r
+        } catch (EXIException e) {\r
+            getSchemaResult = document\r
+                    .createElement(XmlNetconfConstants.RPC_ERROR);\r
+        }\r
+\r
+        logger.info("{} operation successful", START_EXI);\r
+        logger.debug("received start-exi message {} ", XmlUtil.toString(document));\r
+        return getSchemaResult;\r
+\r
+    }\r
+\r
+    @Override\r
+    public void setNetconfSession(NetconfSession s) {\r
+        netconfSession = s;\r
+    }\r
+\r
+    public NetconfSession getNetconfSession() {\r
+        return netconfSession;\r
+    }\r
+\r
+\r
+}\r
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 (file)
index 0000000..98a7205
--- /dev/null
@@ -0,0 +1,73 @@
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.netconf.impl.mapping.operations;\r
+\r
+import org.opendaylight.controller.netconf.api.NetconfDocumentedException;\r
+import org.opendaylight.controller.netconf.api.NetconfOperationRouter;\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiDecoderHandler;\r
+import org.opendaylight.controller.netconf.impl.mapping.ExiEncoderHandler;\r
+import org.opendaylight.controller.netconf.mapping.api.DefaultNetconfOperation;\r
+import org.opendaylight.controller.netconf.mapping.api.HandlingPriority;\r
+import org.opendaylight.controller.netconf.util.mapping.AbstractNetconfOperation;\r
+import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;\r
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+\r
+public class DefaultStopExi extends AbstractNetconfOperation implements DefaultNetconfOperation {\r
+\r
+    public static final String STOP_EXI = "stop-exi";\r
+    private NetconfSession netconfSession;\r
+\r
+    private static final Logger logger = LoggerFactory\r
+            .getLogger(DefaultStartExi.class);\r
+\r
+    public DefaultStopExi(String netconfSessionIdForReporting) {\r
+        super(netconfSessionIdForReporting);\r
+    }\r
+\r
+    @Override\r
+    protected HandlingPriority canHandle(String operationName,\r
+            String netconfOperationNamespace) {\r
+        if (operationName.equals(STOP_EXI) == false)\r
+            return HandlingPriority.CANNOT_HANDLE;\r
+        if (netconfOperationNamespace\r
+                .equals(XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0) == false)\r
+            return HandlingPriority.CANNOT_HANDLE;\r
+\r
+        return HandlingPriority.HANDLE_WITH_DEFAULT_PRIORITY;\r
+    }\r
+\r
+    @Override\r
+    protected Element handle(Document document, XmlElement operationElement,\r
+            NetconfOperationRouter opRouter) throws NetconfDocumentedException {\r
+\r
+        netconfSession.remove(ExiDecoderHandler.class);\r
+        netconfSession.removeAfterMessageSent(ExiEncoderHandler.HANDLER_NAME);\r
+\r
+        Element getSchemaResult = document.createElement(XmlNetconfConstants.OK);\r
+        XmlUtil.addNamespaceAttr(getSchemaResult,\r
+                XmlNetconfConstants.URN_IETF_PARAMS_XML_NS_NETCONF_BASE_1_0);\r
+        logger.info("{} operation successful", STOP_EXI);\r
+        logger.debug("received stop-exi message {} ", XmlUtil.toString(document));\r
+        return getSchemaResult;\r
+    }\r
+\r
+    @Override\r
+    public void setNetconfSession(NetconfSession s) {\r
+        this.netconfSession = s;\r
+    }\r
+\r
+    public NetconfSession getNetconfSession() {\r
+        return netconfSession;\r
+    }\r
+}
\ No newline at end of file
index a9bea34..3dd6e68 100644 (file)
@@ -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<HandlingPriority, Set<NetconfOperation>> sortedPriority = getSortedNetconfOperationsWithCanHandle(message);
+        TreeMap<HandlingPriority, Set<NetconfOperation>> 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<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(Document message) {
+    private TreeMap<HandlingPriority, Set<NetconfOperation>> getSortedNetconfOperationsWithCanHandle(
+            Document message, NetconfSession session) {
         TreeMap<HandlingPriority, Set<NetconfOperation>> 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<NetconfOperation> netconfOperations = sortedPriority.get(handlingPriority);
                 netconfOperations = checkIfNoOperationsOnPriority(sortedPriority, handlingPriority, netconfOperations);
@@ -197,4 +218,7 @@ public class NetconfOperationRouterImpl implements NetconfOperationRouter {
         return "NetconfOperationRouterImpl{" + "netconfOperationServiceSnapshot=" + netconfOperationServiceSnapshot
                 + '}';
     }
+
+
+
 }
index 6a3f911..eb4b4b9 100644 (file)
@@ -2,6 +2,7 @@
 <hello xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
     <capabilities>
         <capability>urn:ietf:params:netconf:base:1.0</capability>
+        <capability>urn:ietf:params:netconf:capability:exi:1.0</capability>
     </capabilities>
     <session-id>1</session-id>
 </hello>
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 (file)
index 0000000..6b0316b
--- /dev/null
@@ -0,0 +1,44 @@
+package org.opendaylight.controller.netconf.impl;\r
+\r
+import static junit.framework.Assert.assertNotNull;\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.buffer.Unpooled;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.junit.Test;\r
+import org.opendaylight.controller.netconf.api.NetconfMessage;\r
+import org.opendaylight.controller.netconf.util.test.XmlFileLoader;\r
+import org.opendaylight.controller.netconf.util.xml.ExiParameters;\r
+import org.opendaylight.controller.netconf.util.xml.ExiUtil;\r
+import org.opendaylight.controller.netconf.util.xml.XmlElement;\r
+\r
+\r
+\r
+public class ExiEncodeDecodeTest  {\r
+    @Test\r
+    public void encodeExi() throws Exception{\r
+\r
+        String startExiString = XmlFileLoader.xmlFileToString("netconfMessages/startExi.xml");\r
+        assertNotNull(startExiString);\r
+\r
+        NetconfMessage startExiMessage = XmlFileLoader.xmlFileToNetconfMessage(("netconfMessages/startExi.xml"));\r
+        assertNotNull(startExiMessage);\r
+\r
+        ExiParameters exiParams = new ExiParameters();\r
+        exiParams.setParametersFromXmlElement(XmlElement.fromDomElement(startExiMessage.getDocument().getDocumentElement()));\r
+        assertNotNull(exiParams);\r
+\r
+        ByteBuf encodedBuf = Unpooled.buffer();\r
+        ByteBuf sourceBuf = Unpooled.copiedBuffer(startExiString.getBytes());\r
+        ExiUtil.encode(sourceBuf, encodedBuf, exiParams);\r
+\r
+        List<Object> newOut = new ArrayList<Object>();\r
+        ExiUtil.decode(encodedBuf, newOut, exiParams);\r
+\r
+        ByteBuf decodedBuf = (ByteBuf)newOut.get(0);\r
+        String decodedString = new String(decodedBuf.array(),"UTF-8");\r
+        assertNotNull(decodedString);\r
+    }\r
+}\r
index 1512d54..e9fe857 100644 (file)
@@ -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 (file)
index 0000000..f6f05f6
--- /dev/null
@@ -0,0 +1,7 @@
+package org.opendaylight.controller.netconf.mapping.api;\r
+\r
+import org.opendaylight.controller.netconf.api.NetconfSession;\r
+\r
+public interface DefaultNetconfOperation {\r
+    void setNetconfSession(NetconfSession s);\r
+}\r
index 22a7307..c9e04e3 100644 (file)
@@ -21,6 +21,6 @@ public interface NetconfOperationFilter extends Comparable<NetconfOperationFilte
     Document doFilter(Document message, NetconfOperationRouter operationRouter, NetconfOperationFilterChain filterChain)
             throws NetconfDocumentedException;
 
-    int getSoringOrder();
+    int getSortingOrder();
 
 }
index d6bf624..4638a10 100644 (file)
             <artifactId>netty-handler</artifactId>
             <version>${netconf.netty.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.siemens.ct.exi</groupId>
+            <artifactId>exificient</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.controller.thirdparty</groupId>
             <artifactId>ganymed</artifactId>
@@ -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,
                         </Export-Package>
                         <Import-Package>
                             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,
                             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,
                         </Import-Package>
                     </instructions>
                 </configuration>
index 868ddbd..b67f48f 100644 (file)
@@ -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<Object> 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);
index 5850e64..86081b7 100644 (file)
@@ -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<String, Attr> 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 (file)
index 0000000..63dfcde
--- /dev/null
@@ -0,0 +1,128 @@
+package org.opendaylight.controller.netconf.util.xml;\r
+\r
+import com.siemens.ct.exi.CodingMode;\r
+import com.siemens.ct.exi.FidelityOptions;\r
+import com.siemens.ct.exi.GrammarFactory;\r
+import com.siemens.ct.exi.exceptions.EXIException;\r
+import com.siemens.ct.exi.grammars.Grammars;\r
+\r
+public class ExiParameters {\r
+\r
+    private static final String EXI_PARAMETER_ALIGNMENT = "alignment";\r
+    private static final String EXI_PARAMETER_BYTE_ALIGNED = "byte-aligned";\r
+    private static final String EXI_PARAMETER_COMPRESSED = "compressed";\r
+\r
+    private static final String EXI_PARAMETER_FIDELITY = "fidelity";\r
+    private static final String EXI_FIDELITY_DTD = "dtd";\r
+    private static final String EXI_FIDELITY_LEXICAL_VALUES = "lexical-values";\r
+    private static final String EXI_FIDELITY_COMMENTS = "comments";\r
+    private static final String EXI_FIDELITY_PIS = "pis";\r
+    private static final String EXI_FIDELITY_PREFIXES = "prefixes";\r
+\r
+    private static final String EXI_PARAMETER_SCHEMA = "schema";\r
+    private static final String EXI_PARAMETER_SCHEMA_NONE = "none";\r
+    private static final String EXI_PARAMETER_SCHEMA_BUILT_IN = "builtin";\r
+    private static final String EXI_PARAMETER_SCHEMA_BASE_1_1 = "base:1.1";\r
+\r
+    private static final String NETCONF_XSD_LOCATION = "";\r
+\r
+    private FidelityOptions fidelityOptions;\r
+    private Grammars grammars;\r
+    private CodingMode codingMode = CodingMode.BIT_PACKED;\r
+\r
+    public void setParametersFromXmlElement(XmlElement operationElement)\r
+            throws EXIException {\r
+\r
+        if (operationElement.getElementsByTagName(EXI_PARAMETER_ALIGNMENT)\r
+                .getLength() > 0) {\r
+\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_PARAMETER_BYTE_ALIGNED)\r
+                    .getLength() > 0) {\r
+                this.codingMode = CodingMode.BYTE_PACKED;\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_PARAMETER_BYTE_ALIGNED).getLength() > 0) {\r
+                this.codingMode = CodingMode.BYTE_PACKED;\r
+            }\r
+            if (operationElement.getElementsByTagName(EXI_PARAMETER_COMPRESSED)\r
+                    .getLength() > 0) {\r
+                this.codingMode = CodingMode.COMPRESSION;\r
+            }\r
+        }\r
+\r
+        if (operationElement.getElementsByTagName(EXI_PARAMETER_FIDELITY)\r
+                .getLength() > 0) {\r
+\r
+            this.fidelityOptions = FidelityOptions.createDefault();\r
+\r
+            if (operationElement.getElementsByTagName(EXI_FIDELITY_DTD)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(FidelityOptions.FEATURE_DTD,\r
+                        true);\r
+            }\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_FIDELITY_LEXICAL_VALUES)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(\r
+                        FidelityOptions.FEATURE_LEXICAL_VALUE, true);\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(EXI_FIDELITY_COMMENTS)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(\r
+                        FidelityOptions.FEATURE_COMMENT, true);\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(EXI_FIDELITY_PIS)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(FidelityOptions.FEATURE_PI,\r
+                        true);\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(EXI_FIDELITY_PREFIXES)\r
+                    .getLength() > 0) {\r
+                this.fidelityOptions.setFidelity(\r
+                        FidelityOptions.FEATURE_PREFIX, true);\r
+            }\r
+\r
+        }\r
+\r
+        if (operationElement.getElementsByTagName(EXI_PARAMETER_SCHEMA)\r
+                .getLength() > 0) {\r
+\r
+            GrammarFactory grammarFactory = GrammarFactory.newInstance();\r
+            if (operationElement\r
+                    .getElementsByTagName(EXI_PARAMETER_SCHEMA_NONE)\r
+                    .getLength() > 0) {\r
+                this.grammars = grammarFactory.createSchemaLessGrammars();\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_PARAMETER_SCHEMA_BUILT_IN).getLength() > 0) {\r
+                this.grammars = grammarFactory.createXSDTypesOnlyGrammars();\r
+            }\r
+\r
+            if (operationElement.getElementsByTagName(\r
+                    EXI_PARAMETER_SCHEMA_BASE_1_1).getLength() > 0) {\r
+                this.grammars = grammarFactory\r
+                        .createGrammars(NETCONF_XSD_LOCATION);\r
+            }\r
+\r
+        }\r
+    }\r
+\r
+    public FidelityOptions getFidelityOptions() {\r
+        return fidelityOptions;\r
+    }\r
+\r
+    public Grammars getGrammars() {\r
+        return grammars;\r
+    }\r
+\r
+    public CodingMode getCodingMode() {\r
+        return codingMode;\r
+    }\r
+\r
+}\r
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 (file)
index 0000000..8baa68e
--- /dev/null
@@ -0,0 +1,91 @@
+package org.opendaylight.controller.netconf.util.xml;\r
+\r
+import io.netty.buffer.ByteBuf;\r
+import io.netty.buffer.EmptyByteBuf;\r
+import io.netty.buffer.Unpooled;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.ByteArrayOutputStream;\r
+import java.io.IOException;\r
+import java.util.List;\r
+\r
+import javax.xml.parsers.ParserConfigurationException;\r
+\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+import org.w3c.dom.Document;\r
+import org.xml.sax.SAXException;\r
+\r
+import com.siemens.ct.exi.EXIFactory;\r
+import com.siemens.ct.exi.api.dom.DOMBuilder;\r
+import com.siemens.ct.exi.api.dom.DOMWriter;\r
+import com.siemens.ct.exi.exceptions.EXIException;\r
+import com.siemens.ct.exi.helpers.DefaultEXIFactory;\r
+\r
+public class ExiUtil {\r
+\r
+    private final static Logger logger = LoggerFactory.getLogger(ExiUtil.class);\r
+\r
+\r
+\r
+    public static void encode(final Object msg, final ByteBuf out,\r
+            ExiParameters parameters)\r
+            throws EXIException, IOException, SAXException {\r
+        final byte[] bytes = toExi(msg, parameters);\r
+        out.writeBytes(bytes);\r
+    }\r
+\r
+    public static void decode(ByteBuf in, List<Object> out,\r
+            ExiParameters parameters) throws ParserConfigurationException, EXIException, IOException\r
+             {\r
+        if (in instanceof EmptyByteBuf){\r
+            return;\r
+        }\r
+\r
+        EXIFactory exiFactory = DefaultEXIFactory.newInstance();\r
+        if (parameters.getGrammars() != null) {\r
+            exiFactory.setGrammars(parameters.getGrammars());\r
+        }\r
+\r
+        if (parameters.getFidelityOptions() != null) {\r
+            exiFactory.setFidelityOptions(parameters.getFidelityOptions());\r
+        }\r
+\r
+        exiFactory.setCodingMode(parameters.getCodingMode());\r
+        try (ByteArrayInputStream exiIS = new ByteArrayInputStream(((ByteBuf)in).readBytes(((ByteBuf)in).readableBytes()).array())){\r
+            DOMBuilder domBuilder = new DOMBuilder(exiFactory);\r
+            ByteBuf result = Unpooled.copiedBuffer(XmlUtil.toString(domBuilder.parse(exiIS)).getBytes());\r
+            exiIS.close();\r
+            out.add(result);\r
+        }\r
+    }\r
+\r
+    private static byte[] toExi(Object msg, ExiParameters parameters) throws EXIException, IOException,\r
+            SAXException {\r
+\r
+        if (!(msg instanceof ByteBuf)){\r
+              return Unpooled.EMPTY_BUFFER.array();\r
+        }\r
+\r
+        EXIFactory exiFactory = DefaultEXIFactory.newInstance();\r
+        if (parameters.getGrammars() != null) {\r
+            exiFactory.setGrammars(parameters.getGrammars());\r
+        }\r
+\r
+        if (parameters.getFidelityOptions() != null) {\r
+            exiFactory.setFidelityOptions(parameters.getFidelityOptions());\r
+        }\r
+\r
+        Document doc = XmlUtil.readXmlToDocument(new String( ((ByteBuf)msg).readBytes(((ByteBuf)msg).readableBytes()).array(),"UTF-8"));\r
+        exiFactory.setCodingMode(parameters.getCodingMode());\r
+\r
+        try (ByteArrayOutputStream exiOS = new ByteArrayOutputStream()){\r
+            DOMWriter domWriter = new DOMWriter(exiFactory);\r
+            domWriter.setOutput(exiOS);\r
+            domWriter.encode(doc) ;\r
+            exiOS.close();\r
+            return exiOS.toByteArray();\r
+        }\r
+    }\r
+\r
+}\r
index 7cb0bb0..c37b4ab 100644 (file)
@@ -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);
     }
index 0791812..3e862fa 100644 (file)
@@ -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";
index 2980389..5e3a7ac 100644 (file)
@@ -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;
index 8b60719..28cb4d8 100644 (file)
@@ -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 (file)
index 0000000..6b9e945
--- /dev/null
@@ -0,0 +1,9 @@
+<rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" a="64" message-id="a">\r
+<start-exi>\r
+<alignment>pre-compression</alignment>\r
+<fidelity>\r
+<dtd/>\r
+<lexical-values/>\r
+</fidelity>\r
+</start-exi>\r
+</rpc>
\ 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 (file)
index 0000000..4168d21
--- /dev/null
@@ -0,0 +1,3 @@
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">\r
+    <stop-exi/>\r
+</rpc>
\ No newline at end of file
index 5447f7f..5efff5d 100644 (file)
@@ -27,6 +27,7 @@
         <module>netconf-mapping-api</module>
         <module>netconf-client</module>
         <module>../../third-party/ganymed</module>
+        <module>../../third-party/com.siemens.ct.exi</module>
     </modules>
 
     <profiles>
@@ -46,6 +47,7 @@
         <maven.bundle.version>2.3.7</maven.bundle.version>
         <slf4j.version>1.7.2</slf4j.version>
         <netconf.netty.version>4.0.10.Final</netconf.netty.version>
+        <ct.exi.version>0.9.2</ct.exi.version>
     </properties>
 
     <dependencies>
                 <artifactId>logback-config</artifactId>
                 <version>${config.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.siemens.ct.exi</groupId>
+                <artifactId>exificient</artifactId>
+                <version>${ct.exi.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
diff --git a/third-party/com.siemens.ct.exi/pom.xml b/third-party/com.siemens.ct.exi/pom.xml
new file mode 100644 (file)
index 0000000..237222c
--- /dev/null
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <!-- Get some common settings for the project we are using it in -->
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.thirdparty</artifactId>
+    <version>1.1.1-SNAPSHOT</version>
+    <relativePath>../commons/thirdparty</relativePath>
+  </parent>
+  <scm>
+    <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+    <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+    <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+    <tag>HEAD</tag>
+  </scm>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.controller.thirdparty</groupId>
+  <artifactId>exificient</artifactId>
+  <version>0.9.2</version>
+  <packaging>bundle</packaging>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.6</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Embed-Dependency>*;scope=!provided;type=!pom;inline=false</Embed-Dependency>
+            <Embed-Transitive>false</Embed-Transitive>
+            <Export-Package>
+              com.siemens.ct.exi.*,
+            </Export-Package>
+            <Import-Package>
+                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
+            </Import-Package>
+          </instructions>
+          <manifestLocation>${project.basedir}/META-INF</manifestLocation>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+
+  <dependencies>
+    <dependency>
+        <groupId>com.siemens.ct.exi</groupId>
+        <artifactId>exificient</artifactId>
+        <version>0.9.2</version>
+    </dependency>
+  </dependencies>
+
+</project>