Merge "Backward compatibility for User management"
authorAndrew Kim <andrekim@cisco.com>
Sun, 23 Feb 2014 01:50:47 +0000 (01:50 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Sun, 23 Feb 2014 01:50:47 +0000 (01:50 +0000)
130 files changed:
opendaylight/commons/opendaylight/pom.xml
opendaylight/commons/protocol-framework/src/main/java/org/opendaylight/protocol/framework/AbstractSessionNegotiator.java
opendaylight/config/config-manager/pom.xml
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BindingIndependentMappingServiceTracker.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ConfigManagerActivator.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTracker.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTracker.java [moved from opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ExtenderBundleTracker.java with 90% similarity]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/ModuleInfoBundleTracker.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/RuntimeGeneratedMappingServiceActivator.java [moved from opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/osgi/Activator.java with 56% similarity]
opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModule.java
opendaylight/config/netty-event-executor-config/src/main/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleFactory.java
opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/GlobalEventExecutorModuleTest.java
opendaylight/config/netty-threadgroup-config/src/main/java/org/opendaylight/controller/config/yang/netty/threadgroup/NettyThreadgroupModule.java
opendaylight/config/shutdown-impl/src/main/java/org/opendaylight/controller/config/yang/shutdown/impl/ShutdownServiceImpl.java
opendaylight/config/shutdown-impl/src/test/java/org/opendaylight/controller/config/yang/shutdown/impl/ShutdownTest.java
opendaylight/config/threadpool-config-impl/pom.xml
opendaylight/config/yang-test/src/main/yang/config-test-impl.yang
opendaylight/config/yang-test/src/main/yang/types/test-types.yang
opendaylight/config/yang-test/src/test/java/org/opendaylight/controller/config/yang/test/impl/NetconfTestImplModuleTest.java
opendaylight/configuration/api/pom.xml
opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationContainerService.java
opendaylight/configuration/implementation/pom.xml
opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationService.java
opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ContainerConfigurationService.java
opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini
opendaylight/distribution/opendaylight/src/main/resources/configuration/initial/00-netty.xml
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.xtend [deleted file]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryNotificationProvider.java
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java [new file with mode: 0644]
opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.xtend [deleted file]
opendaylight/md-sal/model/model-flow-service/src/main/yang/flow-capable-transaction.yang
opendaylight/md-sal/model/model-flow-service/src/main/yang/sal-table.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/opendaylight-flow-statistics.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/opendaylight-flow-table-statistics.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/opendaylight-group-statistics.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/opendaylight-meter-statistics.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/opendaylight-port-statistics.yang
opendaylight/md-sal/model/model-flow-statistics/src/main/yang/opendaylight-queue-statistics.yang
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/SingletonHolder.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/NotificationBrokerImpl.xtend
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.xtend
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/SimpleInput.java
opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/DataServiceTest.java
opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/RoutedServiceTest.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChange.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeEvent.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangeListener.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataChangePublisher.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataCommitHandler.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataModification.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataModificationTransactionFactory.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataProvider.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataReader.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/DataStore.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChain.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/data/TransactionChainFactory.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/MutableRoutingTable.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RoutedRegistration.java
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/routing/RoutingTable.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/RoutingUtils.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/TwoPhaseCommit.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerImpl.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareDataStoreAdapter.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/util/YangDataOperations.xtend
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.xtend
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/rest/api/RestconfService.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/MediaTypesTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestDeleteOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestGetOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestOperationUtils.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPostOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/test/RestPutOperationTest.java
opendaylight/md-sal/sal-rest-connector/src/test/java/org/opendaylight/controller/sal/restconf/impl/websockets/test/RestStream.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/ConfigPersisterNotificationHandler.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/AbstractNetconfSession.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfSessionPreferences.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/jmx/CommitJMXNotification.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/jmx/DefaultCommitOperationMXBean.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/DefaultCommitNotificationProducer.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiator.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/MessageHeaderTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/MessageParserTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfConfigPersisterITTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractChannelInitializer.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/AbstractNetconfSessionNegotiator.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/NetconfUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ChunkedFramingMechanismEncoder.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/EOMFramingMechanismEncoder.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/FramingMechanismHandlerFactory.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfChunkAggregator.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfEOMAggregator.java [moved from opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageAggregator.java with 79% similarity]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfHelloMessageToXMLEncoder.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageChunkDecoder.java [deleted file]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageToXMLEncoder.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfXMLToHelloMessageDecoder.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfXMLToMessageDecoder.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/SshHandler.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/authentication/LoginPassword.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/Invoker.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshClient.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshClientAdapter.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/client/SshSession.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/ChannelInputStream.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/ChannelOutputStream.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/ssh/virtualsocket/VirtualSocket.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfHelloMessageAdditionalHeader.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageConstants.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageHeader.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/messages/SendErrorExceptionUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/osgi/NetconfConfigUtil.java
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XMLNetconfUtil.java
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/XmlNetconfValidator.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/handler/NetconfChunkAggregatorTest.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/messages/NetconfMessageFactoryTest.java
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_identities.xml
third-party/ganymed/pom.xml

index d32be92fc8f1bf40b0c53503781953bb0dc1bf7f..328dfafe3f7a239c7e2f1846087ad8aee9a4bd10 100644 (file)
@@ -98,7 +98,7 @@
     <forwardingrulesmanager.version>0.5.1-SNAPSHOT</forwardingrulesmanager.version>
     <statisticsmanager.version>0.5.1-SNAPSHOT</statisticsmanager.version>
     <clustering.services.version>0.5.1-SNAPSHOT</clustering.services.version>
-    <configuration.version>0.4.2-SNAPSHOT</configuration.version>
+    <configuration.version>0.4.3-SNAPSHOT</configuration.version>
     <topologymanager.version>0.4.2-SNAPSHOT</topologymanager.version>
     <protocol_plugin.stub.version>0.4.2-SNAPSHOT</protocol_plugin.stub.version>
     <clustering.stub.version>0.4.2-SNAPSHOT</clustering.stub.version>
index 9f9f811e889f85c20352db331187f008b812bd85..d41e8106c5aec85166b43d72241b7fb600921801 100644 (file)
@@ -8,6 +8,8 @@
 package org.opendaylight.protocol.framework;
 
 import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelInboundHandlerAdapter;
 import io.netty.util.concurrent.Promise;
@@ -26,7 +28,7 @@ import com.google.common.base.Preconditions;
  * @param <S> Protocol session type, has to extend ProtocolSession<M>
  */
 public abstract class AbstractSessionNegotiator<M, S extends AbstractProtocolSession<?>> extends ChannelInboundHandlerAdapter implements SessionNegotiator<S> {
-    private final Logger logger = LoggerFactory.getLogger(AbstractSessionNegotiator.class);
+    private final Logger LOG = LoggerFactory.getLogger(AbstractSessionNegotiator.class);
     private final Promise<S> promise;
     protected final Channel channel;
 
@@ -39,42 +41,63 @@ public abstract class AbstractSessionNegotiator<M, S extends AbstractProtocolSes
     protected abstract void handleMessage(M msg) throws Exception;
 
     protected final void negotiationSuccessful(final S session) {
-        logger.debug("Negotiation on channel {} successful with session {}", channel, session);
+        LOG.debug("Negotiation on channel {} successful with session {}", channel, session);
         channel.pipeline().replace(this, "session", session);
         promise.setSuccess(session);
     }
 
     protected final void negotiationFailed(final Throwable cause) {
-        logger.debug("Negotiation on channel {} failed", channel, cause);
+        LOG.debug("Negotiation on channel {} failed", channel, cause);
         channel.close();
         promise.setFailure(cause);
     }
 
+    /**
+     * Send a message to peer and fail negotiation if it does not reach
+     * the peer.
+     *
+     * @param msg Message which should be sent.
+     */
+    protected final void sendMessage(final M msg) {
+        this.channel.writeAndFlush(msg).addListener(
+                new ChannelFutureListener() {
+                    @Override
+                    public void operationComplete(final ChannelFuture f) {
+                        if (!f.isSuccess()) {
+                            LOG.info("Failed to send message {}", msg, f.cause());
+                            negotiationFailed(f.cause());
+                        } else {
+                            LOG.trace("Message {} sent to socket", msg);
+                        }
+                    }
+                });
+    }
+
     @Override
     public final void channelActive(final ChannelHandlerContext ctx) {
-        logger.debug("Starting session negotiation on channel {}", channel);
+        LOG.debug("Starting session negotiation on channel {}", channel);
         try {
             startNegotiation();
         } catch (Exception e) {
-            logger.warn("Unexpected negotiation failure", e);
+            LOG.warn("Unexpected negotiation failure", e);
             negotiationFailed(e);
         }
     }
 
     @Override
     public final void channelRead(final ChannelHandlerContext ctx, final Object msg) {
-        logger.debug("Negotiation read invoked on channel {}", channel);
+        LOG.debug("Negotiation read invoked on channel {}", channel);
         try {
             handleMessage((M)msg);
         } catch (Exception e) {
-            logger.debug("Unexpected error while handling negotiation message {}", msg, e);
+            LOG.debug("Unexpected error while handling negotiation message {}", msg, e);
             negotiationFailed(e);
         }
     }
 
     @Override
     public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) {
-        logger.info("Unexpected error during negotiation", cause);
+        LOG.info("Unexpected error during negotiation", cause);
         negotiationFailed(cause);
     }
 }
index 52377ae0255e2466865419f15aa640cbd7dc4f70..524cd1ff9ec12e8d051055df2e9b7cb3dc620426 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>mockito-configuration</artifactId>
         </dependency>
+
+        <!--Dependencies regardign RuntimeGeneratedMappingService-->
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-impl</artifactId>
+        </dependency>
+        <!--End-->
+
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>config-util</artifactId>
index 16a0605cd4c39bc020a80a4da1f3870eb17109df..dbc862a53d1f1f4f7531aa0e53fd349db7663fe2 100644 (file)
@@ -44,7 +44,7 @@ public class BindingIndependentMappingServiceTracker implements ServiceTrackerCu
         this.service = service;
         CodecRegistry codecRegistry = service.getCodecRegistry();
         logger.debug("Codec registry acquired {}", codecRegistry);
-        activator.initConfigManager(ctx, codecRegistry);
+//        activator.initConfigManager(ctx, codecRegistry);
         return service;
     }
 
index e4e070885c44559336103542a6af269239313d60..d464cb9006af15b24de4e1e517f57883a893fd47 100644 (file)
@@ -8,14 +8,18 @@
 package org.opendaylight.controller.config.manager.impl.osgi;
 
 import java.lang.management.ManagementFactory;
+import java.util.Collection;
 
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.MBeanServer;
 
 import org.opendaylight.controller.config.manager.impl.ConfigRegistryImpl;
 import org.opendaylight.controller.config.manager.impl.jmx.ConfigRegistryJMXRegistrator;
+import org.opendaylight.controller.config.manager.impl.osgi.mapping.ModuleInfoBundleTracker;
+import org.opendaylight.controller.config.manager.impl.osgi.mapping.RuntimeGeneratedMappingServiceActivator;
 import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
 import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
@@ -25,38 +29,40 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class ConfigManagerActivator implements BundleActivator {
-    private static final Logger logger = LoggerFactory
-            .getLogger(ConfigManagerActivator.class);
+    private static final Logger logger = LoggerFactory.getLogger(ConfigManagerActivator.class);
 
-    private ExtenderBundleTracker extenderBundleTracker;
+    private ExtensibleBundleTracker<Collection<Registration<YangModuleInfo>>> bundleTracker;
     private ConfigRegistryImpl configRegistry;
     private ConfigRegistryJMXRegistrator configRegistryJMXRegistrator;
     private ServiceRegistration configRegistryServiceRegistration;
 
-    private ServiceTracker<BindingIndependentMappingService, BindingIndependentMappingService> tracker;
+    private final MBeanServer configMBeanServer = ManagementFactory.getPlatformMBeanServer();
+
+    private RuntimeGeneratedMappingServiceActivator mappingServiceActivator;
 
     @Override
     public void start(BundleContext context) throws Exception {
-        BindingIndependentMappingServiceTracker mappingServiceTracker = new BindingIndependentMappingServiceTracker(
-                context, this);
-        tracker = new ServiceTracker<BindingIndependentMappingService, BindingIndependentMappingService>(
-                context, BindingIndependentMappingService.class, mappingServiceTracker);
-
-        logger.debug("Waiting for codec registry");
-
-        tracker.open();
-    }
 
-    void initConfigManager(BundleContext context, CodecRegistry codecRegistry) {
-        BundleContextBackedModuleFactoriesResolver bundleContextBackedModuleFactoriesResolver =
-                new BundleContextBackedModuleFactoriesResolver(context);
-        MBeanServer configMBeanServer = ManagementFactory.getPlatformMBeanServer();
+        // track bundles containing YangModuleInfo
+        ModuleInfoBundleTracker moduleInfoBundleTracker = new ModuleInfoBundleTracker();
+        mappingServiceActivator = new RuntimeGeneratedMappingServiceActivator(moduleInfoBundleTracker);
+        CodecRegistry codecRegistry = mappingServiceActivator.startRuntimeMappingService(context).getCodecRegistry();
 
+        // start config registry
+        BundleContextBackedModuleFactoriesResolver bundleContextBackedModuleFactoriesResolver = new BundleContextBackedModuleFactoriesResolver(
+                context);
+        configRegistry = new ConfigRegistryImpl(bundleContextBackedModuleFactoriesResolver, configMBeanServer,
+                codecRegistry);
 
-        // TODO push codecRegistry/IdentityCodec to dependencyResolver
+        // track bundles containing factories
+        BlankTransactionServiceTracker blankTransactionServiceTracker = new BlankTransactionServiceTracker(
+                configRegistry);
+        ModuleFactoryBundleTracker moduleFactoryBundleTracker = new ModuleFactoryBundleTracker(
+                blankTransactionServiceTracker);
 
-        configRegistry = new ConfigRegistryImpl(
-                bundleContextBackedModuleFactoriesResolver, configMBeanServer, codecRegistry);
+        // start extensible tracker
+        bundleTracker = new ExtensibleBundleTracker<>(context, moduleInfoBundleTracker, moduleFactoryBundleTracker);
+        bundleTracker.open();
 
         // register config registry to OSGi
         configRegistryServiceRegistration = context.registerService(ConfigRegistryImpl.class, configRegistry, null);
@@ -69,29 +75,20 @@ public class ConfigManagerActivator implements BundleActivator {
             throw new RuntimeException("Config Registry was already registered to JMX", e);
         }
 
-        // track bundles containing factories
-        BlankTransactionServiceTracker blankTransactionServiceTracker = new BlankTransactionServiceTracker(configRegistry);
-        extenderBundleTracker = new ExtenderBundleTracker(context, blankTransactionServiceTracker);
-        extenderBundleTracker.open();
-
-        ServiceTracker<?, ?> serviceTracker = new ServiceTracker(context, ModuleFactory.class, blankTransactionServiceTracker);
+        ServiceTracker<ModuleFactory, Object> serviceTracker = new ServiceTracker<>(context, ModuleFactory.class,
+                blankTransactionServiceTracker);
         serviceTracker.open();
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        try {
-            tracker.close();
-        } catch (Exception e) {
-            logger.warn("Exception while closing tracker", e);
-        }
         try {
             configRegistry.close();
         } catch (Exception e) {
             logger.warn("Exception while closing config registry", e);
         }
         try {
-            extenderBundleTracker.close();
+            bundleTracker.close();
         } catch (Exception e) {
             logger.warn("Exception while closing extender", e);
         }
@@ -107,5 +104,10 @@ public class ConfigManagerActivator implements BundleActivator {
         } catch (Exception e) {
             logger.warn("Exception while unregistering config registry", e);
         }
+        try {
+            mappingServiceActivator.close();
+        } catch (Exception e) {
+            logger.warn("Exception while closing mapping service", e);
+        }
     }
 }
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTracker.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTracker.java
new file mode 100644 (file)
index 0000000..c1ebba7
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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.config.manager.impl.osgi;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * Extensible bundle tracker. Takes several BundleTrackerCustomizers and propagates bundle events to all of them.
+ * Primary customizer
+ *
+ * @param <T>
+ */
+public final class ExtensibleBundleTracker<T> extends BundleTracker<T> {
+
+    private final BundleTrackerCustomizer<T> primaryTracker;
+    private final BundleTrackerCustomizer<?>[] additionalTrackers;
+
+    private static final Logger logger = LoggerFactory.getLogger(ExtensibleBundleTracker.class);
+
+    public ExtensibleBundleTracker(BundleContext context, BundleTrackerCustomizer<T> primaryBundleTrackerCustomizer,
+                                   BundleTrackerCustomizer<?>... additionalBundleTrackerCustomizers) {
+        this(context, Bundle.ACTIVE, primaryBundleTrackerCustomizer, additionalBundleTrackerCustomizers);
+    }
+
+    public ExtensibleBundleTracker(BundleContext context, int bundleState,
+                                   BundleTrackerCustomizer<T> primaryBundleTrackerCustomizer,
+                                   BundleTrackerCustomizer<?>... additionalBundleTrackerCustomizers) {
+        super(context, bundleState, null);
+        this.primaryTracker = primaryBundleTrackerCustomizer;
+        this.additionalTrackers = additionalBundleTrackerCustomizers;
+        logger.trace("Registered as extender with context {} and bundle state {}", context, bundleState);
+    }
+
+    @Override
+    public T addingBundle(final Bundle bundle, final BundleEvent event) {
+        T primaryTrackerRetVal = primaryTracker.addingBundle(bundle, event);
+
+        forEachAdditionalBundle(new BundleStrategy() {
+            @Override
+            public void execute(BundleTrackerCustomizer<?> tracker) {
+                tracker.addingBundle(bundle, event);
+            }
+        });
+
+        return primaryTrackerRetVal;
+    }
+
+    @Override
+    public void modifiedBundle(final Bundle bundle, final BundleEvent event, final T object) {
+        primaryTracker.modifiedBundle(bundle, event, object);
+
+        forEachAdditionalBundle(new BundleStrategy() {
+            @Override
+            public void execute(BundleTrackerCustomizer<?> tracker) {
+                tracker.modifiedBundle(bundle, event, null);
+            }
+        });
+
+    }
+
+    @Override
+    public void removedBundle(final Bundle bundle, final BundleEvent event, final T object) {
+        primaryTracker.removedBundle(bundle, event, object);
+
+        forEachAdditionalBundle(new BundleStrategy() {
+            @Override
+            public void execute(BundleTrackerCustomizer<?> tracker) {
+                tracker.removedBundle(bundle, event, null);
+            }
+        });
+    }
+
+    private void forEachAdditionalBundle(BundleStrategy lambda) {
+        for (BundleTrackerCustomizer<?> trac : additionalTrackers) {
+            lambda.execute(trac);
+        }
+    }
+
+    private static interface BundleStrategy {
+        void execute(BundleTrackerCustomizer<?> tracker);
+    }
+
+}
@@ -16,10 +16,9 @@ import java.util.List;
 import org.apache.commons.io.IOUtils;
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
 import org.osgi.framework.ServiceRegistration;
-import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -33,14 +32,12 @@ import org.slf4j.LoggerFactory;
  * the services are unregistered automatically.
  * Code based on http://www.toedter.com/blog/?p=236
  */
-public class ExtenderBundleTracker extends BundleTracker<Object> {
+public class ModuleFactoryBundleTracker implements BundleTrackerCustomizer<Object> {
     private final BlankTransactionServiceTracker blankTransactionServiceTracker;
-    private static final Logger logger = LoggerFactory.getLogger(ExtenderBundleTracker.class);
+    private static final Logger logger = LoggerFactory.getLogger(ModuleFactoryBundleTracker.class);
 
-    public ExtenderBundleTracker(BundleContext context, BlankTransactionServiceTracker blankTransactionServiceTracker) {
-        super(context, Bundle.ACTIVE, null);
+    public ModuleFactoryBundleTracker(BlankTransactionServiceTracker blankTransactionServiceTracker) {
         this.blankTransactionServiceTracker = blankTransactionServiceTracker;
-        logger.trace("Registered as extender with context {}", context);
     }
 
     @Override
@@ -62,9 +59,13 @@ public class ExtenderBundleTracker extends BundleTracker<Object> {
         return bundle;
     }
 
+    @Override
+    public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+        // NOOP
+    }
+
     @Override
     public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
-        super.removedBundle(bundle,event,object);
         // workaround for service tracker not getting removed service event
         blankTransactionServiceTracker.blankTransaction();
     }
diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/ModuleInfoBundleTracker.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/ModuleInfoBundleTracker.java
new file mode 100644 (file)
index 0000000..8ba290f
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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.config.manager.impl.osgi.mapping;
+
+import org.apache.commons.io.IOUtils;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import static java.lang.String.format;
+
+/**
+ * Tracks bundles and attempts to retrieve YangModuleInfo.
+ */
+public final class ModuleInfoBundleTracker implements BundleTrackerCustomizer<Collection<Registration<YangModuleInfo>>> {
+
+    private static final Logger logger = LoggerFactory.getLogger(ModuleInfoBundleTracker.class);
+    public static final String GET_MODULE_INFO_METHOD = "getModuleInfo";
+
+    public static final String MODULE_INFO_PROVIDER_PATH_PREFIX = "META-INF/services/";
+
+    private ModuleInfoBackedContext moduleInfoLoadingStrategy = ModuleInfoBackedContext.create();
+
+    public GeneratedClassLoadingStrategy getModuleInfoLoadingStrategy() {
+        return moduleInfoLoadingStrategy;
+    }
+
+    @Override
+    public Collection<Registration<YangModuleInfo>> addingBundle(Bundle bundle, BundleEvent event) {
+        URL resource = bundle.getEntry(MODULE_INFO_PROVIDER_PATH_PREFIX + YangModelBindingProvider.class.getName());
+
+        if(resource==null) {
+            return null;
+        }
+
+        List<Registration<YangModuleInfo>> registrations = new LinkedList<>();
+
+        try (InputStream inputStream = resource.openStream()) {
+            List<String> lines = IOUtils.readLines(inputStream);
+            for (String moduleInfoName : lines) {
+                YangModuleInfo moduleInfo = retrieveModuleInfo(moduleInfoName, bundle);
+                registrations.add(moduleInfoLoadingStrategy.registerModuleInfo(moduleInfo));
+            }
+
+
+        } catch (Exception e) {
+            logger.error("Error while reading {}", resource, e);
+            throw new RuntimeException(e);
+        }
+
+        return registrations;
+    }
+
+    @Override
+    public void modifiedBundle(Bundle bundle, BundleEvent event, Collection<Registration<YangModuleInfo>> object) {
+        // NOOP
+    }
+
+    @Override
+    public void removedBundle(Bundle bundle, BundleEvent event, Collection<Registration<YangModuleInfo>> regs) {
+        if(regs == null) {
+            return;
+        }
+
+        for (Registration<YangModuleInfo> reg : regs) {
+            try {
+                reg.close();
+            } catch (Exception e) {
+                throw new RuntimeException("Unable to unregister YangModuleInfo " + reg.getInstance(), e);
+            }
+        }
+    }
+
+    private static YangModuleInfo retrieveModuleInfo(String moduleInfoClass, Bundle bundle) {
+        String errorMessage;
+        Class<?> clazz = loadClass(moduleInfoClass, bundle);
+
+        if (YangModelBindingProvider.class.isAssignableFrom(clazz) == false) {
+            errorMessage = logMessage("Class {} does not implement {} in bundle {}", clazz, YangModelBindingProvider.class, bundle);
+            throw new IllegalStateException(errorMessage);
+        }
+
+        try {
+            Object instance = clazz.newInstance();
+            Object result = clazz.getMethod(GET_MODULE_INFO_METHOD).invoke(instance);
+
+            if (YangModuleInfo.class.isAssignableFrom(result.getClass()) == false) {
+                errorMessage = logMessage("Error invoking method not found {} in bundle {}, reason {}",
+                        GET_MODULE_INFO_METHOD, bundle, "Not assignable from " + YangModuleInfo.class);
+            } else {
+                return (YangModuleInfo) result;
+            }
+
+        } catch (InstantiationException e) {
+            errorMessage = logMessage("Could not instantiate {} in bundle {}, reason {}", moduleInfoClass, bundle, e);
+        } catch (IllegalAccessException e) {
+            errorMessage = logMessage("Illegal access during instatiation of class {} in bundle {}, reason {}",
+                    moduleInfoClass, bundle, e);
+        } catch (NoSuchMethodException e) {
+            errorMessage = logMessage("Method not found {} in bundle {}, reason {}", GET_MODULE_INFO_METHOD, bundle, e);
+        } catch (InvocationTargetException e) {
+            errorMessage = logMessage("Error invoking method {} in bundle {}, reason {}", GET_MODULE_INFO_METHOD,
+                    bundle, e);
+        }
+
+        throw new IllegalStateException(errorMessage);
+    }
+
+    private static Class<?> loadClass(String moduleInfoClass, Bundle bundle) {
+        try {
+            return bundle.loadClass(moduleInfoClass);
+        } catch (ClassNotFoundException e) {
+            String errorMessage = logMessage("Could not find class {} in bunde {}, reason {}", moduleInfoClass, bundle, e);
+            throw new IllegalStateException(errorMessage);
+        }
+    }
+
+    public static String logMessage(String slfMessage, Object... params) {
+        logger.info(slfMessage, params);
+        String formatMessage = slfMessage.replaceAll("\\{\\}", "%s");
+        return format(formatMessage, params);
+    }
+}
@@ -1,50 +1,51 @@
 /*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ * 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.sal.binding.osgi;
+package org.opendaylight.controller.config.manager.impl.osgi.mapping;
 
-import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
+import javassist.ClassPool;
 import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
 import org.opendaylight.yangtools.yang.data.impl.codec.BindingIndependentMappingService;
 import org.opendaylight.yangtools.yang.model.api.SchemaServiceListener;
-import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
 import java.util.Hashtable;
 
-public class Activator implements BundleActivator {
+public class RuntimeGeneratedMappingServiceActivator implements AutoCloseable {
+
+    private static final ClassPool CLASS_POOL = ClassPool.getDefault();
 
-    private ServiceRegistration<?> reg;
     private ServiceRegistration<SchemaServiceListener> listenerReg;
     private ServiceRegistration<BindingIndependentMappingService> mappingReg;
+    private ModuleInfoBundleTracker moduleInfoBundleTracker;
 
-    @Override
-    public void start(BundleContext context) throws Exception {
-                RuntimeGeneratedMappingServiceImpl service = new RuntimeGeneratedMappingServiceImpl();
-        service.setPool(SingletonHolder.CLASS_POOL);
+    public RuntimeGeneratedMappingServiceActivator(ModuleInfoBundleTracker moduleInfoBundleTracker) {
+        this.moduleInfoBundleTracker = moduleInfoBundleTracker;
+    }
+
+    public RuntimeGeneratedMappingServiceImpl startRuntimeMappingService(BundleContext context) {
+        RuntimeGeneratedMappingServiceImpl service = new RuntimeGeneratedMappingServiceImpl(moduleInfoBundleTracker.getModuleInfoLoadingStrategy());
+        service.setPool(CLASS_POOL);
         service.init();
         startRuntimeMappingService(service, context);
+        return service;
     }
 
     private void startRuntimeMappingService(RuntimeGeneratedMappingServiceImpl service, BundleContext context) {
         Hashtable<String, String> properties = new Hashtable<String, String>();
         listenerReg = context.registerService(SchemaServiceListener.class, service, properties);
         mappingReg = context.registerService(BindingIndependentMappingService.class, service, properties);
-        
+
     }
 
     @Override
-    public void stop(BundleContext context) throws Exception {
-        if(listenerReg != null) {
-            listenerReg.unregister();
-        }
-        if(mappingReg != null) {
-            mappingReg.unregister();
-        }
+    public void close() throws Exception {
+        mappingReg.unregister();
+        listenerReg.unregister();
     }
 }
index 3c52d8c17af7bfadba1d49e42a4d72b0b11459be..2c4c2117840e89f74e98f1e2ef94e27a56f72424 100644 (file)
  */
 package org.opendaylight.controller.config.yang.netty.eventexecutor;
 
-import io.netty.util.concurrent.AbstractEventExecutor;
+import com.google.common.reflect.AbstractInvocationHandler;
+import com.google.common.reflect.Reflection;
 import io.netty.util.concurrent.EventExecutor;
-import io.netty.util.concurrent.EventExecutorGroup;
-import io.netty.util.concurrent.Future;
 import io.netty.util.concurrent.GlobalEventExecutor;
-import io.netty.util.concurrent.ScheduledFuture;
 
-import java.util.concurrent.Callable;
+import java.lang.reflect.Method;
 import java.util.concurrent.TimeUnit;
 
-/**
-*
-*/
 public final class GlobalEventExecutorModule extends
         org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModule {
 
@@ -51,91 +46,35 @@ public final class GlobalEventExecutorModule extends
 
     @Override
     public java.lang.AutoCloseable createInstance() {
-        return new GlobalEventExecutorCloseable(GlobalEventExecutor.INSTANCE);
+        final CloseableGlobalEventExecutorMixin closeableGlobalEventExecutorMixin =
+                new CloseableGlobalEventExecutorMixin(GlobalEventExecutor.INSTANCE);
+        return Reflection.newProxy(AutoCloseableEventExecutor.class, new AbstractInvocationHandler() {
+            @Override
+            protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable {
+                if (method.getName().equals("close")) {
+                    closeableGlobalEventExecutorMixin.close();
+                    return null;
+                } else {
+                    return method.invoke(GlobalEventExecutor.INSTANCE, args);
+                }
+            }
+        });
     }
 
-    static final private class GlobalEventExecutorCloseable extends AbstractEventExecutor implements AutoCloseable {
-
-        private EventExecutor executor;
-
-        public GlobalEventExecutorCloseable(EventExecutor executor) {
-            this.executor = executor;
-        }
-
-        @Override
-        public EventExecutorGroup parent() {
-            return this.executor.parent();
-        }
-
-        @Override
-        public boolean inEventLoop(Thread thread) {
-            return this.executor.inEventLoop(thread);
-        }
-
-        @Override
-        public boolean isShuttingDown() {
-            return this.executor.isShuttingDown();
-        }
-
-        @Override
-        public Future<?> shutdownGracefully(long quietPeriod, long timeout, TimeUnit unit) {
-            return this.executor.shutdownGracefully(quietPeriod, timeout, unit);
-        }
-
-        @Override
-        public Future<?> terminationFuture() {
-            return this.executor.terminationFuture();
-        }
-
-        @Override
-        public boolean isShutdown() {
-            return this.executor.isShutdown();
-        }
+    public static interface AutoCloseableEventExecutor extends EventExecutor, AutoCloseable {
 
-        @Override
-        public boolean isTerminated() {
-            return this.executor.isTerminated();
-        }
-
-        @Override
-        public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
-            return this.executor.awaitTermination(timeout, unit);
-        }
-
-        @Override
-        public void execute(Runnable command) {
-            this.executor.execute(command);
-        }
-
-        @Override
-        public void close() throws Exception {
-            shutdownGracefully();
-        }
-
-        @SuppressWarnings("deprecation")
-        @Override
-        public void shutdown() {
-            this.executor.shutdown();
-        }
-
-        @Override
-        public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
-            return this.executor.scheduleWithFixedDelay(command, initialDelay, delay, unit);
-        }
+    }
 
-        @Override
-        public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
-            return this.executor.schedule(command, delay, unit);
-        }
+    public static class CloseableGlobalEventExecutorMixin implements AutoCloseable {
+        private final GlobalEventExecutor eventExecutor;
 
-        @Override
-        public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
-            return this.executor.schedule(callable, delay, unit);
+        public CloseableGlobalEventExecutorMixin(GlobalEventExecutor eventExecutor) {
+            this.eventExecutor = eventExecutor;
         }
 
         @Override
-        public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
-            return this.executor.scheduleAtFixedRate(command, initialDelay, period, unit);
+        public void close() {
+            eventExecutor.shutdownGracefully(0, 1, TimeUnit.SECONDS);
         }
     }
 }
index c03ade8b5fc63aded18e2540360723c639f82d11..1585bbf6de3752c77599a058bdd2b098303e8962 100644 (file)
@@ -7,21 +7,34 @@
  */
 
 /**
-* Generated file
-
-* Generated from: yang module name: netty-event-executor  yang module local name: netty-global-event-executor
-* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
-* Generated at: Tue Nov 12 10:44:21 CET 2013
-*
-* Do not modify this file unless it is present under src/main directory
-*/
+ * Generated file
+
+ * Generated from: yang module name: netty-event-executor  yang module local name: netty-global-event-executor
+ * Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+ * Generated at: Tue Nov 12 10:44:21 CET 2013
+ *
+ * Do not modify this file unless it is present under src/main directory
+ */
 package org.opendaylight.controller.config.yang.netty.eventexecutor;
 
-/**
-*
-*/
-public class GlobalEventExecutorModuleFactory extends org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModuleFactory
-{
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.osgi.framework.BundleContext;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+public class GlobalEventExecutorModuleFactory extends org.opendaylight.controller.config.yang.netty.eventexecutor.AbstractGlobalEventExecutorModuleFactory {
+    public static final String SINGLETON_NAME = "singleton";
+
 
+    @Override
+    public GlobalEventExecutorModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, GlobalEventExecutorModule oldModule, AutoCloseable oldInstance, BundleContext bundleContext) {
+        checkArgument(SINGLETON_NAME.equals(instanceName),"Illegal instance name '" + instanceName + "', only allowed name is " + SINGLETON_NAME);
+        return super.instantiateModule(instanceName, dependencyResolver, oldModule, oldInstance, bundleContext);
+    }
 
+    @Override
+    public GlobalEventExecutorModule instantiateModule(String instanceName, DependencyResolver dependencyResolver, BundleContext bundleContext) {
+        checkArgument(SINGLETON_NAME.equals(instanceName),"Illegal instance name '" + instanceName + "', only allowed name is " + SINGLETON_NAME);
+        return super.instantiateModule(instanceName, dependencyResolver, bundleContext);
+    }
 }
index 71c4b192e5ae3c0c64dcb0d1f43770ddf8fb9d89..f29895c6d00c3428c0329b5aae5be1d494b2530f 100644 (file)
@@ -8,9 +8,6 @@
 
 package org.opendaylight.controller.config.yang.netty.eventexecutor;
 
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.ObjectName;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.config.api.ConflictingVersionException;
@@ -20,10 +17,16 @@ import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
 public class GlobalEventExecutorModuleTest extends AbstractConfigTest {
 
     private GlobalEventExecutorModuleFactory factory;
-    private final String instanceName = "netty1";
+    private final String instanceName = GlobalEventExecutorModuleFactory.SINGLETON_NAME;
 
     @Before
     public void setUp() {
@@ -37,12 +40,23 @@ public class GlobalEventExecutorModuleTest extends AbstractConfigTest {
         ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
 
         createInstance(transaction, instanceName);
-        createInstance(transaction, instanceName + 2);
+
         transaction.validateConfig();
         CommitStatus status = transaction.commit();
 
-        assertBeanCount(2, factory.getImplementationName());
-        assertStatus(status, 2, 0, 0);
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 1, 0, 0);
+    }
+
+    @Test
+    public void testConflictingName() throws Exception {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        try {
+            createInstance(transaction, instanceName + "x");
+            fail();
+        }catch(IllegalArgumentException e){
+            assertTrue(e.getMessage() + " failure", e.getMessage().contains("only allowed name is singleton"));
+        }
     }
 
     @Test
index 3d5a3bf4adf00e78ce5537a884eeb3ad9142d42c..06c9ae885d15e13625c42746f13940a944b83271 100644 (file)
@@ -21,6 +21,8 @@ import io.netty.channel.nio.NioEventLoopGroup;
 
 import org.opendaylight.controller.config.api.JmxAttributeValidationException;
 
+import java.util.concurrent.TimeUnit;
+
 /**
 *
 */
@@ -61,7 +63,7 @@ public final class NettyThreadgroupModule extends org.opendaylight.controller.co
 
         @Override
         public void close() throws Exception {
-            shutdownGracefully();
+            shutdownGracefully(0, 1, TimeUnit.SECONDS);
         }
     }
 }
index 584ea1766e2cd7ebaba141f7f02449473bec88b1..f9622192fec873f3fc01c1396aa4c06ccb8f1624 100644 (file)
@@ -82,6 +82,7 @@ class Impl implements ShutdownService {
 
 class StopSystemBundleThread extends Thread {
     private static final Logger logger = LoggerFactory.getLogger(StopSystemBundleThread.class);
+    public static final String CONFIG_MANAGER_SYMBOLIC_NAME = "org.opendaylight.controller.config-manager";
     private final Bundle systemBundle;
 
     StopSystemBundleThread(Bundle systemBundle) {
@@ -94,6 +95,14 @@ class StopSystemBundleThread extends Thread {
         try {
             // wait so that JMX response is received
             Thread.sleep(1000);
+            // first try to stop config-manager
+            Bundle configManager = findConfigManager();
+            if (configManager != null){
+                logger.debug("Stopping config-manager");
+                configManager.stop();
+                Thread.sleep(1000);
+            }
+            logger.debug("Stopping system bundle");
             systemBundle.stop();
         } catch (BundleException e) {
             logger.warn("Can not stop OSGi server", e);
@@ -101,6 +110,16 @@ class StopSystemBundleThread extends Thread {
             logger.warn("Shutdown process interrupted", e);
         }
     }
+
+    private Bundle findConfigManager() {
+        for(Bundle bundle: systemBundle.getBundleContext().getBundles()){
+            if (CONFIG_MANAGER_SYMBOLIC_NAME.equals(bundle.getSymbolicName())) {
+                return bundle;
+            }
+        }
+        return null;
+    }
+
 }
 
 class CallSystemExitThread extends Thread {
index 5887e98f30daa4816da2bfb1e1215a6385ebc783..d1abe08d52b64453ee038a8a8b053e80ae08c586 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleF
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
 import org.osgi.framework.Bundle;
 
+import javax.management.InstanceNotFoundException;
 import javax.management.JMX;
 import javax.management.ObjectName;
 import java.util.Collections;
@@ -26,15 +27,14 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.opendaylight.controller.config.yang.shutdown.impl.ShutdownModuleFactory.NAME;
 
 public class ShutdownTest extends AbstractConfigTest {
     private final ShutdownModuleFactory factory = new ShutdownModuleFactory();
     @Mock
-    private Bundle mockedSysBundle;
+    private Bundle mockedSysBundle, mockedConfigManager;
+
 
     @Before
     public void setUp() throws Exception {
@@ -44,6 +44,13 @@ public class ShutdownTest extends AbstractConfigTest {
         doReturn(mockedSysBundle).when(mockedContext).getBundle(0);
         mockedContext.getBundle(0);
         doNothing().when(mockedSysBundle).stop();
+        doNothing().when(mockedConfigManager).stop();
+        doReturn(mockedContext).when(mockedSysBundle).getBundleContext();
+        doReturn(new Bundle[]{mockedSysBundle, mockedConfigManager}).when(mockedContext).getBundles();
+        doReturn("system bundle").when(mockedSysBundle).getSymbolicName();
+        doReturn(StopSystemBundleThread.CONFIG_MANAGER_SYMBOLIC_NAME).when(mockedConfigManager).getSymbolicName();
+
+
         ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
         // initialize default instance
         transaction.commit();
@@ -80,13 +87,22 @@ public class ShutdownTest extends AbstractConfigTest {
 
     @Test
     public void testWithSecret() throws Exception {
+        String secret = "secret";
+        setSecret(secret);
+        shutdownViaRuntimeJMX(secret);
+    }
+
+    private void setSecret(String secret) throws InstanceNotFoundException {
         ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
         ObjectName on = transaction.lookupConfigBean(NAME, NAME);
         ShutdownModuleMXBean proxy = transaction.newMXBeanProxy(on, ShutdownModuleMXBean.class);
-        String secret = "secret";
         proxy.setSecret(secret);
         transaction.commit();
-        shutdownViaRuntimeJMX(secret);
+    }
+
+    @Test
+    public void testWrongSecret() throws Exception {
+        setSecret("secret");
         try {
             ShutdownRuntimeMXBean runtime = JMX.newMXBeanProxy(platformMBeanServer, runtimeON, ShutdownRuntimeMXBean.class);
             runtime.shutdown("foo", 60000L, null);
@@ -109,12 +125,9 @@ public class ShutdownTest extends AbstractConfigTest {
         assertStopped();
     }
 
-
     private void assertStopped() throws Exception {
-        Thread.sleep(2000); // happens on another thread
+        Thread.sleep(3000); // happens on another thread
+        verify(mockedConfigManager).stop();
         verify(mockedSysBundle).stop();
-        verifyNoMoreInteractions(mockedSysBundle);
-        reset(mockedSysBundle);
-        doNothing().when(mockedSysBundle).stop();
     }
 }
index 49a01819d805071805ae44b05997edf008fdd726..08f1d554f6c4e515356163a5a99f2ea9efc35713 100644 (file)
@@ -71,7 +71,7 @@
                   </Private-Package>
                   <Export-Package>
                       org.opendaylight.controller.config.threadpool.util,
-                      org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.threadpool.impl.rev130405.*,
+                      org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.threadpool.impl.*,
                   </Export-Package>
                </instructions>
             </configuration>
index 6ee379623bf128216a8328e5533918b9d543fb27..c82da58c150ff8067c0d9933b50250228eec0431 100644 (file)
@@ -41,28 +41,20 @@ module config-test-impl {
         config:java-name-prefix IdentityTest;
     }
 
-    identity test-identity1 {
-
-    }
-
-    identity test-identity2 {
-        base test-identity1;
-    }
-
     augment "/config:modules/config:module/config:configuration" {
             case impl-identity-test {
                 when "/config:modules/config:module/config:type = 'impl-identity-test'";
 
                 leaf afi {
                     type identityref {
-                        base test-identity1;
+                        base tt:test-identity1;
                     }
                 }
 
                 container identities-container {
                     leaf afi {
                         type identityref {
-                            base test-identity1;
+                            base tt:test-identity1;
                         }
                     }
                 }
@@ -70,19 +62,19 @@ module config-test-impl {
                 list identities {
                     leaf afi {
                         type identityref {
-                            base test-identity1;
+                            base tt:test-identity1;
                         }
                     }
                     leaf safi {
                         type identityref {
-                            base test-identity1;
+                            base tt:test-identity1;
                         }
                     }
 
                     container identities-inner {
                         leaf afi {
                             type identityref {
-                                base test-identity1;
+                                base tt:test-identity1;
                             }
                         }
                     }
index 8c086d8aceb1d5ec21c06f398e57fcd46d8bda62..df5387be2c1f2581e2a44872ef596e62ec76d628 100644 (file)
@@ -31,4 +31,13 @@ module test-types {
         }
       }
 
+
+
+    identity test-identity1 {
+
+    }
+
+    identity test-identity2 {
+        base test-identity1;
+    }
 }
index 31b4c78fe3013d78b1dc09504e6f9c1c5d4918e2..281c1aade55db8972553f578595d89e3128d5d46 100644 (file)
@@ -19,8 +19,8 @@ import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.test.impl.rev130403.TestIdentity1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.test.impl.rev130403.TestIdentity2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity2;
 import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
 import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
 
index 97b2d25fc1b62399fc0c7fe3f60d6d701695c03d..8a5cd99a10c7e6894457d40e45973cbf746bea2a 100644 (file)
@@ -15,7 +15,7 @@
   </scm>
 
   <artifactId>configuration</artifactId>
-  <version>0.4.2-SNAPSHOT</version>
+  <version>0.4.3-SNAPSHOT</version>
   <packaging>bundle</packaging>
 
   <build>
index ee571b83e1c9c4e919eb688f0f965ab633219b21..b8461ce3b340beca89a4be52e2f29cc4b7c58d17 100644 (file)
@@ -15,10 +15,20 @@ package org.opendaylight.controller.configuration;
 public interface IConfigurationContainerService extends IConfigurationServiceCommon {
 
     /**
-     * Bundle will call this function to ask ContainerConfigurationService to provide the
-     * directory location of container
+     * This function returns the path to the configuration directory of the
+     * current container.
      *
-     * @return The path to active container directory
+     * @return The path to active container's configuration directory
      */
-    String getConfigurationRoot();
+    public String getConfigurationRoot();
+
+    /**
+     * Function checks whether there exists a saved configuration for this
+     * container (This is essentially checking whether the container's root
+     * configuration directory exists)
+     *
+     * @return True iff container config has been saved at least once
+     */
+    public boolean hasBeenSaved();
+
 }
index 8259243fdc8d2710a12681de962a0fb7c09a3323..0846dc58a3873adf414b64e34f99fbda3477aba4 100644 (file)
@@ -15,7 +15,7 @@
   </scm>
 
   <artifactId>configuration.implementation</artifactId>
-  <version>0.4.2-SNAPSHOT</version>
+  <version>0.4.3-SNAPSHOT</version>
   <packaging>bundle</packaging>
 
   <build>
index 4c0f3a2da5f08b409e6c751e9e8828359ce7e850..dd73675070c95ce2bf3365bf8589843322ddf53d 100644 (file)
@@ -85,6 +85,9 @@ public class ConfigurationService implements IConfigurationService, ICacheUpdate
 
     public void init() {
         logger.info("ConfigurationService Manager init");
+
+        // Create the default startup directory, so that container unaware apps can initiate save
+        createContainerDirectory(ROOT + GlobalConstants.DEFAULT.toString());
     }
 
     public void start() {
@@ -112,7 +115,7 @@ public class ConfigurationService implements IConfigurationService, ICacheUpdate
         List<String> containerList = new ArrayList<String>();
         for (IConfigurationAware configurationAware : this.configurationAwareList) {
             if (configurationAware instanceof IConfigurationContainerService) {
-                String containerFilePath = ((ContainerConfigurationService)configurationAware).getConfigurationRoot();
+                String containerFilePath = ((IConfigurationContainerService)configurationAware).getConfigurationRoot();
                 containerList.add(containerFilePath);
             }
         }
@@ -120,12 +123,21 @@ public class ConfigurationService implements IConfigurationService, ICacheUpdate
     }
 
     private void createContainerDirectory(IConfigurationAware configurationAware) {
-        String containerFilePath = ((ContainerConfigurationService) configurationAware).getConfigurationRoot();
-        if (!new File(containerFilePath).exists()) {
-            boolean created = new File(containerFilePath).mkdir();
-            if (!created) {
-               logger.error("Failed to create startup config directory: {}", containerFilePath);
+        String containerFilePath = ((IConfigurationContainerService) configurationAware).getConfigurationRoot();
+        createContainerDirectory(containerFilePath);
+    }
+
+    private void createContainerDirectory(String containerFilePath) {
+
+        try {
+            if (!new File(containerFilePath).exists()) {
+                boolean created = new File(containerFilePath).mkdir();
+                if (!created) {
+                    logger.error("Failed to create config directory: {}", containerFilePath);
+                }
             }
+        } catch (Exception e) {
+            logger.error("Failed to create config directory: {} ({})", containerFilePath, e.getMessage());
         }
     }
 
index 3e067254edb721cd6e5b7adb109c1e96badbadb2..a36d4cc6d78588df5828b175de0facd9fe666f33 100644 (file)
@@ -9,6 +9,7 @@
 
 package org.opendaylight.controller.configuration.internal;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Dictionary;
@@ -57,6 +58,7 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
             .synchronizedSet(new HashSet<IConfigurationContainerAware>());
     private ObjectReader objReader;
     private ObjectWriter objWriter;
+    private String containerName;
 
     public void addConfigurationContainerAware(
             IConfigurationContainerAware configurationAware) {
@@ -88,7 +90,7 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
 
     void init(Component c) {
         Dictionary<?, ?> props = c.getServiceProperties();
-        String containerName = (props != null) ? (String) props.get("containerName") :
+        containerName = (props != null) ? (String) props.get("containerName") :
             GlobalConstants.DEFAULT.toString();
         root =  String.format("%s%s/", GlobalConstants.STARTUPHOME.toString(), containerName);
     }
@@ -127,13 +129,14 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
             Status status = configurationAware.saveConfiguration();
             if (!status.isSuccess()) {
                 success = false;
-                logger.warn("Failed to save config for {}", configurationAware.getClass().getSimpleName());
+                logger.warn("Failed to save config for {} ({})", configurationAware.getClass().getSimpleName(),
+                        status.getDescription());
             }
         }
         if (success) {
             return new Status(StatusCode.SUCCESS);
         } else {
-            return new Status(StatusCode.INTERNALERROR, "Failed to Save All Configurations");
+            return new Status(StatusCode.INTERNALERROR, "Failed to save one or more configurations");
         }
     }
 
@@ -200,6 +203,10 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
 
     @Override
     public Status persistConfiguration(List<ConfigurationObject> config, String fileName) {
+        if (!hasBeenSaved()) {
+            return new Status(StatusCode.NOTALLOWED,
+                    String.format("Container %s has not been saved yet", containerName));
+        }
         String destination = String.format("%s%s", root, fileName);
         return objWriter.write(config, destination);
     }
@@ -219,4 +226,15 @@ public class ContainerConfigurationService implements IConfigurationContainerSer
         }
         return (List<ConfigurationObject>) obj;
     }
+
+    @Override
+    public boolean hasBeenSaved() {
+        try {
+            File configRoot = new File(this.getConfigurationRoot());
+            return configRoot.exists();
+        } catch (Exception e) {
+            return false;
+        }
+
+    }
 }
index 1ddfe1c7f354d23162353e2dbaa046c8ea281c7d..99f8df358eaab4075aebecfd69e7349e79c5755d 100644 (file)
@@ -83,6 +83,7 @@ connection.scheme = ANY_CONTROLLER_ONE_MASTER
 
 # Embedded Tomcat configuration File
 org.eclipse.gemini.web.tomcat.config.path=configuration/tomcat-server.xml
+org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
 
 # Open Flow related system parameters
 # TCP port on which the controller is listening (default 6633)
index 9ba590820a04a1dfdcb403b3168ce6f336186c13..2365c700f9fe085c762b6e91cbe8396522487acc 100644 (file)
@@ -23,7 +23,7 @@
                 </module>
                 <module>
                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty:eventexecutor">netty:netty-global-event-executor</type>
-                    <name>global-event-executor</name>
+                    <name>singleton</name>
                 </module>
             </modules>
             
@@ -43,7 +43,7 @@
                     <type xmlns:netty="urn:opendaylight:params:xml:ns:yang:controller:netty">netty:netty-event-executor</type>
                     <instance>
                         <name>global-event-executor</name>
-                        <provider>/modules/module[type='netty-global-event-executor'][name='global-event-executor']</provider>
+                        <provider>/modules/module[type='netty-global-event-executor'][name='singleton']</provider>
                     </instance>
                 </service>
                 <service>
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.java
new file mode 100644 (file)
index 0000000..2dce505
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ * 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.sal.compatibility;
+
+import org.eclipse.xtend2.lib.StringConcatenation;
+import org.eclipse.xtext.xbase.lib.Conversions;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+
+import java.util.List;
+
+@SuppressWarnings("all")
+public class InventoryMapping {
+  public static NodeConnector toAdNodeConnector(final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector> identifier) {
+    final List<PathArgument> path = identifier.getPath();
+    final PathArgument lastPathArgument = IterableExtensions.<PathArgument>last(path);
+    final NodeConnectorKey tpKey = ((IdentifiableItem<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector,NodeConnectorKey>) lastPathArgument).getKey();
+    return InventoryMapping.nodeConnectorFromId(tpKey.getId().getValue());
+  }
+  
+  public static Node toAdNode(final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> identifier) {
+    final List<PathArgument> path = identifier.getPath();
+    final PathArgument lastPathArgument = IterableExtensions.<PathArgument>last(path);
+    final NodeKey tpKey = ((IdentifiableItem<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node,NodeKey>) lastPathArgument).getKey();
+    return InventoryMapping.nodeFromNodeId(tpKey.getId().getValue());
+  }
+  
+  public static NodeRef toNodeRef(final Node node) {
+    final NodeId nodeId = new NodeId(InventoryMapping.toNodeId(node));
+    final NodeKey nodeKey = new NodeKey(nodeId);
+    final InstanceIdentifierBuilder<? extends Object> builder = InstanceIdentifier.builder();
+    final InstanceIdentifierBuilder<Nodes> nodes = builder.<Nodes>node(Nodes.class);
+    final InstanceIdentifierBuilder<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> child =
+            nodes.<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, NodeKey>child(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node.class, nodeKey);
+    final InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node> path = child.toInstance();
+    return new NodeRef(path);
+  }
+  
+  public static NodeKey toNodeKey(final Node node) {
+    final NodeId nodeId = new NodeId(InventoryMapping.toNodeId(node));
+    return new NodeKey(nodeId);
+  }
+  
+  public static NodeConnectorKey toNodeConnectorKey(final NodeConnector nc) {
+    final NodeConnectorId nodeConnectorId = new NodeConnectorId(InventoryMapping.toNodeConnectorId(nc));
+    return new NodeConnectorKey(nodeConnectorId);
+  }
+  
+  public static String toNodeId(final Node node) {
+    final StringConcatenation builder = new StringConcatenation();
+    builder.append("ad-sal:");
+    builder.append(node.getType(), "");
+    builder.append("::");
+    builder.append(node.getNodeIDString(), "");
+    return builder.toString();
+  }
+  
+  public static String toNodeConnectorId(final NodeConnector nc) {
+    final StringConcatenation builder = new StringConcatenation();
+    builder.append(InventoryMapping.toNodeId(nc.getNode()), "");
+    builder.append("::");
+    builder.append(nc.getNodeConnectorIDString(), "");
+    return builder.toString();
+  }
+  
+  public static Node nodeFromNodeId(final String nodeId) {
+    final String[] split = nodeId.split("::");
+    return InventoryMapping.nodeFromString(split);
+  }
+  
+  public static NodeConnector nodeConnectorFromId(final String invId) {
+    final String[] split = invId.split("::");
+    return InventoryMapping.nodeConnectorFromString(split);
+  }
+  
+  private static NodeConnector nodeConnectorFromString(final String[] string) {
+    final List<String> subList = ((List<String>)Conversions.doWrapArray(string)).subList(0, 1);
+    final Node node = InventoryMapping.nodeFromString(((String[])Conversions.unwrapArray(subList, String.class)));
+    final String index3 = string[2];
+    return NodeConnector.fromStringNoNode(index3, node);
+  }
+  
+  private static Node nodeFromString(final String[] strings) {
+      String index0 = strings[0];
+      final String type = index0.substring(6);
+      String id = strings[1];
+      return Node.fromString(type, id);
+  }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/InventoryMapping.xtend
deleted file mode 100644 (file)
index 0ea9918..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.sal.compatibility
-
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
-
-class InventoryMapping {
-
-    static def org.opendaylight.controller.sal.core.NodeConnector toAdNodeConnector(
-        InstanceIdentifier<NodeConnector> identifier) {
-        val tpKey = (identifier.path.last as IdentifiableItem<NodeConnector,NodeConnectorKey>).key;
-        return nodeConnectorFromId(tpKey.id.value);
-    }
-
-    static def org.opendaylight.controller.sal.core.Node toAdNode(InstanceIdentifier<Node> identifier) {
-        val tpKey = (identifier.path.last as IdentifiableItem<Node,NodeKey>).key;
-        return nodeFromNodeId(tpKey.id.value);
-    }
-    
-    
-     static def NodeRef toNodeRef(org.opendaylight.controller.sal.core.Node node) {
-        val nodeId = new NodeKey(new NodeId(node.toNodeId))
-        val path = InstanceIdentifier.builder().node(Nodes).child(Node,nodeId).toInstance;
-        return new NodeRef(path);
-    }
-
-    static def NodeKey toNodeKey(org.opendaylight.controller.sal.core.Node node) {
-        val nodeId = new NodeId(node.toNodeId)
-        return new NodeKey(nodeId);
-    }
-
-    static def NodeConnectorKey toNodeConnectorKey(org.opendaylight.controller.sal.core.NodeConnector nc) {
-        val nodeId = new NodeConnectorId(nc.toNodeConnectorId)
-        return new NodeConnectorKey(nodeId);
-    }
-
-    static def String toNodeId(org.opendaylight.controller.sal.core.Node node) {
-        '''ad-sal:«node.type»::«node.nodeIDString»'''
-    }
-
-    static def String toNodeConnectorId(org.opendaylight.controller.sal.core.NodeConnector nc) {
-        '''«nc.node.toNodeId»::«nc.nodeConnectorIDString»'''
-    }
-
-    static def org.opendaylight.controller.sal.core.Node nodeFromNodeId(String nodeId) {
-        return nodeFromString(nodeId.split("::"))
-    }
-
-    static def nodeConnectorFromId(String invId) {
-        return nodeConnectorFromString(invId.split("::"));
-    }
-
-    private static def org.opendaylight.controller.sal.core.NodeConnector nodeConnectorFromString(String[] string) {
-        val node = nodeFromString(string.subList(0, 1));
-        return org.opendaylight.controller.sal.core.NodeConnector.fromStringNoNode(string.get(2), node);
-    }
-
-    private static def org.opendaylight.controller.sal.core.Node nodeFromString(String[] strings) {
-        val type = strings.get(0).substring(6);
-        org.opendaylight.controller.sal.core.Node.fromString(type, strings.get(1))
-    }
-
-}
index 23a98ff39aedff07e034573b0398735a21da7110..6a9db37dbbfabf8a7fcbd82c3c08130de1690ab8 100644 (file)
@@ -1,5 +1,7 @@
 package org.opendaylight.controller.sal.compatibility;
 
+import java.util.List;
+
 import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.inventory.IPluginOutInventoryService;
@@ -11,8 +13,6 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.List;
-
 public class InventoryNotificationProvider implements AutoCloseable{
 
     private ListenerRegistration<DataChangeListener> nodeConnectorDataChangeListenerRegistration;
@@ -33,7 +33,7 @@ public class InventoryNotificationProvider implements AutoCloseable{
                 && inventoryPublisher!= null){
 
             if(nodeConnectorDataChangeListener == null){
-                InstanceIdentifier nodeConnectorPath = InstanceIdentifier.builder(Nodes.class).child(Node.class).child(NodeConnector.class).build();
+                InstanceIdentifier<NodeConnector> nodeConnectorPath = InstanceIdentifier.builder(Nodes.class).child(Node.class).child(NodeConnector.class).build();
                 nodeConnectorDataChangeListener = new NodeConnectorDataChangeListener();
                 nodeConnectorDataChangeListener.setInventoryPublisher(inventoryPublisher);
                 nodeConnectorDataChangeListenerRegistration = dataProviderService.registerDataChangeListener(nodeConnectorPath, nodeConnectorDataChangeListener);
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.java
new file mode 100644 (file)
index 0000000..0486f34
--- /dev/null
@@ -0,0 +1,396 @@
+/**
+ * Copyright (c) 2014 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.sal.compatibility;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import org.eclipse.xtext.xbase.lib.Exceptions;
+import org.opendaylight.controller.sal.common.util.Arguments;
+import org.opendaylight.controller.sal.core.AdvertisedBandwidth;
+import org.opendaylight.controller.sal.core.Bandwidth;
+import org.opendaylight.controller.sal.core.Buffers;
+import org.opendaylight.controller.sal.core.Capabilities;
+import org.opendaylight.controller.sal.core.Config;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.MacAddress;
+import org.opendaylight.controller.sal.core.Name;
+import org.opendaylight.controller.sal.core.NodeConnector.NodeConnectorIDType;
+import org.opendaylight.controller.sal.core.PeerBandwidth;
+import org.opendaylight.controller.sal.core.Property;
+import org.opendaylight.controller.sal.core.SupportedBandwidth;
+import org.opendaylight.controller.sal.core.Tables;
+import org.opendaylight.controller.sal.core.TimeStamp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FeatureCapability;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityArpMatchIp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityFlowStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityIpReasm;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityPortStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityQueueStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityStp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityTableStats;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.flow.node.SwitchFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+
+@SuppressWarnings("all")
+public class NodeMapping {
+  public final static String MD_SAL_TYPE = "MD_SAL";
+  
+  private final static Class<Node> NODE_CLASS = Node.class;
+  
+  private final static Class<NodeConnector> NODECONNECTOR_CLASS = NodeConnector.class;
+  
+  private NodeMapping() {
+    throw new UnsupportedOperationException("Utility class. Instantiation is not allowed.");
+  }
+  
+  public static org.opendaylight.controller.sal.core.Node toADNode(final InstanceIdentifier<? extends Object> node) throws ConstructionException {
+    NodeId nodeId = NodeMapping.toNodeId(node);
+    return NodeMapping.toADNode(nodeId);
+  }
+  
+  public static org.opendaylight.controller.sal.core.Node toADNode(final NodeId id) {
+    try {
+      String aDNodeId = NodeMapping.toADNodeId(id);
+      return  new org.opendaylight.controller.sal.core.Node(NodeMapping.MD_SAL_TYPE, aDNodeId);
+    } catch (Throwable e) {
+      throw Exceptions.sneakyThrow(e);
+    }
+  }
+  
+  public static NodeId toNodeId(final InstanceIdentifier<? extends Object> node) {
+    Preconditions.<InstanceIdentifier<? extends Object>>checkNotNull(node);
+    List<PathArgument> path = node.getPath();
+    Preconditions.<List<PathArgument>>checkNotNull(path);
+    int size = path.size();
+    Preconditions.checkArgument(size >= 2);
+    final PathArgument arg = path.get(1);
+    final IdentifiableItem item = Arguments.<IdentifiableItem>checkInstanceOf(arg, IdentifiableItem.class);
+    Identifier key = item.getKey();
+    final NodeKey nodeKey = Arguments.<NodeKey>checkInstanceOf(key, NodeKey.class);
+    return nodeKey.getId();
+  }
+  
+  public static String toADNodeId(final NodeId nodeId) {
+    Preconditions.<NodeId>checkNotNull(nodeId);
+    return nodeId.getValue();
+  }
+  
+  public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorRef source) throws ConstructionException {
+    Preconditions.<NodeConnectorRef>checkNotNull(source);
+    final InstanceIdentifier<?> path = Preconditions.<InstanceIdentifier<? extends Object>>checkNotNull(source.getValue());
+    Preconditions.checkArgument(path.getPath().size() >= 3);
+    final PathArgument arg = path.getPath().get(2);
+    final IdentifiableItem item = Arguments.<IdentifiableItem>checkInstanceOf(arg,IdentifiableItem.class);
+    final NodeConnectorKey connectorKey = Arguments.<NodeConnectorKey>checkInstanceOf(item.getKey(), NodeConnectorKey.class);
+    return NodeMapping.toADNodeConnector(connectorKey.getId(), NodeMapping.toNodeId(path));
+  }
+  
+  public static org.opendaylight.controller.sal.core.NodeConnector toADNodeConnector(final NodeConnectorId ncid, final NodeId nid) {
+    try {
+      String nodeConnectorType = NodeMapping.toNodeConnectorType(ncid, nid);
+      Object aDNodeConnectorId = NodeMapping.toADNodeConnectorId(ncid, nid);
+      org.opendaylight.controller.sal.core.Node aDNode = NodeMapping.toADNode(nid);
+      return new org.opendaylight.controller.sal.core.NodeConnector(nodeConnectorType, aDNodeConnectorId, aDNode);
+    } catch (Throwable e) {
+      throw Exceptions.sneakyThrow(e);
+    }
+  }
+  
+  public static String toNodeConnectorType(final NodeConnectorId ncId, final NodeId nodeId) {
+    if (ncId.equals(toLocalNodeConnectorId(nodeId))) {
+        return NodeConnectorIDType.SWSTACK;
+    } else if (ncId.equals(toNormalNodeConnectorId(nodeId))) {
+        return NodeConnectorIDType.HWPATH;
+    } else if (ncId.equals(toControllerNodeConnectorId(nodeId))) {
+        return NodeConnectorIDType.CONTROLLER;
+    }
+    return MD_SAL_TYPE;
+  }
+
+  public static Object toADNodeConnectorId(final NodeConnectorId nodeConnectorId, final NodeId nodeId) {
+    if (nodeConnectorId.equals(toLocalNodeConnectorId(nodeId)) ||
+        nodeConnectorId.equals(toNormalNodeConnectorId(nodeId)) ||
+        nodeConnectorId.equals(toControllerNodeConnectorId(nodeId))) {
+        return org.opendaylight.controller.sal.core.NodeConnector.SPECIALNODECONNECTORID;
+    }
+    return nodeConnectorId.getValue();
+  }
+  
+  public static NodeConnectorId toControllerNodeConnectorId(final NodeId node) {
+    return new NodeConnectorId(node.getValue() + ":" + 4294967293L);
+  }
+  
+  public static NodeConnectorId toLocalNodeConnectorId(final NodeId node) {
+    return new NodeConnectorId(node.getValue() + ":" + 4294967294L);
+  }
+  
+  public static NodeConnectorId toNormalNodeConnectorId(final NodeId node) {
+    return new NodeConnectorId(node.getValue() + ":" + 4294967290L);
+  }
+  
+  public static NodeRef toNodeRef(final org.opendaylight.controller.sal.core.Node node) {
+    Preconditions.checkArgument(MD_SAL_TYPE.equals(node.getType()));
+    final String nodeId = Arguments.<String>checkInstanceOf(node.getID(), String.class);
+    final NodeKey nodeKey = new NodeKey(new NodeId(nodeId));
+    final InstanceIdentifier<Node> nodePath = InstanceIdentifier.builder().node(Nodes.class).child(NODE_CLASS, nodeKey).toInstance();
+    return new NodeRef(nodePath);
+  }
+  
+  public static NodeConnectorRef toNodeConnectorRef(final org.opendaylight.controller.sal.core.NodeConnector nodeConnector) {
+
+    final NodeRef node = NodeMapping.toNodeRef(nodeConnector.getNode());
+    final InstanceIdentifier<Node> nodePath = ((InstanceIdentifier<Node>) node.getValue());
+    NodeConnectorId nodeConnectorId = null;
+
+    if (nodeConnector.getID().equals(org.opendaylight.controller.sal.core.NodeConnector.SPECIALNODECONNECTORID)) {
+        final NodeId nodeId = toNodeId(nodePath);
+        final String nodeConnectorType = nodeConnector.getType();
+        if (nodeConnectorType.equals(NodeConnectorIDType.SWSTACK)) {
+            nodeConnectorId = toLocalNodeConnectorId(nodeId);
+        } else if (nodeConnectorType.equals(NodeConnectorIDType.HWPATH)) {
+            nodeConnectorId = toNormalNodeConnectorId(nodeId);
+        } else if (nodeConnectorType.equals(NodeConnectorIDType.CONTROLLER)) {
+            nodeConnectorId = toControllerNodeConnectorId(nodeId);
+        }
+    } else {
+        nodeConnectorId = new NodeConnectorId(Arguments.<String>checkInstanceOf(nodeConnector.getID(), String.class));
+    }
+    final NodeConnectorKey connectorKey = new NodeConnectorKey(nodeConnectorId);
+    final InstanceIdentifier<NodeConnector> path = InstanceIdentifier.builder(nodePath).child(NODECONNECTOR_CLASS, connectorKey).toInstance();
+    return new NodeConnectorRef(path);
+  }
+  
+  public static org.opendaylight.controller.sal.core.Node toADNode(final NodeRef node) throws ConstructionException {
+    return NodeMapping.toADNode(node.getValue());
+  }
+  
+  public static HashSet<Property> toADNodeConnectorProperties(final NodeConnectorUpdated nc) {
+    final FlowCapableNodeConnectorUpdated fcncu = nc.<FlowCapableNodeConnectorUpdated>getAugmentation(FlowCapableNodeConnectorUpdated.class);
+    if (!Objects.equal(fcncu, null)) {
+      return NodeMapping.toADNodeConnectorProperties(fcncu);
+    }
+    return new HashSet<Property>();
+  }
+  
+  public static HashSet<Property> toADNodeConnectorProperties(final NodeConnector nc) {
+    final FlowCapableNodeConnector fcnc = nc.<FlowCapableNodeConnector>getAugmentation(FlowCapableNodeConnector.class);
+    if (!Objects.equal(fcnc, null)) {
+      return NodeMapping.toADNodeConnectorProperties(fcnc);
+    }
+    return new HashSet<Property>();
+  }
+  
+  public static HashSet<Property> toADNodeConnectorProperties(final FlowNodeConnector fcncu) {
+
+    final HashSet<org.opendaylight.controller.sal.core.Property> props = new HashSet<>();
+    if (fcncu != null) {
+        if (fcncu.getCurrentFeature() != null && toAdBandwidth(fcncu.getCurrentFeature()) != null) {
+            props.add(toAdBandwidth(fcncu.getCurrentFeature()));
+        }
+        if (fcncu.getAdvertisedFeatures() != null && toAdAdvertizedBandwidth(fcncu.getAdvertisedFeatures()) != null) {
+            props.add(toAdAdvertizedBandwidth(fcncu.getAdvertisedFeatures()));
+        }
+        if (fcncu.getSupported() != null && toAdSupportedBandwidth(fcncu.getSupported()) != null) {
+            props.add(toAdSupportedBandwidth(fcncu.getSupported()));
+        }
+        if (fcncu.getPeerFeatures() != null && toAdPeerBandwidth(fcncu.getPeerFeatures()) != null) {
+            props.add(toAdPeerBandwidth(fcncu.getPeerFeatures()));
+        }
+        if (fcncu.getName() != null && toAdName(fcncu.getName()) != null) {
+            props.add(toAdName(fcncu.getName()));
+        }
+        if (fcncu.getConfiguration() != null && toAdConfig(fcncu.getConfiguration()) != null) {
+            props.add(toAdConfig(fcncu.getConfiguration()));
+        }
+        if (fcncu.getState() != null && toAdState(fcncu.getState()) != null) {
+            props.add(toAdState(fcncu.getState()));
+        }
+    }
+    return props;
+  }
+  
+  public static Name toAdName(final String name) {
+    return new Name(name);
+  }
+  
+  public static Config toAdConfig(final PortConfig pc) {
+    Config config = null;
+    if (pc.isPORTDOWN()) {
+        config = new Config(Config.ADMIN_DOWN);
+    } else {
+        config = new Config(Config.ADMIN_UP);
+    }
+    return config;
+  }
+  
+  public static org.opendaylight.controller.sal.core.State toAdState(final State s) {
+
+    org.opendaylight.controller.sal.core.State state = null;
+    if (s.isLinkDown()) {
+        state = new org.opendaylight.controller.sal.core.State(org.opendaylight.controller.sal.core.State.EDGE_DOWN);
+    } else {
+        state = new org.opendaylight.controller.sal.core.State(org.opendaylight.controller.sal.core.State.EDGE_UP);
+    }
+    return state;
+  }
+  
+  public static Bandwidth toAdBandwidth(final PortFeatures pf) {
+    Bandwidth bw = null;
+    if (pf.isTenMbHd() || pf.isTenMbFd()) {
+        bw = new Bandwidth(Bandwidth.BW10Mbps);
+    } else if (pf.isHundredMbHd() || pf.isHundredMbFd()) {
+        bw = new Bandwidth(Bandwidth.BW100Mbps);
+    } else if (pf.isOneGbHd() || pf.isOneGbFd()) {
+        bw = new Bandwidth(Bandwidth.BW1Gbps);
+    } else if (pf.isOneGbFd()) {
+        bw = new Bandwidth(Bandwidth.BW10Gbps);
+    } else if (pf.isTenGbFd()) {
+        bw = new Bandwidth(Bandwidth.BW10Gbps);
+    } else if (pf.isFortyGbFd()) {
+        bw = new Bandwidth(Bandwidth.BW40Gbps);
+    } else if (pf.isHundredGbFd()) {
+        bw = new Bandwidth(Bandwidth.BW100Gbps);
+    } else if (pf.isOneTbFd()) {
+        bw = new Bandwidth(Bandwidth.BW1Tbps);
+    }
+    return bw;
+  }
+  
+  public static AdvertisedBandwidth toAdAdvertizedBandwidth(final PortFeatures pf) {
+    AdvertisedBandwidth abw = null;
+    final Bandwidth bw = toAdBandwidth(pf);
+    if (bw != null) {
+        abw = new AdvertisedBandwidth(bw.getValue());
+    }
+    return abw;
+  }
+  
+  public static SupportedBandwidth toAdSupportedBandwidth(final PortFeatures pf) {
+    SupportedBandwidth sbw = null;
+    final Bandwidth bw = toAdBandwidth(pf);
+    if (bw != null) {
+        sbw = new SupportedBandwidth(bw.getValue());
+    }
+    return sbw;
+  }
+  
+  public static PeerBandwidth toAdPeerBandwidth(final PortFeatures pf) {
+    PeerBandwidth pbw = null;
+    final Bandwidth bw = toAdBandwidth(pf);
+    if (bw != null) {
+        pbw = new PeerBandwidth(bw.getValue());
+    }
+    return pbw;
+  }
+  
+  public static HashSet<Property> toADNodeProperties(final NodeUpdated nu) {
+    final FlowCapableNodeUpdated fcnu = nu.getAugmentation(FlowCapableNodeUpdated.class);
+    if (fcnu != null) {
+        return toADNodeProperties(fcnu, nu.getId());
+    }
+    return new HashSet<org.opendaylight.controller.sal.core.Property>();
+  }
+  
+  public static HashSet<Property> toADNodeProperties(final FlowNode fcnu, final NodeId id) {
+
+    final HashSet<org.opendaylight.controller.sal.core.Property> props = new HashSet<>();
+
+    if (fcnu != null) {
+        props.add(toADTimestamp());
+
+        // props.add(fcnu.supportedActions.toADActions) - TODO
+        if (id != null) {
+            props.add(toADMacAddress(id));
+        }
+        SwitchFeatures switchFeatures = fcnu.getSwitchFeatures();
+        if (switchFeatures != null) {
+            if (switchFeatures.getMaxTables() != null) {
+                props.add(toADTables(switchFeatures.getMaxTables()));
+            }
+            if (switchFeatures.getCapabilities() != null) {
+                props.add(toADCapabiliities(switchFeatures.getCapabilities()));
+            }
+            if (switchFeatures.getMaxBuffers() != null) {
+                props.add(toADBuffers(switchFeatures.getMaxBuffers()));
+            }
+        }
+    }
+    return props;
+  }
+  
+  public static TimeStamp toADTimestamp() {
+    final Date date = new Date();
+    final TimeStamp timestamp = new TimeStamp(date.getTime(), "connectedSince");
+    return timestamp;
+  }
+  
+  public static MacAddress toADMacAddress(final NodeId id) {
+    final String nodeId = id.getValue().replaceAll("openflow:", "");
+    long lNodeId = Long.parseLong(nodeId);
+    lNodeId = Long.valueOf(lNodeId).longValue();
+    byte[] bytesFromDpid = ToSalConversionsUtils.bytesFromDpid(lNodeId);
+    return new MacAddress(bytesFromDpid);
+  }
+  
+  public static Tables toADTables(final Short tables) {
+    return new Tables(tables.byteValue());
+  }
+  
+  public static Capabilities toADCapabiliities(final List<Class<? extends FeatureCapability>> capabilities) {
+
+    int b = 0;
+    for (Class<? extends FeatureCapability> capability : capabilities) {
+        if (capability.equals(FlowFeatureCapabilityFlowStats.class)) {
+            b = Capabilities.CapabilitiesType.FLOW_STATS_CAPABILITY.getValue() | b;
+        } else if (capability.equals(FlowFeatureCapabilityTableStats.class)) {
+            b = Capabilities.CapabilitiesType.TABLE_STATS_CAPABILITY.getValue() | b;
+        } else if (capability.equals(FlowFeatureCapabilityPortStats.class)) {
+            b = Capabilities.CapabilitiesType.PORT_STATS_CAPABILITY.getValue() | b;
+        } else if (capability.equals(FlowFeatureCapabilityStp.class)) {
+            b = Capabilities.CapabilitiesType.STP_CAPABILITY.getValue() | b;
+        } else if (capability.equals(FlowFeatureCapabilityIpReasm.class)) {
+            b = Capabilities.CapabilitiesType.IP_REASSEM_CAPABILITY.getValue() | b;
+        } else if (capability.equals(FlowFeatureCapabilityQueueStats.class)) {
+            b = Capabilities.CapabilitiesType.QUEUE_STATS_CAPABILITY.getValue() | b;
+        } else if (capability.equals(FlowFeatureCapabilityArpMatchIp.class)) {
+            b = Capabilities.CapabilitiesType.ARP_MATCH_IP_CAPABILITY.getValue() | b;
+        }
+    }
+    return new Capabilities(b);
+  }
+  
+  public static Buffers toADBuffers(final Long buffers) {
+    return new Buffers(buffers.intValue());
+  }
+}
diff --git a/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.xtend b/opendaylight/md-sal/compatibility/sal-compatibility/src/main/java/org/opendaylight/controller/sal/compatibility/NodeMapping.xtend
deleted file mode 100644 (file)
index debcbac..0000000
+++ /dev/null
@@ -1,364 +0,0 @@
-/*
- * Copyright (c) 2014 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.sal.compatibility
-
-import org.opendaylight.controller.sal.core.Node
-import org.opendaylight.controller.sal.core.NodeConnector
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
-
-import static com.google.common.base.Preconditions.*;
-import static extension org.opendaylight.controller.sal.common.util.Arguments.*;
-import static extension org.opendaylight.controller.sal.compatibility.ToSalConversionsUtils.*;
-
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey
-import org.opendaylight.controller.sal.core.ConstructionException
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnectorUpdated
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortFeatures
-import org.opendaylight.controller.sal.core.Bandwidth
-import org.opendaylight.controller.sal.core.AdvertisedBandwidth
-import org.opendaylight.controller.sal.core.SupportedBandwidth
-import org.opendaylight.controller.sal.core.PeerBandwidth
-import org.opendaylight.controller.sal.core.Name
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.PortConfig
-import org.opendaylight.controller.sal.core.Config
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.port.rev130925.flow.capable.port.State
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeUpdated
-import java.util.HashSet
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeUpdated
-import org.opendaylight.controller.sal.core.Tables
-import java.util.List
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FeatureCapability
-import org.opendaylight.controller.sal.core.Buffers
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityFlowStats
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityTableStats
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityIpReasm
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityPortStats
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityStp
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityQueueStats
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityArpMatchIp
-import org.opendaylight.controller.sal.core.Capabilities
-import org.opendaylight.controller.sal.core.MacAddress
-import java.util.Date
-import org.opendaylight.controller.sal.core.TimeStamp
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNodeConnector
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowNode
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector
-
-public class NodeMapping {
-
-    public static val MD_SAL_TYPE = "MD_SAL";
-    private static val NODE_CLASS = org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-    private static val NODECONNECTOR_CLASS = org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.
-        NodeConnector;
-
-    private new() {
-        throw new UnsupportedOperationException("Utility class. Instantiation is not allowed.");
-    }
-
-    public static def toADNode(InstanceIdentifier<?> node) throws ConstructionException {
-        return node.toNodeId.toADNode
-    }
-
-    public static def toADNode(NodeId id) {
-        return new Node(MD_SAL_TYPE, id.toADNodeId);
-    }
-
-    public static def toNodeId(InstanceIdentifier<?> node) {
-        checkNotNull(node);
-        checkNotNull(node.getPath());
-        checkArgument(node.getPath().size() >= 2);
-        val arg = node.getPath().get(1);
-        val item = arg.checkInstanceOf(IdentifiableItem);
-        val nodeKey = item.getKey().checkInstanceOf(NodeKey);
-        return nodeKey.id
-    }
-
-    public static def toADNodeId(NodeId nodeId) {
-        checkNotNull(nodeId);
-        return nodeId.value
-    }
-
-    public static def toADNodeConnector(NodeConnectorRef source) throws ConstructionException {
-        checkNotNull(source);
-        val InstanceIdentifier<?> path = checkNotNull(source.getValue());
-        checkArgument(path.path.size() >= 3);
-        val arg = path.getPath().get(2);
-        val item = arg.checkInstanceOf(IdentifiableItem);
-        val connectorKey = item.getKey().checkInstanceOf(NodeConnectorKey);
-        return connectorKey.id.toADNodeConnector(path.toNodeId)
-    }
-    
-    public static def toADNodeConnector(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId ncid,
-        org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId nid) {
-            return new NodeConnector(ncid.toNodeConnectorType(nid),
-            ncid.toADNodeConnectorId(nid), nid.toADNode);
-     }
-
-    public static def toNodeConnectorType(NodeConnectorId ncId, NodeId nodeId) {
-        if (ncId.equals(nodeId.toLocalNodeConnectorId)) {
-            return NodeConnector.NodeConnectorIDType.SWSTACK
-        } else if (ncId.equals(nodeId.toNormalNodeConnectorId)) {
-            return NodeConnector.NodeConnectorIDType.HWPATH
-        } else if (ncId.equals(nodeId.toControllerNodeConnectorId)) {
-            return NodeConnector.NodeConnectorIDType.CONTROLLER
-        }
-        return MD_SAL_TYPE
-    }
-
-    public static def toADNodeConnectorId(NodeConnectorId nodeConnectorId, NodeId nodeId) {
-        if (nodeConnectorId.equals(nodeId.toLocalNodeConnectorId) ||
-            nodeConnectorId.equals(nodeId.toNormalNodeConnectorId) ||
-            nodeConnectorId.equals(nodeId.toControllerNodeConnectorId)) {
-            return NodeConnector.SPECIALNODECONNECTORID
-        }
-        return nodeConnectorId.value
-    }
-
-    public static def toControllerNodeConnectorId(NodeId node) {
-        return new NodeConnectorId(node.value + ":" + 4294967293L)
-    }
-
-    public static def toLocalNodeConnectorId(NodeId node) {
-        return new NodeConnectorId(node.value + ":" + 4294967294L)
-    }
-
-    public static def toNormalNodeConnectorId(NodeId node) {
-        return new NodeConnectorId(node.value + ":" + 4294967290L)
-    }
-
-    public static def toNodeRef(Node node) {
-        checkArgument(MD_SAL_TYPE.equals(node.getType()));
-        var nodeId = node.ID.checkInstanceOf(String)
-        val nodeKey = new NodeKey(new NodeId(nodeId));
-        val nodePath = InstanceIdentifier.builder().node(Nodes).child(NODE_CLASS, nodeKey).toInstance();
-        return new NodeRef(nodePath);
-    }
-
-    public static def toNodeConnectorRef(NodeConnector nodeConnector) {
-        val node = nodeConnector.node.toNodeRef();
-        val nodePath = node.getValue() as InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node>
-        var NodeConnectorId nodeConnectorId
-        if (nodeConnector.ID.equals(NodeConnector.SPECIALNODECONNECTORID)) {
-            if (nodeConnector.type.equals(NodeConnector.NodeConnectorIDType.SWSTACK)) {
-                nodeConnectorId = nodePath.toNodeId.toLocalNodeConnectorId
-            } else if (nodeConnector.type.equals(NodeConnector.NodeConnectorIDType.HWPATH)) {
-                nodeConnectorId = nodePath.toNodeId.toNormalNodeConnectorId
-            } else if (nodeConnector.type.equals(NodeConnector.NodeConnectorIDType.CONTROLLER)) {
-                nodeConnectorId = nodePath.toNodeId.toControllerNodeConnectorId
-            }
-        } else {
-            nodeConnectorId = new NodeConnectorId(nodeConnector.ID.checkInstanceOf(String))
-        }
-        val connectorKey = new NodeConnectorKey(nodeConnectorId);
-        val path = InstanceIdentifier.builder(nodePath).child(NODECONNECTOR_CLASS, connectorKey).toInstance();
-        return new NodeConnectorRef(path);
-    }
-
-    public static def toADNode(NodeRef node) throws ConstructionException {
-        return toADNode(node.getValue());
-    }
-
-    public static def toADNodeConnectorProperties(NodeConnectorUpdated nc) {
-        val fcncu = nc.getAugmentation(FlowCapableNodeConnectorUpdated)
-        if (fcncu != null) {
-            return fcncu.toADNodeConnectorProperties
-        }
-        return new HashSet<org.opendaylight.controller.sal.core.Property>();
-    }
-
-    public static def toADNodeConnectorProperties(org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector nc) {
-        val fcnc = nc.getAugmentation(FlowCapableNodeConnector)
-        if (fcnc != null) {
-            return fcnc.toADNodeConnectorProperties
-        }
-        return new HashSet<org.opendaylight.controller.sal.core.Property>();
-    }
-
-    public static def toADNodeConnectorProperties(FlowNodeConnector fcncu) {
-        val props = new HashSet<org.opendaylight.controller.sal.core.Property>();
-        if (fcncu != null) {
-            if (fcncu.currentFeature != null && fcncu.currentFeature.toAdBandwidth != null) {
-                props.add(fcncu.currentFeature.toAdBandwidth)
-            }
-            if (fcncu.advertisedFeatures != null && fcncu.advertisedFeatures.toAdAdvertizedBandwidth != null) {
-                props.add(fcncu.advertisedFeatures.toAdAdvertizedBandwidth)
-            }
-            if (fcncu.supported != null && fcncu.supported.toAdSupportedBandwidth != null) {
-                props.add(fcncu.supported.toAdSupportedBandwidth)
-            }
-            if (fcncu.peerFeatures != null && fcncu.peerFeatures.toAdPeerBandwidth != null) {
-                props.add(fcncu.peerFeatures.toAdPeerBandwidth)
-            }
-            if (fcncu.name != null && fcncu.name.toAdName != null) {
-                props.add(fcncu.name.toAdName)
-            }
-            if (fcncu.configuration != null && fcncu.configuration.toAdConfig != null) {
-                props.add(fcncu.configuration.toAdConfig)
-            }
-            if (fcncu.state != null && fcncu.state.toAdState != null) {
-                props.add(fcncu.state.toAdState)
-            }
-        }
-        return props
-    }
-
-    public static def toAdName(String name) {
-        return new Name(name)
-    }
-
-    public static def toAdConfig(PortConfig pc) {
-        var Config config;
-        if (pc.PORTDOWN) {
-            config = new Config(Config.ADMIN_DOWN)
-        } else {
-            config = new Config(Config.ADMIN_UP)
-        }
-        return config
-    }
-
-    public static def toAdState(State s) {
-        var org.opendaylight.controller.sal.core.State state
-        if (s.linkDown) {
-            state = new org.opendaylight.controller.sal.core.State(org.opendaylight.controller.sal.core.State.EDGE_DOWN)
-        } else {
-            state = new org.opendaylight.controller.sal.core.State(org.opendaylight.controller.sal.core.State.EDGE_UP)
-        }
-        return state
-    }
-
-    public static def toAdBandwidth(PortFeatures pf) {
-        var Bandwidth bw = null
-        if (pf.isTenMbHd || pf.isTenMbFd) {
-            bw = new Bandwidth(Bandwidth.BW10Mbps)
-        } else if (pf.isHundredMbHd || pf.isHundredMbFd) {
-            bw = new Bandwidth(Bandwidth.BW100Mbps)
-        } else if (pf.isOneGbHd || pf.isOneGbFd) {
-            bw = new Bandwidth(Bandwidth.BW1Gbps)
-        } else if (pf.isOneGbFd) {
-            bw = new Bandwidth(Bandwidth.BW10Gbps)
-        } else if (pf.isTenGbFd) {
-            bw = new Bandwidth(Bandwidth.BW10Gbps)
-        } else if (pf.isFortyGbFd) {
-            bw = new Bandwidth(Bandwidth.BW40Gbps)
-        } else if (pf.isHundredGbFd) {
-            bw = new Bandwidth(Bandwidth.BW100Gbps)
-        } else if (pf.isOneTbFd) {
-            bw = new Bandwidth(Bandwidth.BW1Tbps)
-        }
-        return bw;
-    }
-
-    public static def toAdAdvertizedBandwidth(PortFeatures pf) {
-        var AdvertisedBandwidth abw
-        val bw = pf.toAdBandwidth
-        if (bw != null) {
-            abw = new AdvertisedBandwidth(bw.value)
-        }
-        return abw
-    }
-
-    public static def toAdSupportedBandwidth(PortFeatures pf) {
-        var SupportedBandwidth sbw
-        val bw = pf.toAdBandwidth
-        if (bw != null) {
-            sbw = new SupportedBandwidth(bw.value)
-        }
-        return sbw
-    }
-
-    public static def toAdPeerBandwidth(PortFeatures pf) {
-        var PeerBandwidth pbw
-        val bw = pf.toAdBandwidth
-        if (bw != null) {
-            pbw = new PeerBandwidth(bw.value)
-        }
-        return pbw
-    }
-
-    public static def toADNodeProperties(NodeUpdated nu) {
-        val fcnu = nu.getAugmentation(FlowCapableNodeUpdated)
-        if (fcnu != null) {
-            return fcnu.toADNodeProperties(nu.id)
-        }
-        return new HashSet<org.opendaylight.controller.sal.core.Property>();
-
-    }
-
-    public static def toADNodeProperties(FlowNode fcnu, NodeId id) {
-        val props = new HashSet<org.opendaylight.controller.sal.core.Property>();
-        if (fcnu != null) {
-            props.add(toADTimestamp)
-
-            // props.add(fcnu.supportedActions.toADActions) - TODO
-            if (id != null) {
-                props.add(id.toADMacAddress)
-            }
-            if (fcnu.switchFeatures != null) {
-                if (fcnu.switchFeatures.maxTables != null) {
-                    props.add(fcnu.switchFeatures.maxTables.toADTables)
-                }
-                if (fcnu.switchFeatures.capabilities != null) {
-                    props.add(fcnu.switchFeatures.capabilities.toADCapabiliities)
-                }
-                if (fcnu.switchFeatures.maxBuffers != null) {
-                    props.add(fcnu.switchFeatures.maxBuffers.toADBuffers)
-                }
-            }
-        }
-        return props;
-    }
-
-    public static def toADTimestamp() {
-        val date = new Date();
-        val timestamp = new TimeStamp(date.time, "connectedSince")
-        return timestamp;
-    }
-
-    public static def toADMacAddress(NodeId id) {
-        return new MacAddress(Long.parseLong(id.value.replaceAll("openflow:", "")).longValue.bytesFromDpid)
-    }
-
-    public static def toADTables(Short tables) {
-        return new Tables(tables.byteValue)
-    }
-
-    public static def toADCapabiliities(List<Class<? extends FeatureCapability>> capabilities) {
-        var int b
-        for (capability : capabilities) {
-            if (capability.equals(FlowFeatureCapabilityFlowStats)) {
-                b = Capabilities.CapabilitiesType.FLOW_STATS_CAPABILITY.value.bitwiseOr(b)
-            } else if (capability.equals(FlowFeatureCapabilityTableStats)) {
-                b = Capabilities.CapabilitiesType.TABLE_STATS_CAPABILITY.value.bitwiseOr(b)
-            } else if (capability.equals(FlowFeatureCapabilityPortStats)) {
-                b = Capabilities.CapabilitiesType.PORT_STATS_CAPABILITY.value.bitwiseOr(b)
-            } else if (capability.equals(FlowFeatureCapabilityStp)) {
-                b = Capabilities.CapabilitiesType.STP_CAPABILITY.value.bitwiseOr(b)
-            } else if (capability.equals(FlowFeatureCapabilityIpReasm)) {
-                b = Capabilities.CapabilitiesType.IP_REASSEM_CAPABILITY.value.bitwiseOr(b)
-            } else if (capability.equals(FlowFeatureCapabilityQueueStats)) {
-                b = Capabilities.CapabilitiesType.QUEUE_STATS_CAPABILITY.value.bitwiseOr(b)
-            } else if (capability.equals(FlowFeatureCapabilityArpMatchIp)) {
-                b = Capabilities.CapabilitiesType.ARP_MATCH_IP_CAPABILITY.value.bitwiseOr(b)
-            }
-        }
-        return new Capabilities(b)
-    }
-
-    public static def toADBuffers(Long buffers) {
-        return new Buffers(buffers.intValue)
-    }
-
-}
index 1c675f015dfd4a4964214bb289c4b765a05b1846..160291cf21a3f494daa221bb961290a35687127a 100644 (file)
@@ -1,17 +1,17 @@
 module flow-capable-transaction {
-       namespace "urn:opendaylight:flow:transaction";
+    namespace "urn:opendaylight:flow:transaction";
     prefix type;
 
     import opendaylight-inventory {prefix inv; revision-date "2013-08-19";}
     import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
     import yang-ext {prefix ext; revision-date "2013-07-09";}
-    
+
     revision "2013-11-03" {
         description "Initial revision";
     }
 
     typedef transaction-id {
-       type uint64;
+        type uint64;
     }
     // This refers to MD-SAL transaction reference.
     grouping transaction-metadata {
@@ -19,13 +19,22 @@ module flow-capable-transaction {
             type inet:uri;
         }
     }
-    
+
     grouping transaction-aware {
         leaf transaction-id {
             type transaction-id;
         }
     }
 
+    grouping multipart-transaction-aware {
+        uses transaction-aware;
+
+        leaf moreReplies {
+            type boolean;
+            default false;
+        }
+    }
+
     rpc get-next-transaction-id {
         input {
             leaf node {
@@ -34,7 +43,7 @@ module flow-capable-transaction {
             }
         }
         output {
-               uses transaction-aware;
+            uses transaction-aware;
         }
     }
 
@@ -50,4 +59,4 @@ module flow-capable-transaction {
             }
         }
     }
-}
\ No newline at end of file
+}
index 66990d473f84e21af3fcb1af3c46993bd1e1eb9b..b125116bb10ebfaf8b8e694677d633f687c5e81f 100644 (file)
@@ -33,10 +33,7 @@ module sal-table {
     
     notification table-updated {
         uses "inv:node-context-ref";
-        uses tr:transaction-aware;
-        leaf moreReplies {
-            type boolean;
-        }
+        uses tr:multipart-transaction-aware;
         uses table-type:table-features;
     }
 }
index 94e2c0a42831f98b4dc14887e0bd356d2db15221..e0df924a0ea5434f81a804efec6447169c22448b 100644 (file)
@@ -10,51 +10,51 @@ module opendaylight-flow-statistics {
     import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";}
     import flow-capable-transaction {prefix tr;}
     import ietf-inet-types {prefix inet; revision-date "2010-09-24";}
-    
+
 
     revision "2013-08-19" {
         description "Initial revision of flow statistics service";
     }
-       
-       //Augment flow statistics data to the flow-capable-node->table->flow
-       augment "/inv:nodes/inv:node/flow-node:table/flow-node:flow" {
+
+    //Augment flow statistics data to the flow-capable-node->table->flow
+    augment "/inv:nodes/inv:node/flow-node:table/flow-node:flow" {
         ext:augment-identifier "flow-statistics-data";
         uses flow-statistics;
     }
-       
-       grouping flow-statistics {
+
+    grouping flow-statistics {
         container flow-statistics {
             //config "false";
-               uses flow-types:flow;
-               uses stat-types:generic-statistics;
+            uses flow-types:flow;
+            uses stat-types:generic-statistics;
+        }
+    }
+
+    typedef flow-id {
+        description "flow id";
+        type inet:uri;
+    }
+
+    grouping flow-and-statistics-map-list {
+        description "List of flow and statistics map";
+        list flow-and-statistics-map-list {
+            key "flow-id";
+            leaf flow-id {
+                type flow-id;
+            }
+            uses flow-and-statistics-map;
         }
-       }    
-       
-       typedef flow-id {
-               description "flow id";
-               type inet:uri;
-       }
-       
-       grouping flow-and-statistics-map-list {
-               description "List of flow and statistics map";
-               list flow-and-statistics-map-list {
-                       key "flow-id";
-                       leaf flow-id {
-                               type flow-id;
-                       }
-                       uses flow-and-statistics-map;
-               }
-       }
-       
-       grouping flow-and-statistics-map{
-               description "Mapping between flow and its statistics";
-               uses flow-types:flow;
-               uses stat-types:generic-statistics;
-       }
-       
+    }
+
+    grouping flow-and-statistics-map{
+        description "Mapping between flow and its statistics";
+        uses flow-types:flow;
+        uses stat-types:generic-statistics;
+    }
+
     // RPC calls to fetch flow statistics
     rpc get-all-flows-statistics-from-all-flow-tables {
-       description "Fetch statistics of all the flow present in all the flow tables of the switch"; 
+        description "Fetch statistics of all the flow present in all the flow tables of the switch";
         input {
             uses inv:node-context-ref;
         }
@@ -62,15 +62,15 @@ module opendaylight-flow-statistics {
             uses flow-and-statistics-map-list;
             uses tr:transaction-aware;
         }
-    
+
     }
 
     rpc get-all-flow-statistics-from-flow-table {
-       description "Fetch statistics of all the flow present in the specific flow table of the switch"; 
+        description "Fetch statistics of all the flow present in the specific flow table of the switch";
         input {
             uses inv:node-context-ref;
             leaf table-id {
-               type table-types:table-id;
+                type table-types:table-id;
             }
         }
         output {
@@ -80,7 +80,7 @@ module opendaylight-flow-statistics {
     }
 
     rpc get-flow-statistics-from-flow-table {
-       description "Fetch statistics of the specific flow present in the specific flow table of the switch"; 
+        description "Fetch statistics of the specific flow present in the specific flow table of the switch";
         input {
             uses inv:node-context-ref;
             uses flow-types:flow;
@@ -92,61 +92,58 @@ module opendaylight-flow-statistics {
     }
 
     notification flows-statistics-update {
-       description "Flows statistics sent by switch";
-               leaf moreReplies {
+        description "Flows statistics sent by switch";
+        leaf moreReplies {
             type boolean;
         }
         uses inv:node;
-               uses flow-and-statistics-map-list;
-               uses tr:transaction-aware;
+        uses flow-and-statistics-map-list;
+        uses tr:transaction-aware;
     }
 
-       //Models for aggregate flow statistics collection
-       augment "/inv:nodes/inv:node/flow-node:table" {
+    //Models for aggregate flow statistics collection
+    augment "/inv:nodes/inv:node/flow-node:table" {
         ext:augment-identifier "aggregate-flow-statistics-data";
         uses aggregate-flow-statistics;
     }
-       
-       grouping aggregate-flow-statistics {
+
+    grouping aggregate-flow-statistics {
         container aggregate-flow-statistics {
             //config "false";
-               uses stat-types:aggregate-flow-statistics;
+            uses stat-types:aggregate-flow-statistics;
         }
-       }    
-       
+    }
+
     // RPC calls to fetch aggregate flow statistics
     rpc get-aggregate-flow-statistics-from-flow-table-for-all-flows {
-       description "Fetch aggregate statistics for all the flows present in the specific flow table of the switch"; 
+        description "Fetch aggregate statistics for all the flows present in the specific flow table of the switch";
         input {
             uses inv:node-context-ref;
             leaf table-id {
-               type table-types:table-id;
+                type table-types:table-id;
             }
         }
         output {
-               uses stat-types:aggregate-flow-statistics;
+            uses stat-types:aggregate-flow-statistics;
             uses tr:transaction-aware;
         }
     }
     rpc get-aggregate-flow-statistics-from-flow-table-for-given-match {
-       description "Fetch aggregate statistics for all the flow matches to the given match from the given table of the switch"; 
+        description "Fetch aggregate statistics for all the flow matches to the given match from the given table of the switch";
         input {
             uses inv:node-context-ref;
             uses flow-types:flow;
         }
         output {
-               uses stat-types:aggregate-flow-statistics;
+            uses stat-types:aggregate-flow-statistics;
             uses tr:transaction-aware;
         }
     }
 
     notification aggregate-flow-statistics-update {
-       description "Aggregate flow statistics for a table, sent by switch";
-               leaf moreReplies {
-            type boolean;
-        }
+        description "Aggregate flow statistics for a table, sent by switch";
         uses inv:node;
-               uses stat-types:aggregate-flow-statistics;
-               uses tr:transaction-aware;
+        uses stat-types:aggregate-flow-statistics;
+        uses tr:multipart-transaction-aware;
     }
 }
index ab84f50f31922ff9d27d4184978d05e8af2ce980..431ef50624c0f66e917cb65bf35e21e1bbbd0bdc 100644 (file)
@@ -2,7 +2,7 @@ module opendaylight-flow-table-statistics {
     namespace "urn:opendaylight:flow:table:statistics";
     prefix flowtablestat;
 
-       import flow-capable-transaction {prefix tr;}
+    import flow-capable-transaction {prefix tr;}
     import yang-ext {prefix ext; revision-date "2013-07-09";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";}
@@ -19,50 +19,47 @@ module opendaylight-flow-table-statistics {
     }
     
     //Augment flow table statistics data to the table
-       augment "/inv:nodes/inv:node/flow-node:table" {
+    augment "/inv:nodes/inv:node/flow-node:table" {
         ext:augment-identifier "flow-table-statistics-data";
         uses flow-table-statistics;
     }
-       
-       grouping flow-table-statistics {
+    
+    grouping flow-table-statistics {
         container flow-table-statistics {
             //config "false";
-               uses stat-types:generic-table-statistics;
+            uses stat-types:generic-table-statistics;
         }
-       }    
+    }    
     
     //RPC calls to fetch flow table statistics
     grouping flow-table-and-statistics-map {
-       list flow-table-and-statistics-map {
-               key "table-id";
-               leaf table-id {
-                       type table-types:table-id;
-               }
-               uses stat-types:generic-table-statistics;
-       }
+        list flow-table-and-statistics-map {
+            key "table-id";
+            leaf table-id {
+                type table-types:table-id;
+            }
+            uses stat-types:generic-table-statistics;
+        }
     }
     
     rpc get-flow-tables-statistics {
-       description "Fetch statistics of all the flow tables present on the tarnet node";
-       input {
-               uses inv:node-context-ref;
-       }
-       output {
-               uses flow-table-and-statistics-map;
-               uses tr:transaction-aware;
-       }
+        description "Fetch statistics of all the flow tables present on the tarnet node";
+        input {
+            uses inv:node-context-ref;
+        }
+        output {
+            uses flow-table-and-statistics-map;
+            uses tr:transaction-aware;
+        }
     }
     
     //Notification to receive table statistics update
     
     notification flow-table-statistics-update {
-       description "Receive flow table statistics update";
-       
-               leaf moreReplies {
-            type boolean;
-        }
+        description "Receive flow table statistics update";
+        
         uses inv:node;
-               uses flow-table-and-statistics-map;
-               uses tr:transaction-aware;
+        uses flow-table-and-statistics-map;
+        uses tr:multipart-transaction-aware;
     }
 }
index 2f5c5bbe0a7a0c05fd7d913b71417fab860c4011..777981991804fea1a7181548f82428460f61e620 100644 (file)
@@ -16,37 +16,37 @@ module opendaylight-group-statistics {
         description "Initial revision of group statistics service";
     }
     
-       grouping group-statistics {
+    grouping group-statistics {
         container group-statistics {
             //config "false";
             uses group-types:group-statistics;
         }
-       }    
+    }    
     
     augment "/inv:nodes/inv:node/fni:group" {
         ext:augment-identifier "node-group-statistics";
         uses group-statistics;
     }
 
-       grouping group-desc {
+    grouping group-desc {
         container group-desc {
             //config "false";
             uses group-types:group;
         }
-       }
+    }
     
     augment "/inv:nodes/inv:node/fni:group" {
         ext:augment-identifier "node-group-desc-stats";
         uses group-desc;
     }
 
-       grouping group-features {
-               container group-features {
+    grouping group-features {
+            container group-features {
             //config "false";
             uses group-types:group-features-reply;
         }
     }
-           
+        
     augment "/inv:nodes/inv:node" {
         ext:augment-identifier "node-group-features";
         uses group-features;
@@ -103,29 +103,20 @@ module opendaylight-group-statistics {
     //Notification calls
     
     notification group-statistics-updated {
-        leaf moreReplies {
-            type boolean;
-        }
         uses inv:node;
         uses group-types:group-statistics-reply;
-        uses tr:transaction-aware;
+        uses tr:multipart-transaction-aware;
     }
     
     notification group-desc-stats-updated {
-        leaf moreReplies {
-            type boolean;
-        }
         uses inv:node;
         uses group-types:group-desc-stats-reply;
-        uses tr:transaction-aware;
+        uses tr:multipart-transaction-aware;
     }
 
     notification group-features-updated {
-        leaf moreReplies {
-            type boolean;
-        }
         uses inv:node;
         uses group-types:group-features-reply;
-        uses tr:transaction-aware;
+        uses tr:multipart-transaction-aware;
     }
 }
index b2cf78b61de21902c31c6ae2b91d2112ca0d41de..0055dc39bdef417548fb5ef0ddcfa118cff74c03 100644 (file)
@@ -90,32 +90,20 @@ module opendaylight-meter-statistics {
     //Notification calls
     
     notification meter-statistics-updated {
-        leaf moreReplies {
-            type boolean;
-        }
-        
         uses inv:node;
         uses meter-types:meter-statistics-reply;
-        uses tr:transaction-aware;
+        uses tr:multipart-transaction-aware;
     }
     
     notification meter-config-stats-updated {
-        leaf moreReplies {
-            type boolean;
-        }
-        
         uses inv:node;
         uses meter-types:meter-config-stats-reply;
-        uses tr:transaction-aware;
+        uses tr:multipart-transaction-aware;
     }
 
     notification meter-features-updated {
-        leaf moreReplies {
-            type boolean;
-        }
-        
         uses inv:node;
         uses meter-types:meter-features-reply;
-        uses tr:transaction-aware;
+        uses tr:multipart-transaction-aware;
     }
 }
index 22f0aca5e780107b3f42795ea5252f65e266df57..e711877a0229012571d18a95d7e3da8cc4376896 100644 (file)
@@ -2,7 +2,7 @@ module opendaylight-port-statistics {
     namespace "urn:opendaylight:port:statistics";
     prefix portstat;
 
-       import flow-capable-transaction {prefix tr;}
+    import flow-capable-transaction {prefix tr;}
     import yang-ext {prefix ext; revision-date "2013-07-09";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import opendaylight-statistics-types {prefix stat-types;revision-date "2013-09-25";}
@@ -14,64 +14,61 @@ module opendaylight-port-statistics {
     revision "2013-12-14" {
         description "Initial revision of port statistics model";
     }
-    
+
     //Augment port statistics data to the flow-capable-node-connector
-       augment "/inv:nodes/inv:node/inv:node-connector" {
+    augment "/inv:nodes/inv:node/inv:node-connector" {
         ext:augment-identifier "flow-capable-node-connector-statistics-data";
         uses flow-capable-node-connector-statistics;
     }
-       
-       grouping flow-capable-node-connector-statistics {
+    
+    grouping flow-capable-node-connector-statistics {
         container flow-capable-node-connector-statistics {
             //config "false";
             uses stat-types:node-connector-statistics;
         }
-       }    
-       
+    }
+    
     // RPC calls
     rpc get-all-node-connectors-statistics {
-       description "Get statistics for all node connectors from the node";
+        description "Get statistics for all node connectors from the node";
         input {
             uses inv:node-context-ref;
         }
         output {
-                       uses node-connector-statistics-and-port-number-map;
+            uses node-connector-statistics-and-port-number-map;
             uses tr:transaction-aware;
         }
     }
-    
+
     rpc get-node-connector-statistics {
-       description "Get statistics for given node connector from the node";
-       input {
-               uses inv:node-context-ref;
-               leaf node-connector-id {
-                       type inv:node-connector-id;
-               }
-       }
-       output {
+        description "Get statistics for given node connector from the node";
+        input {
+            uses inv:node-context-ref;
+            leaf node-connector-id {
+                type inv:node-connector-id;
+            }
+        }
+        output {
             uses stat-types:node-connector-statistics;
             uses tr:transaction-aware;
-       }
+        }
     }
-    
-    //Notification for node connector statistics update
-       grouping node-connector-statistics-and-port-number-map {
-               description "List of map - node connectors and their statistics";
-               list node-connector-statistics-and-port-number-map {
-                       key "node-connector-id";
-                       leaf node-connector-id {
-                               type inv:node-connector-id;
-                       }
-                       uses stat-types:node-connector-statistics;
-               }
-       }
 
-       notification node-connector-statistics-update {
-        leaf moreReplies {
-            type boolean;
+    //Notification for node connector statistics update
+    grouping node-connector-statistics-and-port-number-map {
+        description "List of map - node connectors and their statistics";
+        list node-connector-statistics-and-port-number-map {
+            key "node-connector-id";
+            leaf node-connector-id {
+                type inv:node-connector-id;
+            }
+            uses stat-types:node-connector-statistics;
         }
+    }
+
+    notification node-connector-statistics-update {
         uses inv:node;
-               uses node-connector-statistics-and-port-number-map;
-        uses tr:transaction-aware;
+        uses node-connector-statistics-and-port-number-map;
+        uses tr:multipart-transaction-aware;
     }
 }
index 9c48cfdbe874ae7fb1c128cf703bd2a94e2fbad2..caf52aa9efddbb656784776f2995002ab75b85f2 100644 (file)
@@ -2,7 +2,7 @@ module opendaylight-queue-statistics {
     namespace "urn:opendaylight:queue:statistics";
     prefix queuestat;
 
-       import flow-capable-transaction {prefix tr;}
+    import flow-capable-transaction {prefix tr;}
     import yang-ext {prefix ext; revision-date "2013-07-09";}
     import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
     import flow-node-inventory {prefix flow-node;revision-date "2013-08-19";}
@@ -18,35 +18,35 @@ module opendaylight-queue-statistics {
     }
     
     //Augment queue statistics data to the flow-capable-node-connector
-       augment "/inv:nodes/inv:node/inv:node-connector/flow-node:queue" {
+    augment "/inv:nodes/inv:node/inv:node-connector/flow-node:queue" {
         ext:augment-identifier "flow-capable-node-connector-queue-statistics-data";
         uses flow-capable-node-connector-queue-statistics;
     }
-       
-       grouping flow-capable-node-connector-queue-statistics {
+    
+    grouping flow-capable-node-connector-queue-statistics {
         container flow-capable-node-connector-queue-statistics {
             //config "false";
             uses stat-types:generic-queue-statistics;
         }
-       }    
-       
-       //RPC calls to fetch queue statistics
+    }    
+    
+    //RPC calls to fetch queue statistics
     grouping queue-id-and-statistics-map {
-       list queue-id-and-statistics-map {
-               key "queue-id node-connector-id";
-               leaf queue-id {
-                       type queue-types:queue-id;
-               }
-               leaf node-connector-id {
-                       type inv:node-connector-id;
-               }
-               
+        list queue-id-and-statistics-map {
+            key "queue-id node-connector-id";
+            leaf queue-id {
+                type queue-types:queue-id;
+            }
+            leaf node-connector-id {
+                type inv:node-connector-id;
+            }
+            
             uses stat-types:generic-queue-statistics;
-       }
+        }
     }
     
     rpc get-all-queues-statistics-from-all-ports {
-       description "Get statistics for all the queues attached to all the ports from the node";
+        description "Get statistics for all the queues attached to all the ports from the node";
         input {
             uses inv:node-context-ref;
         }
@@ -57,44 +57,41 @@ module opendaylight-queue-statistics {
     }
     
     rpc get-all-queues-statistics-from-given-port {
-       description "Get statistics for all queues for given port of the node";
-       input {
-               uses inv:node-context-ref;
-               leaf node-connector-id {
-                       type inv:node-connector-id;
-               }
-       }
-       output {
+        description "Get statistics for all queues for given port of the node";
+        input {
+            uses inv:node-context-ref;
+            leaf node-connector-id {
+                type inv:node-connector-id;
+            }
+        }
+        output {
             uses queue-id-and-statistics-map;
             uses tr:transaction-aware;
-       }
+        }
     }
     
     rpc get-queue-statistics-from-given-port {
-       description "Get statistics for given queues from given port of the node";
-       input {
-               uses inv:node-context-ref;
-               leaf node-connector-id {
-                       type inv:node-connector-id;
-               }
-               leaf queue-id {
-                       type queue-types:queue-id;
-               }
-       }
-       output {
+        description "Get statistics for given queues from given port of the node";
+        input {
+            uses inv:node-context-ref;
+            leaf node-connector-id {
+                type inv:node-connector-id;
+            }
+            leaf queue-id {
+                type queue-types:queue-id;
+            }
+        }
+        output {
             uses queue-id-and-statistics-map;
             uses tr:transaction-aware;
-       }
+        }
     }
 
     //Notification for port statistics update
 
-       notification queue-statistics-update {
-        leaf moreReplies {
-            type boolean;
-        }
+    notification queue-statistics-update {
         uses inv:node;
-               uses queue-id-and-statistics-map;
-        uses tr:transaction-aware;
+        uses queue-id-and-statistics-map;
+        uses tr:multipart-transaction-aware;
     }
 }
index 53674987772a50567f3fcdd23310c6c8700b2e52..28ffff8b2d0a368b3a9843c3591151bcb996d7a9 100644 (file)
@@ -91,7 +91,6 @@
                 <configuration>
                     <instructions>
                         <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
-                        <Bundle-Activator>org.opendaylight.controller.sal.binding.osgi.Activator</Bundle-Activator>
                         <Export-package>
                             org.opendaylight.controller.sal.binding.spi.*,
                         </Export-package>
index a0bbb28d9e07624e23ad0afd094c347c27d2fce2..4deef69198216c5d0f6fe1578caccee90dbc1458 100644 (file)
@@ -9,7 +9,10 @@ package org.opendaylight.controller.sal.binding.codegen.impl;
 
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
 
 import javassist.ClassPool;
 
@@ -22,18 +25,31 @@ import com.google.common.util.concurrent.ThreadFactoryBuilder;
 
 public class SingletonHolder {
 
-    public static final ClassPool CLASS_POOL = new ClassPool();
+    public static final ClassPool CLASS_POOL = ClassPool.getDefault();
     public static final org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator RPC_GENERATOR_IMPL = new org.opendaylight.controller.sal.binding.codegen.impl.RuntimeCodeGenerator(
             CLASS_POOL);
     public static final RuntimeCodeGenerator RPC_GENERATOR = RPC_GENERATOR_IMPL;
     public static final NotificationInvokerFactory INVOKER_FACTORY = RPC_GENERATOR_IMPL.getInvokerFactory();
+
+    public static final int CORE_NOTIFICATION_THREADS = 4;
+    public static final int MAX_NOTIFICATION_THREADS = 32;
+    public static final int NOTIFICATION_THREAD_LIFE = 15;
+
     private static ListeningExecutorService NOTIFICATION_EXECUTOR = null;
     private static ListeningExecutorService COMMIT_EXECUTOR = null;
     private static ListeningExecutorService CHANGE_EVENT_EXECUTOR = null;
 
+    /**
+     * @deprecated This method is only used from configuration modules and thus callers of it
+     *             should use service injection to make the executor configurable.
+     */
+    @Deprecated
     public static synchronized final ListeningExecutorService getDefaultNotificationExecutor() {
         if (NOTIFICATION_EXECUTOR == null) {
-            NOTIFICATION_EXECUTOR = createNamedExecutor("md-sal-binding-notification-%d");
+            ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("md-sal-binding-notification-%d").build();
+            ExecutorService executor = new ThreadPoolExecutor(CORE_NOTIFICATION_THREADS, MAX_NOTIFICATION_THREADS,
+                    NOTIFICATION_THREAD_LIFE, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), factory);
+            NOTIFICATION_EXECUTOR = MoreExecutors.listeningDecorator(executor);
         }
         return NOTIFICATION_EXECUTOR;
     }
@@ -46,13 +62,13 @@ public class SingletonHolder {
     public static synchronized final ListeningExecutorService getDefaultCommitExecutor() {
         if (COMMIT_EXECUTOR == null) {
             ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("md-sal-binding-commit-%d").build();
-           /*
-            * FIXME: this used to be newCacheThreadPool(), but MD-SAL does not have transaction
-            *        ordering guarantees, which means that using a concurrent threadpool results
-            *        in application data being committed in random order, potentially resulting
-            *        in inconsistent data being present. Once proper primitives are introduced,
-            *        concurrency can be reintroduced.
-            */
+            /*
+             * FIXME: this used to be newCacheThreadPool(), but MD-SAL does not have transaction
+             *        ordering guarantees, which means that using a concurrent threadpool results
+             *        in application data being committed in random order, potentially resulting
+             *        in inconsistent data being present. Once proper primitives are introduced,
+             *        concurrency can be reintroduced.
+             */
             ExecutorService executor = Executors.newSingleThreadExecutor(factory);
             COMMIT_EXECUTOR = MoreExecutors.listeningDecorator(executor);
         }
@@ -60,12 +76,6 @@ public class SingletonHolder {
         return COMMIT_EXECUTOR;
     }
 
-    private static ListeningExecutorService createNamedExecutor(String format) {
-        ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat(format).build();
-        ExecutorService executor = Executors.newCachedThreadPool(factory);
-        return MoreExecutors.listeningDecorator(executor);
-    }
-
     public static ExecutorService getDefaultChangeEventExecutor() {
         if (CHANGE_EVENT_EXECUTOR == null) {
             ThreadFactory factory = new ThreadFactoryBuilder().setDaemon(true).setNameFormat("md-sal-binding-change-%d").build();
index 9a431fec74f4a3cf7c3f4d694f6c2000df3de718..bf82302e548404cb4969cb01046dfae5b726c330 100644 (file)
@@ -8,25 +8,25 @@
 package org.opendaylight.controller.sal.binding.impl\r
 \r
 import com.google.common.collect.HashMultimap\r
+import com.google.common.collect.ImmutableSet\r
 import com.google.common.collect.Multimap\r
-import java.util.Collection\r
+import com.google.common.collect.Multimaps\r
 import java.util.Collections\r
 import java.util.concurrent.Callable\r
 import java.util.concurrent.ExecutorService\r
+import java.util.concurrent.Future\r
+import java.util.Set\r
 import org.opendaylight.controller.sal.binding.api.NotificationListener\r
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService\r
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService.NotificationInterestListener\r
+import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder\r
 import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker\r
 import org.opendaylight.yangtools.concepts.AbstractObjectRegistration\r
 import org.opendaylight.yangtools.concepts.ListenerRegistration\r
 import org.opendaylight.yangtools.concepts.Registration\r
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry\r
 import org.opendaylight.yangtools.yang.binding.Notification\r
 import org.slf4j.LoggerFactory\r
-import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder\rimport com.google.common.collect.Multimaps\r
-import org.opendaylight.yangtools.concepts.util.ListenerRegistry\r
-import org.opendaylight.controller.sal.binding.api.NotificationProviderService.NotificationInterestListener\rimport java.util.Set\r
-import java.util.Set\r
-import com.google.common.collect.ImmutableSet\r
-import java.util.concurrent.Future\r
 \r
 class NotificationBrokerImpl implements NotificationProviderService, AutoCloseable {\r
     \r
@@ -69,11 +69,6 @@ class NotificationBrokerImpl implements NotificationProviderService, AutoCloseab
         notification.class.interfaces.filter[it != Notification && Notification.isAssignableFrom(it)]\r
     }\r
 \r
-    @SuppressWarnings("unchecked")\r
-    private def notifyAll(Collection<NotificationListener<?>> listeners, Notification notification) {\r
-        listeners.forEach[(it as NotificationListener).onNotification(notification)]\r
-    }\r
-\r
     @Deprecated\r
     override addNotificationListener(org.opendaylight.yangtools.yang.binding.NotificationListener listener) {\r
         throw new UnsupportedOperationException("Deprecated method. Use registerNotificationListener instead.");\r
index 95de575b518f698fab1f0dce58da2c6a3992b14f..c60686d209cecbee4aeb13ae513fe6082c889cdf 100644 (file)
@@ -7,13 +7,11 @@
  */
 package org.opendaylight.controller.sal.binding.impl.util
 
-import java.util.Map.Entry
-import org.opendaylight.yangtools.concepts.Path
-import java.util.Map
-import java.util.Set
+import com.google.common.collect.Multimap
 import java.util.Collection
 import java.util.HashSet
-import com.google.common.collect.Multimap
+import java.util.Map.Entry
+import org.opendaylight.yangtools.concepts.Path
 
 class MapUtils {
 
index b56b94a67b8ea8c63f7f5f3bd8b976761683c699..0a38c90a6af6b3f7763ac08437c381168ca03fa1 100644 (file)
@@ -16,5 +16,5 @@ import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
 public interface SimpleInput extends DataObject,Augmentable<SimpleInput> {
 
     @RoutingContext(BaseIdentity.class)
-    InstanceIdentifier getIdentifier();
+    InstanceIdentifier<?> getIdentifier();
 }
index 4e4416777b8eaed7f48aa1ddbb102a3a2b6c84ec..e8a52d069d72825c1cf71a6e9511abc70e900edd 100644 (file)
@@ -23,8 +23,6 @@ public class TestHelper {
 
     public static final String CONTROLLER_MODELS = "org.opendaylight.controller.model";
     public static final String YANGTOOLS_MODELS = "org.opendaylight.yangtools.model";
-    private static final String OPENDAYLIGHT_SNAPSHOT = "http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/";
-    private static final String OPENDAYLIGHT_RELEASE = "http://nexus.opendaylight.org/content/repositories/opendaylight.release/";
 
     public static Option mdSalCoreBundles() {
         return new DefaultCompositeOption( //
index 105f6e59a3d25def3de74d039e0c3dc794d94a37..8a390b337e1849ae8cf2c15f7799073ace928ee2 100644 (file)
@@ -7,15 +7,17 @@
  */
 package org.opendaylight.controller.test.sal.binding.it;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 
 import java.util.concurrent.Future;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
-import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer;
 import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
 import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.core.api.Broker;
@@ -34,8 +36,8 @@ import com.google.inject.Inject;
 public class DataServiceTest extends AbstractTest {
 
     protected DataBrokerService consumerDataService;
-    
-    
+
+
     @Inject
     Broker broker2;
 
@@ -56,59 +58,58 @@ public class DataServiceTest extends AbstractTest {
 
         assertNotNull(consumerDataService);
 
-        
+
         DataModificationTransaction transaction = consumerDataService.beginTransaction();
         assertNotNull(transaction);
-        
+
         NodeRef node1 = createNodeRef("0");
         DataObject  node = consumerDataService.readConfigurationData(node1.getValue());
         assertNull(node);
         Node nodeData1 = createNode("0");
-        
+
         transaction.putConfigurationData(node1.getValue(), nodeData1);
         Future<RpcResult<TransactionStatus>> commitResult = transaction.commit();
         assertNotNull(commitResult);
-        
+
         RpcResult<TransactionStatus> result = commitResult.get();
-        
+
         assertNotNull(result);
         assertNotNull(result.getResult());
         assertEquals(TransactionStatus.COMMITED, result.getResult());
-        
+
         Node readedData = (Node) consumerDataService.readConfigurationData(node1.getValue());
         assertNotNull(readedData);
         assertEquals(nodeData1.getKey(), readedData.getKey());
-        
-        
+
+
         DataModificationTransaction transaction2 = consumerDataService.beginTransaction();
         assertNotNull(transaction);
-        
+
         transaction2.removeConfigurationData(node1.getValue());
-        
+
         Future<RpcResult<TransactionStatus>> commitResult2 = transaction2.commit();
         assertNotNull(commitResult2);
-        
+
         RpcResult<TransactionStatus> result2 = commitResult2.get();
-        
+
         assertNotNull(result2);
         assertNotNull(result2.getResult());
         assertEquals(TransactionStatus.COMMITED, result2.getResult());
-    
+
         DataObject readedData2 = consumerDataService.readConfigurationData(node1.getValue());
         assertNull(readedData2);
-        
-    
+
+
     }
 
-    
+
     private static NodeRef createNodeRef(String string) {
         NodeKey key = new NodeKey(new NodeId(string));
-        InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key)
-                .toInstance();
+        InstanceIdentifier<Node> path = InstanceIdentifier.builder(Nodes.class).child(Node.class, key).build();
 
         return new NodeRef(path);
     }
-    
+
     private static Node createNode(String string) {
         NodeBuilder ret = new NodeBuilder();
         NodeId id = new NodeId(string);
index befe70376468eef0d9687817268c312638698506..9c24ca08303b4f524198808b174ce0af67469bc6 100644 (file)
@@ -192,8 +192,7 @@ public class RoutedServiceTest extends AbstractTest {
      */
     private static NodeRef createNodeRef(String string) {
         NodeKey key = new NodeKey(new NodeId(string));
-        InstanceIdentifier<Node> path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key)
-                .toInstance();
+        InstanceIdentifier<Node> path = InstanceIdentifier.builder(Nodes.class).child(Node.class, key).build();
 
         return new NodeRef(path);
     }
index 30a607d95b6a025619e836dd26097707704ecae3..ebffbcc811747307f2a3a67a7b83cb403d5757c2 100644 (file)
@@ -10,41 +10,40 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import java.util.Map;
 import java.util.Set;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface DataChange<P/* extends Path<P> */, D> {
+public interface DataChange<P extends Path<P>, D> {
 
     /**
      * Returns a map of paths and newly created objects
-     * 
+     *
      * @return map of paths and newly created objects
      */
     Map<P, D> getCreatedOperationalData();
 
     /**
      * Returns a map of paths and newly created objects
-     * 
+     *
      * @return map of paths and newly created objects
      */
     Map<P, D> getCreatedConfigurationData();
 
     /**
      * Returns a map of paths and respective updated objects after update.
-     * 
+     *
      * Original state of the object is in
      * {@link #getOriginalOperationalData()}
-     * 
+     *
      * @return map of paths and newly created objects
      */
     Map<P, D> getUpdatedOperationalData();
 
     /**
      * Returns a map of paths and respective updated objects after update.
-     * 
+     *
      * Original state of the object is in
      * {@link #getOriginalConfigurationData()}
-     * 
+     *
      * @return map of paths and newly created objects
      */
     Map<P, D> getUpdatedConfigurationData();
@@ -53,34 +52,34 @@ public interface DataChange<P/* extends Path<P> */, D> {
 
     /**
      * Returns a set of paths of removed objects.
-     * 
+     *
      * Original state of the object is in
      * {@link #getOriginalConfigurationData()}
-     * 
+     *
      * @return map of paths and newly created objects
      */
     Set<P> getRemovedConfigurationData();
 
     /**
      * Returns a set of paths of removed objects.
-     * 
+     *
      * Original state of the object is in
      * {@link #getOriginalOperationalData()}
-     * 
+     *
      * @return map of paths and newly created objects
      */
     Set<P> getRemovedOperationalData();
 
     /**
      * Return a map of paths and original state of updated and removed objectd.
-     * 
+     *
      * @return map of paths and original state of updated and removed objectd.
      */
     Map<P, D> getOriginalConfigurationData();
 
     /**
      * Return a map of paths and original state of updated and removed objectd.
-     * 
+     *
      * @return map of paths and original state of updated and removed objectd.
      */
     Map<P, D> getOriginalOperationalData();
index d62e176e62d1beeb22c934f7c82aa3a713909b91..15d1daa1bbe882393f863e892728490c212f5e71 100644 (file)
@@ -8,36 +8,37 @@
 package org.opendaylight.controller.md.sal.common.api.data;
 
 import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface DataChangeEvent<P,D> extends DataChange<P, D>, Immutable {
+public interface DataChangeEvent<P extends Path<P>,D> extends DataChange<P, D>, Immutable {
 
     /**
      * Returns a orignal subtree of data, which starts at the path
      * where listener was registered.
-     * 
+     *
      */
     D getOriginalConfigurationSubtree();
 
     /**
      * Returns a new subtree of data, which starts at the path
      * where listener was registered.
-     * 
+     *
      */
     D getOriginalOperationalSubtree();
-    
-    
-    
+
+
+
     /**
      * Returns a updated subtree of data, which starts at the path
      * where listener was registered.
-     * 
+     *
      */
     D getUpdatedConfigurationSubtree();
 
     /**
      * Returns a udpated subtree of data, which starts at the path
      * where listener was registered.
-     * 
+     *
      */
     D getUpdatedOperationalSubtree();
 }
index 8b87139c7f97e78d09be1fad70fd192af52e48b2..8787a3fe8d82de85bc7e064177501e017d041cca 100644 (file)
@@ -9,10 +9,9 @@ package org.opendaylight.controller.md.sal.common.api.data;
 
 import java.util.EventListener;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface DataChangeListener<P/* extends Path<P> */,D> extends EventListener {
+public interface DataChangeListener<P extends Path<P>, D> extends EventListener {
 
     void onDataChanged(DataChangeEvent<P, D> change);
 }
index 66645e5538d6efb0935231100c0a72890ed09a70..0c4c6d179ff84faf955fb6989d8ca900cbb8722e 100644 (file)
@@ -7,12 +7,10 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
-
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Path;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
-public interface DataChangePublisher<P/* extends Path<P> */,D, L extends DataChangeListener<P,D>> {
+public interface DataChangePublisher<P extends Path<P>, D, L extends DataChangeListener<P,D>> {
 
     ListenerRegistration<L> registerDataChangeListener(P path, L listener);
 
index 90de13d15e8229238f36c5ec59b1180babcff1ae..939ff9513513ff1de802746facfdd09844952b76 100644 (file)
@@ -8,30 +8,29 @@
 package org.opendaylight.controller.md.sal.common.api.data;
 
 import org.opendaylight.controller.sal.common.DataStoreIdentifier;
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 /**
  * Two phase commit handler (cohort) of the two-phase commit protocol of data.
- * 
+ *
  * <p>
  * The provider should expose the implementation of DataCommitHandler if it's
  * functionality depends on any subset of data stored in data repositories, in
  * order to participate in {@link DataBrokerService#commit(DataStoreIdentifier)
  * operation.
- * 
+ *
  * <p>
  * Operations of two-phase commit handlers should not change data in data store,
  * this is responsibility of the coordinator (broker or some component of the
  * broker).
- * 
+ *
  * The commit handlers are responsible for changing the internal state of the
  * provider to reflect the commited changes in data.
- * 
+ *
  * <h3>Two-phase commit</h3>
- * 
+ *
  * <h4>Commit Request Phase</h4>
- * 
+ *
  * <ol>
  * <li> <code>Consumer</code> edits data by invocation of
  * <code>DataBrokerService.editCandidateData(DataStoreIdentifier, DataRoot)</code>
@@ -51,9 +50,9 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
  * </ol>
  * <li><code>Broker</code> starts a commit finish phase
  * </ol>
- * 
+ *
  * <h4>Commit Finish Phase</h4>
- * 
+ *
  * <ol>
  * <li>For each <code>CommitTransaction</code> from Commit Request phase
  * <ol>
@@ -69,7 +68,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
  * <li>If error occured, the broker starts a commit rollback phase.
  * </ul>
  * </ol>
- * 
+ *
  * <h4>Commit Rollback Phase</h4>
  * <li>For each <code>DataCommitTransaction</code> from Commit Request phase
  * <ol>
@@ -78,43 +77,43 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
  * <li>The provider rollbacks a commit and returns an {@link RpcResult} of
  * rollback. </ol>
  * <li>Broker returns a error result to the consumer.
- * 
+ *
  * @param <P> Class representing a path
  * @param <D> Superclass from which all data objects are derived from.
  */
-public interface DataCommitHandler<P/* extends Path<P> */,D> {
+public interface DataCommitHandler<P extends Path<P>, D> {
+
 
-    
     DataCommitTransaction<P, D> requestCommit(DataModification<P,D> modification);
 
-    public interface DataCommitTransaction<P/* extends Path<P> */,D> {
+    public interface DataCommitTransaction<P extends Path<P>, D> {
 
         DataModification<P,D> getModification();
 
         /**
-         * 
+         *
          * Finishes a commit.
-         * 
+         *
          * This callback is invoked by commit coordinator to finish commit action.
-         * 
+         *
          * The implementation is required to finish transaction or return unsuccessful
          * rpc result if something went wrong.
-         * 
+         *
          * The provider (commit handler) should apply all changes to its state
          * which are a result of data change-
-         * 
+         *
          * @return
          */
         RpcResult<Void> finish() throws IllegalStateException;
 
         /**
          * Rollbacks a commit.
-         * 
+         *
          * This callback is invoked by commit coordinator to finish commit action.
-         * 
+         *
          * The provider (commit handler) should rollback all changes to its state
          * which were a result of previous request commit.
-         * 
+         *
          * @return
          * @throws IllegalStateException
          *             If the method is invoked after {@link #finish()}
index 00db6064aa3bb54fa2a1f123be45d67289e63c52..f6662c388aa36e0092cf0ec8b5f262dcf981d163 100644 (file)
@@ -10,11 +10,10 @@ package org.opendaylight.controller.md.sal.common.api.data;
 import java.util.concurrent.Future;
 
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 
-//FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-//import org.opendaylight.yangtools.concepts.Path;
-public interface DataModification<P/* extends Path<P> */, D> extends DataChange<P, D>, DataReader<P, D> {
+public interface DataModification<P extends Path<P>, D> extends DataChange<P, D>, DataReader<P, D> {
 
     /**
      * Returns transaction identifier
index 64d90f6fd5e8ae0ceb471c051287eb8fb298bdbc..34f6fe970dd2e0105e6a21d32ca7049815ea87e7 100644 (file)
@@ -7,10 +7,9 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface DataModificationTransactionFactory<P/* extends Path<P> */,D> {
+public interface DataModificationTransactionFactory<P extends Path<P> ,D> {
 
     DataModification<P, D> beginTransaction();
 }
index 6c108bf5e49c1c6cb7fc3717e5f77649558e830f..dae9a1144b966a2e3c5e61884c1281e09a6229f3 100644 (file)
@@ -7,9 +7,8 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface DataProvider<P/* extends Path<P> */,D> extends DataReader<P, D> {
+public interface DataProvider<P extends Path<P>, D> extends DataReader<P, D> {
 
 }
index 7240a506bea5c0612f1c75424b85d544a09f9ec6..14731d688c964adaf264d8909a4c3e90ccc4484e 100644 (file)
@@ -7,23 +7,22 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
 /**
  * Reader for reading YANG subtrees based on their path.
- * 
+ *
  * Reader is requested to return object at specified path and all it's subnodes
  * known to the reader or null if node is not found in this reader.
  *
  * @param <P> Path Type
  * @param <D> Data Type
  */
-public interface DataReader<P/* extends Path<P> */,D> {
+public interface DataReader<P extends Path<P> ,D> {
 
     /**
      * Reads data from Operational data store located at provided path
-     * 
+     *
      * @param path Path to data
      * @return
      */
index ed5499870a9402cb0a8ef6f625a7528d14f8797a..3520ba1819b42fb0ce37ae3548631cd80753334b 100644 (file)
@@ -7,7 +7,9 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
-public interface DataStore<P, D> extends //
+import org.opendaylight.yangtools.concepts.Path;
+
+public interface DataStore<P extends Path<P>, D> extends //
         DataReader<P, D>, //
         DataModificationTransactionFactory<P, D> {
 
index ff3aa2e325af0146d5cd878ea9aed88c350d4a6c..d542935dd6dbf0fdb91ce72b273d6bc9c87b2668 100644 (file)
@@ -7,12 +7,14 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
+import org.opendaylight.yangtools.concepts.Path;
+
 /**
  * A chain of transactions. Transactions in a chain need to be committed in sequence and each
  * transaction should see the effects of previous transactions as if they happened. A chain
  * makes no guarantees of atomicity, in fact transactions are committed as soon as possible.
  */
-public interface TransactionChain<P/* extends Path<P> */, D> extends AutoCloseable {
+public interface TransactionChain<P extends Path<P>, D> extends AutoCloseable {
     /**
      * Create a new transaction which will continue the chain. The previous transaction
      * has to be either COMMITTED or CANCELLED.
index 4e7e12e0a15e3c5060a59eff76c35d9896ff00eb..94d21f5fd6bb02736a360592dc6826a3c70e4ae4 100644 (file)
@@ -7,10 +7,12 @@
  */
 package org.opendaylight.controller.md.sal.common.api.data;
 
+import org.opendaylight.yangtools.concepts.Path;
+
 /**
  * Interface for creating transaction chains.
  */
-public interface TransactionChainFactory<P/* extends Path<P> */, D> {
+public interface TransactionChainFactory<P extends Path<P>, D> {
     /**
      * Create a new transaction chain. The chain will be initialized to read
      * from its backing datastore, with no outstanding transaction. Listener
index 1139d03357999f5d71d3b0326ab1c621a14da984..f99c13ecf53499ab6770d9107025cb7f91828b8a 100644 (file)
@@ -8,10 +8,9 @@
 package org.opendaylight.controller.md.sal.common.api.routing;
 
 import org.opendaylight.yangtools.concepts.Mutable;
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface MutableRoutingTable<C,P/* extends Path<P> */,T> extends RoutingTable<C,P,T>, Mutable {
+public interface MutableRoutingTable<C, P extends Path<P>, T> extends RoutingTable<C,P,T>, Mutable {
     
     void setDefaultRoute(T target);
     void updateRoute(P path,T target);
index 37ec2f6f1f90d4bae0e681d40e5674c1076ec504..5200c90561ecdb464060e0ba112a687de065c9ec 100644 (file)
@@ -7,11 +7,10 @@
  */
 package org.opendaylight.controller.md.sal.common.api.routing;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.concepts.Registration;
 
-public interface RoutedRegistration<C,P/* extends Path<P> */,S> extends Registration<S> {
+public interface RoutedRegistration<C, P extends Path<P>, S> extends Registration<S> {
 
     void registerPath(C context, P path);
     void unregisterPath(C context, P path);
index 211cf188795a1feee2d2abe11a028ff0b6a0786f..4402f69a5f73896f8f905c190a7743f3f0b28e80 100644 (file)
@@ -9,10 +9,9 @@ package org.opendaylight.controller.md.sal.common.api.routing;
 
 import java.util.Map;
 
-// FIXME: After 0.6 Release of YANGTools refactor to use Path marker interface for arguments.
-// import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.concepts.Path;
 
-public interface RoutingTable<C,P/* extends Path<P> */,T> {
+public interface RoutingTable<C, P extends Path<P>, T> {
 
     C getIdentifier();
     
index 274f084f01d420cf291723d96949382da5c0cd7d..9001aaa4dede9ded757c68b737446ea11a09db79 100644 (file)
@@ -16,28 +16,28 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 
 public class RoutingUtils {
-    
+
     public static <C,P> RouteChange<C,P> removalChange(C context,P path) {
         final ImmutableMap<C, Set<P>> announcements = ImmutableMap.<C,Set<P>>of();
         final ImmutableMap<C, Set<P>> removals = ImmutableMap.<C,Set<P>>of(context, ImmutableSet.of(path));
         return new RouteChangeImpl<C,P>(announcements, removals);
     }
-    
+
     public static <C,P> RouteChange<C,P> announcementChange(C context,P path) {
         final ImmutableMap<C, Set<P>> announcements = ImmutableMap.<C,Set<P>>of(context, ImmutableSet.of(path));
         final ImmutableMap<C, Set<P>> removals = ImmutableMap.<C,Set<P>>of();
         return new RouteChangeImpl<C,P>(announcements, removals);
     }
-    
-    
+
+
     public static <C,P> RouteChange<C,P> change(Map<C, Set<P>> announcements,
             Map<C, Set<P>> removals) {
         final ImmutableMap<C, Set<P>> immutableAnnouncements = ImmutableMap.<C,Set<P>>copyOf(announcements);
         final ImmutableMap<C, Set<P>> immutableRemovals = ImmutableMap.<C,Set<P>>copyOf(removals);
         return new RouteChangeImpl<C,P>(immutableAnnouncements, immutableRemovals);
     }
-    
-    
+
+
     private static class RouteChangeImpl<C,P> implements RouteChange<C, P> {
         private final Map<C, Set<P>> removal;
         private final Map<C, Set<P>> announcement;
@@ -52,7 +52,7 @@ public class RoutingUtils {
         public Map<C, Set<P>> getAnnouncements() {
             return announcement;
         }
-        
+
         @Override
         public Map<C, Set<P>> getRemovals() {
             return removal;
@@ -78,7 +78,7 @@ public class RoutingUtils {
             if (getClass() != obj.getClass()) {
                 return false;
             }
-            RouteChangeImpl other = (RouteChangeImpl) obj;
+            RouteChangeImpl<?, ?> other = (RouteChangeImpl<?, ?>) obj;
             if (announcement == null) {
                 if (other.announcement != null)
                     return false;
@@ -95,5 +95,5 @@ public class RoutingUtils {
     }
 
 
-    
+
 }
index bfffb594cb6fd73d9654d402be5a66aa076eaa30..ed186dcf314fd0ea075ad81bc3b3e19fb942a48b 100644 (file)
@@ -408,7 +408,7 @@ public abstract class AbstractDataBroker<P extends Path<P>, D extends Object, DC
         Preconditions.checkNotNull(transaction);
         transaction.changeStatus(TransactionStatus.SUBMITED);
         final TwoPhaseCommit<P, D, DCL> task = new TwoPhaseCommit<P, D, DCL>(transaction, this);
-        ;
+
         this.getSubmittedTransactionsCount().getAndIncrement();
         return this.getExecutor().submit(task);
     }
index e99fc0f24c16d424524c2d1642d2109a5193c173..33de1d83dae3cf40ff875625b979a3182783cf20 100644 (file)
@@ -61,6 +61,17 @@ public class TwoPhaseCommit<P extends Path<P>, D extends Object, DCL extends Dat
 
         log.trace("Transaction: {} Affected Subtrees:", transactionId, changedPaths);
 
+        // The transaction has no effects, let's just shortcut it
+        if (changedPaths.isEmpty()) {
+            dataBroker.getFinishedTransactionsCount().getAndIncrement();
+            transaction.changeStatus(TransactionStatus.COMMITED);
+
+            log.trace("Transaction: {} Finished successfully (no effects).", transactionId);
+
+            return Rpcs.<TransactionStatus> getRpcResult(true, TransactionStatus.COMMITED,
+                    Collections.<RpcError> emptySet());
+        }
+
         final ImmutableList.Builder<ListenerStateCapture<P, D, DCL>> listenersBuilder = ImmutableList.builder();
         listenersBuilder.addAll(dataBroker.affectedListeners(changedPaths));
         filterProbablyAffectedListeners(dataBroker.probablyAffectedListeners(changedPaths),listenersBuilder);
@@ -211,14 +222,12 @@ public class TwoPhaseCommit<P extends Path<P>, D extends Object, DCL extends Dat
             @Override
             public void run() {
                 for (final ListenerStateCapture<P, D, DCL> listenerSet : listeners) {
-                    {
-                        DataChangeEvent<P, D> changeEvent = listenerSet.createEvent(transaction);
-                        for (final DataChangeListenerRegistration<P, D, DCL> listener : listenerSet.getListeners()) {
-                            try {
-                                listener.getInstance().onDataChanged(changeEvent);
-                            } catch (Exception e) {
-                                log.error("Unhandled exception when invoking listener {}", listener);
-                            }
+                    DataChangeEvent<P, D> changeEvent = listenerSet.createEvent(transaction);
+                    for (final DataChangeListenerRegistration<P, D, DCL> listener : listenerSet.getListeners()) {
+                        try {
+                            listener.getInstance().onDataChanged(changeEvent);
+                        } catch (Exception e) {
+                            log.error("Unhandled exception when invoking listener {}", listener, e);
                         }
                     }
                 }
index 8f734d7d4c3934a22c1ca91af146534a0a5fac5b..3bbdab2c0722d656aba74035186faa4bc0d843aa 100644 (file)
@@ -8,32 +8,27 @@
 package org.opendaylight.controller.sal.dom.broker;
 
 import java.util.Collections
-import java.util.HashMap
 import java.util.HashSet
-import java.util.Map
 import java.util.Set
 import java.util.concurrent.Callable
 import java.util.concurrent.ExecutorService
 import java.util.concurrent.Executors
 import java.util.concurrent.Future
+import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener
 import org.opendaylight.controller.sal.core.api.Broker
-import org.opendaylight.controller.sal.core.api.BrokerService
 import org.opendaylight.controller.sal.core.api.Consumer
 import org.opendaylight.controller.sal.core.api.Provider
-import org.opendaylight.controller.sal.core.spi.BrokerModule
+import org.opendaylight.controller.sal.core.api.RpcImplementation
+import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
+import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
+import org.opendaylight.controller.sal.core.api.RpcRoutingContext
+import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter
 import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.common.RpcResult
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import org.osgi.framework.BundleContext
 import org.slf4j.LoggerFactory
-import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter
-import org.opendaylight.yangtools.concepts.ListenerRegistration
-import org.opendaylight.controller.sal.core.api.RpcRegistrationListener
-import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry
-import org.opendaylight.controller.sal.core.api.RpcImplementation
-import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener
-import org.opendaylight.controller.sal.core.api.RpcRoutingContext
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 
 public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
     private static val log = LoggerFactory.getLogger(BrokerImpl);
index cc44613e448ad520063120f31c481e987f032ee5..95d0018b2117c8c970a61c7902bbc44f2b3d8396 100644 (file)
@@ -7,29 +7,26 @@
  */
 package org.opendaylight.controller.sal.dom.broker.impl
 
-import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.controller.md.sal.common.api.data.DataReader
-import org.opendaylight.yangtools.yang.common.QName
 import java.net.URI
-import java.util.List
-import org.opendaylight.yangtools.yang.data.api.Node
 import java.util.ArrayList
-import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
-import java.util.Map
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
-import org.opendaylight.yangtools.yang.data.api.SimpleNode
+import java.util.Collection
 import java.util.Collections
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
 import java.util.HashMap
-import static com.google.common.base.Preconditions.*;
-import java.util.Collection
-import java.util.Set
+import java.util.Map
 import java.util.Map.Entry
-import org.slf4j.LoggerFactory
+import java.util.Set
+import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.api.SimpleNode
 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.slf4j.LoggerFactory
+
+import static com.google.common.base.Preconditions.*
 
 class DataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier, CompositeNode> {
     private static val LOG = LoggerFactory.getLogger(DataReaderRouter);
@@ -42,7 +39,6 @@ class DataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier, Compos
         var name = pathArgument?.nodeType;
         val nodes = new ArrayList<Node<?>>();
         val keyNodes = new HashMap<QName, SimpleNode<?>>();
-        val iterator = data.iterator;
         for(dataBit : data) {
             try {
                 if(pathArgument != null && dataBit != null) {
index 9600881e505abdeb8c4d5022d4f1c91c94907e80..12835ccf0a235ec2a312e32313818525425c6f36 100644 (file)
@@ -18,9 +18,11 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
 import org.opendaylight.controller.sal.core.api.data.DataStore
 import java.util.HashSet
+import org.slf4j.LoggerFactory
+import org.slf4j.Logger
 
-class HashMapDataStore implements DataStore, AutoCloseable {
-
+final class HashMapDataStore implements DataStore, AutoCloseable {
+    private val Logger LOG = LoggerFactory.getLogger(HashMapDataStore)
 
     val Map<InstanceIdentifier, CompositeNode> configuration = new ConcurrentHashMap();
     val Map<InstanceIdentifier, CompositeNode> operational = new ConcurrentHashMap();
@@ -28,12 +30,11 @@ class HashMapDataStore implements DataStore, AutoCloseable {
     
     
     override containsConfigurationPath(InstanceIdentifier path) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
-        
+        return configuration.containsKey(path)
     }
     
     override containsOperationalPath(InstanceIdentifier path) {
-        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+        return operational.containsKey(path)
     }
     
     override getStoredConfigurationPaths() {
@@ -45,10 +46,12 @@ class HashMapDataStore implements DataStore, AutoCloseable {
     }
 
     override readConfigurationData(InstanceIdentifier path) {
+        LOG.trace("Reading configuration path {}", path)
         configuration.get(path);
     }
 
     override readOperationalData(InstanceIdentifier path) {
+        LOG.trace("Reading operational path {}", path)
         operational.get(path);
     }
 
@@ -65,11 +68,21 @@ class HashMapDataStore implements DataStore, AutoCloseable {
     def RpcResult<Void> finish(HashMapDataStoreTransaction transaction) {
         val modification = transaction.modification;
         for (removal : modification.removedConfigurationData) {
+            LOG.trace("Removing configuration path {}", removal)
             remove(configuration,removal);
         }
         for (removal : modification.removedOperationalData) {
+            LOG.trace("Removing operational path {}", removal)
             remove(operational,removal);
         }
+        if (LOG.isTraceEnabled()) {
+            for (a : modification.updatedConfigurationData.keySet) {
+                LOG.trace("Adding configuration path {}", a)
+            }
+            for (a : modification.updatedOperationalData.keySet) {
+                LOG.trace("Adding operational path {}", a)
+            }
+        }
         configuration.putAll(modification.updatedConfigurationData);
         operational.putAll(modification.updatedOperationalData);
 
@@ -84,6 +97,7 @@ class HashMapDataStore implements DataStore, AutoCloseable {
             }
         }
         for(pathToRemove : affected) {
+            LOG.trace("Removed path {}", pathToRemove)
             map.remove(pathToRemove);
         }
         
index b02a37c3003e594b728554f6c5a0124961872ce3..602afd7c0cf01d4bccc810e0b0dc2d1e5d9a0fd4 100644 (file)
@@ -150,7 +150,7 @@ public class SchemaAwareDataStoreAdapter extends AbstractLockableDelegator<DataS
 
     protected CompositeNode mergeData(InstanceIdentifier path, CompositeNode stored, CompositeNode modified,
             boolean config) {
-        long startTime = System.nanoTime();
+        // long startTime = System.nanoTime();
         try {
             DataSchemaNode node = schemaNodeFor(path);
             return YangDataOperations.merge(node, stored, modified, config);
index 1e89281df498b34d82bea1f3e6b08574c0941a06..d80e405b4e05dc7df3bd9ed5c9de3610644e7b18 100644 (file)
@@ -38,12 +38,6 @@ class YangDataOperations {
         throw new IllegalArgumentException("Supplied node is not data node container.");
     }
 
-    private def static checkConfigurational(DataSchemaNode node, boolean config) {
-        if (config) {
-            checkArgument(node.configuration, "Supplied composite node is not configurational.");
-        }
-    }
-
     private static dispatch def Iterable<? extends Node<?>> mergeMultiple(LeafSchemaNode node, List<Node<?>> original,
         List<Node<?>> modified, boolean configurational) {
         checkArgument(original.size === 1);
index f409ecdade553e91065e85d9fc2024150e21eba5..e5a24fcf63914f35492f50e7186ff2ed844761e4 100644 (file)
@@ -16,30 +16,23 @@ import java.util.Collections
 import java.util.List
 import java.util.Set
 import java.util.concurrent.atomic.AtomicInteger
+import org.opendaylight.controller.netconf.api.NetconfMessage
 import org.opendaylight.controller.sal.common.util.Rpcs
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.common.RpcResult
 import org.opendaylight.yangtools.yang.data.api.CompositeNode
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode
-import java.util.Collections
-import java.util.List
-import java.util.Set
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
 import org.opendaylight.yangtools.yang.data.api.Node
 import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
 import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
 import org.opendaylight.yangtools.yang.model.api.SchemaContext
 import org.w3c.dom.Document
 import org.w3c.dom.Element
-import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
-import org.opendaylight.controller.netconf.api.NetconfMessage
-import org.opendaylight.yangtools.yang.common.RpcResult
 
 class NetconfMapping {
 
index cef5df9e579fb5c8142ca186364044c591421a91..f6c39bf8c5a3ac70d75b8490f01aa2c5dfe73bc7 100644 (file)
@@ -16,6 +16,7 @@ import javax.ws.rs.PUT;
 import javax.ws.rs.Path;
 import javax.ws.rs.PathParam;
 import javax.ws.rs.Produces;
+import javax.ws.rs.Encoded;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
@@ -106,25 +107,25 @@ public interface RestconfService {
     @Path("/config/{identifier:.+}")
     @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public StructuredData readConfigurationData(@PathParam("identifier") String identifier);
+    public StructuredData readConfigurationData(@Encoded @PathParam("identifier") String identifier);
 
     @GET
     @Path("/operational/{identifier:.+}")
     @Produces({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public StructuredData readOperationalData(@PathParam("identifier") String identifier);
+    public StructuredData readOperationalData(@Encoded @PathParam("identifier") String identifier);
 
     @PUT
     @Path("/config/{identifier:.+}")
     @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public Response updateConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+    public Response updateConfigurationData(@Encoded @PathParam("identifier") String identifier, CompositeNode payload);
 
     @POST
     @Path("/config/{identifier:.+}")
     @Consumes({Draft02.MediaTypes.DATA+JSON,Draft02.MediaTypes.DATA+XML, 
                MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_XML})
-    public Response createConfigurationData(@PathParam("identifier") String identifier, CompositeNode payload);
+    public Response createConfigurationData(@Encoded @PathParam("identifier") String identifier, CompositeNode payload);
 
     @POST
     @Path("/config")
@@ -134,10 +135,10 @@ public interface RestconfService {
 
     @DELETE
     @Path("/config/{identifier:.+}")
-    public Response deleteConfigurationData(@PathParam("identifier") String identifier);
+    public Response deleteConfigurationData(@Encoded @PathParam("identifier") String identifier);
 
     @GET
     @Path("/streams/stream/{identifier:.+}")
-    public Response subscribeToStream(@PathParam("identifier") String identifier, @Context UriInfo uriInfo);
+    public Response subscribeToStream(@Encoded @PathParam("identifier") String identifier, @Context UriInfo uriInfo);
 
 }
index c2b82eae632290cc60d48df245d70fa1c583e8b8..482dcf8e8b37e5427c2470122bae9a15e3189a84 100644 (file)
@@ -57,6 +57,8 @@ class ControllerContext implements SchemaServiceListener {
     val static MOUNT_MODULE = "yang-ext"
     val static MOUNT_NODE = "mount"
     public val static MOUNT = "yang-ext:mount"
+    val static URI_ENCODING_CHAR_SET = "ISO-8859-1"
+    val static URI_SLASH_PLACEHOLDER = "%2F";
 
     @Property
     var SchemaContext globalSchema;
@@ -98,7 +100,8 @@ class ControllerContext implements SchemaServiceListener {
 
     private def InstanceIdWithSchemaNode toIdentifier(String restconfInstance, boolean toMountPointIdentifier) {
         checkPreconditions
-        val pathArgs = Lists.newArrayList(Splitter.on("/").split(restconfInstance))
+        val encodedPathArgs = Lists.newArrayList(Splitter.on("/").split(restconfInstance))
+        val pathArgs = urlPathArgsDecode(encodedPathArgs)
         pathArgs.omitFirstAndLastEmptyString
         if (pathArgs.empty) {
             return null;
@@ -353,7 +356,8 @@ class ControllerContext implements SchemaServiceListener {
 
     private def toUriString(Object object) {
         if(object === null) return "";
-        return URLEncoder.encode(object.toString)
+//        return object.toString.replace("/",URI_SLASH_PLACEHOLDER)
+        return URLEncoder.encode(object.toString,URI_ENCODING_CHAR_SET)        
     }
     
     private def InstanceIdWithSchemaNode collectPathArguments(InstanceIdentifierBuilder builder, List<String> strings,
@@ -599,11 +603,23 @@ class ControllerContext implements SchemaServiceListener {
     }
 
     override onGlobalContextUpdated(SchemaContext context) {
-        this.globalSchema = context;
-        for (operation : context.operations) {
-            val qname = operation.QName;
-            qnameToRpc.put(qname, operation);
+        if (context !== null) {
+            qnameToRpc.clear
+            this.globalSchema = context;
+            for (operation : context.operations) {
+                val qname = operation.QName;
+                qnameToRpc.put(qname, operation);
+            }
         }
     }
 
+
+    def urlPathArgsDecode(List<String> strings) {
+        val List<String> decodedPathArgs = new ArrayList();
+        for (pathArg : strings) {
+            decodedPathArgs.add(URLDecoder.decode(pathArg, URI_ENCODING_CHAR_SET))
+        }
+        return decodedPathArgs
+    }    
+
 }
index e1d7e6a62447d3b1145c4bb672267ec77e4fc762..5a2c964b8b15a8eb46c6fea2cc46e77c350cdcdf 100644 (file)
@@ -15,7 +15,6 @@ import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.JSON;
 import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.XML;
-import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.createUri;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -24,6 +23,7 @@ import java.io.UnsupportedEncodingException;
 import javax.ws.rs.client.Entity;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
 
 import org.glassfish.jersey.server.ResourceConfig;
 import org.glassfish.jersey.test.JerseyTest;
@@ -70,7 +70,7 @@ public class MediaTypesTest extends JerseyTest {
   public void testPostOperationsWithInputDataMediaTypes() throws UnsupportedEncodingException {
       String uriPrefix = "/operations/";
       String uriPath = "ietf-interfaces:interfaces";
-      String uri = createUri(uriPrefix, uriPath);
+      String uri = uriPrefix + uriPath;
       when(restconfService.invokeRpc(eq(uriPath), any(CompositeNode.class))).thenReturn(null);
       post(uri, Draft02.MediaTypes.OPERATION+JSON, Draft02.MediaTypes.OPERATION+JSON, jsonData);
       verify(restconfService, times(1)).invokeRpc(eq(uriPath), any(CompositeNode.class));
@@ -96,7 +96,7 @@ public class MediaTypesTest extends JerseyTest {
     public void testGetConfigMediaTypes() throws UnsupportedEncodingException {
         String uriPrefix = "/config/";
         String uriPath = "ietf-interfaces:interfaces";
-        String uri = createUri(uriPrefix, uriPath);
+        String uri = uriPrefix + uriPath;
         when(restconfService.readConfigurationData(uriPath)).thenReturn(null);
         get(uri, Draft02.MediaTypes.DATA+JSON);
         verify(restconfService, times(1)).readConfigurationData(uriPath);
@@ -118,7 +118,7 @@ public class MediaTypesTest extends JerseyTest {
     public void testGetOperationalMediaTypes() throws UnsupportedEncodingException {
         String uriPrefix = "/operational/";
         String uriPath = "ietf-interfaces:interfaces";
-        String uri = createUri(uriPrefix, uriPath);
+        String uri = uriPrefix + uriPath;
         when(restconfService.readOperationalData(uriPath)).thenReturn(null);
         get(uri, Draft02.MediaTypes.DATA+JSON);
         verify(restconfService, times(1)).readOperationalData(uriPath);
@@ -140,7 +140,7 @@ public class MediaTypesTest extends JerseyTest {
     public void testPutConfigMediaTypes() throws UnsupportedEncodingException {
         String uriPrefix = "/config/";
         String uriPath = "ietf-interfaces:interfaces";
-        String uri = createUri(uriPrefix, uriPath);
+        String uri = uriPrefix + uriPath;
         when(restconfService.updateConfigurationData(eq(uriPath), any(CompositeNode.class))).thenReturn(null);
         put(uri, null, Draft02.MediaTypes.DATA+JSON, jsonData);
         verify(restconfService, times(1)).updateConfigurationData(eq(uriPath), any(CompositeNode.class));
@@ -160,7 +160,7 @@ public class MediaTypesTest extends JerseyTest {
     public void testPostConfigWithPathMediaTypes() throws UnsupportedEncodingException {
         String uriPrefix = "/config/";
         String uriPath = "ietf-interfaces:interfaces";
-        String uri = createUri(uriPrefix, uriPath);
+        String uri = uriPrefix + uriPath;
         when(restconfService.createConfigurationData(eq(uriPath), any(CompositeNode.class))).thenReturn(null);
         post(uri, null, Draft02.MediaTypes.DATA+JSON, jsonData);
         verify(restconfService, times(1)).createConfigurationData(eq(uriPath), any(CompositeNode.class));
@@ -179,7 +179,7 @@ public class MediaTypesTest extends JerseyTest {
     @Test
     public void testPostConfigMediaTypes() throws UnsupportedEncodingException {
         String uriPrefix = "/config/";
-        String uri = createUri(uriPrefix, "");
+        String uri = uriPrefix;
         when(restconfService.createConfigurationData(any(CompositeNode.class))).thenReturn(null);
         post(uri, null, Draft02.MediaTypes.DATA+JSON, jsonData);
         verify(restconfService, times(1)).createConfigurationData(any(CompositeNode.class));
@@ -199,7 +199,7 @@ public class MediaTypesTest extends JerseyTest {
     public void testDeleteConfigMediaTypes() throws UnsupportedEncodingException {
         String uriPrefix = "/config/";
         String uriPath = "ietf-interfaces:interfaces";
-        String uri = createUri(uriPrefix, uriPath);
+        String uri = uriPrefix + uriPath;
         when(restconfService.deleteConfigurationData(eq(uriPath))).thenReturn(null);
         target(uri).request("fooMediaType").delete();
         verify(restconfService, times(1)).deleteConfigurationData(uriPath);
index 73b4b3a2af4d8092b2076d7b79c6c78aabc004f6..408b14acfe8e67d93fb45c31a55fd0700f9b23a5 100644 (file)
@@ -12,7 +12,6 @@ import static org.junit.Assert.assertNotNull;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.createUri;
 
 import java.io.FileNotFoundException;
 import java.io.UnsupportedEncodingException;
@@ -72,7 +71,7 @@ public class RestDeleteOperationTest extends JerseyTest {
 
     @Test
     public void deleteConfigStatusCodes() throws UnsupportedEncodingException {
-        String uri = createUri("/config/", "test-interface:interfaces");
+        String uri = "/config/test-interface:interfaces";
         Future<RpcResult<TransactionStatus>> dummyFuture = createFuture(TransactionStatus.COMMITED);
         when(brokerFacade.commitConfigurationDataDelete(any(InstanceIdentifier.class))).thenReturn(dummyFuture);
         Response response = target(uri).request(MediaType.APPLICATION_XML).delete();
index 1e01020e78925f6b8b33606da8f43967a584ff12..6f507f96e27faf82550e4bc92a842528b888c5c0 100644 (file)
@@ -12,7 +12,6 @@ import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.createUri;
 
 import java.io.FileNotFoundException;
 import java.io.UnsupportedEncodingException;
@@ -94,10 +93,10 @@ public class RestGetOperationTest extends JerseyTest {
     @Test
     public void getOperationalStatusCodes() throws UnsupportedEncodingException {
         mockReadOperationalDataMethod();
-        String uri = createUri("/operational/", "ietf-interfaces:interfaces/interface/eth0");
+        String uri = "/operational/ietf-interfaces:interfaces/interface/eth0";
         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
 
-        uri = createUri("/operational/", "wrong-module:interfaces/interface/eth0");
+        uri = "/operational/wrong-module:interfaces/interface/eth0";
         assertEquals(400, get(uri, MediaType.APPLICATION_XML));
     }
 
@@ -107,10 +106,10 @@ public class RestGetOperationTest extends JerseyTest {
     @Test
     public void getConfigStatusCodes() throws UnsupportedEncodingException {
         mockReadConfigurationDataMethod();
-        String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
+        String uri = "/config/ietf-interfaces:interfaces/interface/eth0";
         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
 
-        uri = createUri("/config/", "wrong-module:interfaces/interface/eth0");
+        uri = "/config/wrong-module:interfaces/interface/eth0";
         assertEquals(400, get(uri, MediaType.APPLICATION_XML));
     }
 
@@ -129,11 +128,10 @@ public class RestGetOperationTest extends JerseyTest {
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
-        String uri = createUri("/config/",
-                "ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont/cont1");
+        String uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont/cont1";
         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
 
-        uri = createUri("/config/", "ietf-interfaces:interfaces/yang-ext:mount/test-module:cont/cont1");
+        uri = "/config/ietf-interfaces:interfaces/yang-ext:mount/test-module:cont/cont1";
         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
     }
 
@@ -149,7 +147,7 @@ public class RestGetOperationTest extends JerseyTest {
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
-        String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/0/yang-ext:mount/");
+        String uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/";
         assertEquals(200, get(uri, MediaType.APPLICATION_XML));
     }
 
@@ -158,7 +156,7 @@ public class RestGetOperationTest extends JerseyTest {
     public void getModulesTest() throws UnsupportedEncodingException, FileNotFoundException {
         ControllerContext.getInstance().setGlobalSchema(schemaContextModules);
 
-        String uri = createUri("/modules", "");
+        String uri = "/modules";
 
         Response response = target(uri).request("application/yang.api+json").get();
         validateModulesResponseJson(response);
@@ -172,7 +170,7 @@ public class RestGetOperationTest extends JerseyTest {
     public void getModuleTest() throws FileNotFoundException, UnsupportedEncodingException {
         ControllerContext.getInstance().setGlobalSchema(schemaContextModules);
 
-        String uri = createUri("/modules/module/module2/2014-01-02", "");
+        String uri = "/modules/module/module2/2014-01-02";
 
         Response response = target(uri).request("application/yang.api+xml").get();
         assertEquals(200, response.getStatus());
@@ -197,7 +195,7 @@ public class RestGetOperationTest extends JerseyTest {
     public void getOperationsTest() throws FileNotFoundException, UnsupportedEncodingException {
         ControllerContext.getInstance().setGlobalSchema(schemaContextModules);
 
-        String uri = createUri("/operations", "");
+        String uri = "/operations";
 
         Response response = target(uri).request("application/yang.api+xml").get();
         assertEquals(200, response.getStatus());
@@ -238,7 +236,7 @@ public class RestGetOperationTest extends JerseyTest {
 
         controllerContext.setMountService(mockMountService);
 
-        String uri = createUri("/operations/", "ietf-interfaces:interfaces/interface/0/yang-ext:mount/");
+        String uri = "/operations/ietf-interfaces:interfaces/interface/0/yang-ext:mount/";
 
         Response response = target(uri).request("application/yang.api+xml").get();
         assertEquals(200, response.getStatus());
@@ -329,7 +327,7 @@ public class RestGetOperationTest extends JerseyTest {
 
         controllerContext.setMountService(mockMountService);
 
-        String uri = createUri("/modules/", "ietf-interfaces:interfaces/interface/0/yang-ext:mount/");
+        String uri = "/modules/ietf-interfaces:interfaces/interface/0/yang-ext:mount/";
 
         Response response = target(uri).request("application/yang.api+json").get();
         assertEquals(200, response.getStatus());
@@ -371,8 +369,7 @@ public class RestGetOperationTest extends JerseyTest {
 
         controllerContext.setMountService(mockMountService);
 
-        String uri = createUri("/modules/module/",
-                "ietf-interfaces:interfaces/interface/0/yang-ext:mount/module1-behind-mount-point/2014-02-03");
+        String uri = "/modules/module/ietf-interfaces:interfaces/interface/0/yang-ext:mount/module1-behind-mount-point/2014-02-03";
 
         Response response = target(uri).request("application/yang.api+json").get();
         assertEquals(200, response.getStatus());
index a0e61a6fa12335239ba94efd386e841eda745d1c..7bf4782790506631de6652a2ef67126071d9ba74 100644 (file)
@@ -7,12 +7,6 @@
  */
 package org.opendaylight.controller.sal.restconf.impl.test;
 
-import java.io.UnsupportedEncodingException;
-import java.net.URI;
-import java.net.URLEncoder;
-
-import com.google.common.base.Charsets;
-
 public class RestOperationUtils {
 
     public static final String JSON = "+json";
@@ -20,8 +14,4 @@ public class RestOperationUtils {
 
     private RestOperationUtils() {
     }
-
-    public static String createUri(String prefix, String encodedPart) throws UnsupportedEncodingException {
-        return URI.create(prefix + URLEncoder.encode(encodedPart, Charsets.US_ASCII.name()).toString()).toASCIIString();
-    }
 }
index 050aa9ab240575c8a216f8e4678787c25fdb3003..11264e7f860dcdd9c2820f7a8a89b056add4fca8 100644 (file)
@@ -109,7 +109,7 @@ public class RestPostOperationTest extends JerseyTest {
     public void postOperationsStatusCodes() throws UnsupportedEncodingException {
         controllerContext.setSchemas(schemaContextTestModule);
         mockInvokeRpc(cnSnDataOutput, true);
-        String uri = createUri("/operations/", "test-module:rpc-test");
+        String uri = "/operations/test-module:rpc-test";
         assertEquals(200, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
 
         mockInvokeRpc(null, true);
@@ -118,7 +118,7 @@ public class RestPostOperationTest extends JerseyTest {
         mockInvokeRpc(null, false);
         assertEquals(500, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
 
-        uri = createUri("/operations/", "test-module:rpc-wrongtest");
+        uri = "/operations/test-module:rpc-wrongtest";
         assertEquals(404, post(uri, MediaType.APPLICATION_XML, xmlDataRpcInput));
     }
 
@@ -126,7 +126,7 @@ public class RestPostOperationTest extends JerseyTest {
     public void postConfigOnlyStatusCodes() throws UnsupportedEncodingException {
         controllerContext.setSchemas(schemaContextYangsIetf);
         mockCommitConfigurationDataPostMethod(TransactionStatus.COMMITED);
-        String uri = createUri("/config", "");
+        String uri = "/config";
         assertEquals(204, post(uri, MediaType.APPLICATION_XML, xmlDataAbsolutePath));
 
         mockCommitConfigurationDataPostMethod(null);
@@ -140,7 +140,7 @@ public class RestPostOperationTest extends JerseyTest {
     public void postConfigStatusCodes() throws UnsupportedEncodingException {
         controllerContext.setSchemas(schemaContextYangsIetf);
         mockCommitConfigurationDataPostMethod(TransactionStatus.COMMITED);
-        String uri = createUri("/config/", "ietf-interfaces:interfaces");
+        String uri = "/config/ietf-interfaces:interfaces";
         assertEquals(204, post(uri, MediaType.APPLICATION_XML, xmlDataInterfaceAbsolutePath));
 
         mockCommitConfigurationDataPostMethod(null);
@@ -167,9 +167,9 @@ public class RestPostOperationTest extends JerseyTest {
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
-        String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/0/");
+        String uri = "/config/ietf-interfaces:interfaces/interface/0/";
         assertEquals(204, post(uri, Draft02.MediaTypes.DATA + XML, xmlData4));
-        uri = createUri("/config/", "ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont");
+        uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont";
         assertEquals(204, post(uri, Draft02.MediaTypes.DATA + XML, xmlData3));
     }
 
@@ -206,13 +206,13 @@ public class RestPostOperationTest extends JerseyTest {
         ArgumentCaptor<InstanceIdentifier> instanceIdCaptor = ArgumentCaptor.forClass(InstanceIdentifier.class);
         ArgumentCaptor<CompositeNode> compNodeCaptor = ArgumentCaptor.forClass(CompositeNode.class);
 
-        String URI_1 = createUri("/config", "");
+        String URI_1 = "/config";
         assertEquals(204, post(URI_1, Draft02.MediaTypes.DATA + XML, xmlTestInterface));
         verify(brokerFacade).commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture());
         String identifier = "[(urn:ietf:params:xml:ns:yang:test-interface?revision=2014-07-01)interfaces]";
         assertEquals(identifier, instanceIdCaptor.getValue().getPath().toString());
 
-        String URI_2 = createUri("/config/", "test-interface:interfaces");
+        String URI_2 = "/config/test-interface:interfaces";
         assertEquals(204, post(URI_2, Draft02.MediaTypes.DATA + XML, xmlBlockData));
         verify(brokerFacade, times(2))
                 .commitConfigurationDataPost(instanceIdCaptor.capture(), compNodeCaptor.capture());
@@ -227,17 +227,13 @@ public class RestPostOperationTest extends JerseyTest {
         when(brokerFacade.commitConfigurationDataPost(any(InstanceIdentifier.class), any(CompositeNode.class)))
                 .thenReturn(null);
 
-        String URI_1 = createUri("/config", "");
+        String URI_1 = "/config";
         assertEquals(202, post(URI_1, Draft02.MediaTypes.DATA + XML, xmlTestInterface));
 
-        String URI_2 = createUri("/config/", "test-interface:interfaces");
+        String URI_2 = "/config/test-interface:interfaces";
         assertEquals(202, post(URI_2, Draft02.MediaTypes.DATA + XML, xmlBlockData));
     }
 
-    private String createUri(String prefix, String encodedPart) throws UnsupportedEncodingException {
-        return URI.create(prefix + URLEncoder.encode(encodedPart, Charsets.US_ASCII.name()).toString()).toASCIIString();
-    }
-
     private static void initMocking() {
         controllerContext = ControllerContext.getInstance();
         controllerContext.setSchemas(schemaContext);
index 2ba4a38c88582f9cb1c4ba49a8a586024c070e37..3af2945526466fabf3e9c139b79eb4134107752f 100644 (file)
@@ -11,7 +11,6 @@ import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.createUri;
 
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -95,7 +94,7 @@ public class RestPutOperationTest extends JerseyTest {
      */
     @Test
     public void putConfigStatusCodes() throws UnsupportedEncodingException {
-        String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/eth0");
+        String uri = "/config/ietf-interfaces:interfaces/interface/eth0";
         mockCommitConfigurationDataPutMethod(TransactionStatus.COMMITED);
         assertEquals(200, put(uri, MediaType.APPLICATION_XML, xmlData));
 
@@ -121,10 +120,10 @@ public class RestPutOperationTest extends JerseyTest {
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
-        String uri = createUri("/config/", "ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont");
+        String uri = "/config/ietf-interfaces:interfaces/interface/0/yang-ext:mount/test-module:cont";
         assertEquals(200, put(uri, MediaType.APPLICATION_XML, xmlData2));
 
-        uri = createUri("/config/", "ietf-interfaces:interfaces/yang-ext:mount/test-module:cont");
+        uri = "/config/ietf-interfaces:interfaces/yang-ext:mount/test-module:cont";
         assertEquals(200, put(uri, MediaType.APPLICATION_XML, xmlData2));
     }
 
@@ -144,7 +143,7 @@ public class RestPutOperationTest extends JerseyTest {
 
         ControllerContext.getInstance().setMountService(mockMountService);
 
-        String uri = createUri("/config/", "ietf-interfaces:interfaces/yang-ext:mount");
+        String uri = "/config/ietf-interfaces:interfaces/yang-ext:mount";
         assertEquals(200, put(uri, MediaType.APPLICATION_XML, xmlData3));
     }
 
index 4dcc63e89aa76d27bc58cfdeebce4243f7bbaa23..d9ef2ef243986bb63960f8212f4ab2bbf81346f6 100644 (file)
@@ -11,7 +11,6 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
-import static org.opendaylight.controller.sal.restconf.impl.test.RestOperationUtils.createUri;
 
 import java.io.FileNotFoundException;
 import java.io.UnsupportedEncodingException;
@@ -69,13 +68,13 @@ public class RestStream extends JerseyTest {
 
     @Test
     public void testCallRpcCallGet() throws UnsupportedEncodingException, InterruptedException {
-        String uri = createUri("/operations/", "sal-remote:create-data-change-event-subscription");
+        String uri = "/operations/sal-remote:create-data-change-event-subscription";
         Response responseWithStreamName = post(uri, MediaType.APPLICATION_XML, getRpcInput());
         String xmlResponse = responseWithStreamName.readEntity(String.class);
         assertNotNull(xmlResponse);
         assertTrue(xmlResponse.contains("<stream-name>ietf-interfaces:interfaces/ietf-interfaces:interface/eth0</stream-name>"));
 
-        uri = createUri("/streams/stream/", "ietf-interfaces:interfaces/ietf-interfaces:interface/eth0");
+        uri = "/streams/stream/ietf-interfaces:interfaces/ietf-interfaces:interface/eth0";
         Response responseWithRedirectionUri = get(uri, MediaType.APPLICATION_XML);
         final URI websocketServerUri = responseWithRedirectionUri.getLocation();
         assertNotNull(websocketServerUri);
index d699d224bbc1bfd387d5fc6d2974b670e7b83412..72d62efe84c21cfcf47e1c0d7ac8eb60bdbc97a7 100644 (file)
@@ -78,8 +78,8 @@ import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 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.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.test.impl.rev130403.TestIdentity1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.test.impl.rev130403.TestIdentity2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127.TestIdentity2;
 import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
 import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
 import org.opendaylight.yangtools.yang.model.api.Module;
index e319d2cb679260718c9eade75234b9996170007c..2d89bbc55c03d59d3ad7e648426df91562fc6fde 100644 (file)
@@ -49,7 +49,7 @@ public class ConfigPersisterNotificationHandler implements Closeable {
     private static void registerAsJMXListener(MBeanServerConnection mBeanServerConnection, ConfigPersisterNotificationListener listener) {
         logger.trace("Called registerAsJMXListener");
         try {
-            mBeanServerConnection.addNotificationListener(DefaultCommitOperationMXBean.objectName, listener, null, null);
+            mBeanServerConnection.addNotificationListener(DefaultCommitOperationMXBean.OBJECT_NAME, listener, null, null);
         } catch (InstanceNotFoundException | IOException e) {
             throw new RuntimeException("Cannot register as JMX listener to netconf", e);
         }
@@ -58,7 +58,7 @@ public class ConfigPersisterNotificationHandler implements Closeable {
     @Override
     public synchronized void close() {
         // unregister from JMX
-        ObjectName on = DefaultCommitOperationMXBean.objectName;
+        ObjectName on = DefaultCommitOperationMXBean.OBJECT_NAME;
         try {
             if (mBeanServerConnection.isRegistered(on)) {
                 mBeanServerConnection.removeNotificationListener(on, listener);
index bd75c27dd6abf36c794f85459accdcaa2bb3b35d..f85d9b9f304f8cf8de63e90f185d63fb64e82811 100644 (file)
@@ -22,13 +22,13 @@ public abstract class AbstractNetconfSession<S extends NetconfSession, L extends
     private final long sessionId;
     private boolean up = false;
 
-    protected final Channel channel;
+    private final Channel channel;
 
     protected AbstractNetconfSession(L sessionListener, Channel channel, long sessionId) {
         this.sessionListener = sessionListener;
         this.channel = channel;
         this.sessionId = sessionId;
-        logger.debug("Session {} created", toString());
+        logger.debug("Session {} created", sessionId);
     }
 
     protected abstract S thisInstance();
index 1ec46c8d6f1e58912e76c57bd4674f7d70e8c37c..be3040802cdfdc4ab7eaf3ac266914e936de82b0 100644 (file)
@@ -9,7 +9,7 @@
 package org.opendaylight.controller.netconf.api;
 
 public class NetconfSessionPreferences {
-    protected final NetconfMessage helloMessage;
+    private final NetconfMessage helloMessage;
 
     public NetconfSessionPreferences(final NetconfMessage helloMessage) {
         this.helloMessage = helloMessage;
index 0c4174000fe80dc231efd9aeb5702a2832834580..74cd4a4e05a5186cf6c4df5543b03a106c61fa3e 100644 (file)
@@ -17,12 +17,12 @@ public class CommitJMXNotification extends NetconfJMXNotification {
 
     private final Element configSnapshot;
 
-    private static final String afterCommitMessageTemplate = "Commit successful: %s";
+    private static final String AFTER_COMMIT_MESSAGE_TEMPLATE = "Commit successful: %s";
     private final Set<String> capabilities;
 
     CommitJMXNotification(NotificationBroadcasterSupport source, String message, Element cfgSnapshot,
             Set<String> capabilities) {
-        super(TransactionProviderJMXNotificationType.commit, source, String.format(afterCommitMessageTemplate, message));
+        super(TransactionProviderJMXNotificationType.commit, source, String.format(AFTER_COMMIT_MESSAGE_TEMPLATE, message));
         this.configSnapshot = cfgSnapshot;
         this.capabilities = capabilities;
     }
index a170d2905fee69135ab904525d266aa638d61331..e45d3c38a209ee26f0ba2b92e63637ad155f6c01 100644 (file)
@@ -14,7 +14,7 @@ import javax.management.ObjectName;
 
 public interface DefaultCommitOperationMXBean {
 
-    static String typeName = "NetconfNotificationProvider";
-    public static ObjectName objectName = ObjectNameUtil.createONWithDomainAndType(typeName);
+    String TYPE_NAME = "NetconfNotificationProvider";
+    ObjectName OBJECT_NAME = ObjectNameUtil.createONWithDomainAndType(TYPE_NAME);
 
 }
index 693fc1378390abcd89c0f582e75a055d10580c98..4461054437ce61ef47fd2eea76a9b23ae15b5ef3 100644 (file)
@@ -31,7 +31,7 @@ public class DefaultCommitNotificationProducer extends NotificationBroadcasterSu
 
     private final MBeanServer mbeanServer;
 
-    private final ObjectName on = DefaultCommitOperationMXBean.objectName;
+    private final ObjectName on = DefaultCommitOperationMXBean.OBJECT_NAME;
 
     public DefaultCommitNotificationProducer(MBeanServer mBeanServer) {
         this.mbeanServer = mBeanServer;
index 1b4dfff42baeb0423597af3c90168592db146724..f8024922cfc5a5ba021e97b519493ae80a02c4d2 100644 (file)
@@ -49,7 +49,7 @@ public class NetconfServerSessionNegotiator extends
 
         logger.debug("Additional header from hello parsed as {} from {}", parsedHeader, additionalHeader);
 
-        return new NetconfServerSession(sessionListener, channel, sessionPreferences.getSessionId(), parsedHeader);
+        return new NetconfServerSession(sessionListener, channel, getSessionPreferences().getSessionId(), parsedHeader);
     }
 
    }
index 95f7353600fcfb67a5626a496d76642613c4bb5a..b8dc9550c7f1fff5b4a544d3be0bc68f07f6d235 100644 (file)
@@ -26,6 +26,7 @@ import java.lang.management.ManagementFactory;
 import java.net.InetSocketAddress;
 import java.util.Dictionary;
 import java.util.Hashtable;
+import java.util.concurrent.TimeUnit;
 
 public class NetconfImplActivator implements BundleActivator {
 
@@ -88,7 +89,7 @@ public class NetconfImplActivator implements BundleActivator {
         logger.info("Shutting down netconf because YangStoreService service was removed");
 
         commitNot.close();
-        eventLoopGroup.shutdownGracefully();
+        eventLoopGroup.shutdownGracefully(0, 1, TimeUnit.SECONDS);
         timer.stop();
 
         regMonitoring.unregister();
index aa3c5d4d9ba539167dd08aa3117dc45fbb7cc9b8..959e2ff144810c2017131e8041229e86b1cabd64 100644 (file)
@@ -8,33 +8,24 @@
 
 package org.opendaylight.controller.netconf.impl;
 
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageHeader;
-
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
-public class MessageHeaderTest {
-
-    private NetconfMessageHeader header = null;
-
-    @Before
-    public void setUp() {
-        this.header = new NetconfMessageHeader();
-    }
+import org.junit.Test;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageHeader;
 
+public class MessageHeaderTest {
     @Test
     public void testFromBytes() {
         final byte[] raw = new byte[] { (byte) 0x0a, (byte) 0x23, (byte) 0x35, (byte) 0x38, (byte) 0x0a };
-        this.header.fromBytes(raw);
-        assertEquals(58, this.header.getLength());
+        NetconfMessageHeader header = NetconfMessageHeader.fromBytes(raw);
+        assertEquals(58, header.getLength());
     }
 
     @Test
     public void testToBytes() {
-        this.header.setLength(123);
+        NetconfMessageHeader header = new NetconfMessageHeader(123);
         assertArrayEquals(new byte[] { (byte) 0x0a, (byte) 0x23, (byte) 0x31, (byte) 0x32, (byte) 0x33, (byte) 0x0a },
-                this.header.toBytes());
+                header.toBytes());
     }
 }
index 85bccba14ff01da5d559ad83ff6080e0ef5b6b42..d1c0b066d7a0a5ef15399a0544deb380177b0b01 100644 (file)
@@ -22,9 +22,10 @@ import java.util.Queue;
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
+import org.opendaylight.controller.netconf.util.handler.ChunkedFramingMechanismEncoder;
 import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageChunkDecoder;
+import org.opendaylight.controller.netconf.util.handler.NetconfChunkAggregator;
+import org.opendaylight.controller.netconf.util.handler.NetconfEOMAggregator;
 import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
 import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
 import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
@@ -47,7 +48,7 @@ public class MessageParserTest {
                 FramingMechanismHandlerFactory.createHandler(FramingMechanism.CHUNK),
                 new NetconfMessageToXMLEncoder(),
 
-                new NetconfMessageAggregator(FramingMechanism.CHUNK), new NetconfMessageChunkDecoder(),
+                new NetconfChunkAggregator(),
                 new NetconfXMLToMessageDecoder());
 
         testChunkChannel.writeOutbound(this.msg);
@@ -59,26 +60,25 @@ public class MessageParserTest {
         enc.encode(null, msg, out);
         int msgLength = out.readableBytes();
 
-        int chunkCount = msgLength / NetconfMessageConstants.MAX_CHUNK_SIZE;
-        if ((msgLength % NetconfMessageConstants.MAX_CHUNK_SIZE) != 0) {
+        int chunkCount = msgLength / ChunkedFramingMechanismEncoder.DEFAULT_CHUNK_SIZE;
+        if ((msgLength % ChunkedFramingMechanismEncoder.DEFAULT_CHUNK_SIZE) != 0) {
             chunkCount++;
         }
         for (int i = 1; i <= chunkCount; i++) {
             ByteBuf recievedOutbound = (ByteBuf) messages.poll();
-            int exptHeaderLength = NetconfMessageConstants.MAX_CHUNK_SIZE;
+            int exptHeaderLength = ChunkedFramingMechanismEncoder.DEFAULT_CHUNK_SIZE;
             if (i == chunkCount) {
-                exptHeaderLength = msgLength - (NetconfMessageConstants.MAX_CHUNK_SIZE * (i - 1));
-                byte[] eom = new byte[NetconfMessageConstants.endOfChunk.length];
-                recievedOutbound.getBytes(recievedOutbound.readableBytes() - NetconfMessageConstants.endOfChunk.length,
+                exptHeaderLength = msgLength - (ChunkedFramingMechanismEncoder.DEFAULT_CHUNK_SIZE * (i - 1));
+                byte[] eom = new byte[NetconfMessageConstants.END_OF_CHUNK.length];
+                recievedOutbound.getBytes(recievedOutbound.readableBytes() - NetconfMessageConstants.END_OF_CHUNK.length,
                         eom);
-                assertArrayEquals(NetconfMessageConstants.endOfChunk, eom);
+                assertArrayEquals(NetconfMessageConstants.END_OF_CHUNK, eom);
             }
 
             byte[] header = new byte[String.valueOf(exptHeaderLength).length()
                     + NetconfMessageConstants.MIN_HEADER_LENGTH - 1];
             recievedOutbound.getBytes(0, header);
-            NetconfMessageHeader messageHeader = new NetconfMessageHeader();
-            messageHeader.fromBytes(header);
+            NetconfMessageHeader messageHeader = NetconfMessageHeader.fromBytes(header);
             assertEquals(exptHeaderLength, messageHeader.getLength());
 
             testChunkChannel.writeInbound(recievedOutbound);
@@ -94,15 +94,14 @@ public class MessageParserTest {
     public void testEOMFramingMechanismOnPipeline() throws Exception {
         EmbeddedChannel testChunkChannel = new EmbeddedChannel(
                 FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM),
-                new NetconfMessageToXMLEncoder(), new NetconfMessageAggregator(
-                        FramingMechanism.EOM), new NetconfXMLToMessageDecoder());
+                new NetconfMessageToXMLEncoder(), new NetconfEOMAggregator(), new NetconfXMLToMessageDecoder());
 
         testChunkChannel.writeOutbound(this.msg);
         ByteBuf recievedOutbound = (ByteBuf) testChunkChannel.readOutbound();
 
-        byte[] eom = new byte[NetconfMessageConstants.endOfMessage.length];
-        recievedOutbound.getBytes(recievedOutbound.readableBytes() - NetconfMessageConstants.endOfMessage.length, eom);
-        assertArrayEquals(NetconfMessageConstants.endOfMessage, eom);
+        byte[] eom = new byte[NetconfMessageConstants.END_OF_MESSAGE.length];
+        recievedOutbound.getBytes(recievedOutbound.readableBytes() - NetconfMessageConstants.END_OF_MESSAGE.length, eom);
+        assertArrayEquals(NetconfMessageConstants.END_OF_MESSAGE, eom);
 
         testChunkChannel.writeInbound(recievedOutbound);
         NetconfMessage receivedMessage = (NetconfMessage) testChunkChannel.readInbound();
index 0037981a3e0103f95cd83a945af5aa83c11dd477..1035c9f9fe3afd9c8a0bda0e3b3709ff2800df1d 100644 (file)
@@ -7,9 +7,27 @@
  */
 package org.opendaylight.controller.netconf.it;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
+import static junit.framework.Assert.assertEquals;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import io.netty.channel.ChannelFuture;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetSocketAddress;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+
 import org.apache.commons.lang3.StringUtils;
 import org.junit.After;
 import org.junit.Assert;
@@ -44,33 +62,13 @@ import org.opendaylight.controller.netconf.monitoring.osgi.NetconfMonitoringOper
 import org.opendaylight.controller.netconf.persist.impl.ConfigPersisterNotificationHandler;
 import org.opendaylight.controller.netconf.util.test.XmlFileLoader;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.w3c.dom.Element;
 
-import javax.management.InstanceNotFoundException;
-import javax.management.Notification;
-import javax.management.NotificationListener;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.InetSocketAddress;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-import static junit.framework.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 
 public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
 
-    private static final Logger logger =  LoggerFactory.getLogger(NetconfConfigPersisterITTest.class);
-
     private static final InetSocketAddress tcpAddress = new InetSocketAddress("127.0.0.1", 12023);
 
 
@@ -163,7 +161,7 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
 
     private VerifyingNotificationListener createCommitNotificationListener() throws InstanceNotFoundException {
         VerifyingNotificationListener listener = new VerifyingNotificationListener();
-        platformMBeanServer.addNotificationListener(DefaultCommitNotificationProducer.objectName, listener, null, null);
+        platformMBeanServer.addNotificationListener(DefaultCommitNotificationProducer.OBJECT_NAME, listener, null, null);
         return listener;
     }
 
@@ -230,7 +228,7 @@ public class NetconfConfigPersisterITTest extends AbstractNetconfConfigTest {
         public VerifyingPersister() throws IOException {
             Persister mockedAggregator = mock(Persister.class);
 
-            doAnswer(new Answer() {
+            doAnswer(new Answer<Object>() {
                 @Override
                 public Object answer(InvocationOnMock invocation) throws Throwable {
                     ConfigSnapshotHolder configSnapshot = (ConfigSnapshotHolder) invocation.getArguments()[0];
index be2c32e34fd8816b28ed1a844437b5d0c133ea56..7a840be02af697f1cd73dad423c8b610b2a664da 100644 (file)
@@ -7,11 +7,23 @@
  */
 package org.opendaylight.controller.netconf.it;
 
-import com.google.common.base.Charsets;
-import com.google.common.base.Optional;
-import com.google.common.collect.Sets;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import io.netty.channel.ChannelFuture;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
 import junit.framework.Assert;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.matchers.JUnitMatchers;
@@ -41,19 +53,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
-
-import static org.mockito.Matchers.anyLong;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
 
 public class NetconfMonitoringITTest extends AbstractNetconfConfigTest {
 
@@ -162,6 +164,8 @@ public class NetconfMonitoringITTest extends AbstractNetconfConfigTest {
             }
         }
 
+        sock.close();
+
         org.junit.Assert.assertThat(responseBuilder.toString(), JUnitMatchers.containsString("<capability>urn:ietf:params:netconf:capability:candidate:1.0</capability>"));
         org.junit.Assert.assertThat(responseBuilder.toString(), JUnitMatchers.containsString("<username>tomas</username>"));
     }
index 0910d9403ad98af67427d9dc818e1ddcff216878..48a45845a4a6fe7f57a722bc5678d8fc8447b54d 100644 (file)
@@ -13,8 +13,8 @@ import io.netty.util.concurrent.Promise;
 
 import org.opendaylight.controller.netconf.api.NetconfSession;
 import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
+import org.opendaylight.controller.netconf.util.handler.NetconfEOMAggregator;
 import org.opendaylight.controller.netconf.util.handler.NetconfHelloMessageToXMLEncoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
 import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
 import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
 
@@ -27,7 +27,7 @@ public abstract class AbstractChannelInitializer<S extends NetconfSession> {
     public static final String NETCONF_SESSION_NEGOTIATOR = "negotiator";
 
     public void initialize(SocketChannel ch, Promise<S> promise) {
-        ch.pipeline().addLast(NETCONF_MESSAGE_AGGREGATOR, new NetconfMessageAggregator(FramingMechanism.EOM));
+        ch.pipeline().addLast(NETCONF_MESSAGE_AGGREGATOR, new NetconfEOMAggregator());
         initializeMessageDecoder(ch);
         ch.pipeline().addLast(NETCONF_MESSAGE_FRAME_ENCODER, FramingMechanismHandlerFactory.createHandler(FramingMechanism.EOM));
         initializeMessageEncoder(ch);
index 9986b82bd8d6902a084e77a1a11a6421125ccb17..71f08339c803774d3d3b50a701b2d55454e9081e 100644 (file)
@@ -8,19 +8,30 @@
 
 package org.opendaylight.controller.netconf.util;
 
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.ssl.SslHandler;
+import io.netty.util.Timeout;
+import io.netty.util.Timer;
+import io.netty.util.TimerTask;
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.GenericFutureListener;
+import io.netty.util.concurrent.Promise;
+
 import java.util.concurrent.TimeUnit;
 
+import io.netty.channel.ChannelInboundHandlerAdapter;
 import org.opendaylight.controller.netconf.api.AbstractNetconfSession;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.api.NetconfSessionListener;
 import org.opendaylight.controller.netconf.api.NetconfSessionPreferences;
 import org.opendaylight.controller.netconf.util.handler.FramingMechanismHandlerFactory;
-import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageAggregator;
-import org.opendaylight.controller.netconf.util.handler.NetconfMessageChunkDecoder;
+import org.opendaylight.controller.netconf.util.handler.NetconfChunkAggregator;
 import org.opendaylight.controller.netconf.util.handler.NetconfMessageToXMLEncoder;
 import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
 import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
+import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.opendaylight.protocol.framework.AbstractSessionNegotiator;
 import org.slf4j.Logger;
@@ -31,25 +42,13 @@ import org.w3c.dom.NodeList;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 
-import io.netty.channel.Channel;
-import io.netty.channel.ChannelHandler;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.ssl.SslHandler;
-import io.netty.util.Timeout;
-import io.netty.util.Timer;
-import io.netty.util.TimerTask;
-import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.GenericFutureListener;
-import io.netty.util.concurrent.Promise;
-
 public abstract class AbstractNetconfSessionNegotiator<P extends NetconfSessionPreferences, S extends AbstractNetconfSession<S, L>, L extends NetconfSessionListener<S>>
 extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
 
     private static final Logger logger = LoggerFactory.getLogger(AbstractNetconfSessionNegotiator.class);
     public static final String NAME_OF_EXCEPTION_HANDLER = "lastExceptionHandler";
-    public static final String CHUNK_DECODER_CHANNEL_HANDLER_KEY = "chunkDecoder";
 
-    protected final P sessionPreferences;
+    private final P sessionPreferences;
 
     private final L sessionListener;
     private Timeout timeout;
@@ -81,14 +80,15 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
             Future<Channel> future = sslHandler.get().handshakeFuture();
             future.addListener(new GenericFutureListener<Future<? super Channel>>() {
                 @Override
-                public void operationComplete(Future<? super Channel> future) throws Exception {
+                public void operationComplete(Future<? super Channel> future) {
                     Preconditions.checkState(future.isSuccess(), "Ssl handshake was not successful");
                     logger.debug("Ssl handshake complete");
                     start();
                 }
             });
-        } else
+        } else {
             start();
+        }
     }
 
     private static Optional<SslHandler> getSslHandler(Channel channel) {
@@ -96,31 +96,19 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
         return sslHandler == null ? Optional.<SslHandler> absent() : Optional.of(sslHandler);
     }
 
+    public P getSessionPreferences() {
+        return sessionPreferences;
+    }
+
     private void start() {
         final NetconfMessage helloMessage = this.sessionPreferences.getHelloMessage();
         logger.debug("Session negotiation started with hello message {}", XmlUtil.toString(helloMessage.getDocument()));
 
-        channel.pipeline().addLast(NAME_OF_EXCEPTION_HANDLER, new ChannelHandler() {
-            @Override
-            public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
-            }
-
-            @Override
-            public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
-            }
-
-            @Override
-            public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
-                logger.warn("An exception occurred during negotiation on channel {}", channel.localAddress(), cause);
-                cancelTimeout();
-                negotiationFailed(cause);
-                changeState(State.FAILED);
-            }
-        });
+        channel.pipeline().addLast(NAME_OF_EXCEPTION_HANDLER, new ExceptionHandlingInboundChannelHandler());
 
         timeout = this.timer.newTimeout(new TimerTask() {
             @Override
-            public void run(final Timeout timeout) throws Exception {
+            public void run(final Timeout timeout) {
                 synchronized (this) {
                     if (state != State.ESTABLISHED) {
                         logger.debug("Connection timeout after {}, session is in state {}", timeout, state);
@@ -135,42 +123,33 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
             }
         }, connectionTimeoutMillis, TimeUnit.MILLISECONDS);
 
-        sendMessage(helloMessage);
+        // FIXME, make sessionPreferences return HelloMessage, move NetconfHelloMessage to API
+        sendMessage((NetconfHelloMessage)helloMessage);
         changeState(State.OPEN_WAIT);
     }
 
     private void cancelTimeout() {
-        if(timeout!=null)
+        if(timeout!=null) {
             timeout.cancel();
-    }
-
-    private void sendMessage(NetconfMessage message) {
-        this.channel.writeAndFlush(message);
+        }
     }
 
     @Override
     protected void handleMessage(NetconfHelloMessage netconfMessage) {
-        final Document doc = netconfMessage.getDocument();
+        Preconditions.checkNotNull(netconfMessage != null, "netconfMessage");
 
-        // Only Hello message should arrive during negotiation
-        if (netconfMessage instanceof NetconfHelloMessage) {
+        final Document doc = netconfMessage.getDocument();
 
-            replaceHelloMessageHandlers();
+        replaceHelloMessageHandlers();
 
-            if (shouldUseChunkFraming(doc)) {
-                insertChunkFramingToPipeline();
-            }
+        if (shouldUseChunkFraming(doc)) {
+            insertChunkFramingToPipeline();
+        }
 
-            changeState(State.ESTABLISHED);
-            S session = getSession(sessionListener, channel, (NetconfHelloMessage)netconfMessage);
+        changeState(State.ESTABLISHED);
+        S session = getSession(sessionListener, channel, netconfMessage);
 
-            negotiationSuccessful(session);
-        } else {
-            final IllegalStateException cause = new IllegalStateException(
-                    "Received message was not hello as expected, but was " + XmlUtil.toString(doc));
-            logger.warn("Negotiation of netconf session failed", cause);
-            negotiationFailed(cause);
-        }
+        negotiationSuccessful(session);
     }
 
     /**
@@ -180,9 +159,7 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
         replaceChannelHandler(channel, AbstractChannelInitializer.NETCONF_MESSAGE_FRAME_ENCODER,
                 FramingMechanismHandlerFactory.createHandler(FramingMechanism.CHUNK));
         replaceChannelHandler(channel, AbstractChannelInitializer.NETCONF_MESSAGE_AGGREGATOR,
-                new NetconfMessageAggregator(FramingMechanism.CHUNK));
-        channel.pipeline().addAfter(AbstractChannelInitializer.NETCONF_MESSAGE_AGGREGATOR,
-                CHUNK_DECODER_CHANNEL_HANDLER_KEY, new NetconfMessageChunkDecoder());
+                new NetconfChunkAggregator());
     }
 
     private boolean shouldUseChunkFraming(Document doc) {
@@ -222,14 +199,31 @@ extends AbstractSessionNegotiator<NetconfHelloMessage, S> {
     }
 
     private static boolean isStateChangePermitted(State state, State newState) {
-        if (state == State.IDLE && newState == State.OPEN_WAIT)
+        if (state == State.IDLE && newState == State.OPEN_WAIT) {
             return true;
-        if (state == State.OPEN_WAIT && newState == State.ESTABLISHED)
+        }
+        if (state == State.OPEN_WAIT && newState == State.ESTABLISHED) {
             return true;
-        if (state == State.OPEN_WAIT && newState == State.FAILED)
+        }
+        if (state == State.OPEN_WAIT && newState == State.FAILED) {
             return true;
+        }
 
         logger.debug("Transition from {} to {} is not allowed", state, newState);
         return false;
     }
+
+    /**
+     * Handler to catch exceptions in pipeline during negotiation
+     */
+    private final class ExceptionHandlingInboundChannelHandler extends ChannelInboundHandlerAdapter {
+
+        @Override
+        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
+            logger.warn("An exception occurred during negotiation on channel {}", channel.localAddress(), cause);
+            cancelTimeout();
+            negotiationFailed(cause);
+            changeState(State.FAILED);
+        }
+    }
 }
index aae2f71b86b6f67aa08d57bd374407c59d17651d..796ab91a504040e87197f9032d85e4699d4c80b5 100644 (file)
@@ -27,10 +27,12 @@ import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 
-public class NetconfUtil {
+public final class NetconfUtil {
 
     private static final Logger logger = LoggerFactory.getLogger(NetconfUtil.class);
 
+    private NetconfUtil() {}
+
     public static NetconfMessage createMessage(final File f) {
         Preconditions.checkNotNull(f, "File parameter was null");
         try {
index d8dd7881653b466b24886da068f1d6bab529027b..ccc80a7b71248758cc2ce9a3c00225a0dab3fc49 100644 (file)
@@ -8,36 +8,51 @@
 
 package org.opendaylight.controller.netconf.util.handler;
 
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageHeader;
-
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToByteEncoder;
 
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageHeader;
+
+import com.google.common.base.Preconditions;
+
 public class ChunkedFramingMechanismEncoder extends MessageToByteEncoder<ByteBuf> {
+    public static final int DEFAULT_CHUNK_SIZE = 8192;
+    public static final int MIN_CHUNK_SIZE = 128;
+    public static final int MAX_CHUNK_SIZE = 16 * 1024 * 1024;
 
-    private NetconfMessageHeader messageHeader = new NetconfMessageHeader();
+    private final int chunkSize;
 
-    private final static int MAX_CHUNK_SIZE = NetconfMessageConstants.MAX_CHUNK_SIZE;
+    public ChunkedFramingMechanismEncoder() {
+        this(DEFAULT_CHUNK_SIZE);
+    }
+
+    public ChunkedFramingMechanismEncoder(int chunkSize) {
+        Preconditions.checkArgument(chunkSize > MIN_CHUNK_SIZE);
+        Preconditions.checkArgument(chunkSize < MAX_CHUNK_SIZE);
+        this.chunkSize = chunkSize;
+    }
+
+    public final int getChunkSize() {
+        return chunkSize;
+    }
 
     @Override
     protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
-        while (msg.readableBytes() > MAX_CHUNK_SIZE) {
-            ByteBuf chunk = Unpooled.buffer(MAX_CHUNK_SIZE);
-            chunk.writeBytes(createChunkHeader(MAX_CHUNK_SIZE));
-            chunk.writeBytes(msg.readBytes(MAX_CHUNK_SIZE));
+        while (msg.readableBytes() > chunkSize) {
+            ByteBuf chunk = Unpooled.buffer(chunkSize);
+            chunk.writeBytes(createChunkHeader(chunkSize));
+            chunk.writeBytes(msg.readBytes(chunkSize));
             ctx.write(chunk);
         }
         out.writeBytes(createChunkHeader(msg.readableBytes()));
         out.writeBytes(msg.readBytes(msg.readableBytes()));
-        out.writeBytes(NetconfMessageConstants.endOfChunk);
+        out.writeBytes(NetconfMessageConstants.END_OF_CHUNK);
     }
 
     private ByteBuf createChunkHeader(int chunkSize) {
-        messageHeader.setLength(chunkSize);
-        return Unpooled.wrappedBuffer(messageHeader.toBytes());
+        return Unpooled.wrappedBuffer(NetconfMessageHeader.toBytes(chunkSize));
     }
-
 }
index 7ec5a8f8dcd6c7304b8e7f5edbf7d292acb70199..a3efe8a16bd0c541971e7a4c0ca172b83144d3d5 100644 (file)
@@ -8,20 +8,16 @@
 
 package org.opendaylight.controller.netconf.util.handler;
 
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
-
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToByteEncoder;
 
-public class EOMFramingMechanismEncoder extends MessageToByteEncoder<ByteBuf> {
-
-    private byte[] eom = NetconfMessageConstants.endOfMessage;
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
 
+public class EOMFramingMechanismEncoder extends MessageToByteEncoder<ByteBuf> {
     @Override
     protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
         out.writeBytes(msg);
-        out.writeBytes(eom);
+        out.writeBytes(NetconfMessageConstants.END_OF_MESSAGE);
     }
-
 }
index 0d98084343a49355e22210868d5c08310dca460a..1f7a32dc704ca2698112b0e5e9d90c9cdb503a87 100644 (file)
@@ -17,7 +17,9 @@ import io.netty.handler.codec.MessageToByteEncoder;
 
 public class FramingMechanismHandlerFactory {
 
-    private final static Logger logger = LoggerFactory.getLogger(FramingMechanismHandlerFactory.class);
+    private static final Logger logger = LoggerFactory.getLogger(FramingMechanismHandlerFactory.class);
+
+    private FramingMechanismHandlerFactory() {}
 
     public static MessageToByteEncoder<ByteBuf> createHandler(FramingMechanism framingMechanism) {
         logger.debug("{} framing mechanism was selected.", framingMechanism);
diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfChunkAggregator.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfChunkAggregator.java
new file mode 100644 (file)
index 0000000..219e92c
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * 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.util.handler;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.CompositeByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+
+public class NetconfChunkAggregator extends ByteToMessageDecoder {
+    private final static Logger logger = LoggerFactory.getLogger(NetconfChunkAggregator.class);
+    public static final int DEFAULT_MAXIMUM_CHUNK_SIZE = 16 * 1024 * 1024;
+
+    private static enum State {
+        HEADER_ONE, // \n
+        HEADER_TWO, // #
+        HEADER_LENGTH_FIRST, // [1-9]
+        HEADER_LENGTH_OTHER, // [0-9]*\n
+        DATA,
+        FOOTER_ONE, // \n
+        FOOTER_TWO, // #
+        FOOTER_THREE, // #
+        FOOTER_FOUR, // \n
+    }
+
+    private final int maxChunkSize = DEFAULT_MAXIMUM_CHUNK_SIZE;
+    private State state = State.HEADER_ONE;
+    private long chunkSize;
+    private CompositeByteBuf chunk;
+
+    @Override
+    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+        while (in.isReadable()) {
+            switch (state) {
+            case HEADER_ONE:
+            {
+                final byte b = in.readByte();
+                if (b != '\n') {
+                    logger.debug("Got byte {} while waiting for {}", b, (byte)'\n');
+                    throw new IllegalStateException("Malformed chunk header encountered (byte 0)");
+                }
+
+                state = State.HEADER_TWO;
+
+                initChunk();
+                break;
+            }
+            case HEADER_TWO:
+            {
+                final byte b = in.readByte();
+                if (b != '#') {
+                    logger.debug("Got byte {} while waiting for {}", b, (byte)'#');
+                    throw new IllegalStateException("Malformed chunk header encountered (byte 1)");
+                }
+
+                state = State.HEADER_LENGTH_FIRST;
+                break;
+            }
+            case HEADER_LENGTH_FIRST:
+            {
+                final byte b = in.readByte();
+                chunkSize = processHeaderLengthFirst(b);
+                state = State.HEADER_LENGTH_OTHER;
+                break;
+            }
+            case HEADER_LENGTH_OTHER:
+            {
+                final byte b = in.readByte();
+                if (b == '\n') {
+                    state = State.DATA;
+                    break;
+                }
+
+                if (b < '0' || b > '9') {
+                    logger.debug("Got byte {} while waiting for {}-{}", b, (byte)'0', (byte)'9');
+                    throw new IllegalStateException("Invalid chunk size encountered");
+                }
+
+                chunkSize *= 10;
+                chunkSize += b - '0';
+
+                if (chunkSize > maxChunkSize) {
+                    logger.debug("Parsed chunk size {}, maximum allowed is {}", chunkSize, maxChunkSize);
+                    throw new IllegalStateException("Maximum chunk size exceeded");
+                }
+                break;
+            }
+            case DATA:
+                /*
+                 * FIXME: this gathers all data into one big chunk before passing
+                 *        it on. Make sure the pipeline can work with partial data
+                 *        and then change this piece to pass the data on as it
+                 *        comes through.
+                 */
+                if (in.readableBytes() < chunkSize) {
+                    logger.debug("Buffer has {} bytes, need {} to complete chunk", in.readableBytes(), chunkSize);
+                    in.discardReadBytes();
+                    return;
+                }
+
+                aggregateChunks(in.readBytes((int) chunkSize));
+                state = State.FOOTER_ONE;
+                break;
+            case FOOTER_ONE:
+            {
+                final byte b = in.readByte();
+                if (b != '\n') {
+                    logger.debug("Got byte {} while waiting for {}", b, (byte)'\n');
+                    throw new IllegalStateException("Malformed chunk footer encountered (byte 0)");
+                }
+
+                state = State.FOOTER_TWO;
+                chunkSize = 0;
+                break;
+            }
+            case FOOTER_TWO:
+            {
+                final byte b = in.readByte();
+
+                if (b != '#') {
+                    logger.debug("Got byte {} while waiting for {}", b, (byte)'#');
+                    throw new IllegalStateException("Malformed chunk footer encountered (byte 1)");
+                }
+
+                state = State.FOOTER_THREE;
+                break;
+            }
+            case FOOTER_THREE:
+            {
+                final byte b = in.readByte();
+
+                // In this state, either header-of-new-chunk or message-end is expected
+                // Depends on the next character
+
+                if (isHeaderLengthFirst(b)) {
+                    // Extract header length#1 from new chunk
+                    chunkSize = processHeaderLengthFirst(b);
+                    // Proceed with next chunk processing
+                    state = State.HEADER_LENGTH_OTHER;
+                } else if (b == '#') {
+                    state = State.FOOTER_FOUR;
+                } else {
+                    logger.debug("Got byte {} while waiting for {} or {}-{}", b, (byte) '#', (byte) '1', (byte) '9');
+                    throw new IllegalStateException("Malformed chunk footer encountered (byte 2)");
+                }
+
+                break;
+            }
+            case FOOTER_FOUR:
+            {
+                final byte b = in.readByte();
+                if (b != '\n') {
+                    logger.debug("Got byte {} while waiting for {}", b, (byte)'\n');
+                    throw new IllegalStateException("Malformed chunk footer encountered (byte 3)");
+                }
+
+                state = State.HEADER_ONE;
+                out.add(chunk);
+                chunk = null;
+                break;
+            }
+            }
+        }
+
+        in.discardReadBytes();
+    }
+
+    private void initChunk() {
+        chunk = Unpooled.compositeBuffer();
+    }
+
+    private void aggregateChunks(ByteBuf newChunk) {
+        chunk.addComponent(chunk.numComponents(), newChunk);
+
+        // Update writer index, addComponent does not update it
+        chunk.writerIndex(chunk.writerIndex() + newChunk.readableBytes());
+    }
+
+    private static int processHeaderLengthFirst(byte b) {
+        if (isHeaderLengthFirst(b) == false) {
+            logger.debug("Got byte {} while waiting for {}-{}", b, (byte)'1', (byte)'9');
+            throw new IllegalStateException("Invalid chunk size encountered (byte 0)");
+        }
+
+        return b - '0';
+    }
+
+    private static boolean isHeaderLengthFirst(byte b) {
+        return b >= '1' && b <= '9';
+    }
+}
@@ -8,32 +8,24 @@
 
 package org.opendaylight.controller.netconf.util.handler;
 
-import com.google.common.base.Charsets;
 import io.netty.buffer.ByteBuf;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.ByteToMessageDecoder;
-import org.opendaylight.controller.netconf.util.messages.FramingMechanism;
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.util.List;
 
-public class NetconfMessageAggregator extends ByteToMessageDecoder {
-
-    private final static Logger logger = LoggerFactory.getLogger(NetconfMessageAggregator.class);
+import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-    private byte[] eom = NetconfMessageConstants.endOfMessage;
+import com.google.common.base.Charsets;
 
-    public NetconfMessageAggregator(FramingMechanism framingMechanism) {
-        if (framingMechanism == FramingMechanism.CHUNK) {
-            eom = NetconfMessageConstants.endOfChunk;
-        }
-    }
+public class NetconfEOMAggregator extends ByteToMessageDecoder {
+    private final static Logger logger = LoggerFactory.getLogger(NetconfEOMAggregator.class);
 
     @Override
     protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
-        int index = indexOfSequence(in, eom);
+        int index = indexOfSequence(in, NetconfMessageConstants.END_OF_MESSAGE);
         if (index == -1) {
             logger.debug("Message is not complete, read again.");
             if (logger.isTraceEnabled()) {
@@ -43,7 +35,7 @@ public class NetconfMessageAggregator extends ByteToMessageDecoder {
             ctx.read();
         } else {
             ByteBuf msg = in.readBytes(index);
-            in.readBytes(eom.length);
+            in.readBytes(NetconfMessageConstants.END_OF_MESSAGE.length);
             in.discardReadBytes();
             logger.debug("Message is complete.");
             out.add(msg);
index a87d175d78e2f901d70de1efd5a7466223a21001..65d5b270254dcbd9503a98791c4c9f878d3442f9 100644 (file)
@@ -7,12 +7,18 @@
  */
 package org.opendaylight.controller.netconf.util.handler;
 
-import java.nio.ByteBuffer;
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelHandlerContext;
+
+import java.io.IOException;
+
+import javax.xml.transform.TransformerException;
 
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Charsets;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
@@ -39,9 +45,9 @@ import com.google.common.base.Preconditions;
  * </pre>
  */
 public final class NetconfHelloMessageToXMLEncoder extends NetconfMessageToXMLEncoder {
-
     @Override
-    protected ByteBuffer encodeMessage(NetconfMessage msg) {
+    @VisibleForTesting
+    public void encode(ChannelHandlerContext ctx, NetconfMessage msg, ByteBuf out) throws IOException, TransformerException {
         Preconditions.checkState(msg instanceof NetconfHelloMessage, "Netconf message of type %s expected, was %s",
                 NetconfHelloMessage.class, msg.getClass());
         Optional<NetconfHelloMessageAdditionalHeader> headerOptional = ((NetconfHelloMessage) msg)
@@ -50,15 +56,9 @@ public final class NetconfHelloMessageToXMLEncoder extends NetconfMessageToXMLEn
         // If additional header present, serialize it along with netconf hello
         // message
         if (headerOptional.isPresent()) {
-            byte[] bytesFromHeader = headerOptional.get().toFormattedString().getBytes(Charsets.UTF_8);
-            byte[] bytesFromMessage = xmlToString(msg.getDocument()).getBytes(Charsets.UTF_8);
-
-            ByteBuffer byteBuffer = ByteBuffer.allocate(bytesFromHeader.length + bytesFromMessage.length)
-                    .put(bytesFromHeader).put(bytesFromMessage);
-            byteBuffer.flip();
-            return byteBuffer;
+            out.writeBytes(headerOptional.get().toFormattedString().getBytes(Charsets.UTF_8));
         }
 
-        return super.encodeMessage(msg);
+        super.encode(ctx, msg, out);
     }
 }
diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageChunkDecoder.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/handler/NetconfMessageChunkDecoder.java
deleted file mode 100644 (file)
index 5c00b9b..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.util.handler;
-
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.Unpooled;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.ByteToMessageDecoder;
-
-import java.nio.charset.Charset;
-import java.util.List;
-
-import org.opendaylight.controller.netconf.api.NetconfDeserializerException;
-import org.opendaylight.controller.netconf.util.messages.NetconfMessageConstants;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class NetconfMessageChunkDecoder extends ByteToMessageDecoder {
-
-    private final static Logger logger = LoggerFactory.getLogger(NetconfMessageChunkDecoder.class);
-
-    @Override
-    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
-        ByteBuf byteBufMsg = Unpooled.buffer(in.readableBytes());
-        int chunkSize = -1;
-        boolean isParsed = false;
-        while (in.isReadable()) {
-            try {
-                if (!isParsed) {
-                    chunkSize = readHeader(in);
-                    isParsed = true;
-                }
-                if (chunkSize != -1 && isParsed) {
-                    in.readBytes(byteBufMsg, chunkSize);
-                    isParsed = false;
-                } else {
-                    throw new NetconfDeserializerException("Unable to parse chunked data or header.");
-                }
-            } catch (Exception e) {
-                logger.error("Failed to decode chunked message.", e);
-                this.exceptionCaught(ctx, e);
-            }
-        }
-        out.add(byteBufMsg);
-        isParsed = false;
-    }
-
-    private int readHeader(ByteBuf in) {
-        ByteBuf chunkSize = Unpooled.buffer(NetconfMessageConstants.MIN_HEADER_LENGTH,
-                NetconfMessageConstants.MAX_HEADER_LENGTH);
-        byte b = in.readByte();
-        if (b != 10)
-            return -1;
-        b = in.readByte();
-        if (b != 35)
-            return -1;
-        while ((b = in.readByte()) != 10) {
-            chunkSize.writeByte(b);
-        }
-        return Integer.parseInt(chunkSize.toString(Charset.forName("UTF-8")));
-    }
-
-}
index df0f7ef46a72b30318cfa2a75e5c8e8d6564c4b8..f9792a6c5bf0e2965bead5df9b1c8671ce7d600e 100644 (file)
@@ -8,24 +8,32 @@
 package org.opendaylight.controller.netconf.util.handler;
 
 import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufOutputStream;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.handler.codec.MessageToByteEncoder;
 
-import java.nio.ByteBuffer;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
 
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Comment;
-import org.w3c.dom.Document;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
 import com.google.common.base.Optional;
 
 public class NetconfMessageToXMLEncoder extends MessageToByteEncoder<NetconfMessage> {
     private static final Logger LOG = LoggerFactory.getLogger(NetconfMessageToXMLEncoder.class);
+    private static final TransformerFactory FACTORY = TransformerFactory.newInstance();
 
     private final Optional<String> clientId;
 
@@ -39,7 +47,7 @@ public class NetconfMessageToXMLEncoder extends MessageToByteEncoder<NetconfMess
 
     @Override
     @VisibleForTesting
-    public void encode(ChannelHandlerContext ctx, NetconfMessage msg, ByteBuf out) throws Exception {
+    public void encode(ChannelHandlerContext ctx, NetconfMessage msg, ByteBuf out) throws IOException, TransformerException {
         LOG.debug("Sent to encode : {}", msg);
 
         if (clientId.isPresent()) {
@@ -47,17 +55,14 @@ public class NetconfMessageToXMLEncoder extends MessageToByteEncoder<NetconfMess
             msg.getDocument().appendChild(comment);
         }
 
-        final ByteBuffer msgBytes = encodeMessage(msg);
-
-        LOG.trace("Putting message \n{}", xmlToString(msg.getDocument()));
-        out.writeBytes(msgBytes);
-    }
-
-    protected ByteBuffer encodeMessage(NetconfMessage msg) {
-        return Charsets.UTF_8.encode(xmlToString(msg.getDocument()));
-    }
+        try (OutputStream os = new ByteBufOutputStream(out)) {
+            Transformer transformer = FACTORY.newTransformer();
+            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
 
-    protected String xmlToString(Document doc) {
-        return XmlUtil.toString(doc, false);
+            StreamResult result = new StreamResult(new OutputStreamWriter(os));
+            DOMSource source = new DOMSource(msg.getDocument());
+            transformer.transform(source, result);
+        }
     }
 }
index 42586a5ecc60433d28a8fa89bbe57d3e958fdee1..c4808e0868d0f59b1378f5900b5151933edf696e 100644 (file)
@@ -7,6 +7,12 @@
  */
 package org.opendaylight.controller.netconf.util.handler;
 
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+
+import java.io.ByteArrayInputStream;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.List;
@@ -14,8 +20,12 @@ import java.util.List;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage;
 import org.opendaylight.controller.netconf.util.messages.NetconfHelloMessageAdditionalHeader;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Charsets;
 import com.google.common.collect.ImmutableList;
 
@@ -25,7 +35,8 @@ import com.google.common.collect.ImmutableList;
  * {@link org.opendaylight.controller.netconf.util.messages.NetconfHelloMessage}
  * . Used by netconf server to retrieve information about session metadata.
  */
-public class NetconfXMLToHelloMessageDecoder extends NetconfXMLToMessageDecoder {
+public final class NetconfXMLToHelloMessageDecoder extends ByteToMessageDecoder {
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfXMLToHelloMessageDecoder.class);
 
     private static final List<byte[]> POSSIBLE_ENDS = ImmutableList.of(
             new byte[] { ']', '\n' },
@@ -35,34 +46,46 @@ public class NetconfXMLToHelloMessageDecoder extends NetconfXMLToMessageDecoder
             new byte[] { '\r', '\n', '[' },
             new byte[] { '\n', '[' });
 
-    private String additionalHeaderCache;
-
     @Override
-    protected byte[] preprocessMessageBytes(byte[] bytes) {
-        // Extract bytes containing header with additional metadata
-
-        if (startsWithAdditionalHeader(bytes)) {
-            // Auth information containing username, ip address... extracted for monitoring
-            int endOfAuthHeader = getAdditionalHeaderEndIndex(bytes);
-            if (endOfAuthHeader > -1) {
-                byte[] additionalHeaderBytes = Arrays.copyOfRange(bytes, 0, endOfAuthHeader + 2);
-                additionalHeaderCache = additionalHeaderToString(additionalHeaderBytes);
-                bytes = Arrays.copyOfRange(bytes, endOfAuthHeader + 2, bytes.length);
-            }
+    @VisibleForTesting
+    public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
+        if (in.readableBytes() == 0) {
+            LOG.debug("No more content in incoming buffer.");
+            return;
         }
 
-        return bytes;
-    }
+        in.markReaderIndex();
+        try {
+            LOG.trace("Received to decode: {}", ByteBufUtil.hexDump(in));
+            byte[] bytes = new byte[in.readableBytes()];
+            in.readBytes(bytes);
+
+            logMessage(bytes);
+
+            // Extract bytes containing header with additional metadata
+            String additionalHeader = null;
+            if (startsWithAdditionalHeader(bytes)) {
+                // Auth information containing username, ip address... extracted for monitoring
+                int endOfAuthHeader = getAdditionalHeaderEndIndex(bytes);
+                if (endOfAuthHeader > -1) {
+                    byte[] additionalHeaderBytes = Arrays.copyOfRange(bytes, 0, endOfAuthHeader + 2);
+                    additionalHeader = additionalHeaderToString(additionalHeaderBytes);
+                    bytes = Arrays.copyOfRange(bytes, endOfAuthHeader + 2, bytes.length);
+                }
+            }
 
-    @Override
-    protected void cleanUpAfterDecode() {
-        additionalHeaderCache = null;
-    }
+            Document doc = XmlUtil.readXmlToDocument(new ByteArrayInputStream(bytes));
 
-    @Override
-    protected NetconfMessage buildNetconfMessage(Document doc) {
-        return new NetconfHelloMessage(doc, additionalHeaderCache == null ? null
-                : NetconfHelloMessageAdditionalHeader.fromString(additionalHeaderCache));
+            final NetconfMessage message;
+            if (additionalHeader != null) {
+                message = new NetconfHelloMessage(doc, NetconfHelloMessageAdditionalHeader.fromString(additionalHeader));
+            } else {
+                message = new NetconfHelloMessage(doc);
+            }
+            out.add(message);
+        } finally {
+            in.discardReadBytes();
+        }
     }
 
     private int getAdditionalHeaderEndIndex(byte[] bytes) {
@@ -102,15 +125,23 @@ public class NetconfXMLToHelloMessageDecoder extends NetconfXMLToMessageDecoder
         return -1;
     }
 
+
+    private void logMessage(byte[] bytes) {
+        String s = Charsets.UTF_8.decode(ByteBuffer.wrap(bytes)).toString();
+        LOG.debug("Parsing message \n{}", s);
+    }
+
     private boolean startsWithAdditionalHeader(byte[] bytes) {
         for (byte[] possibleStart : POSSIBLE_STARTS) {
             int i = 0;
             for (byte b : possibleStart) {
-                if(bytes[i++] != b)
+                if(bytes[i++] != b) {
                     break;
+                }
 
-                if(i == possibleStart.length)
+                if(i == possibleStart.length) {
                     return true;
+                }
             }
         }
 
index b697edfb053229fd75f602798c10150f0152b86c..06a4dc7207204d573f5abb2cc28c32318fee891d 100644 (file)
@@ -7,73 +7,32 @@
  */
 package org.opendaylight.controller.netconf.util.handler;
 
-import java.io.ByteArrayInputStream;
-import java.nio.ByteBuffer;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufInputStream;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.handler.codec.ByteToMessageDecoder;
+
 import java.util.List;
 
-import org.opendaylight.controller.netconf.api.NetconfDeserializerException;
 import org.opendaylight.controller.netconf.api.NetconfMessage;
 import org.opendaylight.controller.netconf.util.xml.XmlUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Charsets;
 
-import io.netty.buffer.ByteBuf;
-import io.netty.buffer.ByteBufUtil;
-import io.netty.channel.ChannelHandlerContext;
-import io.netty.handler.codec.ByteToMessageDecoder;
-
-public class NetconfXMLToMessageDecoder extends ByteToMessageDecoder {
+public final class NetconfXMLToMessageDecoder extends ByteToMessageDecoder {
     private static final Logger LOG = LoggerFactory.getLogger(NetconfXMLToMessageDecoder.class);
 
     @Override
     @VisibleForTesting
     public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
-        if (in.readableBytes() == 0) {
-            LOG.debug("No more content in incoming buffer.");
-            return;
-        }
-
-        in.markReaderIndex();
-        try {
+        if (in.readableBytes() != 0) {
             LOG.trace("Received to decode: {}", ByteBufUtil.hexDump(in));
-            byte[] bytes = new byte[in.readableBytes()];
-            in.readBytes(bytes);
-
-            logMessage(bytes);
-
-            bytes = preprocessMessageBytes(bytes);
-            NetconfMessage message;
-            try {
-                Document doc = XmlUtil.readXmlToDocument(new ByteArrayInputStream(bytes));
-                message = buildNetconfMessage(doc);
-            } catch (Exception e) {
-                throw new NetconfDeserializerException("Could not parse message from " + new String(bytes), e);
-            }
-
-            out.add(message);
-        } finally {
-            in.discardReadBytes();
-            cleanUpAfterDecode();
+            out.add(new NetconfMessage(XmlUtil.readXmlToDocument(new ByteBufInputStream(in))));
+        } else {
+            LOG.debug("No more content in incoming buffer.");
         }
     }
-
-    protected void cleanUpAfterDecode() {}
-
-    protected NetconfMessage buildNetconfMessage(Document doc) {
-        return new NetconfMessage(doc);
-    }
-
-    protected byte[] preprocessMessageBytes(byte[] bytes) {
-        return bytes;
-    }
-
-    private void logMessage(byte[] bytes) {
-        String s = Charsets.UTF_8.decode(ByteBuffer.wrap(bytes)).toString();
-        LOG.debug("Parsing message \n{}", s);
-    }
-
 }
index 0d9096c02a3abd1b33204665cb72dc4cbd10e805..49d5a05ae22a6939f992c4637f123f550fb3a4e7 100644 (file)
@@ -29,6 +29,8 @@ import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.Virtua
  * stops at instance of this class. All downstream events are handed of to wrapped {@link org.opendaylight.controller.netconf.util.handler.ssh.client.SshClientAdapter};
  */
 public class SshHandler extends ChannelOutboundHandlerAdapter {
+    private static final String SOCKET = "socket";
+
     private final VirtualSocket virtualSocket = new VirtualSocket();
     private final SshClientAdapter sshClientAdapter;
 
@@ -39,20 +41,20 @@ public class SshHandler extends ChannelOutboundHandlerAdapter {
 
     @Override
     public void handlerAdded(ChannelHandlerContext ctx){
-        if (ctx.channel().pipeline().get("socket") == null) {
-            ctx.channel().pipeline().addFirst("socket", virtualSocket);
+        if (ctx.channel().pipeline().get(SOCKET) == null) {
+            ctx.channel().pipeline().addFirst(SOCKET, virtualSocket);
         }
     }
 
     @Override
-    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
-        if (ctx.channel().pipeline().get("socket") != null) {
-            ctx.channel().pipeline().remove("socket");
+    public void handlerRemoved(ChannelHandlerContext ctx) {
+        if (ctx.channel().pipeline().get(SOCKET) != null) {
+            ctx.channel().pipeline().remove(SOCKET);
         }
     }
 
     @Override
-    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
+    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws IOException {
         this.sshClientAdapter.write((ByteBuf) msg);
     }
 
@@ -60,18 +62,18 @@ public class SshHandler extends ChannelOutboundHandlerAdapter {
     public void connect(final ChannelHandlerContext ctx,
                         SocketAddress remoteAddress,
                         SocketAddress localAddress,
-                        ChannelPromise promise) throws Exception {
+                        ChannelPromise promise) {
         ctx.connect(remoteAddress, localAddress, promise);
 
         promise.addListener(new ChannelFutureListener() {
-            public void operationComplete(ChannelFuture channelFuture) throws Exception {
+            public void operationComplete(ChannelFuture channelFuture) {
                 sshClientAdapter.start(ctx);
             }}
         );
     }
 
     @Override
-    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
+    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) {
         sshClientAdapter.stop(promise);
     }
 }
index 2f1b260bd087fd0f48dccdb0af1911157395d7cf..4aa274c6df34f2f2e9d4151454c4b84f53a41bdb 100644 (file)
@@ -29,7 +29,8 @@ public class LoginPassword extends AuthenticationHandler {
     public void authenticate(Connection connection) throws IOException {
         boolean isAuthenticated = connection.authenticateWithPassword(username, password);
 
-        if (isAuthenticated == false)
+        if (isAuthenticated == false) {
             throw new IOException("Authentication failed.");
+        }
     }
 }
index 8636e5ecb5fe55f22ce01cf9a19fb537397c9b0e..fffb304d26be7b3b32787fa1ae43e5392023bbd8 100644 (file)
@@ -19,6 +19,7 @@ public abstract class Invoker {
     private Invoker(){}
 
     protected boolean isInvoked() {
+        // TODO invoked is always false
         return invoked;
     }
 
@@ -34,7 +35,9 @@ public abstract class Invoker {
         return new Invoker() {
             @Override
             void invoke(SshSession session) throws IOException {
-                if (isInvoked() == true) throw new IllegalStateException("Already invoked.");
+                if (isInvoked()) {
+                    throw new IllegalStateException("Already invoked.");
+                }
 
                 session.startSubSystem(subsystem);
             }
index 3cb608db6a87c3ef121cc6a4edf0f0676fab9912..7beee649abfe0501e60850fda0db79dd96c7bb86 100644 (file)
@@ -23,7 +23,7 @@ import java.util.Map;
  */
 public class SshClient {
     private final VirtualSocket socket;
-    private final Map<Integer, SshSession> openSessions = new HashMap();
+    private final Map<Integer, SshSession> openSessions = new HashMap<>();
     private final AuthenticationHandler authenticationHandler;
     private Connection connection;
 
@@ -33,8 +33,9 @@ public class SshClient {
     }
 
     public SshSession openSession() throws IOException {
-        if (connection == null)
+        if (connection == null) {
             connect();
+        }
 
         Session session = connection.openSession();
         SshSession sshSession = new SshSession(session);
@@ -52,7 +53,7 @@ public class SshClient {
 
     public void closeSession(SshSession session) {
         if (session.getState() == Channel.STATE_OPEN || session.getState() == Channel.STATE_OPENING) {
-            session.session.close();
+            session.close();
         }
     }
 
@@ -62,7 +63,8 @@ public class SshClient {
 
         openSessions.clear();
 
-        if (connection != null)
+        if (connection != null) {
             connection.close();
+        }
     }
 }
index 4213fe3e0642db6257b3e655c407a4394785fca3..6350dd154415b510515f919d94c88d06ecac5314 100644 (file)
@@ -27,16 +27,14 @@ import org.opendaylight.controller.netconf.util.handler.ssh.virtualsocket.Virtua
  * pipeline.
  */
 public class SshClientAdapter implements Runnable {
+    private static final int BUFFER_SIZE = 1024;
+
     private final SshClient sshClient;
     private final Invoker invoker;
 
-    private SshSession session;
-    private InputStream stdOut;
-    private InputStream stdErr;
     private OutputStream stdIn;
 
-    private Queue<ByteBuf> postponned = new LinkedList<>();
-
+    private Queue<ByteBuf> postponed = new LinkedList<>();
 
     private ChannelHandlerContext ctx;
     private ChannelPromise disconnectPromise;
@@ -52,22 +50,22 @@ public class SshClientAdapter implements Runnable {
 
     public void run() {
         try {
-            session = sshClient.openSession();
+            SshSession session = sshClient.openSession();
             invoker.invoke(session);
-            stdOut = session.getStdout();
-            stdErr = session.getStderr();
+            InputStream stdOut = session.getStdout();
+            session.getStderr();
 
             synchronized (lock) {
 
                 stdIn = session.getStdin();
-                ByteBuf message = null;
-                while ((message = postponned.poll()) != null) {
+                ByteBuf message;
+                while ((message = postponed.poll()) != null) {
                     writeImpl(message);
                 }
             }
 
             while (stopRequested.get() == false) {
-                byte[] readBuff = new byte[1024];
+                byte[] readBuff = new byte[BUFFER_SIZE];
                 int c = stdOut.read(readBuff);
                 if (c == -1) {
                     continue;
@@ -89,8 +87,9 @@ public class SshClientAdapter implements Runnable {
             sshClient.close();
 
             synchronized (lock) {
-                if (disconnectPromise != null)
+                if (disconnectPromise != null) {
                     ctx.disconnect(disconnectPromise);
+                }
             }
         }
     }
@@ -99,7 +98,7 @@ public class SshClientAdapter implements Runnable {
     public void write(ByteBuf message) throws IOException {
         synchronized (lock) {
             if (stdIn == null) {
-                postponned.add(message);
+                postponed.add(message);
                 return;
             }
             writeImpl(message);
@@ -119,8 +118,10 @@ public class SshClientAdapter implements Runnable {
     }
 
     public void start(ChannelHandlerContext ctx) {
-        if (this.ctx != null)
-            return; // context is already associated.
+        if (this.ctx != null) {
+            // context is already associated.
+            return;
+        }
         this.ctx = ctx;
         new Thread(this).start();
     }
index df400aa1413e64108dab66190dd763b4778dc0ce..411036c975baf2f29b9f98e4c69b8956acf64474 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.util.handler.ssh.client;
 import ch.ethz.ssh2.Session;
 import ch.ethz.ssh2.StreamGobbler;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -18,8 +19,8 @@ import java.io.OutputStream;
 /**
  * Wrapper class for proprietary SSH sessions implementations
  */
-public class SshSession {
-    final Session session;
+public class SshSession implements Closeable {
+    private final Session session;
 
     public SshSession(Session session) {
         this.session = session;
@@ -61,8 +62,8 @@ public class SshSession {
         return session.waitUntilDataAvailable(timeout);
     }
 
-    public int waitForCondition(int condition_set, long timeout) {
-        return session.waitForCondition(condition_set, timeout);
+    public int waitForCondition(int conditionSet, long timeout) {
+        return session.waitForCondition(conditionSet, timeout);
     }
 
     public Integer getExitStatus() {
@@ -72,4 +73,9 @@ public class SshSession {
     public String getExitSignal() {
         return session.getExitSignal();
     }
+
+    @Override
+    public void close() {
+        session.close();
+    }
 }
index 4b9bfbf5f826ee13c34127d902c2ad583d5f8eb4..313ea932413b63b36c5d20cc6cb1a9570205ab2a 100644 (file)
@@ -39,7 +39,9 @@ public class ChannelInputStream extends InputStream implements ChannelInboundHan
 
             b[off] = (byte)c;
 
-            if(this.bb.readableBytes() == 0) return bytesRead;
+            if(this.bb.readableBytes() == 0) {
+                return bytesRead;
+            }
 
             int ltr = len-1;
             ltr = (ltr <= bb.readableBytes()) ? ltr : bb.readableBytes();
@@ -72,28 +74,23 @@ public class ChannelInputStream extends InputStream implements ChannelInboundHan
         }
     }
 
-    public void channelRegistered(ChannelHandlerContext ctx)
-            throws Exception {
+    public void channelRegistered(ChannelHandlerContext ctx) {
         ctx.fireChannelRegistered();
     }
 
-    public void channelUnregistered(ChannelHandlerContext ctx)
-            throws Exception {
+    public void channelUnregistered(ChannelHandlerContext ctx) {
         ctx.fireChannelUnregistered();
     }
 
-    public void channelActive(ChannelHandlerContext ctx)
-            throws Exception {
+    public void channelActive(ChannelHandlerContext ctx) {
         ctx.fireChannelActive();
     }
 
-    public void channelInactive(ChannelHandlerContext ctx)
-            throws Exception {
+    public void channelInactive(ChannelHandlerContext ctx) {
         ctx.fireChannelInactive();
     }
 
-    public void channelRead(ChannelHandlerContext ctx, Object o)
-            throws Exception {
+    public void channelRead(ChannelHandlerContext ctx, Object o) {
         synchronized(lock) {
             this.bb.discardReadBytes();
             this.bb.writeBytes((ByteBuf) o);
@@ -101,31 +98,25 @@ public class ChannelInputStream extends InputStream implements ChannelInboundHan
         }
     }
 
-    public void channelReadComplete(ChannelHandlerContext ctx)
-            throws Exception {
+    public void channelReadComplete(ChannelHandlerContext ctx) {
         ctx.fireChannelReadComplete();
     }
 
-    public void userEventTriggered(ChannelHandlerContext ctx, Object o)
-            throws Exception {
+    public void userEventTriggered(ChannelHandlerContext ctx, Object o) {
         ctx.fireUserEventTriggered(o);
     }
 
-    public void channelWritabilityChanged(ChannelHandlerContext ctx)
-            throws Exception {
+    public void channelWritabilityChanged(ChannelHandlerContext ctx) {
         ctx.fireChannelWritabilityChanged();
     }
 
-    public void handlerAdded(ChannelHandlerContext ctx)
-            throws Exception {
+    public void handlerAdded(ChannelHandlerContext ctx) {
     }
 
-    public void handlerRemoved(ChannelHandlerContext ctx)
-            throws Exception {
+    public void handlerRemoved(ChannelHandlerContext ctx) {
     }
 
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable)
-            throws Exception {
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {
         ctx.fireExceptionCaught(throwable);
     }
 }
index b1314a6eedfde68f71ccb26e27b0c6d73b8e51cd..cd7ec5439bc422e492b874b64e1be89211213d88 100644 (file)
@@ -14,7 +14,6 @@ import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.ChannelOutboundHandler;
 import io.netty.channel.ChannelPromise;
 
-import java.io.IOException;
 import java.io.OutputStream;
 import java.net.SocketAddress;
 
@@ -27,7 +26,7 @@ public class ChannelOutputStream extends OutputStream implements ChannelOutbound
     private ChannelHandlerContext ctx;
 
     @Override
-    public void flush() throws IOException {
+    public void flush() {
         synchronized(lock) {
             ctx.writeAndFlush(buff).awaitUninterruptibly();
             buff = Unpooled.buffer();
@@ -35,51 +34,44 @@ public class ChannelOutputStream extends OutputStream implements ChannelOutbound
     }
 
     @Override
-    public void write(int b) throws IOException {
+    public void write(int b) {
         synchronized(lock) {
             buff.writeByte(b);
         }
     }
 
     public void bind(ChannelHandlerContext ctx, SocketAddress localAddress,
-                     ChannelPromise promise) throws Exception {
+                     ChannelPromise promise) {
         ctx.bind(localAddress, promise);
     }
 
     public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress,
-                        SocketAddress localAddress, ChannelPromise promise)
-            throws Exception {
+                        SocketAddress localAddress, ChannelPromise promise) {
         this.ctx = ctx;
         ctx.connect(remoteAddress, localAddress, promise);
     }
 
-    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise)
-            throws Exception {
+    public void disconnect(ChannelHandlerContext ctx, ChannelPromise promise) {
         ctx.disconnect(promise);
     }
 
-    public void close(ChannelHandlerContext ctx, ChannelPromise promise)
-            throws Exception {
+    public void close(ChannelHandlerContext ctx, ChannelPromise promise) {
         ctx.close(promise);
     }
 
-    public void deregister(ChannelHandlerContext ctx, ChannelPromise channelPromise)
-            throws Exception {
+    public void deregister(ChannelHandlerContext ctx, ChannelPromise channelPromise) {
         ctx.deregister(channelPromise);
     }
 
-    public void read(ChannelHandlerContext ctx)
-            throws Exception {
+    public void read(ChannelHandlerContext ctx) {
         ctx.read();
     }
 
-    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise)
-            throws Exception {
+    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
         // pass
     }
 
-    public void flush(ChannelHandlerContext ctx)
-            throws Exception {
+    public void flush(ChannelHandlerContext ctx) {
         // pass
     }
 
@@ -91,8 +83,7 @@ public class ChannelOutputStream extends OutputStream implements ChannelOutbound
             throws Exception {
     }
 
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
-            throws Exception {
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
         ctx.fireExceptionCaught(cause);
     }
 }
index 1011ca16be84803d4bfbe6f8f083335782de6538..36c2c1c3295736bf9cc183fbe53256ac847ff15b 100644 (file)
@@ -26,6 +26,9 @@ import java.nio.channels.SocketChannel;
  * are able to use full potential of NIO environment.
  */
 public class VirtualSocket extends Socket implements ChannelHandler {
+    private static final String INPUT_STREAM = "inputStream";
+    private static final String OUTPUT_STREAM = "outputStream";
+
     private final ChannelInputStream chis = new ChannelInputStream();
     private final ChannelOutputStream chos = new ChannelOutputStream();
     private ChannelHandlerContext ctx;
@@ -39,29 +42,30 @@ public class VirtualSocket extends Socket implements ChannelHandler {
         return this.chos;
     }
 
-    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
+    public void handlerAdded(ChannelHandlerContext ctx) {
         this.ctx = ctx;
 
-        if (ctx.channel().pipeline().get("outputStream") == null) {
-            ctx.channel().pipeline().addFirst("outputStream", chos);
+        if (ctx.channel().pipeline().get(OUTPUT_STREAM) == null) {
+            ctx.channel().pipeline().addFirst(OUTPUT_STREAM, chos);
         }
 
-        if (ctx.channel().pipeline().get("inputStream") == null) {
-            ctx.channel().pipeline().addFirst("inputStream", chis);
+        if (ctx.channel().pipeline().get(INPUT_STREAM) == null) {
+            ctx.channel().pipeline().addFirst(INPUT_STREAM, chis);
         }
     }
 
-    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
-        if (ctx.channel().pipeline().get("outputStream") != null) {
-            ctx.channel().pipeline().remove("outputStream");
+    public void handlerRemoved(ChannelHandlerContext ctx) {
+        if (ctx.channel().pipeline().get(OUTPUT_STREAM) != null) {
+            ctx.channel().pipeline().remove(OUTPUT_STREAM);
         }
 
-        if (ctx.channel().pipeline().get("inputStream") != null) {
-            ctx.channel().pipeline().remove("inputStream");
+        if (ctx.channel().pipeline().get(INPUT_STREAM) != null) {
+            ctx.channel().pipeline().remove(INPUT_STREAM);
         }
     }
 
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) throws Exception {
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {
+        // TODO exceptionCaught is deprecated transform this handler
         ctx.fireExceptionCaught(throwable);
     }
 
@@ -80,7 +84,9 @@ public class VirtualSocket extends Socket implements ChannelHandler {
     public InetAddress getInetAddress() {
         InetSocketAddress isa = getInetSocketAddress();
 
-        if (isa == null) throw new VirtualSocketException();
+        if (isa == null) {
+            throw new VirtualSocketException();
+        }
 
         return getInetSocketAddress().getAddress();
     }
index f3ca30d2c40a4f924b0b35b5d196ba53295acb57..d1e064eaeb51cac6ed5462e11ccf0600214fd12d 100644 (file)
@@ -18,7 +18,7 @@ import java.util.regex.Pattern;
  * session's connection. Provided information can be reported via netconf
  * monitoring.
  * <pre>
- * It has pattern "[username; host-address:port; transport; session-identifier;]"
+ * It has PATTERN "[username; host-address:port; transport; session-identifier;]"
  * username - name of account on a remote
  * host-address - client's IP address
  * port - port number
@@ -92,20 +92,20 @@ public class NetconfHelloMessageAdditionalHeader {
     }
 
     // TODO IPv6
-    private static final Pattern pattern = Pattern
+    private static final Pattern PATTERN = Pattern
             .compile("\\[(?<username>[^;]+);(?<address>[0-9\\.]+)[:/](?<port>[0-9]+);(?<transport>[a-z]+)[^\\]]+\\]");
-    private static final Pattern customHeaderPattern = Pattern
+    private static final Pattern CUSTOM_HEADER_PATTERN = Pattern
             .compile("\\[(?<username>[^;]+);(?<address>[0-9\\.]+)[:/](?<port>[0-9]+);(?<transport>[a-z]+);(?<sessionIdentifier>[a-z]+)[^\\]]+\\]");
 
     /**
      * Parse additional header from a formatted string
      */
     public static NetconfHelloMessageAdditionalHeader fromString(String additionalHeader) {
-        additionalHeader = additionalHeader.trim();
-        Matcher matcher = pattern.matcher(additionalHeader);
-        Matcher matcher2 = customHeaderPattern.matcher(additionalHeader);
+        String additionalHeaderTrimmed = additionalHeader.trim();
+        Matcher matcher = PATTERN.matcher(additionalHeaderTrimmed);
+        Matcher matcher2 = CUSTOM_HEADER_PATTERN.matcher(additionalHeaderTrimmed);
         Preconditions.checkArgument(matcher.matches(), "Additional header in wrong format %s, expected %s",
-                additionalHeader, pattern);
+                additionalHeaderTrimmed, PATTERN);
 
         String username = matcher.group("username");
         String address = matcher.group("address");
index 0d83a72bd39b9f8e7fecdd7d9eb39d87f18ed6ef..8bd6b8865933d7191a063055834ce3fb98b0bbe4 100644 (file)
@@ -11,14 +11,19 @@ package org.opendaylight.controller.netconf.util.messages;
 import com.google.common.base.Charsets;
 
 public class NetconfMessageConstants {
+    /**
+     * The NETCONF 1.0 old-style message separator. This is framing mechanism
+     * is used by default.
+     */
+    public static final byte[] END_OF_MESSAGE = "]]>]]>".getBytes(Charsets.UTF_8);
 
-    public static final byte[] endOfMessage = "]]>]]>".getBytes(Charsets.UTF_8);
+    // bytes
 
-    public static final byte[] endOfChunk = "\n##\n".getBytes(Charsets.UTF_8);
+    public static final int MIN_HEADER_LENGTH = 4;
 
-    public static final int MAX_CHUNK_SIZE = 1024; // bytes
+    // bytes
 
-    public static final int MIN_HEADER_LENGTH = 4; // bytes
+    public static final int MAX_HEADER_LENGTH = 13;
 
-    public static final int MAX_HEADER_LENGTH = 13; // bytes
-}
\ No newline at end of file
+    public static final byte[] END_OF_CHUNK = "\n##\n".getBytes(Charsets.UTF_8);
+}
index a61541b9146556f7b71e0766e0c8b99a65a81fd9..fa26455c9875d7245429ef72f2ce11b57c56acac 100644 (file)
@@ -8,49 +8,29 @@
 
 package org.opendaylight.controller.netconf.util.messages;
 
+import java.nio.ByteBuffer;
+
 import com.google.common.base.Charsets;
 import com.google.common.base.Preconditions;
 
-import java.nio.ByteBuffer;
-
 /**
  * Netconf message header is used only when chunked framing mechanism is
  * supported. The header consists of only the length field.
  */
+@Deprecated
 public final class NetconfMessageHeader {
-
-    private long length;
-
     // \n#<length>\n
-    private static final byte[] headerBegin = new byte[] { (byte) 0x0a, (byte) 0x23 };
+    private static final byte[] HEADER_START = new byte[] { (byte) 0x0a, (byte) 0x23 };
+    private static final byte HEADER_END = (byte) 0x0a;
+    private final long length;
 
-    private static final byte headerEnd = (byte) 0x0a;
-
-    private boolean parsed = false;
-
-    public NetconfMessageHeader() {
-
-    }
-
-    public NetconfMessageHeader fromBytes(final byte[] bytes) {
-        // the length is variable therefore bytes between headerBegin and
-        // headerEnd mark the length
-        // the length should be only numbers and therefore easily parsed with
-        // ASCII
-        this.length = Long.parseLong(Charsets.US_ASCII.decode(
-                ByteBuffer.wrap(bytes, headerBegin.length, bytes.length - headerBegin.length - 1)).toString());
-        Preconditions.checkState(this.length < Integer.MAX_VALUE && this.length > 0);
-        this.parsed = true;
-        return this;
+    public NetconfMessageHeader(final long length) {
+        Preconditions.checkArgument(length < Integer.MAX_VALUE && length > 0);
+        this.length = length;
     }
 
     public byte[] toBytes() {
-        final byte[] l = String.valueOf(this.length).getBytes(Charsets.US_ASCII);
-        final byte[] h = new byte[headerBegin.length + l.length + 1];
-        System.arraycopy(headerBegin, 0, h, 0, headerBegin.length);
-        System.arraycopy(l, 0, h, headerBegin.length, l.length);
-        System.arraycopy(new byte[] { headerEnd }, 0, h, headerBegin.length + l.length, 1);
-        return h;
+        return toBytes(this.length);
     }
 
     // FIXME: improve precision to long
@@ -58,22 +38,23 @@ public final class NetconfMessageHeader {
         return (int) this.length;
     }
 
-    public void setLength(final int length) {
-        this.length = length;
-    }
+    public static NetconfMessageHeader fromBytes(final byte[] bytes) {
+        // the length is variable therefore bytes between headerBegin and
+        // headerEnd mark the length
+        // the length should be only numbers and therefore easily parsed with
+        // ASCII
+        long length = Long.parseLong(Charsets.US_ASCII.decode(
+                ByteBuffer.wrap(bytes, HEADER_START.length, bytes.length - HEADER_START.length - 1)).toString());
 
-    /**
-     * @return the parsed
-     */
-    public boolean isParsed() {
-        return this.parsed;
+        return new NetconfMessageHeader(length);
     }
 
-    /**
-     * @param parsed
-     *            the parsed to set
-     */
-    public void setParsed() {
-        this.parsed = false;
+    public static byte[] toBytes(final long length) {
+        final byte[] l = String.valueOf(length).getBytes(Charsets.US_ASCII);
+        final byte[] h = new byte[HEADER_START.length + l.length + 1];
+        System.arraycopy(HEADER_START, 0, h, 0, HEADER_START.length);
+        System.arraycopy(l, 0, h, HEADER_START.length, l.length);
+        System.arraycopy(new byte[] { HEADER_END }, 0, h, HEADER_START.length + l.length, 1);
+        return h;
     }
 }
index 46053e734ebf006154e26d5c8b7564ff6a36eedd..91eb86908b169ca9ecff8a77fb803b2d7ee60184 100644 (file)
@@ -13,7 +13,9 @@ import org.opendaylight.controller.netconf.util.xml.XmlElement;
 import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
 import org.w3c.dom.Document;
 
-public class NetconfMessageUtil {
+public final class NetconfMessageUtil {
+
+    private NetconfMessageUtil() {}
 
     public static boolean isOKMessage(NetconfMessage message) {
         return isOKMessage(message.getDocument());
index 6dc00bb1509e97b0a485b89e90b0248a642e7a1a..de2d6d7e0c354ada3bcf1fb4f1b630b186c34e3c 100644 (file)
@@ -29,9 +29,11 @@ import javax.xml.xpath.XPathExpression;
 import java.io.InputStream;
 import java.util.Map.Entry;
 
-public class SendErrorExceptionUtil {
+public final class SendErrorExceptionUtil {
     private static final Logger logger = LoggerFactory.getLogger(SendErrorExceptionUtil.class);
 
+    private SendErrorExceptionUtil() {}
+
     public static void sendErrorMessage(final NetconfSession session,
             final NetconfDocumentedException sendErrorException) {
         logger.trace("Sending error {}", sendErrorException.getMessage(), sendErrorException);
@@ -68,8 +70,9 @@ public class SendErrorExceptionUtil {
             for (int i = 0; i < incomingAttributes.getLength(); i++) {
                 final Attr attr = (Attr) incomingAttributes.item(i);
                 // skip namespace
-                if (attr.getNodeName().equals(XmlUtil.XMLNS_ATTRIBUTE_KEY))
+                if (attr.getNodeName().equals(XmlUtil.XMLNS_ATTRIBUTE_KEY)) {
                     continue;
+                }
                 rpcReply.setAttributeNode((Attr) errorDocument.importNode(attr, true));
             }
         } catch (final Exception e) {
index 38563cba93eef1f727330b17ff72879a012f70ff..80eaa26de184ddc29993bd847d1c34b0e7becd09 100644 (file)
@@ -17,12 +17,12 @@ import java.net.InetSocketAddress;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
-public class NetconfConfigUtil {
+public final class NetconfConfigUtil {
     private static final Logger logger = LoggerFactory.getLogger(NetconfConfigUtil.class);
 
     private static final String PREFIX_PROP = "netconf.";
 
-
+    private NetconfConfigUtil() {}
 
     private enum InfixProp {
         tcp, ssh
index d9303228f95b55773c3a15e7ef6e0bc7b01cef71..3247e0f7a0e034402fcedda91b2b1e5ece7a1fe8 100644 (file)
@@ -13,7 +13,9 @@ import javax.xml.xpath.XPathExpression;
 import javax.xml.xpath.XPathExpressionException;
 import javax.xml.xpath.XPathFactory;
 
-public class XMLNetconfUtil {
+public final class XMLNetconfUtil {
+
+    private XMLNetconfUtil() {}
 
     public static XPathExpression compileXPath(String xPath) {
         final XPathFactory xPathfactory = XPathFactory.newInstance();
index 18a94c6d07ff7cf74289bfb5d3e057967a61e86c..1fbae1ee2d6e52c404742655ccd059e9038fd803 100644 (file)
@@ -31,9 +31,9 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-public class XmlElement {
+public final class XmlElement {
 
-    public final Element element;
+    private final Element element;
 
     private XmlElement(Element element) {
         this.element = element;
@@ -123,9 +123,6 @@ public class XmlElement {
 
     public void appendChild(Element element) {
         this.element.appendChild(element);
-        // Element newElement = (Element) element.cloneNode(true);
-        // newElement.appendChild(configElement);
-        // return XmlElement.fromDomElement(newElement);
     }
 
     public Element getDomElement() {
@@ -153,10 +150,12 @@ public class XmlElement {
         final List<XmlElement> result = new ArrayList<>();
         for (int i = 0; i < childNodes.getLength(); i++) {
             Node item = childNodes.item(i);
-            if (item instanceof Element == false)
+            if (item instanceof Element == false) {
                 continue;
-            if (strat.accept((Element) item))
+            }
+            if (strat.accept((Element) item)) {
                 result.add(new XmlElement((Element) item));
+            }
         }
 
         return result;
@@ -290,12 +289,12 @@ public class XmlElement {
     public String getNamespace() {
         String namespaceURI = element.getNamespaceURI();
         Preconditions.checkState(namespaceURI != null, "No namespace defined for %s", this);
-        return namespaceURI.toString();
+        return namespaceURI;
     }
 
     @Override
     public String toString() {
-        final StringBuffer sb = new StringBuffer("XmlElement{");
+        final StringBuilder sb = new StringBuilder("XmlElement{");
         sb.append("name='").append(getName()).append('\'');
         if (element.getNamespaceURI() != null) {
             sb.append(", namespace='").append(getNamespace()).append('\'');
@@ -320,7 +319,7 @@ public class XmlElement {
     public Map.Entry<String/* prefix */, String/* namespace */> findNamespaceOfTextContent() {
         Map<String, String> namespaces = extractNamespaces(element);
         String textContent = getTextContent();
-        int indexOfColon = textContent.indexOf(":");
+        int indexOfColon = textContent.indexOf(':');
         String prefix;
         if (indexOfColon > -1) {
             prefix = textContent.substring(0, indexOfColon);
@@ -360,15 +359,18 @@ public class XmlElement {
 
     @Override
     public boolean equals(Object o) {
-        if (this == o)
+        if (this == o) {
             return true;
-        if (o == null || getClass() != o.getClass())
+        }
+        if (o == null || getClass() != o.getClass()) {
             return false;
+        }
 
         XmlElement that = (XmlElement) o;
 
-        if (!element.isEqualNode(that.element))
+        if (!element.isEqualNode(that.element)) {
             return false;
+        }
 
         return true;
     }
@@ -392,7 +394,7 @@ public class XmlElement {
         return true;
     }
 
-    private static interface ElementFilteringStrategy {
+    private interface ElementFilteringStrategy {
         boolean accept(Element e);
     }
 }
index c410cf30b0abd00290bbc178c5ea3c9cbc7c0a21..4a6586cd1d8bf8ee0e9e4cbef66e62048cf1e5e6 100644 (file)
@@ -7,7 +7,9 @@
  */
 package org.opendaylight.controller.netconf.util.xml;
 
-public class XmlNetconfConstants {
+public final class XmlNetconfConstants {
+
+    private XmlNetconfConstants() {}
 
     public static final String MOUNTPOINTS = "mountpoints";
     public static final String MOUNTPOINT = "mountpoint";
index de0ebccdca428d8285d26d74b2f4e9fd54b5d353..8108c8e7402fac29469cf7804efd96e1dc6455df 100644 (file)
@@ -21,8 +21,11 @@ import org.xml.sax.SAXException;
 
 import com.google.common.base.Preconditions;
 
-public class XmlNetconfValidator {
-    static final Schema schema;
+public final class XmlNetconfValidator {
+
+    private static final Schema SCHEMA;
+
+    private XmlNetconfValidator() {}
 
     static {
         final InputStream xmlSchema = XmlNetconfValidator.class.getResourceAsStream("/xml.xsd");
@@ -30,11 +33,11 @@ public class XmlNetconfValidator {
 
         final InputStream rfc4714Schema = XmlNetconfValidator.class.getResourceAsStream("/rfc4741.xsd");
         Preconditions.checkNotNull(rfc4714Schema, "Cannot find rfc4741.xsd");
-        schema = XmlUtil.loadSchema(xmlSchema, rfc4714Schema);
+        SCHEMA = XmlUtil.loadSchema(xmlSchema, rfc4714Schema);
     }
 
     public static void validate(Document inputDocument) throws SAXException, IOException {
-        final Validator validator = schema.newValidator();
+        final Validator validator = SCHEMA.newValidator();
         final Source source = new DOMSource(inputDocument);
         validator.validate(source);
     }
index 137e215a31eb13423b6438671faed529a2fc7ce3..238249dbbd8d49086b38c1696cb6d0cb685909fe 100644 (file)
@@ -41,9 +41,21 @@ import org.xml.sax.SAXException;
 
 import com.google.common.base.Charsets;
 
-public class XmlUtil {
+public final class XmlUtil {
 
     public static final String XMLNS_ATTRIBUTE_KEY = "xmlns";
+    private static final DocumentBuilderFactory BUILDERFACTORY;
+
+    static {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        factory.setCoalescing(true);
+        factory.setIgnoringElementContentWhitespace(true);
+        factory.setIgnoringComments(true);
+        BUILDERFACTORY = factory;
+    }
+
+    private XmlUtil() {}
 
     public static Element readXmlToElement(String xmlContent) throws SAXException, IOException {
         Document doc = readXmlToDocument(xmlContent);
@@ -59,13 +71,15 @@ public class XmlUtil {
         return readXmlToDocument(new ByteArrayInputStream(xmlContent.getBytes(Charsets.UTF_8)));
     }
 
+    // TODO improve exceptions throwing
+    // along with XmlElement
+
     public static Document readXmlToDocument(InputStream xmlContent) throws SAXException, IOException {
-        DocumentBuilderFactory factory = getDocumentBuilderFactory();
         DocumentBuilder dBuilder;
         try {
-            dBuilder = factory.newDocumentBuilder();
+            dBuilder = BUILDERFACTORY.newDocumentBuilder();
         } catch (ParserConfigurationException e) {
-            throw new RuntimeException(e);
+            throw new RuntimeException("Failed to parse XML document", e);
         }
         Document doc = dBuilder.parse(xmlContent);
 
@@ -77,23 +91,13 @@ public class XmlUtil {
         return readXmlToDocument(new FileInputStream(xmlFile)).getDocumentElement();
     }
 
-    private static final DocumentBuilderFactory getDocumentBuilderFactory() {
-        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
-        factory.setNamespaceAware(true);
-        factory.setCoalescing(true);
-        factory.setIgnoringElementContentWhitespace(true);
-        factory.setIgnoringComments(true);
-        return factory;
-    }
-
     public static Document newDocument() {
-        DocumentBuilderFactory factory = getDocumentBuilderFactory();
         try {
-            DocumentBuilder builder = factory.newDocumentBuilder();
+            DocumentBuilder builder = BUILDERFACTORY.newDocumentBuilder();
             Document document = builder.newDocument();
             return document;
         } catch (ParserConfigurationException e) {
-            throw new RuntimeException(e);
+            throw new RuntimeException("Failed to create document", e);
         }
     }
 
@@ -135,14 +139,13 @@ public class XmlUtil {
         try {
             Transformer transformer = TransformerFactory.newInstance().newTransformer();
             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
-            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, addXmlDeclaration == true ? "no" : "yes");
+            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, addXmlDeclaration ? "no" : "yes");
 
             StreamResult result = new StreamResult(new StringWriter());
             DOMSource source = new DOMSource(xml);
             transformer.transform(source, result);
 
-            String xmlString = result.getWriter().toString();
-            return xmlString;
+            return result.getWriter().toString();
         } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) {
             throw new RuntimeException("Unable to serialize xml element " + xml, e);
         }
diff --git a/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/handler/NetconfChunkAggregatorTest.java b/opendaylight/netconf/netconf-util/src/test/java/org/opendaylight/controller/netconf/util/handler/NetconfChunkAggregatorTest.java
new file mode 100644 (file)
index 0000000..bdc1835
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.util.handler;
+
+import com.google.common.base.Charsets;
+import com.google.common.collect.Lists;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import junit.framework.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.util.List;
+
+public class NetconfChunkAggregatorTest {
+
+    private static final String CHUNKED_MESSAGE = "\n#4\n" +
+            "<rpc" +
+            "\n#18\n" +
+            " message-id=\"102\"\n" +
+            "\n#79\n" +
+            "     xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n" +
+            "  <close-session/>\n" +
+            "</rpc>" +
+            "\n##\n";
+
+    public static final String EXPECTED_MESSAGE = "<rpc message-id=\"102\"\n" +
+            "     xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.0\">\n" +
+            "  <close-session/>\n" +
+            "</rpc>";
+
+    private static final String CHUNKED_MESSAGE_ONE = "\n#101\n" + EXPECTED_MESSAGE + "\n##\n";
+
+    private static NetconfChunkAggregator agr;
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        agr = new NetconfChunkAggregator();
+    }
+
+    @Test
+    public void testMultipleChunks() throws Exception {
+        List<Object> output = Lists.newArrayList();
+        ByteBuf input = Unpooled.copiedBuffer(CHUNKED_MESSAGE.getBytes(Charsets.UTF_8));
+        agr.decode(null, input, output);
+
+        Assert.assertEquals(1, output.size());
+        ByteBuf chunk = (ByteBuf) output.get(0);
+
+        Assert.assertEquals(EXPECTED_MESSAGE, chunk.toString(Charsets.UTF_8));
+    }
+
+    @Test
+    public void testOneChunks() throws Exception {
+        List<Object> output = Lists.newArrayList();
+        ByteBuf input = Unpooled.copiedBuffer(CHUNKED_MESSAGE_ONE.getBytes(Charsets.UTF_8));
+        agr.decode(null, input, output);
+
+        Assert.assertEquals(1, output.size());
+        ByteBuf chunk = (ByteBuf) output.get(0);
+
+        Assert.assertEquals(EXPECTED_MESSAGE, chunk.toString(Charsets.UTF_8));
+    }
+
+
+}
index 6b7bffcd862394c678b1dfa69e65bbaad9481f89..18830f85ddcdc8595bc7be40dc8f439d1dc3bec4 100644 (file)
@@ -16,14 +16,13 @@ import java.util.List;
 
 import org.junit.Test;
 import org.opendaylight.controller.netconf.util.handler.NetconfXMLToHelloMessageDecoder;
-import org.opendaylight.controller.netconf.util.handler.NetconfXMLToMessageDecoder;
 
 import com.google.common.io.Files;
 
 public class NetconfMessageFactoryTest {
     @Test
     public void testAuth() throws Exception {
-        NetconfXMLToMessageDecoder parser = new NetconfXMLToHelloMessageDecoder();
+        NetconfXMLToHelloMessageDecoder parser = new NetconfXMLToHelloMessageDecoder();
         File authHelloFile = new File(getClass().getResource("/netconfMessages/client_hello_with_auth.xml").getFile());
 
         final List<Object> out = new ArrayList<>();
index 62c6a20997ed40cd3427f17d6f77d18d83119caf..8062f52e6a9cc2d639dba6e1a85a473bb2a5f444 100644 (file)
                     </type>
                     <name>id-test</name>
                     <identities>
-                        <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity1</afi>
-                        <safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity2</safi>
+                        <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity1</afi>
+                        <safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity2</safi>
                     </identities>
                     <identities>
-                        <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity2</afi>
-                        <safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity1</safi>
+                        <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity2</afi>
+                        <safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity1</safi>
                     </identities>
                     <identities-container>
-                        <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity2</afi>
+                        <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity2</afi>
                     </identities-container>
-                    <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity1</afi>
+                    <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:config:test:types">prefix:test-identity1</afi>
                 </module>
             </modules>
 
index b601eef4b5ef134423d563c86327aabd201bd495..f67828bdab68fb678a67c038568b34d3a87321af 100644 (file)
     <version>1.1-SNAPSHOT</version>
     <packaging>bundle</packaging>
 
-    <properties>
-        <ganymed.version>build209</ganymed.version>
-    </properties>
-
     <dependencies>
         <dependency>
             <groupId>org.osgi</groupId>