Merge "Resolve Bug:445 Remove freemarker from config code generator."
authorTony Tkacik <ttkacik@cisco.com>
Tue, 15 Apr 2014 10:26:02 +0000 (10:26 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 15 Apr 2014 10:26:02 +0000 (10:26 +0000)
153 files changed:
.gitignore
opendaylight/clustering/services_implementation/pom.xml
opendaylight/clustering/services_implementation/src/main/java/org/infinispan/interceptors/distribution/BaseDistributionInterceptor.java [deleted file]
opendaylight/clustering/services_implementation/src/main/resources/config/infinispan-config.xml
opendaylight/commons/opendaylight/pom.xml
opendaylight/commons/protocol-framework/pom.xml
opendaylight/config/config-module-archetype/src/main/resources/archetype-resources/pom.xml
opendaylight/config/config-plugin-parent/pom.xml
opendaylight/config/logback-config/pom.xml
opendaylight/config/netty-threadgroup-config/pom.xml
opendaylight/config/pom.xml
opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini
opendaylight/distribution/opendaylight/src/main/resources/run.bat
opendaylight/distribution/opendaylight/src/main/resources/run.sh
opendaylight/forwardingrulesmanager/api/pom.xml
opendaylight/forwardingrulesmanager/api/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java
opendaylight/forwardingrulesmanager/implementation/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManager.java
opendaylight/md-sal/compatibility/flow-management-compatibility/pom.xml
opendaylight/md-sal/compatibility/inventory-topology-compatibility/pom.xml
opendaylight/md-sal/forwardingrules-manager/pom.xml
opendaylight/md-sal/inventory-manager/pom.xml
opendaylight/md-sal/model/pom.xml
opendaylight/md-sal/pom.xml
opendaylight/md-sal/sal-binding-broker/pom.xml
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/AbstractForwardedTransaction.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/BrokerImplClassLoader.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/BrokerImplClassLoader.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/MountPointManagerImpl.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/RpcProxyContext.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProxyContext.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentConnector.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.xtend [deleted file]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/RuntimeCodeGeneratorTest.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/mock/ReferencableObject.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/util/BindingTestContext.java
opendaylight/md-sal/sal-binding-config/pom.xml
opendaylight/md-sal/sal-binding-dom-it/pom.xml
opendaylight/md-sal/sal-binding-dom-it/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/CrossBrokerRpcTest.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizationException.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizationOperation.java
opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizer.java
opendaylight/md-sal/sal-dom-api/pom.xml
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RoutedRpcDefaultImplementation.java
opendaylight/md-sal/sal-dom-api/src/main/java/org/opendaylight/controller/sal/core/api/RpcImplementation.java
opendaylight/md-sal/sal-dom-broker/pom.xml
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/broker/impl/compat/BackwardsCompatibleTransaction.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/DataChangeEventResolver.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/InMemoryDOMDataStore.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/MutableDataTree.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/StoreUtils.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ListenerRegistrationNode.java [deleted file]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ListenerTree.java [new file with mode: 0644]
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/NodeModification.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/TreeNodeUtils.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/MountPointImpl.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/SchemaAwareRpcBroker.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/osgi/RpcProvisionRegistryProxy.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RoutedRpcProcessor.java
opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/spi/RpcRouter.java
opendaylight/md-sal/sal-netconf-connector/pom.xml
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/InventoryUtils.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDevice.xtend
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceListener.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfDeviceTwoPhaseCommitTransaction.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfInventoryUtils.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfMapping.xtend
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/NetconfRemoteSchemaSourceProvider.java
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/UncancellableFuture.java [new file with mode: 0644]
opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/YangModelInputStreamAdapter.java [deleted file]
opendaylight/md-sal/sal-remote/pom.xml
opendaylight/md-sal/sal-remoterpc-connector/implementation/pom.xml
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ClientImpl.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/RemoteRpcProvider.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/main/java/org/opendaylight/controller/sal/connector/remoterpc/ServerImpl.java
opendaylight/md-sal/sal-remoterpc-connector/implementation/src/test/java/org/opendaylight/controller/sal/connector/remoterpc/ClientImplTest.java
opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/ControllerContext.xtend
opendaylight/md-sal/sal-restconf-broker/pom.xml
opendaylight/md-sal/samples/l2switch/model/pom.xml
opendaylight/md-sal/samples/toaster-consumer/pom.xml
opendaylight/md-sal/samples/toaster-provider/pom.xml
opendaylight/md-sal/samples/toaster/pom.xml
opendaylight/md-sal/statistics-manager/pom.xml
opendaylight/md-sal/topology-lldp-discovery/pom.xml
opendaylight/md-sal/topology-manager/pom.xml
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/osgi/ConfigPersisterActivator.java
opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/ConfigPersisterTest.java
opendaylight/netconf/config-persister-impl/src/test/java/org/opendaylight/controller/netconf/persist/impl/osgi/MockedBundleContext.java
opendaylight/netconf/ietf-netconf-monitoring-extension/pom.xml
opendaylight/netconf/ietf-netconf-monitoring/pom.xml
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfOperationRouter.java
opendaylight/netconf/netconf-api/src/main/java/org/opendaylight/controller/netconf/api/NetconfTerminationReason.java
opendaylight/netconf/netconf-client/pom.xml
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/AbstractNetconfClientNotifySessionListener.java [deleted file]
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClient.java [deleted file]
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/NetconfClientSessionNegotiatorFactory.java
opendaylight/netconf/netconf-client/src/main/java/org/opendaylight/controller/netconf/client/SimpleNetconfClientSessionListener.java
opendaylight/netconf/netconf-client/src/test/java/org/opendaylight/controller/netconf/client/SSHNetconfClientLiveTest.java [deleted file]
opendaylight/netconf/netconf-client/src/test/java/org/opendaylight/controller/netconf/client/test/TestingNetconfClient.java [new file with mode: 0644]
opendaylight/netconf/netconf-impl/pom.xml
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/CapabilityProviderImpl.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerDispatcher.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListener.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionListenerFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiator.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/NetconfServerSessionNegotiatorFactory.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/mapping/operations/DefaultCloseSession.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfImplActivator.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfMonitoringServiceImpl.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationRouterImpl.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListener.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceFactoryListenerImpl.java
opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshotImpl.java [moved from opendaylight/netconf/netconf-impl/src/main/java/org/opendaylight/controller/netconf/impl/osgi/NetconfOperationServiceSnapshot.java with 51% similarity]
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/ConcurrentClientsTest.java
opendaylight/netconf/netconf-impl/src/test/java/org/opendaylight/controller/netconf/impl/NetconfDispatcherImplTest.java
opendaylight/netconf/netconf-it/pom.xml
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.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/NetconfITSecureTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfITTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/NetconfMonitoringITTest.java
opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/pax/IdentityRefNetconfTest.java
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationProvider.java [new file with mode: 0644]
opendaylight/netconf/netconf-mapping-api/src/main/java/org/opendaylight/controller/netconf/mapping/api/NetconfOperationServiceSnapshot.java [moved from opendaylight/sal/yang-prototype/concepts-lang/src/main/java/org/opendaylight/controller/concepts/lang/Acceptor.java with 55% similarity]
opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/CloseableUtil.java [new file with mode: 0644]
opendaylight/netconf/pom.xml
opendaylight/northbound/java-client/pom.xml
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/ReadServiceFilter.java
opendaylight/sal/yang-prototype/concepts-lang/pom.xml [deleted file]
opendaylight/sal/yang-prototype/concepts-lang/src/main/java/org/opendaylight/controller/concepts/lang/AggregateTransformer.java [deleted file]
opendaylight/sal/yang-prototype/concepts-lang/src/main/java/org/opendaylight/controller/concepts/lang/CompositeClassBasedTransformer.java [deleted file]
opendaylight/sal/yang-prototype/concepts-lang/src/main/java/org/opendaylight/controller/concepts/lang/CompositeConditionalTransformer.java [deleted file]
opendaylight/sal/yang-prototype/concepts-lang/src/main/java/org/opendaylight/controller/concepts/lang/InputClassBasedTransformer.java [deleted file]
opendaylight/sal/yang-prototype/concepts-lang/src/main/java/org/opendaylight/controller/concepts/lang/RuleBasedTransformer.java [deleted file]
opendaylight/sal/yang-prototype/concepts-lang/src/main/java/org/opendaylight/controller/concepts/lang/SimpleConditionalTransformer.java [deleted file]
opendaylight/sal/yang-prototype/concepts-lang/src/main/java/org/opendaylight/controller/concepts/lang/Transformer.java [deleted file]
opendaylight/sal/yang-prototype/concepts-lang/src/site/site.xml [deleted file]
opendaylight/sal/yang-prototype/sal/.gitignore [deleted file]
opendaylight/sal/yang-prototype/src/site/markdown/readme.md [deleted file]
opendaylight/sal/yang-prototype/src/site/resources/stylesheet.css [deleted file]
opendaylight/sal/yang-prototype/src/site/site.xml [deleted file]
opendaylight/web/root/src/main/resources/WEB-INF/spring/servlet/security.xml
opendaylight/web/root/src/main/resources/WEB-INF/web.xml

index 175ab5f..6fc003b 100644 (file)
@@ -19,6 +19,8 @@ opendaylight/northbound/integrationtest/logs/*
 *.iws
 .idea
 xtend-gen
+yang-gen-config
+yang-gen-sal
 classes
 out/
 .externalToolBuilders
index d7a3db3..1b72630 100644 (file)
@@ -15,7 +15,7 @@
   </scm>
 
   <artifactId>clustering.services-implementation</artifactId>
-  <version>0.4.2-SNAPSHOT</version>
+  <version>0.4.3-SNAPSHOT</version>
   <packaging>bundle</packaging>
   <properties>
     <!-- Sonar properties using jacoco to retrieve integration test results -->
@@ -68,7 +68,7 @@
               *
             </DynamicImport-Package>
             <Embed-Dependency>
-              infinispan-core,jgroups,jboss-marshalling-river,jboss-marshalling,jboss-logging,staxmapper,narayana-jta;type=!pom;inline=false
+              infinispan-core,infinispan-commons,jgroups,jboss-marshalling-river,jboss-marshalling,jboss-logging,staxmapper,narayana-jta;type=!pom;inline=false
             </Embed-Dependency>
             <Embed-Transitive>
               true
                     <exclude>org.infinispan:infinispan-core:*</exclude>
                   </excludes>
                   <includes>
-                    <include>org.infinispan:infinispan-core:[5.3.0.Final]</include>
+                    <include>org.infinispan:infinispan-core:[6.0.2.Final]</include>
                   </includes>
                 </bannedDependencies>
               </rules>
     <dependency>
       <groupId>org.infinispan</groupId>
       <artifactId>infinispan-core</artifactId>
-      <version>5.3.0.Final</version>
+      <version>6.0.2.Final</version>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.controller</groupId>
diff --git a/opendaylight/clustering/services_implementation/src/main/java/org/infinispan/interceptors/distribution/BaseDistributionInterceptor.java b/opendaylight/clustering/services_implementation/src/main/java/org/infinispan/interceptors/distribution/BaseDistributionInterceptor.java
deleted file mode 100644 (file)
index d495e45..0000000
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009 Red Hat Inc. and/or its affiliates and other
- * contributors as indicated by the @author tags. All rights reserved.
- * See the copyright.txt in the distribution for a full listing of
- * individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.interceptors.distribution;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.infinispan.CacheException;
-import org.infinispan.commands.FlagAffectedCommand;
-import org.infinispan.commands.remote.ClusteredGetCommand;
-import org.infinispan.commands.write.DataWriteCommand;
-import org.infinispan.commands.write.WriteCommand;
-import org.infinispan.container.entries.InternalCacheEntry;
-import org.infinispan.container.entries.InternalCacheValue;
-import org.infinispan.context.InvocationContext;
-import org.infinispan.context.impl.TxInvocationContext;
-import org.infinispan.distribution.DistributionManager;
-import org.infinispan.factories.annotations.Inject;
-import org.infinispan.interceptors.ClusteringInterceptor;
-import org.infinispan.interceptors.locking.ClusteringDependentLogic;
-import org.infinispan.remoting.responses.ClusteredGetResponseValidityFilter;
-import org.infinispan.remoting.responses.ExceptionResponse;
-import org.infinispan.remoting.responses.Response;
-import org.infinispan.remoting.responses.SuccessfulResponse;
-import org.infinispan.remoting.rpc.ResponseFilter;
-import org.infinispan.remoting.rpc.ResponseMode;
-import org.infinispan.remoting.rpc.RpcOptions;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.transaction.xa.GlobalTransaction;
-import org.infinispan.util.logging.Log;
-import org.infinispan.util.logging.LogFactory;
-
-
-/**
- * Base class for distribution of entries across a cluster.
- *
- * @author Manik Surtani
- * @author Mircea.Markus@jboss.com
- * @author Pete Muir
- * @author Dan Berindei <dan@infinispan.org>
- * @since 4.0
- */
-public abstract class BaseDistributionInterceptor extends ClusteringInterceptor {
-
-   protected DistributionManager dm;
-
-   protected ClusteringDependentLogic cdl;
-
-   private static final Log log = LogFactory.getLog(BaseDistributionInterceptor.class);
-
-   @Override
-   protected Log getLog() {
-      return log;
-   }
-
-   @Inject
-   public void injectDependencies(DistributionManager distributionManager, ClusteringDependentLogic cdl) {
-      this.dm = distributionManager;
-      this.cdl = cdl;
-   }
-
-   @Override
-   protected final InternalCacheEntry retrieveFromRemoteSource(Object key, InvocationContext ctx, boolean acquireRemoteLock, FlagAffectedCommand command) throws Exception {
-      GlobalTransaction gtx = acquireRemoteLock ? ((TxInvocationContext)ctx).getGlobalTransaction() : null;
-      ClusteredGetCommand get = cf.buildClusteredGetCommand(key, command.getFlags(), acquireRemoteLock, gtx);
-
-      List<Address> targets = new ArrayList<Address>(stateTransferManager.getCacheTopology().getReadConsistentHash().locateOwners(key));
-      // if any of the recipients has left the cluster since the command was issued, just don't wait for its response
-      targets.retainAll(rpcManager.getTransport().getMembers());
-      ResponseFilter filter = new ClusteredGetResponseValidityFilter(targets, rpcManager.getAddress());
-      RpcOptions options = rpcManager.getRpcOptionsBuilder(ResponseMode.WAIT_FOR_VALID_RESPONSE, false)
-            .responseFilter(filter).build();
-      Map<Address, Response> responses = rpcManager.invokeRemotely(targets, get, options);
-
-      if (!responses.isEmpty()) {
-         for (Response r : responses.values()) {
-            if (r instanceof SuccessfulResponse) {
-               InternalCacheValue cacheValue = (InternalCacheValue) ((SuccessfulResponse) r).getResponseValue();
-               return cacheValue.toInternalCacheEntry(key);
-            }
-         }
-      }
-
-      // TODO If everyone returned null, and the read CH has changed, retry the remote get.
-      // Otherwise our get command might be processed by the old owners after they have invalidated their data
-      // and we'd return a null even though the key exists on
-      return null;
-   }
-
-   protected final Object handleNonTxWriteCommand(InvocationContext ctx, DataWriteCommand command) throws Throwable {
-      if (ctx.isInTxScope()) {
-         throw new CacheException("Attempted execution of non-transactional write command in a transactional invocation context");
-      }
-
-      RecipientGenerator recipientGenerator = new SingleKeyRecipientGenerator(command.getKey());
-
-      // see if we need to load values from remote sources first
-      remoteGetBeforeWrite(ctx, command, recipientGenerator);
-
-      // if this is local mode then skip distributing
-      if (isLocalModeForced(command)) {
-         return invokeNextInterceptor(ctx, command);
-      }
-
-      boolean isSync = isSynchronous(command);
-      if (!ctx.isOriginLocal()) {
-         Object returnValue = invokeNextInterceptor(ctx, command);
-         Address primaryOwner = cdl.getPrimaryOwner(command.getKey());
-            if (primaryOwner.equals(rpcManager.getAddress())) {
-                if (command.isConditional() && !command.isSuccessful()) {
-                    log.tracef(
-                            "Skipping the replication of the conditional command as it did not succeed on primary owner (%s).",
-                            command);
-                    return returnValue;
-                }
-                rpcManager.invokeRemotely(recipientGenerator.generateRecipients(), command,
-                        rpcManager.getDefaultRpcOptions(isSync));
-            } else {
-                log.tracef("Didn't invoke RPC because primaryOwner (%s) didn't match this node (%s)", primaryOwner,
-                           rpcManager.getAddress());
-                log.tracef("Hashcode is (%s) for Key (%s)",
-                           command.getKey().hashCode(), command.getKey());
-            }
-         return returnValue;
-      } else {
-         Address primaryOwner = cdl.getPrimaryOwner(command.getKey());
-         if (primaryOwner.equals(rpcManager.getAddress())) {
-            Object result = invokeNextInterceptor(ctx, command);
-            if (command.isConditional() && !command.isSuccessful()) {
-               log.tracef("Skipping the replication of the conditional command as it did not succeed on primary owner (%s).", command);
-               return result;
-            }
-            List<Address> recipients = recipientGenerator.generateRecipients();
-            log.tracef("I'm the primary owner, sending the command to all (%s) the recipients in order to be applied.", recipients);
-            // check if a single owner has been configured and the target for the key is the local address
-            boolean isSingleOwnerAndLocal = cacheConfiguration.clustering().hash().numOwners() == 1
-                  && recipients != null
-                  && recipients.size() == 1
-                  && recipients.get(0).equals(rpcManager.getTransport().getAddress());
-            if (!isSingleOwnerAndLocal) {
-               rpcManager.invokeRemotely(recipients, command, rpcManager.getDefaultRpcOptions(isSync));
-            }
-            return result;
-         } else {
-            log.tracef("I'm not the primary owner, so sending the command to the primary owner(%s) in order to be forwarded", primaryOwner);
-            log.tracef("Hashcode is (%s) for Key (%s)", command.getKey().hashCode(), command.getKey());
-
-            Object localResult = invokeNextInterceptor(ctx, command);
-            boolean isSyncForwarding = isSync || isNeedReliableReturnValues(command);
-            Map<Address, Response> addressResponseMap = rpcManager.invokeRemotely(Collections.singletonList(primaryOwner), command,
-                  rpcManager.getDefaultRpcOptions(isSyncForwarding));
-            if (!isSyncForwarding) return localResult;
-
-            return getResponseFromPrimaryOwner(primaryOwner, addressResponseMap);
-         }
-      }
-   }
-
-   private Object getResponseFromPrimaryOwner(Address primaryOwner, Map<Address, Response> addressResponseMap) {
-      Response fromPrimaryOwner = addressResponseMap.get(primaryOwner);
-      if (fromPrimaryOwner == null) {
-         log.tracef("Primary owner %s returned null", primaryOwner);
-         return null;
-      }
-      if (!fromPrimaryOwner.isSuccessful()) {
-         Throwable cause = fromPrimaryOwner instanceof ExceptionResponse ? ((ExceptionResponse)fromPrimaryOwner).getException() : null;
-         throw new CacheException("Got unsuccessful response from primary owner: " + fromPrimaryOwner, cause);
-      } else {
-         return ((SuccessfulResponse) fromPrimaryOwner).getResponseValue();
-      }
-   }
-
-   protected abstract void remoteGetBeforeWrite(InvocationContext ctx, WriteCommand command, RecipientGenerator keygen) throws Throwable;
-
-   interface RecipientGenerator {
-
-      Collection<Object> getKeys();
-
-      List<Address> generateRecipients();
-   }
-
-   class SingleKeyRecipientGenerator implements RecipientGenerator {
-      private final Object key;
-      private final Set<Object> keys;
-      private List<Address> recipients = null;
-
-      SingleKeyRecipientGenerator(Object key) {
-         this.key = key;
-         keys = Collections.singleton(key);
-      }
-
-      @Override
-      public List<Address> generateRecipients() {
-         if (recipients == null) {
-            recipients = cdl.getOwners(key);
-         }
-         return recipients;
-      }
-
-      @Override
-      public Collection<Object> getKeys() {
-         return keys;
-      }
-   }
-
-   class MultipleKeysRecipientGenerator implements RecipientGenerator {
-
-      private final Collection<Object> keys;
-      private List<Address> recipients = null;
-
-      MultipleKeysRecipientGenerator(Collection<Object> keys) {
-         this.keys = keys;
-      }
-
-      @Override
-      public List<Address> generateRecipients() {
-         if (recipients == null) {
-            recipients = cdl.getOwners(keys);
-         }
-         return recipients;
-      }
-
-      @Override
-      public Collection<Object> getKeys() {
-         return keys;
-      }
-   }
-}
index 5ec4325..5fb0ddf 100644 (file)
@@ -1,4 +1,4 @@
-<infinispan xsi:schemaLocation="urn:infinispan:config:5.3 http://www.infinispan.org/schemas/infinispan-config-5.3.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:infinispan:config:5.3">
+<infinispan>
   <global>
     <transport>
       <properties>
         jmxDomain="org.infinispan"
         cacheManagerName="SampleCacheManager"/>
   </global>
-  <default>
-    <!-- Configure a synchronous replication cache -->
-    <clustering mode="replication">
-      <sync/>
-    </clustering>
-    <!--
-        Used to register JMX statistics in any available MBean server
-    -->
+
+ <default>
     <jmxStatistics enabled="true"/>
-  </default>
-  <!-- transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup" -->
-  <namedCache name="transactional-type">
+        <clustering mode="replication">
+        <sync/>
+        </clustering>
+        </default>
+ <namedCache name="transactional-type">
     <transaction
         transactionManagerLookupClass="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup"
         syncRollbackPhase="true"
         use1PcForAutoCommitTransactions="true"
         autoCommit="true"
         lockingMode="OPTIMISTIC"
+        useEagerLocking="true"
         useSynchronization="true"
         transactionMode="TRANSACTIONAL"
         />
+        <clustering mode="replication">
+        <sync/>
+        </clustering>
   </namedCache>
+
 </infinispan>
index 3690b85..d5d7e8e 100644 (file)
     <commons.io.version>2.4</commons.io.version>
     <bundlescanner.version>0.4.2-SNAPSHOT</bundlescanner.version>
     <usermanager.version>0.4.2-SNAPSHOT</usermanager.version>
-    <forwardingrulesmanager.version>0.5.1-SNAPSHOT</forwardingrulesmanager.version>
+    <forwardingrulesmanager.version>0.6.0-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.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>
+    <clustering.services_implementation.version>0.4.3-SNAPSHOT</clustering.services_implementation.version>
     <!-- Third party version -->
     <jersey-servlet.version>1.17</jersey-servlet.version>
     <corsfilter.version>7.0.42</corsfilter.version>
     <!-- enforcer version -->
     <enforcer.version>1.3.1</enforcer.version>
     <xtend.version>2.4.3</xtend.version>
-    <xtend.dstdir>${project.build.directory}/generated-sources/xtend-gen</xtend.dstdir>
+    <xtend.dstdir>src/main/xtend-gen</xtend.dstdir>
+    <jmxGeneratorPath>src/main/yang-gen-config</jmxGeneratorPath>
+    <salGeneratorPath>src/main/yang-gen-sal</salGeneratorPath>
   </properties>
 
   <dependencyManagement>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
         <artifactId>clustering.services-implementation</artifactId>
-        <version>${controller.version}</version>
+        <version>${clustering.services_implementation.version}</version>
       </dependency>
       <dependency>
         <groupId>org.opendaylight.controller</groupId>
           <includeTestSourceDirectory>true</includeTestSourceDirectory>
           <sourceDirectory>${project.basedir}</sourceDirectory>
           <includes>**\/*.java,**\/*.xml,**\/*.ini,**\/*.sh,**\/*.bat</includes>
-          <excludes>**\/target\/,**\/bin\/,**\/target-ide\/</excludes>
+          <excludes>**\/target\/,**\/bin\/,**\/target-ide\/,**\/${jmxGeneratorPath}\/,**\/${salGeneratorPath}\/</excludes>
         </configuration>
       </plugin>
       <plugin>
           </execution>
         </executions>
       </plugin>
+      <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>build-helper-maven-plugin</artifactId>
+      </plugin>
     </plugins>
     <pluginManagement>
       <plugins>
                   </execution>
               </executions>
           </plugin>
+          <plugin>
+              <artifactId>maven-clean-plugin</artifactId>
+              <configuration>
+                  <filesets>
+                      <fileset>
+                          <directory>${xtend.dstdir}</directory>
+                          <includes>
+                              <include>**</include>
+                          </includes>
+                      </fileset>
+                      <fileset>
+                          <directory>${jmxGeneratorPath}</directory>
+                          <includes>
+                              <include>**</include>
+                          </includes>
+                      </fileset>
+                      <fileset>
+                          <directory>${salGeneratorPath}</directory>
+                          <includes>
+                              <include>**</include>
+                          </includes>
+                      </fileset>
+                  </filesets>
+              </configuration>
+            </plugin>
+          <plugin>
+             <groupId>org.codehaus.mojo</groupId>
+             <artifactId>build-helper-maven-plugin</artifactId>
+             <version>1.8</version>
+             <executions>
+                <execution>
+                   <id>add-source</id>
+                   <phase>generate-sources</phase>
+                   <goals>
+                      <goal>add-source</goal>
+                   </goals>
+                   <configuration>
+                      <sources>
+                         <source>${jmxGeneratorPath}</source>
+                         <source>${salGeneratorPath}</source>
+                         <source>${xtend.dstdir}</source>
+                      </sources>
+                   </configuration>
+                </execution>
+             </executions>
+            </plugin>
       </plugins>
     </pluginManagement>
   </build>
index 650d2dd..1a1a256 100644 (file)
         <maven>3.0.4</maven>
     </prerequisites>
 
-    <properties>
-        <jmxGeneratorPath>${project.build.directory}/generated-sources/config</jmxGeneratorPath>
-        <salGeneratorPath>${project.build.directory}/generated-sources/sal</salGeneratorPath>
-    </properties>
-
     <dependencies>
         <dependency>
             <groupId>io.netty</groupId>
index 21b1a55..80abd87 100644 (file)
@@ -8,8 +8,6 @@
   <packaging>bundle</packaging>
 
     <properties>
-        <jmxGeneratorPath>${project.build.directory}/generated-sources/config</jmxGeneratorPath>
-        <salGeneratorPath>${project.build.directory}/generated-sources/sal</salGeneratorPath>
         <config.version>${config-api-version}</config.version>
         <yangtools.version>${yang-maven-plugin-version}</yangtools.version>
         <maven.bundle.version>${maven-bundle-plugin-version}</maven.bundle.version>
                 </dependencies>
             </plugin>
 
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <version>1.8</version>
-                <executions>
-                    <execution>
-                        <id>add-source</id>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>add-source</goal>
-                        </goals>
-                        <configuration>
-                            <sources>
-                                <source>${jmxGeneratorPath}</source>
-                            </sources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-
             <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
index e382c33..2c607f8 100644 (file)
         <maven>3.0.4</maven>
     </prerequisites>
 
-    <properties>
-        <jmxGeneratorPath>${project.build.directory}/generated-sources/config</jmxGeneratorPath>
-    </properties>
-
     <build>
         <pluginManagement>
             <plugins>
                         </dependency>
                     </dependencies>
                 </plugin>
-
-                <!-- tell eclipse about generated source folders -->
-                <plugin>
-                    <groupId>org.codehaus.mojo</groupId>
-                    <artifactId>build-helper-maven-plugin</artifactId>
-                    <version>1.8</version>
-                    <executions>
-                        <execution>
-                            <id>add-source</id>
-                            <phase>generate-sources</phase>
-                            <goals>
-                                <goal>add-source</goal>
-                            </goals>
-                            <configuration>
-                                <sources>
-                                    <source>${jmxGeneratorPath}</source>
-                                    <source>${salGeneratorPath}</source>
-                                </sources>
-                            </configuration>
-                        </execution>
-                    </executions>
-                </plugin>
             </plugins>
         </pluginManagement>
     </build>
index fbebda5..2fe515c 100644 (file)
@@ -89,6 +89,7 @@
                 <groupId>org.opendaylight.yangtools</groupId>
                 <artifactId>yang-maven-plugin</artifactId>
             </plugin>
+
         </plugins>
     </build>
 </project>
index 5414335..332426f 100644 (file)
@@ -68,8 +68,6 @@
                 <groupId>org.opendaylight.yangtools</groupId>
                 <artifactId>yang-maven-plugin</artifactId>
             </plugin>
-
-
             <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
index d700075..8efed2d 100644 (file)
@@ -62,7 +62,6 @@
         <osgi.version>5.0.0</osgi.version>
         <jacoco.version>0.6.2.201302030002</jacoco.version>
         <slf4j.version>1.7.2</slf4j.version>
-        <salGeneratorPath>${project.build.directory}/generated-sources/sal</salGeneratorPath>
     </properties>
 
     <dependencies>
                         </dependency>
                     </dependencies>
                 </plugin>
-                <!-- tell eclipse about generated source folders -->
-                <plugin>
-                    <groupId>org.codehaus.mojo</groupId>
-                    <artifactId>build-helper-maven-plugin</artifactId>
-                    <version>1.8</version>
-                    <executions>
-                        <execution>
-                            <id>add-source</id>
-                            <phase>generate-sources</phase>
-                            <goals>
-                                <goal>add-source</goal>
-                            </goals>
-                            <configuration>
-                                <sources>
-                                    <source>${salGeneratorPath}</source>
-                                </sources>
-                            </configuration>
-                        </execution>
-                    </executions>
-                </plugin>
                 <plugin>
                     <groupId>org.apache.maven.plugins</groupId>
                     <artifactId>maven-jar-plugin</artifactId>
index 9df653c..e678ef7 100644 (file)
@@ -47,9 +47,12 @@ eclipse.ignoreApp=true
 osgi.noShutdown=true
 # Clean any cached data on restart of the framework
 osgi.clean=true
+
+# https://bugs.eclipse.org/bugs/show_bug.cgi?id=325578
 # Extend the framework to avoid the resources to be presented with
 # a URL of type bundleresource: but to be presented as file:
 osgi.hook.configurators.include=org.eclipse.virgo.kernel.equinox.extensions.hooks.ExtensionsHookConfigurator
+
 # Directory from where the fileinstall will monitor for new bundles
 felix.fileinstall.dir=./plugins
 # Immediately learn new bundles at startup
index 9d6ac8d..72ccd02 100644 (file)
@@ -10,6 +10,7 @@ SET basedir=%~dp0
 SET debugport=8000
 SET consoleport=2400
 SET jmxport=1088
+SET jvmMaxMemory=
 SET extraJVMOpts=
 SET consoleOpts=-console -consoleLog
 SET PID=
@@ -82,6 +83,11 @@ IF "%~1" NEQ "" (
        )
        GOTO :EOF
     )
+    IF "!CARG:~0,4!"=="-Xmx" (
+       SET jvmMaxMemory=!CARG!
+       SHIFT
+       GOTO :LOOP
+    )
     IF "!CARG:~0,2!"=="-D" (
        SET extraJVMOpts=%extraJVMOpts% !CARG!
        SHIFT
@@ -110,6 +116,19 @@ IF "%debugSuspended%" NEQ "" (
     REM ECHO "DEBUG enabled suspended"
     SET extraJVMOpts=%extraJVMOpts% -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=%debugport%
 )
+
+IF "%jvmMaxMemory%"=="" (
+    SET jvmMaxMemory=-Xmx1G
+    ECHO *****************************************************************
+    ECHO JVM maximum memory was not defined. Setting maximum memory to 1G.
+    ECHO To define the maximum memory, specify the -Xmx setting on the
+    ECHO command line.
+    ECHO                    e.g. run.bat -Xmx1G
+    ECHO *****************************************************************"
+)
+
+SET extraJVMOpts=%extraJVMOpts%  %jvmMaxMemory%
+
 IF "%jmxEnabled%" NEQ "" (
     REM ECHO "JMX enabled "
     SET extraJVMOpts=%extraJVMOpts% -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.port=%jmxport% -Dcom.sun.management.jmxremote
index 64f2c87..21245a0 100755 (executable)
@@ -82,6 +82,7 @@ stopdaemon=0
 statusdaemon=0
 consolestart=1
 dohelp=0
+jvmMaxMemory=""
 extraJVMOpts=""
 agentPath=""
 unknown_option=0
@@ -97,6 +98,7 @@ while true ; do
         -status) statusdaemon=1; shift ;;
         -console) shift ;;
         -help) dohelp=1; shift;;
+        -Xmx*) jvmMaxMemory="$1"; shift;;
         -D*) extraJVMOpts="${extraJVMOpts} $1"; shift;;
         -X*) extraJVMOpts="${extraJVMOpts} $1"; shift;;
         -agentpath:*) agentPath="$1"; shift;;
@@ -114,6 +116,18 @@ if [ "${dohelp}" -eq 1 ]; then
     usage
 fi
 
+if [ "${jvmMaxMemory}" == "" ]; then
+    jvmMaxMemory="-Xmx1G"
+    echo "*****************************************************************"
+    echo "JVM maximum memory was not defined. Setting maximum memory to 1G."
+    echo "To define the maximum memory, specify the -Xmx setting on the"
+    echo "command line. "
+    echo "        e.g. ./run.sh -Xmx1G"
+    echo "*****************************************************************"
+fi
+
+extraJVMOpts="${extraJVMOpts} ${jvmMaxMemory}"
+
 # Validate debug port
 if [[ "${debugport}" -lt 1024 ]] || [[ "${debugport}" -gt 65535 ]]; then
     echo "Debug Port not in the range [1024,65535] ${debugport}"
index 3bd1af3..304a315 100644 (file)
@@ -15,7 +15,7 @@
   </scm>
 
   <artifactId>forwardingrulesmanager</artifactId>
-  <version>0.5.1-SNAPSHOT</version>
+  <version>0.6.0-SNAPSHOT</version>
   <packaging>bundle</packaging>
 
   <build>
index 9d68f84..070e8c4 100644 (file)
@@ -369,6 +369,16 @@ public interface IForwardingRulesManager {
      */
     public Status addStaticFlow(FlowConfig config);
 
+    /**
+     * Add a flow specified by the {@code FlowConfig} object on the current
+     * container, through an asynchronous call.
+     *
+     * @param config
+     *            the {@code FlowConfig} object representing the static flow
+     * @return the {@code Status} object indicating the result of this action.
+     */
+    public Status addStaticFlowAsync(FlowConfig config);
+
     /**
      * Remove a flow specified by the {@code FlowConfig} object on the current
      * container
@@ -379,6 +389,16 @@ public interface IForwardingRulesManager {
      */
     public Status removeStaticFlow(FlowConfig config);
 
+    /**
+     * Remove a flow specified by the {@code FlowConfig} object on the current
+     * container, through an asynchronous call.
+     *
+     * @param config
+     *            the {@code FlowConfig} object representing the static flow
+     * @return the {@code Status} object indicating the result of this action
+     */
+    public Status removeStaticFlowAsync(FlowConfig config);
+
     /**
      * Replace the flow identified by the {@code FlowConfig.name} name for the
      * {@code FlowConfig.node} network node with the new flow specified by
@@ -386,7 +406,7 @@ public interface IForwardingRulesManager {
      *
      * @param config
      *            the {@code FlowConfig} object
-     * @returnthe {@code Status} object indicating the result of this action
+     * @return the {@code Status} object indicating the result of this action
      */
     public Status modifyStaticFlow(FlowConfig config);
 
@@ -401,6 +421,18 @@ public interface IForwardingRulesManager {
      */
     public Status removeStaticFlow(String name, Node node);
 
+    /**
+     * Remove the flow specified by name on the passed network node via an
+     * asynchronous call
+     *
+     * @param name
+     *            for the static flow
+     * @param node
+     *            on which the flow is attached
+     * @return the {@code Status} object indicating the result of this action
+     */
+    public Status removeStaticFlowAsync(String name, Node node);
+
     /**
      * Toggle the installation status of the specified configured flow If the
      * flow configuration status is active, this call will change the flow
index 614c39e..f7b647d 100644 (file)
@@ -1590,6 +1590,10 @@ public class ForwardingRulesManager implements
 
     @Override
     public Status addStaticFlow(FlowConfig config) {
+        return addStaticFlow(config, false);
+    }
+
+    private Status addStaticFlow(FlowConfig config, boolean async) {
         // Configuration object validation
         Status status = config.validate();
         if (!status.isSuccess()) {
@@ -1598,7 +1602,13 @@ public class ForwardingRulesManager implements
             config.setStatus(error);
             return new Status(StatusCode.BADREQUEST, error);
         }
-        return addStaticFlowInternal(config, false);
+        return addStaticFlowInternal(config, async, false);
+    }
+
+
+    @Override
+    public Status addStaticFlowAsync(FlowConfig config) {
+        return addStaticFlow(config, true);
     }
 
     /**
@@ -1616,7 +1626,7 @@ public class ForwardingRulesManager implements
      *            installation on the network node was successful
      * @return The status of this request
      */
-    private Status addStaticFlowInternal(FlowConfig config, boolean restore) {
+    private Status addStaticFlowInternal(FlowConfig config, boolean async, boolean restore) {
         boolean multipleFlowPush = false;
         String error;
         Status status;
@@ -1653,7 +1663,7 @@ public class ForwardingRulesManager implements
             // Program hw
             if (config.installInHw()) {
                 FlowEntry entry = config.getFlowEntry();
-                status = this.installFlowEntry(entry);
+                status = async ? this.installFlowEntryAsync(entry) : this.installFlowEntry(entry);
                 if (!status.isSuccess()) {
                     config.setStatus(status.getDescription());
                     if (!restore) {
@@ -1765,6 +1775,15 @@ public class ForwardingRulesManager implements
 
     @Override
     public Status removeStaticFlow(FlowConfig config) {
+        return removeStaticFlow(config, false);
+    }
+
+    @Override
+    public Status removeStaticFlowAsync(FlowConfig config) {
+        return removeStaticFlow(config, true);
+    }
+
+    private Status removeStaticFlow(FlowConfig config, boolean async) {
         /*
          * No config.isInternal() check as NB does not take this path and GUI
          * cannot issue a delete on an internal generated flow. We need this
@@ -1788,7 +1807,8 @@ public class ForwardingRulesManager implements
         }
 
         // Program the network node
-        Status status = this.uninstallFlowEntry(config.getFlowEntry());
+        Status status = async ? this.uninstallFlowEntryAsync(config.getFlowEntry()) : this.uninstallFlowEntry(config
+                .getFlowEntry());
 
         // Update configuration database if programming was successful
         if (status.isSuccess()) {
@@ -1800,6 +1820,15 @@ public class ForwardingRulesManager implements
 
     @Override
     public Status removeStaticFlow(String name, Node node) {
+       return removeStaticFlow(name, node, false);
+    }
+
+    @Override
+    public Status removeStaticFlowAsync(String name, Node node) {
+        return removeStaticFlow(name, node, true);
+    }
+
+    private Status removeStaticFlow(String name, Node node, boolean async) {
         // Look for the target configuration entry
         Integer key = 0;
         FlowConfig target = null;
@@ -1830,7 +1859,7 @@ public class ForwardingRulesManager implements
         }
 
         // Program the network node
-        Status status = this.removeEntry(target.getFlowEntry(), false);
+        Status status = this.removeEntry(target.getFlowEntry(), async);
 
         // Update configuration database if programming was successful
         if (status.isSuccess()) {
@@ -2081,7 +2110,7 @@ public class ForwardingRulesManager implements
         }
 
         for (ConfigurationObject conf : configurationService.retrieveConfiguration(this, STATIC_FLOWS_FILE_NAME)) {
-            addStaticFlowInternal((FlowConfig) conf, true);
+            addStaticFlowInternal((FlowConfig) conf, false, true);
         }
     }
 
@@ -2193,7 +2222,7 @@ public class ForwardingRulesManager implements
                     // check if the frm really needs to act on the notification.
                     // this is to check against duplicate notifications
                     if(programInternalFlow(proactive, fc)) {
-                        Status status = (proactive) ? addStaticFlowInternal(fc, false) : removeStaticFlow(fc);
+                        Status status = (proactive) ? addStaticFlowInternal(fc, false, false) : removeStaticFlow(fc);
                         if (status.isSuccess()) {
                             log.trace("{} Proactive Static flow: {}", (proactive ? "Installed" : "Removed"), fc.getName());
                         } else {
@@ -2376,7 +2405,7 @@ public class ForwardingRulesManager implements
             if ((staticFlow.getNode().equals(node)) && (staticFlow.getPortGroup().equals(config.getName()))) {
                 for (Short port : data.getPorts()) {
                     FlowConfig derivedFlow = getDerivedFlowConfig(staticFlow, config.getName(), port);
-                    addStaticFlowInternal(derivedFlow, false);
+                    addStaticFlowInternal(derivedFlow, false, false);
                 }
             }
         }
@@ -3240,4 +3269,5 @@ public class ForwardingRulesManager implements
         }
         return list;
     }
+
 }
index fc0ef32..f3fd230 100644 (file)
@@ -30,9 +30,6 @@
         <groupId>org.eclipse.xtend</groupId>
         <artifactId>xtend-maven-plugin</artifactId>
       </plugin>
-      <plugin>
-        <artifactId>maven-clean-plugin</artifactId>
-      </plugin>
     </plugins>
   </build>
 
index b7e193b..aef489e 100644 (file)
@@ -31,9 +31,6 @@
                 <groupId>org.eclipse.xtend</groupId>
                 <artifactId>xtend-maven-plugin</artifactId>
             </plugin>
-            <plugin>
-                <artifactId>maven-clean-plugin</artifactId>
-            </plugin>
         </plugins>
     </build>
 
index 00cbc18..68eaa96 100644 (file)
@@ -31,9 +31,6 @@
                 <groupId>org.eclipse.xtend</groupId>
                 <artifactId>xtend-maven-plugin</artifactId>
             </plugin>
-            <plugin>
-                <artifactId>maven-clean-plugin</artifactId>
-            </plugin>
         </plugins>
     </build>
 
index 362a349..31621de 100644 (file)
@@ -59,9 +59,6 @@
                 <groupId>org.eclipse.xtend</groupId>
                 <artifactId>xtend-maven-plugin</artifactId>
             </plugin>
-            <plugin>
-                <artifactId>maven-clean-plugin</artifactId>
-            </plugin>
         </plugins>
     </build>
 </project>
index 4c8a74c..a2a5264 100644 (file)
                     </dependency>
                 </dependencies>
             </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <version>1.7</version>
-                <executions>
-                    <execution>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>add-source</goal>
-                        </goals>
-                        <configuration>
-                            <sources>
-                                <source>target/generated-sources/sal</source>
-                            </sources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
         </plugins>
     </build>
 
index a45cada..631f111 100644 (file)
                 <!--module>test/sal-rest-connector-it</modulei -->
             </modules>
         </profile>
-        <profile>
-            <id>IDE</id>
-            <activation>
-                <property>
-                    <name>m2e.version</name>
-                </property>
-            </activation>
-            <build>
-                <!-- Put the IDE's build output in a folder other than target,
-                    so that IDE builds don't interact with Maven builds -->
-                <directory>target-ide</directory>
-            </build>
-        </profile>
     </profiles>
 
     <properties>
-        <salGeneratorPath>${project.build.directory}/generated-sources/sal</salGeneratorPath>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 
         <!-- Plugin Versions -->
                     <groupId>org.eclipse.xtend</groupId>
                     <artifactId>xtend-maven-plugin</artifactId>
                     <version>${xtend.version}</version>
-                    <executions>
-                        <execution>
-                            <goals>
-                                <goal>compile</goal>
-                            </goals>
-                            <configuration>
-                                <outputDirectory>${basedir}/src/main/xtend-gen</outputDirectory>
-                            </configuration>
-                        </execution>
-                    </executions>
-                </plugin>
-                <plugin>
-                    <artifactId>maven-clean-plugin</artifactId>
-                    <version>${maven.clean.plugin.version}</version>
-                    <configuration>
-                        <filesets>
-                            <fileset>
-                                <directory>${basedir}/src/main/xtend-gen</directory>
-                                <includes>
-                                    <include>**</include>
-                                </includes>
-                            </fileset>
-                        </filesets>
-                    </configuration>
                 </plugin>
                 <plugin>
                     <groupId>org.jacoco</groupId>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
             </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <version>1.8</version>
-                <executions>
-                    <execution>
-                        <id>add-source</id>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>add-source</goal>
-                        </goals>
-                        <configuration>
-                            <sources>
-                                <source>${project.build.directory}/generated-sources/config</source>
-                                <source>${project.build.directory}/generated-sources/sal</source>
-                                <source>src/main/xtend-gen</source>
-                            </sources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-jar-plugin</artifactId>
index dafb3ef..9976f48 100644 (file)
@@ -30,7 +30,7 @@
                                     <codeGeneratorClass>
                                         org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
                                     </codeGeneratorClass>
-                                    <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
+                                    <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
                                     <additionalConfiguration>
                                         <namespaceToPackage1>
                                             urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
                 </dependencies>
             </plugin>
 
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <version>1.8</version>
-                <executions>
-                    <execution>
-                        <id>add-source</id>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>add-source</goal>
-
-
-                        </goals>
-                        <configuration>
-                            <sources>
-                                <source>${project.build.directory}/generated-sources/config</source>
-                                <source>src/main/xtend-gen</source>
-                            </sources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
             <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
                 <groupId>org.eclipse.xtend</groupId>
                 <artifactId>xtend-maven-plugin</artifactId>
             </plugin>
-            <plugin>
-                <artifactId>maven-clean-plugin</artifactId>
-            </plugin>
             <plugin>
                 <groupId>org.jacoco</groupId>
                 <artifactId>jacoco-maven-plugin</artifactId>
index 4f9c429..6334457 100644 (file)
@@ -21,6 +21,7 @@ import org.eclipse.xtext.xbase.lib.Exceptions;
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadWriteTransaction;
@@ -108,27 +109,34 @@ public class AbstractForwardedTransaction<T extends AsyncTransaction<org.openday
                 .toNormalizedNode(path, data);
 
         org.opendaylight.yangtools.yang.data.api.InstanceIdentifier normalizedPath = normalized.getKey();
-        try {
-            List<PathArgument> currentArguments = new ArrayList<>();
-            DataNormalizationOperation<?> currentOp = codec.getDataNormalizer().getRootOperation();
-            Iterator<PathArgument> iterator = normalizedPath.getPath().iterator();
-            while (iterator.hasNext()) {
-                PathArgument currentArg = iterator.next();
+        List<PathArgument> currentArguments = new ArrayList<>();
+        DataNormalizationOperation<?> currentOp = codec.getDataNormalizer().getRootOperation();
+        Iterator<PathArgument> iterator = normalizedPath.getPath().iterator();
+        while (iterator.hasNext()) {
+            PathArgument currentArg = iterator.next();
+            try {
                 currentOp = currentOp.getChild(currentArg);
-                currentArguments.add(currentArg);
-                org.opendaylight.yangtools.yang.data.api.InstanceIdentifier currentPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
-                        currentArguments);
-                boolean isPresent = writeTransaction.read(store, currentPath).get().isPresent();
-                if (isPresent == false && iterator.hasNext()) {
-                    writeTransaction.put(store, currentPath, currentOp.createDefault(currentArg));
-                }
+            } catch (DataNormalizationException e) {
+                throw new IllegalArgumentException(String.format("Invalid child encountered in path %s", path), e);
+            }
+            currentArguments.add(currentArg);
+            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier currentPath = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(
+                    currentArguments);
+
+            final Optional<NormalizedNode<?, ?>> d;
+            try {
+                d = writeTransaction.read(store, currentPath).get();
+            } catch (InterruptedException | ExecutionException e) {
+                LOG.error("Failed to read pre-existing data from store {} path {}", store, currentPath, e);
+                throw new IllegalStateException("Failed to read pre-existing data", e);
+            }
+
+            if (!d.isPresent() && iterator.hasNext()) {
+                writeTransaction.put(store, currentPath, currentOp.createDefault(currentArg));
             }
-        } catch (InterruptedException | ExecutionException e) {
-            e.printStackTrace();
         }
         //LOG .info("Tx: {} : Putting data {}",getDelegate().getIdentifier(),normalized.getKey());
         writeTransaction.put(store, normalized.getKey(), normalized.getValue());
-
     }
 
     protected void doMerge(final DOMDataWriteTransaction writeTransaction, final LogicalDatastoreType store,
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.java
new file mode 100644 (file)
index 0000000..ea8b6c0
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * 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.codegen;
+
+import com.google.common.base.Objects;
+import java.lang.reflect.Field;
+import java.util.Map;
+import org.eclipse.xtext.xbase.lib.Exceptions;
+import org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+@SuppressWarnings("all")
+public class RuntimeCodeHelper {
+  /**
+   * Helper method to return delegate from ManagedDirectedProxy with use of reflection.
+   *
+   * Note: This method uses reflection, but access to delegate field should be
+   * avoided and called only if neccessary.
+   */
+  public static <T extends RpcService> T getDelegate(final RpcService proxy) {
+    try {
+      Class<? extends RpcService> _class = proxy.getClass();
+      final Field field = _class.getField(RuntimeCodeSpecification.DELEGATE_FIELD);
+      boolean _equals = Objects.equal(field, null);
+      if (_equals) {
+        UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException("Unable to get delegate from proxy");
+        throw _unsupportedOperationException;
+      }
+      try {
+        Object _get = field.get(proxy);
+        return ((T) _get);
+      } catch (Throwable _e) {
+        throw Exceptions.sneakyThrow(_e);
+      }
+    } catch (Throwable _e_1) {
+      throw Exceptions.sneakyThrow(_e_1);
+    }
+  }
+
+  /**
+   * Helper method to set delegate to ManagedDirectedProxy with use of reflection.
+   *
+   * Note: This method uses reflection, but setting delegate field should not occur too much
+   * to introduce any significant performance hits.
+   */
+  public static void setDelegate(final RpcService proxy, final RpcService delegate) {
+    try {
+      Class<? extends RpcService> _class = proxy.getClass();
+      final Field field = _class.getField(RuntimeCodeSpecification.DELEGATE_FIELD);
+      boolean _equals = Objects.equal(field, null);
+      if (_equals) {
+        UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException("Unable to set delegate to proxy");
+        throw _unsupportedOperationException;
+      }
+      boolean _or = false;
+      boolean _equals_1 = Objects.equal(delegate, null);
+      if (_equals_1) {
+        _or = true;
+      } else {
+        Class<? extends Object> _type = field.getType();
+        Class<? extends RpcService> _class_1 = delegate.getClass();
+        boolean _isAssignableFrom = _type.isAssignableFrom(_class_1);
+        _or = (_equals_1 || _isAssignableFrom);
+      }
+      if (_or) {
+        field.set(proxy, delegate);
+      } else {
+        IllegalArgumentException _illegalArgumentException = new IllegalArgumentException("delegate class is not assignable to proxy");
+        throw _illegalArgumentException;
+      }
+    } catch (Throwable _e) {
+      throw Exceptions.sneakyThrow(_e);
+    }
+  }
+
+  /**
+   * Helper method to set delegate to ManagedDirectedProxy with use of reflection.
+   *
+   * Note: This method uses reflection, but setting delegate field should not occur too much
+   * to introduce any significant performance hits.
+   */
+  public static void setDelegate(final Object proxy, final Object delegate) {
+    try {
+      Class<? extends Object> _class = proxy.getClass();
+      final Field field = _class.getField(RuntimeCodeSpecification.DELEGATE_FIELD);
+      boolean _equals = Objects.equal(field, null);
+      if (_equals) {
+        UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException("Unable to set delegate to proxy");
+        throw _unsupportedOperationException;
+      }
+      boolean _or = false;
+      boolean _equals_1 = Objects.equal(delegate, null);
+      if (_equals_1) {
+        _or = true;
+      } else {
+        Class<? extends Object> _type = field.getType();
+        Class<? extends Object> _class_1 = delegate.getClass();
+        boolean _isAssignableFrom = _type.isAssignableFrom(_class_1);
+        _or = (_equals_1 || _isAssignableFrom);
+      }
+      if (_or) {
+        field.set(proxy, delegate);
+      } else {
+        IllegalArgumentException _illegalArgumentException = new IllegalArgumentException("delegate class is not assignable to proxy");
+        throw _illegalArgumentException;
+      }
+    } catch (Throwable _e) {
+      throw Exceptions.sneakyThrow(_e);
+    }
+  }
+
+  public static Map<InstanceIdentifier<? extends Object>,? extends RpcService> getRoutingTable(final RpcService target, final Class<? extends BaseIdentity> tableClass) {
+    try {
+      Class<? extends RpcService> _class = target.getClass();
+      String _routingTableField = RuntimeCodeSpecification.getRoutingTableField(tableClass);
+      final Field field = _class.getField(_routingTableField);
+      boolean _equals = Objects.equal(field, null);
+      if (_equals) {
+        UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException(
+          "Unable to get routing table. Table field does not exists");
+        throw _unsupportedOperationException;
+      }
+      try {
+        Object _get = field.get(target);
+        return ((Map<InstanceIdentifier<? extends Object>,? extends RpcService>) _get);
+      } catch (Throwable _e) {
+        throw Exceptions.sneakyThrow(_e);
+      }
+    } catch (Throwable _e_1) {
+      throw Exceptions.sneakyThrow(_e_1);
+    }
+  }
+
+  public static void setRoutingTable(final RpcService target, final Class<? extends BaseIdentity> tableClass, final Map<InstanceIdentifier<? extends Object>,? extends RpcService> routingTable) {
+    try {
+      Class<? extends RpcService> _class = target.getClass();
+      String _routingTableField = RuntimeCodeSpecification.getRoutingTableField(tableClass);
+      final Field field = _class.getField(_routingTableField);
+      boolean _equals = Objects.equal(field, null);
+      if (_equals) {
+        UnsupportedOperationException _unsupportedOperationException = new UnsupportedOperationException(
+          "Unable to set routing table. Table field does not exists");
+        throw _unsupportedOperationException;
+      }
+      field.set(target, routingTable);
+    } catch (Throwable _e) {
+      throw Exceptions.sneakyThrow(_e);
+    }
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/RuntimeCodeHelper.xtend
deleted file mode 100644 (file)
index dff0d21..0000000
+++ /dev/null
@@ -1,81 +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.binding.codegen
-
-import java.util.Map
-
-import org.opendaylight.yangtools.yang.binding.BaseIdentity
-import org.opendaylight.yangtools.yang.binding.RpcService
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-
-import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.*
-
-class RuntimeCodeHelper {
-    /**
-     * Helper method to return delegate from ManagedDirectedProxy with use of reflection.
-     * 
-     * Note: This method uses reflection, but access to delegate field should be 
-     * avoided and called only if neccessary.
-     * 
-     */
-    public static def <T extends RpcService> getDelegate(RpcService proxy) {
-        val field = proxy.class.getField(DELEGATE_FIELD)
-        if (field == null) throw new UnsupportedOperationException("Unable to get delegate from proxy");
-        return field.get(proxy) as T
-    }
-
-    /**
-     * Helper method to set delegate to ManagedDirectedProxy with use of reflection.
-     * 
-     * Note: This method uses reflection, but setting delegate field should not occur too much
-     * to introduce any significant performance hits.
-     * 
-     */
-    public static def void setDelegate(RpcService proxy, RpcService delegate) {
-        val field = proxy.class.getField(DELEGATE_FIELD)
-        if (field == null) throw new UnsupportedOperationException("Unable to set delegate to proxy");
-        if (delegate == null || field.type.isAssignableFrom(delegate.class)) {
-            field.set(proxy, delegate)
-        } else
-            throw new IllegalArgumentException("delegate class is not assignable to proxy");
-    }
-    
-        /**
-     * Helper method to set delegate to ManagedDirectedProxy with use of reflection.
-     * 
-     * Note: This method uses reflection, but setting delegate field should not occur too much
-     * to introduce any significant performance hits.
-     * 
-     */
-    public static def void setDelegate(Object proxy, Object delegate) {
-        val field = proxy.class.getField(DELEGATE_FIELD)
-        if (field == null) throw new UnsupportedOperationException("Unable to set delegate to proxy");
-        if (delegate == null || field.type.isAssignableFrom(delegate.class)) {
-            field.set(proxy, delegate)
-        } else
-            throw new IllegalArgumentException("delegate class is not assignable to proxy");
-    }
-    
-
-    public static def Map<InstanceIdentifier<?>, ? extends RpcService> getRoutingTable(RpcService target,
-        Class<? extends BaseIdentity> tableClass) {
-        val field = target.class.getField(tableClass.routingTableField)
-        if (field == null) throw new UnsupportedOperationException(
-            "Unable to get routing table. Table field does not exists");
-        return field.get(target) as Map<InstanceIdentifier<? extends Object>, ? extends RpcService>;
-    }
-
-    public static def void setRoutingTable(RpcService target, Class<? extends BaseIdentity> tableClass,
-        Map<InstanceIdentifier<?>, ? extends RpcService> routingTable) {
-         val field = target.class.getField(tableClass.routingTableField)
-        if (field == null) throw new UnsupportedOperationException(
-            "Unable to set routing table. Table field does not exists");
-        field.set(target,routingTable);
-    }
-
-}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.java
new file mode 100644 (file)
index 0000000..0bc11d9
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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.codegen;
+
+import java.lang.reflect.Method;
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+@SuppressWarnings("all")
+public class YangtoolsMappingHelper {
+  public static boolean isNotificationCallback(final Method it) {
+      return it.getName().startsWith("on") && (it.getParameterTypes().length == 1) &&
+              Notification.class.isAssignableFrom(it.getParameterTypes()[0]);
+  }
+
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/YangtoolsMappingHelper.xtend
deleted file mode 100644 (file)
index 18d3e26..0000000
+++ /dev/null
@@ -1,19 +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.binding.codegen
-
-import java.lang.reflect.Method
-import org.opendaylight.yangtools.yang.binding.Notification
-
-public static class YangtoolsMappingHelper {
-
-    public static def boolean isNotificationCallback(Method it) {
-        return name.startsWith("on") && parameterTypes.size === 1 &&
-            Notification.isAssignableFrom(parameterTypes.get(0))
-    }
-}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/BrokerImplClassLoader.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/BrokerImplClassLoader.java
new file mode 100644 (file)
index 0000000..cab4fe9
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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.codegen.impl;
+
+import org.eclipse.xtext.xbase.lib.Exceptions;
+
+@SuppressWarnings("all")
+public class BrokerImplClassLoader extends ClassLoader {
+  private final ClassLoader spiClassLoader;
+
+  public BrokerImplClassLoader(final ClassLoader model, final ClassLoader spi) {
+    super(model);
+    this.spiClassLoader = spi;
+  }
+
+  public Class<? extends Object> loadClass(final String name) throws ClassNotFoundException {
+    try {
+      return super.loadClass(name);
+    } catch (ClassNotFoundException e) {
+        return this.spiClassLoader.loadClass(name);
+    }
+  }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/BrokerImplClassLoader.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/BrokerImplClassLoader.xtend
deleted file mode 100644 (file)
index 6481c9d..0000000
+++ /dev/null
@@ -1,29 +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.binding.codegen.impl
-
-import java.lang.ClassLoader
-
-class BrokerImplClassLoader extends ClassLoader {
-
-    val ClassLoader spiClassLoader
-    
-    public new(ClassLoader model, ClassLoader spi) {
-        super(model)
-        spiClassLoader = spi;
-    }
-
-    override public loadClass(String name) throws ClassNotFoundException {
-        try {
-            return super.loadClass(name);
-        } catch (ClassNotFoundException e) {
-            return spiClassLoader.loadClass(name);
-        }
-    }
-
-}
index 48ccbfb..9ede01b 100644 (file)
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
-package org.opendaylight.controller.sal.binding.impl;\r
-\r
+package org.opendaylight.controller.sal.binding.impl;
+
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter;
 import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker;
 import org.opendaylight.controller.sal.binding.api.data.DataChangeListener;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
-import org.opendaylight.controller.sal.binding.impl.util.BindingAwareDataReaderRouter;
+import org.opendaylight.yangtools.concepts.Registration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.util.DataObjectReadingUtil;
 
 import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMap.Builder;
 import com.google.common.collect.Maps;
-\r
-\r
-public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier<? extends DataObject>, DataObject, DataChangeListener> //\r
-       implements DataProviderService, AutoCloseable {\r
-\r
+
+public class DataBrokerImpl extends
+        AbstractDataBroker<InstanceIdentifier<? extends DataObject>, DataObject, DataChangeListener> //
+        implements DataProviderService, AutoCloseable {
+
     private final static class ContainsWildcarded implements Predicate<InstanceIdentifier<? extends DataObject>> {
 
-        private final  InstanceIdentifier<? extends DataObject> key;
+        private final InstanceIdentifier<? extends DataObject> key;
 
-        public ContainsWildcarded(InstanceIdentifier<? extends DataObject> key) {
+        public ContainsWildcarded(final InstanceIdentifier<? extends DataObject> key) {
             this.key = key;
         }
 
         @Override
-        public boolean apply(InstanceIdentifier<? extends DataObject> input) {
+        public boolean apply(final InstanceIdentifier<? extends DataObject> input) {
             return key.containsWildcarded(input);
         }
     }
 
     private final static class IsContainedWildcarded implements Predicate<InstanceIdentifier<? extends DataObject>> {
 
-        private final  InstanceIdentifier<? extends DataObject> key;
+        private final InstanceIdentifier<? extends DataObject> key;
 
-        public IsContainedWildcarded(InstanceIdentifier<? extends DataObject> key) {
+        public IsContainedWildcarded(final InstanceIdentifier<? extends DataObject> key) {
             this.key = key;
         }
 
         @Override
-        public boolean apply(InstanceIdentifier<? extends DataObject> input) {
+        public boolean apply(final InstanceIdentifier<? extends DataObject> input) {
             return input.containsWildcarded(key);
         }
     }
 
-    private final AtomicLong nextTransaction = new AtomicLong();\r
-    private final AtomicLong createdTransactionsCount = new AtomicLong();\r
-\r
-    public AtomicLong getCreatedTransactionsCount() {\r
-        return createdTransactionsCount;\r
-    }\r
-\r
-    public DataBrokerImpl() {\r
-        setDataReadRouter(new BindingAwareDataReaderRouter());\r
-    }\r
-\r
-    @Override\r
-    public DataTransactionImpl beginTransaction() {\r
-        String transactionId = "BA-" + nextTransaction.getAndIncrement();\r
-        createdTransactionsCount.getAndIncrement();\r
-        return new DataTransactionImpl(transactionId,this);\r
-    }\r
-\r
-    @Override\r
-    public void close() {\r
-\r
+    private final AtomicLong nextTransaction = new AtomicLong();
+    private final AtomicLong createdTransactionsCount = new AtomicLong();
+    private final DelegatingDataReadRouter router = new DelegatingDataReadRouter();
+    private DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> rootCommitHandler;
+
+    public DataBrokerImpl() {
+        setDataReadRouter(router);
+    }
+
+    public void setDataReadDelegate(final DataReader<InstanceIdentifier<? extends DataObject>, DataObject> delegate) {
+        router.setDelegate(delegate);
+    }
+
+    public AtomicLong getCreatedTransactionsCount() {
+        return createdTransactionsCount;
+    }
+
+    @Override
+    public DataTransactionImpl beginTransaction() {
+        String transactionId = "BA-" + nextTransaction.getAndIncrement();
+        createdTransactionsCount.getAndIncrement();
+        return new DataTransactionImpl(transactionId, this);
     }
 
     @Override
-    protected Predicate<InstanceIdentifier<? extends DataObject>> createContainsPredicate(final
-            InstanceIdentifier<? extends DataObject> key) {
+    public void close() {
+
+    }
+
+    @Override
+    protected Predicate<InstanceIdentifier<? extends DataObject>> createContainsPredicate(
+            final InstanceIdentifier<? extends DataObject> key) {
         return new ContainsWildcarded(key);
     }
 
     @Override
-    protected Predicate<InstanceIdentifier<? extends DataObject>> createIsContainedPredicate(final
-            InstanceIdentifier<? extends DataObject> key) {
+    protected Predicate<InstanceIdentifier<? extends DataObject>> createIsContainedPredicate(
+            final InstanceIdentifier<? extends DataObject> key) {
         return new IsContainedWildcarded(key);
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
     @Override
     protected Map<InstanceIdentifier<? extends DataObject>, DataObject> deepGetBySubpath(
-            Map<InstanceIdentifier<? extends DataObject>, DataObject> dataSet,
-            InstanceIdentifier<? extends DataObject> path) {
+            final Map<InstanceIdentifier<? extends DataObject>, DataObject> dataSet,
+            final InstanceIdentifier<? extends DataObject> path) {
         Builder<InstanceIdentifier<? extends DataObject>, DataObject> builder = ImmutableMap.builder();
-        Map<InstanceIdentifier<? extends DataObject>, DataObject> potential = Maps.filterKeys(dataSet, createIsContainedPredicate(path));
-        for(Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : potential.entrySet()) {
+        Map<InstanceIdentifier<? extends DataObject>, DataObject> potential = Maps.filterKeys(dataSet,
+                createIsContainedPredicate(path));
+        for (Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry : potential.entrySet()) {
             try {
-                builder.putAll(DataObjectReadingUtil.readData(entry.getValue(),(InstanceIdentifier)entry.getKey(),path));
+                builder.putAll(DataObjectReadingUtil.readData(entry.getValue(), (InstanceIdentifier) entry.getKey(),
+                        path));
             } catch (Exception e) {
                 // FIXME : Log exception;
             }
@@ -108,5 +121,58 @@ public class DataBrokerImpl extends AbstractDataBroker<InstanceIdentifier<? exte
         return builder.build();
 
     }
-\r
+
+    public class DelegatingDataReadRouter extends
+            AbstractDataReadRouter<InstanceIdentifier<? extends DataObject>, DataObject> {
+
+        private DataReader<InstanceIdentifier<? extends DataObject>, DataObject> delegate;
+
+        @Override
+        public DataObject readConfigurationData(final InstanceIdentifier<? extends DataObject> path) {
+            return delegate.readConfigurationData(path);
+        }
+
+        public void setDelegate(final DataReader<InstanceIdentifier<? extends DataObject>, DataObject> delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public DataObject readOperationalData(final InstanceIdentifier<? extends DataObject> path) {
+            return delegate.readOperationalData(path);
+        }
+
+        @Override
+        protected DataObject merge(final InstanceIdentifier<? extends DataObject> path, final Iterable<DataObject> data) {
+            throw new UnsupportedOperationException("Not supported");
+        }
+
+        @Override
+        public Registration<DataReader<InstanceIdentifier<? extends DataObject>, DataObject>> registerConfigurationReader(
+                final InstanceIdentifier<? extends DataObject> path,
+                final DataReader<InstanceIdentifier<? extends DataObject>, DataObject> reader) {
+            throw new UnsupportedOperationException("Not supported");
+        }
+
+        @Override
+        public Registration<DataReader<InstanceIdentifier<? extends DataObject>, DataObject>> registerOperationalReader(
+                final InstanceIdentifier<? extends DataObject> path,
+                final DataReader<InstanceIdentifier<? extends DataObject>, DataObject> reader) {
+            throw new UnsupportedOperationException("Not supported");
+        }
+    }
+
+    @Override
+    protected ImmutableList<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> affectedCommitHandlers(
+            final Set<InstanceIdentifier<? extends DataObject>> paths) {
+        ImmutableList.Builder<DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject>> handlersBuilder = ImmutableList.builder();
+        return handlersBuilder //
+                .add(rootCommitHandler) //
+                .addAll(super.affectedCommitHandlers(paths)) //
+                .build();
+    }
+
+    public void setRootCommitHandler(final DataCommitHandler<InstanceIdentifier<? extends DataObject>, DataObject> commitHandler) {
+        rootCommitHandler = commitHandler;
+    }
+
 }
index 29ba57f..b999a6f 100644 (file)
@@ -118,6 +118,11 @@ public class MountPointManagerImpl implements MountProviderService {
             super(rpcRegistry, notificationBroker, dataBroker);
             this.identifier = identifier;
         }
+
+        // Needed only for BI Connector
+        public DataBrokerImpl getDataBrokerImpl() {
+            return (DataBrokerImpl) getDataBroker();
+        }
         
         @Override
         public InstanceIdentifier<?> getIdentifier() {
index fe2681f..6d675b4 100644 (file)
@@ -60,7 +60,7 @@ class NotificationBrokerImpl implements NotificationProviderService, AutoCloseab
     override publish(Notification notification, ExecutorService service) {\r
         val allTypes = notification.notificationTypes\r
 \r
-        var Iterable<NotificationListener<?>> listenerToNotify = Collections.emptySet();\r
+        var Iterable<NotificationListener<? extends Object>> listenerToNotify = Collections.emptySet();\r
         for (type : allTypes) {\r
             listenerToNotify = listenerToNotify + listeners.get(type as Class<? extends Notification>)\r
         }\r
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProxyContext.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProxyContext.java
new file mode 100644 (file)
index 0000000..3b6a253
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.impl;
+
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.osgi.framework.ServiceRegistration;
+
+@SuppressWarnings("all")
+public class RpcProxyContext {
+  public RpcProxyContext(final Class<? extends RpcService> proxyClass) {
+    this.proxyClass = proxyClass;
+  }
+
+  protected final Class<? extends RpcService> proxyClass;
+
+  protected RpcService _proxy;
+
+  public RpcService getProxy() {
+    return this._proxy;
+  }
+
+  public void setProxy(final RpcService proxy) {
+    this._proxy = proxy;
+  }
+
+  protected ServiceRegistration<? extends RpcService> _registration;
+
+  public ServiceRegistration<? extends RpcService> getRegistration() {
+    return this._registration;
+  }
+
+  public void setRegistration(final ServiceRegistration<? extends RpcService> registration) {
+    this._registration = registration;
+  }
+}
\ No newline at end of file
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProxyContext.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/RpcProxyContext.xtend
deleted file mode 100644 (file)
index 0749459..0000000
+++ /dev/null
@@ -1,26 +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.binding.impl
-
-import org.opendaylight.yangtools.yang.binding.RpcService
-import org.osgi.framework.ServiceRegistration
-
-class RpcProxyContext {
-       
-       new(Class<? extends RpcService> proxyClass) {
-               this.proxyClass = proxyClass
-       }
-       
-       protected val Class<? extends RpcService> proxyClass;
-       
-       @Property
-       protected var RpcService proxy;
-       
-       @Property
-       protected var ServiceRegistration<? extends RpcService> registration;
-}
\ No newline at end of file
index 37c0dfa..93849c2 100644 (file)
@@ -35,7 +35,6 @@ import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandlerRegistration;
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
-import org.opendaylight.controller.md.sal.common.api.data.DataReader;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChange;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangePublisher;
@@ -46,6 +45,8 @@ import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
 import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider;
 import org.opendaylight.controller.sal.binding.api.rpc.RpcContextIdentifier;
 import org.opendaylight.controller.sal.binding.api.rpc.RpcRouter;
+import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl;
+import org.opendaylight.controller.sal.binding.impl.MountPointManagerImpl.BindingMountPointImpl;
 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl;
 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl.GlobalRpcRegistrationListener;
 import org.opendaylight.controller.sal.binding.impl.RpcProviderRegistryImpl.RouterInstantiationListener;
@@ -90,6 +91,7 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSet.Builder;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 
 public class BindingIndependentConnector implements //
         RuntimeDataProvider, //
@@ -100,8 +102,6 @@ public class BindingIndependentConnector implements //
 
     private final Logger LOG = LoggerFactory.getLogger(BindingIndependentConnector.class);
 
-    @SuppressWarnings("deprecation")
-    private static final InstanceIdentifier<? extends DataObject> ROOT = InstanceIdentifier.builder().toInstance();
 
     private static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ROOT_BI = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
             .builder().toInstance();
@@ -140,8 +140,6 @@ public class BindingIndependentConnector implements //
 
     };
 
-    private Registration<DataReader<InstanceIdentifier<? extends DataObject>, DataObject>> baDataReaderRegistration;
-
     private boolean rpcForwarding = false;
 
     private boolean dataForwarding = false;
@@ -306,11 +304,23 @@ public class BindingIndependentConnector implements //
             dataForwarding = true;
             return;
         }
-        checkState(!dataForwarding, "Connector is already forwarding data.");
-        baDataReaderRegistration = baDataService.registerDataReader(ROOT, this);
-        baCommitHandlerRegistration = baDataService.registerCommitHandler(ROOT, bindingToDomCommitHandler);
-        biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler);
-        baDataService.registerCommitHandlerListener(domToBindingCommitHandler);
+
+        final DataProviderService baData;
+        if (baDataService instanceof BindingMountPointImpl) {
+            baData = ((BindingMountPointImpl)baDataService).getDataBrokerImpl();
+            LOG.debug("Extracted BA Data provider {} from mount point {}", baData, baDataService);
+        } else {
+            baData = baDataService;
+        }
+
+        if (baData instanceof DataBrokerImpl) {
+            checkState(!dataForwarding, "Connector is already forwarding data.");
+            ((DataBrokerImpl) baData).setDataReadDelegate(this);
+            ((DataBrokerImpl) baData).setRootCommitHandler(bindingToDomCommitHandler);
+            biCommitHandlerRegistration = biDataService.registerCommitHandler(ROOT_BI, domToBindingCommitHandler);
+            baDataService.registerCommitHandlerListener(domToBindingCommitHandler);
+        }
+
         dataForwarding = true;
     }
 
@@ -690,8 +700,9 @@ public class BindingIndependentConnector implements //
             }
         }
 
+
         @Override
-        public RpcResult<CompositeNode> invokeRpc(final QName rpc, final CompositeNode domInput) {
+        public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(final QName rpc, final CompositeNode domInput) {
             checkArgument(rpc != null);
             checkArgument(domInput != null);
 
@@ -700,10 +711,11 @@ public class BindingIndependentConnector implements //
             RpcService rpcService = baRpcRegistry.getRpcService(rpcType);
             checkState(rpcService != null);
             CompositeNode domUnwrappedInput = domInput.getFirstCompositeByName(QName.create(rpc, "input"));
+
             try {
-                return resolveInvocationStrategy(rpc).invokeOn(rpcService, domUnwrappedInput);
+                return Futures.immediateFuture(resolveInvocationStrategy(rpc).invokeOn(rpcService, domUnwrappedInput));
             } catch (Exception e) {
-                throw new IllegalStateException(e);
+                return Futures.immediateFailedFuture(e);
             }
         }
 
@@ -804,21 +816,25 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
-            if(biRpcRegistry != null) {
-                CompositeNode xml = mappingService.toDataDom(input);
-                CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
-                RpcResult<CompositeNode> result = biRpcRegistry.invokeRpc(rpc, wrappedXml);
-                Object baResultValue = null;
-                if (result.getResult() != null) {
-                    baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(), result.getResult());
-                }
-                RpcResult<?> baResult = Rpcs.getRpcResult(result.isSuccessful(), baResultValue, result.getErrors());
-                return Futures.<RpcResult<?>> immediateFuture(baResult);
+        public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
+            if(biRpcRegistry == null) {
+                return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
             }
-            return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
-        }
 
+            CompositeNode xml = mappingService.toDataDom(input);
+            CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc, ImmutableList.<Node<?>> of(xml));
+
+            return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml), new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
+                @Override
+                public RpcResult<?> apply(RpcResult<CompositeNode> input) {
+                    Object baResultValue = null;
+                    if (input.getResult() != null) {
+                        baResultValue = mappingService.dataObjectFromDataDom(outputClass.get(), input.getResult());
+                    }
+                    return Rpcs.getRpcResult(input.isSuccessful(), baResultValue, input.getErrors());
+                }
+            });
+        }
     }
 
     private class NoInputNoOutputInvocationStrategy extends RpcInvocationStrategy {
@@ -867,18 +883,21 @@ public class BindingIndependentConnector implements //
         }
 
         @Override
-        public Future<RpcResult<?>> forwardToDomBroker(final DataObject input) {
-            if(biRpcRegistry != null) {
-                CompositeNode xml = mappingService.toDataDom(input);
-                CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc,ImmutableList.<Node<?>>of(xml));
-                RpcResult<CompositeNode> result = biRpcRegistry.invokeRpc(rpc, wrappedXml);
-                Object baResultValue = null;
-                RpcResult<?> baResult = Rpcs.<Void>getRpcResult(result.isSuccessful(), null, result.getErrors());
-                return Futures.<RpcResult<?>>immediateFuture(baResult);
+        public ListenableFuture<RpcResult<?>> forwardToDomBroker(final DataObject input) {
+            if(biRpcRegistry == null) {
+                return Futures.<RpcResult<?>> immediateFuture(Rpcs.getRpcResult(false));
             }
-            return Futures.<RpcResult<?>>immediateFuture(Rpcs.getRpcResult(false));
-        }
 
+            CompositeNode xml = mappingService.toDataDom(input);
+            CompositeNode wrappedXml = ImmutableCompositeNode.create(rpc,ImmutableList.<Node<?>>of(xml));
+
+            return Futures.transform(biRpcRegistry.invokeRpc(rpc, wrappedXml), new Function<RpcResult<CompositeNode>, RpcResult<?>>() {
+                @Override
+                public RpcResult<?> apply(RpcResult<CompositeNode> input) {
+                    return Rpcs.<Void>getRpcResult(input.isSuccessful(), null, input.getErrors());
+                }
+            });
+        }
     }
 
     public boolean isRpcForwarding() {
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.java
new file mode 100644 (file)
index 0000000..b031663
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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.binding.impl.util;
+
+import java.util.Iterator;
+import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@SuppressWarnings("all")
+public class BindingAwareDataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier<? extends DataObject>,DataObject> {
+  protected DataObject merge(final InstanceIdentifier<? extends DataObject> path, final Iterable<DataObject> data) {
+    return data.iterator().next();
+  }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/BindingAwareDataReaderRouter.xtend
deleted file mode 100644 (file)
index 5b77580..0000000
+++ /dev/null
@@ -1,20 +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.binding.impl.util
-
-import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.yang.binding.DataObject
-
-class BindingAwareDataReaderRouter extends AbstractDataReadRouter<InstanceIdentifier<? extends DataObject>, DataObject> {
-    
-    override protected merge(InstanceIdentifier<? extends DataObject> path, Iterable<DataObject> data) {
-        return data.iterator.next;
-    }
-    
-}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.java
new file mode 100644 (file)
index 0000000..aa6a9a2
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.binding.impl.util;
+
+import com.google.common.collect.Multimap;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map.Entry;
+import org.opendaylight.yangtools.concepts.Path;
+
+@SuppressWarnings("all")
+public class MapUtils {
+  public static <P extends Path<P>, V extends Object> Collection<Entry<? extends P,? extends V>> getAllChildren(final Multimap<? extends P,? extends V> map, final P path) {
+    HashSet<Entry<? extends P,? extends V>> _hashSet = new HashSet<Entry<? extends P, ? extends V>>();
+    final HashSet<Entry<? extends P,? extends V>> ret = _hashSet;
+    final Collection<? extends Entry<? extends P,? extends V>> entries = map.entries();
+    for (final Entry<? extends P,? extends V> entry : entries) {
+      {
+        final P currentPath = entry.getKey();
+        if (path.contains(currentPath)) {
+          ret.add(entry);
+        } else if (currentPath.contains(path)){
+            ret.add(entry);
+        }
+      }
+    }
+    return ret;
+  }
+}
+
diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/MapUtils.xtend
deleted file mode 100644 (file)
index c60686d..0000000
+++ /dev/null
@@ -1,36 +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.binding.impl.util
-
-import com.google.common.collect.Multimap
-import java.util.Collection
-import java.util.HashSet
-import java.util.Map.Entry
-import org.opendaylight.yangtools.concepts.Path
-
-class MapUtils {
-
-    public static def <P extends Path<P>, V> Collection<Entry<? extends P, ? extends V>> getAllChildren(
-        Multimap<? extends P, ? extends V> map, P path) {
-        val ret = new HashSet();
-        val entries = map.entries;
-
-        for (entry : entries) {
-            val currentPath = entry.key;
-            // If the registered reader processes nested elements
-            if (path.contains(currentPath)) {
-                ret.add(entry);
-            } else if(currentPath.contains(path)) {
-                // If the registered reader is parent of entry
-                ret.add(entry);
-            }
-        }
-
-        return ret;
-    }
-}
index 4afbc29..e6cd1aa 100644 (file)
@@ -14,7 +14,6 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 import javassist.ClassPool;
@@ -40,8 +39,6 @@ import org.opendaylight.yangtools.yang.binding.BaseIdentity;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
 
 public class RuntimeCodeGeneratorTest {
 
@@ -115,7 +112,7 @@ public class RuntimeCodeGeneratorTest {
 
     }
 
-    private void verifyRouting(RpcRouter<FooService> product) {
+    private void verifyRouting(final RpcRouter<FooService> product) {
         assertNotNull("Routing table should be initialized", product.getRoutingTable(BaseIdentity.class));
 
         RpcRoutingTable<BaseIdentity, FooService> routingTable = product.getRoutingTable(BaseIdentity.class);
@@ -159,7 +156,7 @@ public class RuntimeCodeGeneratorTest {
         verify(service[1]).simple(instance_1_input[0]);
     }
 
-    private InstanceIdentifier<?>[][] identifiers(int serviceSize, int instancesPerService) {
+    private InstanceIdentifier<?>[][] identifiers(final int serviceSize, final int instancesPerService) {
         InstanceIdentifier<?>[][] ret = new InstanceIdentifier[serviceSize][];
         int service = 0;
         for (int i = 0; i < serviceSize; i++) {
@@ -175,23 +172,19 @@ public class RuntimeCodeGeneratorTest {
         return ret;
     }
 
-    private InstanceIdentifier<?> referencableIdentifier(int i) {
-        ReferencableObjectKey key = new ReferencableObjectKey(i);
-        IdentifiableItem<ReferencableObject, ReferencableObjectKey> pathArg = new IdentifiableItem<>(
-                ReferencableObject.class, key);
-        return new InstanceIdentifier<ReferencableObject>(Arrays.<PathArgument> asList(pathArg),
-                ReferencableObject.class);
+    private InstanceIdentifier<?> referencableIdentifier(final int i) {
+        return InstanceIdentifier.builder(ReferencableObject.class, new ReferencableObjectKey(i)).build();
     }
 
     private static class SimpleInputImpl implements SimpleInput {
         private final InstanceIdentifier<?> identifier;
 
-        public SimpleInputImpl(InstanceIdentifier<?> _identifier) {
+        public SimpleInputImpl(final InstanceIdentifier<?> _identifier) {
             this.identifier = _identifier;
         }
 
         @Override
-        public <E extends Augmentation<SimpleInput>> E getAugmentation(Class<E> augmentationType) {
+        public <E extends Augmentation<SimpleInput>> E getAugmentation(final Class<E> augmentationType) {
             return null;
         }
 
@@ -230,7 +223,7 @@ public class RuntimeCodeGeneratorTest {
         List<FooUpdate> receivedFoos = new ArrayList<>();
 
         @Override
-        public void onFooUpdate(FooUpdate notification) {
+        public void onFooUpdate(final FooUpdate notification) {
             receivedFoos.add(notification);
         }
 
@@ -242,12 +235,12 @@ public class RuntimeCodeGeneratorTest {
         List<FlowDelete> receivedDeletes = new ArrayList<>();
 
         @Override
-        public void onBarUpdate(BarUpdate notification) {
+        public void onBarUpdate(final BarUpdate notification) {
             receivedBars.add(notification);
         }
 
         @Override
-        public void onFlowDelete(FlowDelete notification) {
+        public void onFlowDelete(final FlowDelete notification) {
             receivedDeletes.add(notification);
         }
 
index 7901bc0..fa56507 100644 (file)
@@ -7,9 +7,12 @@
  */
 package org.opendaylight.controller.sal.binding.test.mock;
 
+import org.opendaylight.yangtools.yang.binding.ChildOf;
 import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataRoot;
 import org.opendaylight.yangtools.yang.binding.Identifiable;
 
-public interface ReferencableObject extends DataObject,Identifiable<ReferencableObjectKey> {
+public interface ReferencableObject extends DataObject,
+    Identifiable<ReferencableObjectKey>,ChildOf<DataRoot>{
 
 }
index 4bad2bb..d6d87ba 100644 (file)
@@ -351,7 +351,6 @@ public class BindingTestContext implements AutoCloseable, SchemaContextProvider
     private void startDomBroker() {
         checkState(executor != null);
         biBrokerImpl = new BrokerImpl();
-        biBrokerImpl.setExecutor(executor);
         biBrokerImpl.setRouter(new SchemaAwareRpcBroker("/", this));
 
     }
index 145dc37..f75995d 100644 (file)
@@ -43,7 +43,7 @@
                                     <codeGeneratorClass>
                                         org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
                                     </codeGeneratorClass>
-                                    <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
+                                    <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
                                     <additionalConfiguration>
                                         <namespaceToPackage1>
                                             urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
                     </dependency>
                 </dependencies>
             </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <version>1.8</version>
-                <executions>
-                    <execution>
-                        <id>add-source</id>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>add-source</goal>
-                        </goals>
-                        <configuration>
-                            <sources>
-                                <source>${project.build.directory}/generated-sources/config</source>
-                            </sources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
         </plugins>
     </build>
 
index 82e3d97..94832c1 100644 (file)
@@ -19,9 +19,6 @@
                 <groupId>org.eclipse.xtend</groupId>
                 <artifactId>xtend-maven-plugin</artifactId>
             </plugin>
-            <plugin>
-                <artifactId>maven-clean-plugin</artifactId>
-            </plugin>
             <plugin>
                 <groupId>org.jacoco</groupId>
                 <artifactId>jacoco-maven-plugin</artifactId>
index b1547b6..ca38ed0 100644 (file)
@@ -50,6 +50,7 @@ import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 
 public class CrossBrokerRpcTest {
@@ -64,7 +65,7 @@ public class CrossBrokerRpcTest {
     public static final NodeId NODE_B = new NodeId("b");
     public static final NodeId NODE_C = new NodeId("c");
     public static final NodeId NODE_D = new NodeId("d");
-    
+
     private static final QName NODE_ID_QNAME = QName.create(Node.QNAME, "id");
     private static final QName ADD_FLOW_QNAME = QName.create(NodeFlowRemoved.QNAME, "add-flow");
 
@@ -78,7 +79,7 @@ public class CrossBrokerRpcTest {
     public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier BI_NODE_C_ID = createBINodeIdentifier(NODE_C);
     public static final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier BI_NODE_D_ID = createBINodeIdentifier(NODE_D);
 
-    
+
 
     @Before
     public void setup() {
@@ -99,7 +100,7 @@ public class CrossBrokerRpcTest {
     }
 
     @Test
-    public void bindingRoutedRpcProvider_DomInvokerTest() {
+    public void bindingRoutedRpcProvider_DomInvokerTest() throws Exception {
 
         flowService//
                 .registerPath(NodeContext.class, BA_NODE_A_ID) //
@@ -114,7 +115,7 @@ public class CrossBrokerRpcTest {
 
         CompositeNode addFlowDom = toDomRpc(ADD_FLOW_QNAME, addFlowA);
         assertNotNull(addFlowDom);
-        RpcResult<CompositeNode> domResult = biRpcInvoker.invokeRpc(ADD_FLOW_QNAME, addFlowDom);
+        RpcResult<CompositeNode> domResult = biRpcInvoker.invokeRpc(ADD_FLOW_QNAME, addFlowDom).get();
         assertNotNull(domResult);
         assertTrue("DOM result is successful.", domResult.isSuccessful());
         assertTrue("Bidning Add Flow RPC was captured.", flowService.getReceivedAddFlows().containsKey(BA_NODE_A_ID));
@@ -128,18 +129,18 @@ public class CrossBrokerRpcTest {
         final AddFlowOutput output = builder.build();
         org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration registration = biRpcRegistry.addRoutedRpcImplementation(ADD_FLOW_QNAME, new RpcImplementation() {
             @Override
-            public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
-                CompositeNode result = testContext.getBindingToDomMappingService().toDataDom(output);
-                return Rpcs.getRpcResult(true, result, ImmutableList.<RpcError>of());
+            public Set<QName> getSupportedRpcs() {
+                return ImmutableSet.of(ADD_FLOW_QNAME);
             }
 
             @Override
-            public Set<QName> getSupportedRpcs() {
-                return ImmutableSet.of(ADD_FLOW_QNAME);
+            public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
+                CompositeNode result = testContext.getBindingToDomMappingService().toDataDom(output);
+                return Futures.immediateFuture(Rpcs.getRpcResult(true, result, ImmutableList.<RpcError>of()));
             }
         });
         registration.registerPath(NodeContext.QNAME, BI_NODE_C_ID);
-        
+
         SalFlowService baFlowInvoker = baRpcRegistry.getRpcService(SalFlowService.class);
         Future<RpcResult<AddFlowOutput>> baResult = baFlowInvoker.addFlow(addFlow(BA_NODE_C_ID).setPriority(500).build());
         assertNotNull(baResult);
diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizationException.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/util/compat/DataNormalizationException.java
new file mode 100644 (file)
index 0000000..f7a15b6
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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.md.sal.common.impl.util.compat;
+
+public class DataNormalizationException extends Exception {
+       private static final long serialVersionUID = 1L;
+
+       public DataNormalizationException(String message) {
+               super(message);
+       }
+
+       public DataNormalizationException(String message, Throwable cause) {
+               super(message, cause);
+       }
+}
index 941f2fd..1055fa8 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * 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.md.sal.common.impl.util.compat;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -70,9 +77,9 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         return Collections.singleton(identifier.getNodeType());
     }
 
-    public abstract DataNormalizationOperation<?> getChild(final PathArgument child);
+    public abstract DataNormalizationOperation<?> getChild(final PathArgument child) throws DataNormalizationException;
 
-    public abstract DataNormalizationOperation<?> getChild(QName child);
+    public abstract DataNormalizationOperation<?> getChild(QName child) throws DataNormalizationException;
 
     public abstract NormalizedNode<?, ?> normalize(Node<?> legacyData);
 
@@ -162,7 +169,13 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
 
             Set<DataNormalizationOperation<?>> usedMixins = new HashSet<>();
             for (Node<?> childLegacy : compositeNode.getValue()) {
-                DataNormalizationOperation childOp = getChild(childLegacy.getNodeType());
+                final DataNormalizationOperation childOp;
+
+                try {
+                    childOp = getChild(childLegacy.getNodeType());
+                } catch (DataNormalizationException e) {
+                    throw new IllegalArgumentException(String.format("Failed to normalize data %s", compositeNode.getValue()), e);
+                }
 
                 // We skip unknown nodes if this node is mixin since
                 // it's nodes and parent nodes are interleaved
@@ -175,8 +188,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
                 if (childOp.isMixin()) {
                     if (usedMixins.contains(childOp)) {
                         // We already run / processed that mixin, so to avoid
-                        // dupliciry we are
-                        // skiping next nodes.
+                        // duplicity we are skipping next nodes.
                         continue;
                     }
                     builder.addChild(childOp.normalize(compositeNode));
@@ -208,7 +220,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        public DataNormalizationOperation<?> getChild(final PathArgument child) {
+        public DataNormalizationOperation<?> getChild(final PathArgument child) throws DataNormalizationException {
             DataNormalizationOperation<?> potential = byArg.get(child);
             if (potential != null) {
                 return potential;
@@ -218,7 +230,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
 
         @Override
-        public DataNormalizationOperation<?> getChild(final QName child) {
+        public DataNormalizationOperation<?> getChild(final QName child) throws DataNormalizationException {
             DataNormalizationOperation<?> potential = byQName.get(child);
             if (potential != null) {
                 return potential;
@@ -486,15 +498,19 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
     }
 
-    public static DataNormalizationOperation<?> fromSchemaAndPathArgument(final DataNodeContainer schema,
-            final QName child) {
+    private static DataNormalizationOperation<?> fromSchemaAndPathArgument(final DataNodeContainer schema,
+            final QName child) throws DataNormalizationException {
         DataSchemaNode potential = schema.getDataChildByName(child);
         if (potential == null) {
             Iterable<org.opendaylight.yangtools.yang.model.api.ChoiceNode> choices = FluentIterable.from(
                     schema.getChildNodes()).filter(org.opendaylight.yangtools.yang.model.api.ChoiceNode.class);
             potential = findChoice(choices, child);
         }
-        checkArgument(potential != null, "Supplied QName %s is not valid according to schema %s", child, schema);
+
+        if (potential == null) {
+            throw new DataNormalizationException(String.format("Supplied QName %s is not valid according to schema %s", child, schema));
+        }
+
         if ((schema instanceof DataSchemaNode) && !((DataSchemaNode) schema).isAugmenting() && potential.isAugmenting()) {
             return fromAugmentation(schema, (AugmentationTarget) schema, potential);
         }
@@ -541,7 +557,7 @@ public abstract class DataNormalizationOperation<T extends PathArgument> impleme
         }
     }
 
-    private static DataNormalizationOperation<?> fromSchema(final DataNodeContainer schema, final PathArgument child) {
+    private static DataNormalizationOperation<?> fromSchema(final DataNodeContainer schema, final PathArgument child) throws DataNormalizationException {
         if (child instanceof AugmentationIdentifier) {
             return fromSchemaAndPathArgument(schema, ((AugmentationIdentifier) child).getPossibleChildNames()
                     .iterator().next());
index 28b2bde..e1fc3c3 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * 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.md.sal.common.impl.util.compat;
 
 import static com.google.common.base.Preconditions.checkArgument;
@@ -7,6 +14,7 @@ import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.Map;
 
+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.AugmentationIdentifier;
@@ -44,18 +52,24 @@ public class DataNormalizer {
 
         DataNormalizationOperation<?> currentOp = operation;
         Iterator<PathArgument> arguments = legacy.getPath().iterator();
-        while ( arguments.hasNext() ) {
-            PathArgument legacyArg = arguments.next();
-            currentOp = currentOp.getChild(legacyArg);
-            checkArgument(currentOp != null, "Legacy Instance Identifier %s is not correct. Normalized Instance Identifier so far %s",legacy,normalizedArgs.build());
-            while (currentOp.isMixin()) {
-                normalizedArgs.add(currentOp.getIdentifier());
-                currentOp = currentOp.getChild(legacyArg.getNodeType());
-            }
-            if(arguments.hasNext() || (!currentOp.isKeyedEntry() || legacyArg instanceof NodeIdentifierWithPredicates || legacyArg instanceof NodeWithValue)) {
-                normalizedArgs.add(legacyArg);
+
+        try {
+            while ( arguments.hasNext() ) {
+                PathArgument legacyArg = arguments.next();
+                currentOp = currentOp.getChild(legacyArg);
+                checkArgument(currentOp != null, "Legacy Instance Identifier %s is not correct. Normalized Instance Identifier so far %s",legacy,normalizedArgs.build());
+                while (currentOp.isMixin()) {
+                    normalizedArgs.add(currentOp.getIdentifier());
+                    currentOp = currentOp.getChild(legacyArg.getNodeType());
+                }
+                if(arguments.hasNext() || (!currentOp.isKeyedEntry() || legacyArg instanceof NodeIdentifierWithPredicates || legacyArg instanceof NodeWithValue)) {
+                    normalizedArgs.add(legacyArg);
+                }
             }
+        } catch (DataNormalizationException e) {
+            throw new IllegalArgumentException(String.format("Failed to normalize path %s", legacy), e);
         }
+
         return new InstanceIdentifier(normalizedArgs.build());
     }
 
@@ -69,12 +83,24 @@ public class DataNormalizer {
 
         DataNormalizationOperation<?> currentOp = operation;
         for (PathArgument arg : normalizedPath.getPath()) {
-            currentOp = currentOp.getChild(arg);
+            try {
+                currentOp = currentOp.getChild(arg);
+            } catch (DataNormalizationException e) {
+                throw new IllegalArgumentException(String.format("Failed to validate normalized path %s", normalizedPath), e);
+            }
         }
-        // Write Augmentaiton data resolution
+
+        // Write Augmentation data resolution
         if (legacyData.getChildren().size() == 1) {
-            DataNormalizationOperation<?> potentialOp = currentOp.getChild(legacyData.getChildren().get(0)
-                    .getNodeType());
+            final DataNormalizationOperation<?> potentialOp;
+
+            try {
+                final QName childType = legacyData.getChildren().get(0).getNodeType();
+                potentialOp = currentOp.getChild(childType);
+            } catch (DataNormalizationException e) {
+                throw new IllegalArgumentException(String.format("Failed to get child operation for %s", legacyData), e);
+            }
+
             if(potentialOp.getIdentifier() instanceof AugmentationIdentifier) {
                 currentOp = potentialOp;
                 ArrayList<PathArgument> reworkedArgs = new ArrayList<>(normalizedPath.getPath());
index 15932d5..181fc5c 100644 (file)
@@ -33,7 +33,7 @@
                                     <codeGeneratorClass>
                                         org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
                                     </codeGeneratorClass>
-                                    <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
+                                    <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
                                     <additionalConfiguration>
                                         <namespaceToPackage1>
                                             urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
                     </dependency>
                 </dependencies>
             </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <version>1.8</version>
-                <executions>
-                    <execution>
-                        <id>add-source</id>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>add-source</goal>
-                        </goals>
-                        <configuration>
-                            <sources>
-                                <source>${project.build.directory}/generated-sources/config</source>
-                            </sources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
         </plugins>
     </build>
     <dependencies>
index c8eb7fd..4f11ba0 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * 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.core.api;
 
 import org.opendaylight.yangtools.yang.common.QName;
@@ -5,8 +12,10 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 public interface RoutedRpcDefaultImplementation {
 
-  public RpcResult<CompositeNode> invokeRpc(QName rpc, InstanceIdentifier identifier, CompositeNode input);
+    ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, InstanceIdentifier identifier, CompositeNode input);
 
 }
index 6b1030a..38b33d5 100644 (file)
@@ -15,6 +15,8 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 /**
  * {@link Provider}'s implementation of an RPC.
  *
@@ -42,8 +44,6 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
  * {@link RpcResult}
  * <li> {@link Broker} returns the {@link RpcResult} to {@link Consumer}
  * </ol>
- *
- *
  */
 public interface RpcImplementation extends Provider.ProviderFunctionality {
 
@@ -59,13 +59,12 @@ public interface RpcImplementation extends Provider.ProviderFunctionality {
     Set<QName> getSupportedRpcs();
 
     /**
-     * Invokes a implementation of specified rpc.
-     *
+     * Invokes a implementation of specified RPC asynchronously.
      *
      * @param rpc
-     *            Rpc to be invoked
+     *            RPC to be invoked
      * @param input
-     *            Input data for rpc.
+     *            Input data for the RPC.
      *
      * @throws IllegalArgumentException
      *             <ul>
@@ -73,9 +72,9 @@ public interface RpcImplementation extends Provider.ProviderFunctionality {
      *             <li>If input is not <code>null</code> and
      *             <code>false == rpc.equals(input.getNodeType)</code>
      *             </ul>
-     * @return RpcResult containing the output of rpc if was executed
-     *         successfully, the list of errors otherwise.
+     * @return Future promising an RpcResult containing the output of
+     *         the RPC if was executed successfully, the list of errors
+     *         otherwise.
      */
-    RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input);
-
+    ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input);
 }
index 5063e43..360988f 100644 (file)
@@ -84,7 +84,7 @@
                                     <codeGeneratorClass>
                                         org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
                                     </codeGeneratorClass>
-                                    <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
+                                    <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
                                     <additionalConfiguration>
                                         <namespaceToPackage1>
                                             urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
                     </instructions>
                 </configuration>
             </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <version>1.8</version>
-                <executions>
-                    <execution>
-                        <id>add-source</id>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>add-source</goal>
-                        </goals>
-                        <configuration>
-                            <sources>
-                                <source>${project.build.directory}/generated-sources/config</source>
-                                <source>src/main/xtend-gen</source>
-                            </sources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
             <plugin>
                 <groupId>org.eclipse.xtend</groupId>
                 <artifactId>xtend-maven-plugin</artifactId>
index fce2494..b905d2f 100644 (file)
@@ -1,3 +1,10 @@
+/*
+ * 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.md.sal.dom.broker.impl.compat;
 
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -14,6 +21,7 @@ import java.util.concurrent.Future;
 
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationException;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizationOperation;
 import org.opendaylight.controller.md.sal.common.impl.util.compat.DataNormalizer;
 import org.opendaylight.controller.md.sal.dom.api.DOMDataReadTransaction;
@@ -232,7 +240,11 @@ public abstract class BackwardsCompatibleTransaction<T extends DOMDataReadTransa
             Iterator<PathArgument> iterator = normalizedPath.getPath().iterator();
             while(iterator.hasNext()) {
                 PathArgument currentArg = iterator.next();
-                currentOp = currentOp.getChild(currentArg);
+                try {
+                    currentOp = currentOp.getChild(currentArg);
+                } catch (DataNormalizationException e) {
+                    throw new IllegalArgumentException(String.format("Invalid child encountered in path %s", normalizedPath), e);
+                }
                 currentArguments.add(currentArg);
                 InstanceIdentifier currentPath = new InstanceIdentifier(currentArguments);
                 boolean isPresent = getDelegate().read(store, currentPath).get().isPresent();
index f231bb5..df2725d 100644 (file)
@@ -10,7 +10,8 @@ import java.util.Set;
 
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.dom.store.impl.DOMImmutableDataChangeEvent.Builder;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree.Walker;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
@@ -28,7 +29,7 @@ public class DataChangeEventResolver {
     private static final DOMImmutableDataChangeEvent NO_CHANGE = builder().build();
     private final ImmutableList.Builder<ChangeListenerNotifyTask> tasks = ImmutableList.builder();
     private InstanceIdentifier rootPath;
-    private ListenerRegistrationNode listenerRoot;
+    private ListenerTree listenerRoot;
     private NodeModification modificationRoot;
     private Optional<StoreMetadataNode> beforeRoot;
     private Optional<StoreMetadataNode> afterRoot;
@@ -42,11 +43,11 @@ public class DataChangeEventResolver {
         return this;
     }
 
-    protected ListenerRegistrationNode getListenerRoot() {
+    protected ListenerTree getListenerRoot() {
         return listenerRoot;
     }
 
-    protected DataChangeEventResolver setListenerRoot(final ListenerRegistrationNode listenerRoot) {
+    protected DataChangeEventResolver setListenerRoot(final ListenerTree listenerRoot) {
         this.listenerRoot = listenerRoot;
         return this;
     }
@@ -79,13 +80,16 @@ public class DataChangeEventResolver {
     }
 
     public Iterable<ChangeListenerNotifyTask> resolve() {
-        LOG.trace("Resolving events for {}" ,modificationRoot);
-        resolveAnyChangeEvent(rootPath, Optional.of(listenerRoot), modificationRoot, beforeRoot, afterRoot);
-        return tasks.build();
+        LOG.trace("Resolving events for {}", modificationRoot);
+
+        try (final Walker w = listenerRoot.getWalker()) {
+            resolveAnyChangeEvent(rootPath, Optional.of(w.getRootNode()), modificationRoot, beforeRoot, afterRoot);
+            return tasks.build();
+        }
     }
 
     private DOMImmutableDataChangeEvent resolveAnyChangeEvent(final InstanceIdentifier path,
-            final Optional<ListenerRegistrationNode> listeners, final NodeModification modification,
+            final Optional<ListenerTree.Node> listeners, final NodeModification modification,
             final Optional<StoreMetadataNode> before, final Optional<StoreMetadataNode> after) {
         // No listeners are present in listener registration subtree
         // no before and after state is present
@@ -119,13 +123,13 @@ public class DataChangeEventResolver {
      * @return
      */
     private DOMImmutableDataChangeEvent resolveCreateEvent(final InstanceIdentifier path,
-            final Optional<ListenerRegistrationNode> listeners, final StoreMetadataNode afterState) {
+            final Optional<ListenerTree.Node> listeners, final StoreMetadataNode afterState) {
         final NormalizedNode<?, ?> node = afterState.getData();
         Builder builder = builder().setAfter(node).addCreated(path, node);
 
         for (StoreMetadataNode child : afterState.getChildren()) {
             PathArgument childId = child.getIdentifier();
-            Optional<ListenerRegistrationNode> childListeners = getChild(listeners, childId);
+            Optional<ListenerTree.Node> childListeners = getChild(listeners, childId);
 
             InstanceIdentifier childPath = StoreUtils.append(path, childId);
             builder.merge(resolveCreateEvent(childPath, childListeners, child));
@@ -135,13 +139,13 @@ public class DataChangeEventResolver {
     }
 
     private DOMImmutableDataChangeEvent resolveDeleteEvent(final InstanceIdentifier path,
-            final Optional<ListenerRegistrationNode> listeners, final StoreMetadataNode beforeState) {
+            final Optional<ListenerTree.Node> listeners, final StoreMetadataNode beforeState) {
         final NormalizedNode<?, ?> node = beforeState.getData();
         Builder builder = builder().setBefore(node).addRemoved(path, node);
 
         for (StoreMetadataNode child : beforeState.getChildren()) {
             PathArgument childId = child.getIdentifier();
-            Optional<ListenerRegistrationNode> childListeners = getChild(listeners, childId);
+            Optional<ListenerTree.Node> childListeners = getChild(listeners, childId);
             InstanceIdentifier childPath = StoreUtils.append(path, childId);
             builder.merge(resolveDeleteEvent(childPath, childListeners, child));
         }
@@ -149,7 +153,7 @@ public class DataChangeEventResolver {
     }
 
     private DOMImmutableDataChangeEvent resolveSubtreeChangeEvent(final InstanceIdentifier path,
-            final Optional<ListenerRegistrationNode> listeners, final NodeModification modification,
+            final Optional<ListenerTree.Node> listeners, final NodeModification modification,
             final StoreMetadataNode before, final StoreMetadataNode after) {
 
         Builder one = builder().setBefore(before.getData()).setAfter(after.getData());
@@ -159,7 +163,7 @@ public class DataChangeEventResolver {
         for (NodeModification childMod : modification.getModifications()) {
             PathArgument childId = childMod.getIdentifier();
             InstanceIdentifier childPath = append(path, childId);
-            Optional<ListenerRegistrationNode> childListen = getChild(listeners, childId);
+            Optional<ListenerTree.Node> childListen = getChild(listeners, childId);
 
             Optional<StoreMetadataNode> childBefore = before.getChild(childId);
             Optional<StoreMetadataNode> childAfter = after.getChild(childId);
@@ -189,13 +193,13 @@ public class DataChangeEventResolver {
     }
 
     private DOMImmutableDataChangeEvent resolveReplacedEvent(final InstanceIdentifier path,
-            final Optional<ListenerRegistrationNode> listeners, final NodeModification modification,
+            final Optional<ListenerTree.Node> listeners, final NodeModification modification,
             final StoreMetadataNode before, final StoreMetadataNode after) {
         // FIXME Add task
         return builder().build();
     }
 
-    private DOMImmutableDataChangeEvent addNotifyTask(final Optional<ListenerRegistrationNode> listeners, final DOMImmutableDataChangeEvent event) {
+    private DOMImmutableDataChangeEvent addNotifyTask(final Optional<ListenerTree.Node> listeners, final DOMImmutableDataChangeEvent event) {
         if (listeners.isPresent()) {
             final Collection<DataChangeListenerRegistration<?>> l = listeners.get().getListeners();
             if (!l.isEmpty()) {
@@ -206,7 +210,7 @@ public class DataChangeEventResolver {
         return event;
     }
 
-    private void addNotifyTask(final ListenerRegistrationNode listenerRegistrationNode, final DataChangeScope scope,
+    private void addNotifyTask(final ListenerTree.Node listenerRegistrationNode, final DataChangeScope scope,
             final DOMImmutableDataChangeEvent event) {
         Collection<DataChangeListenerRegistration<?>> potential = listenerRegistrationNode.getListeners();
         if(!potential.isEmpty()) {
index de0c146..a854c48 100644 (file)
@@ -18,8 +18,7 @@ import java.util.concurrent.atomic.AtomicReference;
 
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode;
-import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerRegistrationNode.DataChangeListenerRegistration;
+import org.opendaylight.controller.md.sal.dom.store.impl.tree.ListenerTree;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.ModificationType;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
@@ -59,7 +58,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     private final ListeningExecutorService executor;
     private final String name;
     private final AtomicLong txCounter = new AtomicLong(0);
-    private final ListenerRegistrationNode listenerTree;
+    private final ListenerTree listenerTree;
     private final AtomicReference<DataAndMetadataSnapshot> snapshot;
 
     private ModificationApplyOperation operationTree;
@@ -69,7 +68,7 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
     public InMemoryDOMDataStore(final String name, final ListeningExecutorService executor) {
         this.name = Preconditions.checkNotNull(name);
         this.executor = Preconditions.checkNotNull(executor);
-        this.listenerTree = ListenerRegistrationNode.createRoot();
+        this.listenerTree = ListenerTree.create();
         this.snapshot = new AtomicReference<DataAndMetadataSnapshot>(DataAndMetadataSnapshot.createEmpty());
         this.operationTree = new AlwaysFailOperation();
     }
@@ -114,12 +113,8 @@ public class InMemoryDOMDataStore implements DOMStore, Identifiable<String>, Sch
         final DataChangeListenerRegistration<L> reg;
         synchronized (this) {
             LOG.debug("{}: Registering data change listener {} for {}",name,listener,path);
-            ListenerRegistrationNode listenerNode = listenerTree;
-            for(PathArgument arg : path.getPath()) {
-                listenerNode = listenerNode.ensureChild(arg);
-            }
 
-            reg = listenerNode.registerDataChangeListener(path, listener, scope);
+            reg = listenerTree.registerDataChangeListener(path, listener, scope);
 
             Optional<StoreMetadataNode> currentState = snapshot.get().read(path);
             if (currentState.isPresent()) {
index f252744..14d8279 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.controller.md.sal.dom.store.impl;
 import static com.google.common.base.Preconditions.checkState;
 
 import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.NodeModification;
 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreMetadataNode;
@@ -22,16 +23,18 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
+/*
+ * FIXME: the thread safety of concurrent write/delete/read/seal operations
+ *        needs to be evaluated.
+ */
 class MutableDataTree {
-
-    private static final Logger log = LoggerFactory.getLogger(MutableDataTree.class);
-
-    final DataAndMetadataSnapshot snapshot;
-    final NodeModification rootModification;
-    final ModificationApplyOperation strategyTree;
-
-    private boolean sealed = false;
+    private static final Logger LOG = LoggerFactory.getLogger(MutableDataTree.class);
+    private final AtomicBoolean sealed = new AtomicBoolean();
+    private final ModificationApplyOperation strategyTree;
+    private final DataAndMetadataSnapshot snapshot;
+    private final NodeModification rootModification;
 
     private MutableDataTree(final DataAndMetadataSnapshot snapshot, final ModificationApplyOperation strategyTree) {
         this.snapshot = snapshot;
@@ -58,7 +61,6 @@ class MutableDataTree {
             return NormalizedNodeUtils.findNode(modification.getKey(), data, path);
         }
         return Optional.absent();
-
     }
 
     private Optional<StoreMetadataNode> resolveSnapshot(
@@ -78,13 +80,13 @@ class MutableDataTree {
             return resolveModificationStrategy(path).apply(modification, modification.getOriginal(),
                     StoreUtils.increase(snapshot.getMetadataTree().getSubtreeVersion()));
         } catch (Exception e) {
-            log.error("Could not create snapshot for {}", path,e);
+            LOG.error("Could not create snapshot for {}", path,e);
             throw e;
         }
     }
 
     private ModificationApplyOperation resolveModificationStrategy(final InstanceIdentifier path) {
-        log.trace("Resolving modification apply strategy for {}", path);
+        LOG.trace("Resolving modification apply strategy for {}", path);
         return TreeNodeUtils.findNodeChecked(strategyTree, path);
     }
 
@@ -103,12 +105,13 @@ class MutableDataTree {
     }
 
     public void seal() {
-        sealed = true;
+        final boolean success = sealed.compareAndSet(false, true);
+        Preconditions.checkState(success, "Attempted to seal an already-sealed Data Tree.");
         rootModification.seal();
     }
 
     private void checkSealed() {
-        checkState(!sealed, "Data Tree is sealed. No further modifications allowed.");
+        checkState(!sealed.get(), "Data Tree is sealed. No further modifications allowed.");
     }
 
     protected NodeModification getRootModification() {
@@ -119,6 +122,4 @@ class MutableDataTree {
     public String toString() {
         return "MutableDataTree [modification=" + rootModification + "]";
     }
-
-
 }
index 02c2a4f..830d7e3 100644 (file)
@@ -24,7 +24,6 @@ import com.google.common.primitives.UnsignedLong;
 public final class StoreUtils {
 
     private final static Function<Identifiable<Object>, Object> EXTRACT_IDENTIFIER = new Function<Identifiable<Object>, Object>() {
-
         @Override
         public Object apply(final Identifiable<Object> input) {
             return input.getIdentifier();
@@ -45,6 +44,11 @@ public final class StoreUtils {
         return new InitialDataChangeEvent(path, data.getData());
     }
 
+    /*
+     * Suppressing warnings here allows us to fool the compiler enough
+     * such that we can reuse a single function for all applicable types
+     * and present it in a type-safe manner to our users.
+     */
     @SuppressWarnings({ "unchecked", "rawtypes" })
     public static <V> Function<Identifiable<V>, V> identifierExtractor() {
         return (Function) EXTRACT_IDENTIFIER;
@@ -90,7 +94,6 @@ public final class StoreUtils {
         public NormalizedNode<?, ?> getUpdatedSubtree() {
             return data;
         }
-
     }
 
     public static <V> Set<V> toIdentifierSet(final Iterable<? extends Identifiable<V>> children) {
@@ -101,7 +104,6 @@ public final class StoreUtils {
         StringBuilder builder = new StringBuilder();
         toStringTree(builder, metaNode, 0);
         return builder.toString();
-
     }
 
     private static void toStringTree(final StringBuilder builder, final StoreMetadataNode metaNode, final int offset) {
@@ -109,15 +111,15 @@ public final class StoreUtils {
         builder.append(prefix).append(toStringTree(metaNode.getIdentifier()));
         NormalizedNode<?, ?> dataNode = metaNode.getData();
         if (dataNode instanceof NormalizedNodeContainer<?, ?, ?>) {
-            builder.append(" {").append("\n");
+            builder.append(" {\n");
             for (StoreMetadataNode child : metaNode.getChildren()) {
                 toStringTree(builder, child, offset + 4);
             }
-            builder.append(prefix).append("}");
+            builder.append(prefix).append('}');
         } else {
-            builder.append(" ").append(dataNode.getValue());
+            builder.append(' ').append(dataNode.getValue());
         }
-        builder.append("\n");
+        builder.append('\n');
     }
 
     private static String toStringTree(final PathArgument identifier) {
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ListenerRegistrationNode.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ListenerRegistrationNode.java
deleted file mode 100644 (file)
index 854c125..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-package org.opendaylight.controller.md.sal.dom.store.impl.tree;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
-import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
-import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
-import org.opendaylight.yangtools.concepts.Identifiable;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Optional;
-
-public class ListenerRegistrationNode implements StoreTreeNode<ListenerRegistrationNode>, Identifiable<PathArgument> {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ListenerRegistrationNode.class);
-
-    private final ListenerRegistrationNode parent;
-    private final Map<PathArgument, ListenerRegistrationNode> children;
-    private final PathArgument identifier;
-    private final HashSet<DataChangeListenerRegistration<?>> listeners;
-
-    private ListenerRegistrationNode(final PathArgument identifier) {
-        this(null, identifier);
-    }
-
-    private ListenerRegistrationNode(final ListenerRegistrationNode parent, final PathArgument identifier) {
-        this.parent = parent;
-        this.identifier = identifier;
-        children = new HashMap<>();
-        listeners = new HashSet<>();
-    }
-
-    public final static ListenerRegistrationNode createRoot() {
-        return new ListenerRegistrationNode(null);
-    }
-
-    @Override
-    public PathArgument getIdentifier() {
-        return identifier;
-    }
-
-    /**
-     * Return the list of current listeners. Any caller wishing to use this method
-     * has to make sure the collection remains unchanged while it's executing. This
-     * means the caller has to synchronize externally both the registration and
-     * unregistration process.
-     *
-     * @return the list of current listeners
-     */
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    public Collection<org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration<?>> getListeners() {
-        return (Collection) listeners;
-    }
-
-    @Override
-    public synchronized Optional<ListenerRegistrationNode> getChild(final PathArgument child) {
-        return Optional.fromNullable(children.get(child));
-    }
-
-    public synchronized ListenerRegistrationNode ensureChild(final PathArgument child) {
-        ListenerRegistrationNode potential = (children.get(child));
-        if (potential == null) {
-            potential = new ListenerRegistrationNode(this, child);
-            children.put(child, potential);
-        }
-        return potential;
-    }
-
-    /**
-     * Registers listener on this node.
-     *
-     * @param path Full path on which listener is registered.
-     * @param listener Listener
-     * @param scope Scope of triggering event.
-     * @return
-     */
-    public synchronized <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> DataChangeListenerRegistration<L> registerDataChangeListener(final InstanceIdentifier path,
-            final L listener, final DataChangeScope scope) {
-
-        DataChangeListenerRegistration<L> listenerReg = new DataChangeListenerRegistration<L>(path,listener, scope, this);
-        listeners.add(listenerReg);
-        LOG.debug("Listener {} registered", listener);
-        return listenerReg;
-    }
-
-    private synchronized void removeListener(final DataChangeListenerRegistration<?> listener) {
-        listeners.remove(listener);
-        LOG.debug("Listener {} unregistered", listener);
-        removeThisIfUnused();
-    }
-
-    private void removeThisIfUnused() {
-        if (parent != null && listeners.isEmpty() && children.isEmpty()) {
-            parent.removeChildIfUnused(this);
-        }
-    }
-
-    public boolean isUnused() {
-        return (listeners.isEmpty() && children.isEmpty()) || areChildrenUnused();
-    }
-
-    private boolean areChildrenUnused() {
-        for (ListenerRegistrationNode child : children.values()) {
-            if (!child.isUnused()) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    private void removeChildIfUnused(final ListenerRegistrationNode listenerRegistrationNode) {
-        // FIXME Remove unnecessary
-    }
-
-    public static class DataChangeListenerRegistration<T extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>>
-            extends AbstractObjectRegistration<T> implements
-            org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration<T> {
-
-        private final DataChangeScope scope;
-        private ListenerRegistrationNode node;
-        private final InstanceIdentifier path;
-
-        public DataChangeListenerRegistration(final InstanceIdentifier path,final T listener, final DataChangeScope scope,
-                final ListenerRegistrationNode node) {
-            super(listener);
-            this.path = path;
-            this.scope = scope;
-            this.node = node;
-        }
-
-        @Override
-        public DataChangeScope getScope() {
-            return scope;
-        }
-
-        @Override
-        protected void removeRegistration() {
-            node.removeListener(this);
-            node = null;
-        }
-
-        @Override
-        public InstanceIdentifier getPath() {
-            return path;
-        }
-    }
-}
diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ListenerTree.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/md/sal/dom/store/impl/tree/ListenerTree.java
new file mode 100644 (file)
index 0000000..83cfcac
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * 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.md.sal.dom.store.impl.tree;
+
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import javax.annotation.concurrent.GuardedBy;
+
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeListener;
+import org.opendaylight.controller.md.sal.dom.store.impl.DataChangeListenerRegistration;
+import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
+import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+public final class ListenerTree {
+    private static final Logger LOG = LoggerFactory.getLogger(ListenerTree.class);
+    private final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
+    private final Node rootNode = new Node(null, null);
+
+    private ListenerTree() {
+
+    }
+
+    public static ListenerTree create() {
+        return new ListenerTree();
+    }
+
+    /**
+     * Registers listener on this node.
+     *
+     * @param path Full path on which listener is registered.
+     * @param listener Listener
+     * @param scope Scope of triggering event.
+     * @return Listener registration
+     */
+    public <L extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> DataChangeListenerRegistration<L> registerDataChangeListener(final InstanceIdentifier path,
+            final L listener, final DataChangeScope scope) {
+
+        // Take the write lock
+        rwLock.writeLock().lock();
+
+        try {
+            Node walkNode = rootNode;
+            for (final PathArgument arg : path.getPath()) {
+                walkNode = walkNode.ensureChild(arg);
+            }
+
+            final Node node = walkNode;
+            DataChangeListenerRegistration<L> reg = new DataChangeListenerRegistrationImpl<L>(listener) {
+                @Override
+                public DataChangeScope getScope() {
+                    return scope;
+                }
+
+                @Override
+                public InstanceIdentifier getPath() {
+                    return path;
+                }
+
+                @Override
+                protected void removeRegistration() {
+                    /*
+                     * TODO: Here's an interesting problem. The way the datastore works, it
+                     *       enqueues requests towards the listener, so the listener will be
+                     *       notified at some point in the future. Now if the registration is
+                     *       closed, we will prevent any new events from being delivered, but
+                     *       we have no way to purge that queue.
+                     *
+                     *       While this does not directly violate the ListenerRegistration
+                     *       contract, it is probably not going to be liked by the users.
+                     */
+
+                    // Take the write lock
+                    ListenerTree.this.rwLock.writeLock().lock();
+                    try {
+                        node.removeListener(this);
+                    } finally {
+                        // Always release the lock
+                        ListenerTree.this.rwLock.writeLock().unlock();
+                    }
+                }
+            };
+
+            node.addListener(reg);
+            return reg;
+        } finally {
+            // Always release the lock
+            rwLock.writeLock().unlock();
+        }
+    }
+
+    public Walker getWalker() {
+        /*
+         * TODO: The only current user of this method is local to the datastore.
+         *       Since this class represents a read-lock, losing a reference to
+         *       it is a _major_ problem, as the registration process will get
+         *       wedged, eventually grinding the system to a halt. Should an
+         *       external user exist, make the Walker a phantom reference, which
+         *       will cleanup the lock if not told to do so.
+         */
+        final Walker ret = new Walker(rwLock.readLock(), rootNode);
+        rwLock.readLock().lock();
+        return ret;
+    }
+
+    public static final class Walker implements AutoCloseable {
+        private final Lock lock;
+        private final Node node;
+
+        @GuardedBy("this")
+        private boolean valid = true;
+
+        private Walker(final Lock lock, final Node node) {
+            this.lock = Preconditions.checkNotNull(lock);
+            this.node = Preconditions.checkNotNull(node);
+        }
+
+        public Node getRootNode() {
+            return node;
+        }
+
+        @Override
+        public synchronized void close() {
+            if (valid) {
+                lock.unlock();
+                valid = false;
+            }
+        }
+    }
+
+    /**
+     * This is a single node within the listener tree. Note that the data returned from
+     * and instance of this class is guaranteed to have any relevance or consistency
+     * only as long as the {@link Walker} instance through which it is reached remains
+     * unclosed.
+     */
+    public static final class Node implements StoreTreeNode<Node>, Identifiable<PathArgument> {
+        private final Collection<DataChangeListenerRegistration<?>> listeners = new ArrayList<>();
+        private final Map<PathArgument, Node> children = new HashMap<>();
+        private final PathArgument identifier;
+        private final Reference<Node> parent;
+
+        private Node(final Node parent, final PathArgument identifier) {
+            this.parent = new WeakReference<>(parent);
+            this.identifier = identifier;
+        }
+
+        @Override
+        public PathArgument getIdentifier() {
+            return identifier;
+        }
+
+        @Override
+        public Optional<Node> getChild(final PathArgument child) {
+            return Optional.fromNullable(children.get(child));
+        }
+
+        /**
+         * Return the list of current listeners. This collection is guaranteed
+         * to be immutable only while the walker, through which this node is
+         * reachable remains unclosed.
+         *
+         * @return the list of current listeners
+         */
+        public Collection<DataChangeListenerRegistration<?>> getListeners() {
+            return listeners;
+        }
+
+        private Node ensureChild(final PathArgument child) {
+            Node potential = children.get(child);
+            if (potential == null) {
+                potential = new Node(this, child);
+                children.put(child, potential);
+            }
+            return potential;
+        }
+
+        private void addListener(final DataChangeListenerRegistration<?> listener) {
+            listeners.add(listener);
+            LOG.debug("Listener {} registered", listener);
+        }
+
+        private void removeListener(final DataChangeListenerRegistrationImpl<?> listener) {
+            listeners.remove(listener);
+            LOG.debug("Listener {} unregistered", listener);
+
+            // We have been called with the write-lock held, so we can perform some cleanup.
+            removeThisIfUnused();
+        }
+
+        private void removeThisIfUnused() {
+            final Node p = parent.get();
+            if (p != null && listeners.isEmpty() && children.isEmpty()) {
+                p.removeChild(identifier);
+            }
+        }
+
+        private void removeChild(final PathArgument arg) {
+            children.remove(arg);
+            removeThisIfUnused();
+        }
+    }
+
+    private abstract static class DataChangeListenerRegistrationImpl<T extends AsyncDataChangeListener<InstanceIdentifier, NormalizedNode<?, ?>>> extends AbstractListenerRegistration<T> //
+    implements DataChangeListenerRegistration<T> {
+        public DataChangeListenerRegistrationImpl(final T listener) {
+            super(listener);
+        }
+    }
+}
index a0c15eb..04fb3b7 100644 (file)
@@ -12,6 +12,8 @@ import static com.google.common.base.Preconditions.checkState;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
+import javax.annotation.concurrent.GuardedBy;
+
 import org.opendaylight.yangtools.concepts.Identifiable;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
@@ -51,6 +53,7 @@ public class NodeModification implements StoreTreeNode<NodeModification>, Identi
 
     private final Map<PathArgument, NodeModification> childModification;
 
+    @GuardedBy("this")
     private boolean sealed = false;
 
     protected NodeModification(final PathArgument identifier, final Optional<StoreMetadataNode> original) {
@@ -173,6 +176,7 @@ public class NodeModification implements StoreTreeNode<NodeModification>, Identi
         this.value = value;
     }
 
+    @GuardedBy("this")
     private void checkSealed() {
         checkState(!sealed, "Node Modification is sealed. No further changes allowed.");
     }
@@ -202,7 +206,8 @@ public class NodeModification implements StoreTreeNode<NodeModification>, Identi
         return !childModification.isEmpty();
     }
 
-    public void updateModificationType(final ModificationType type) {
+    @GuardedBy("this")
+    private void updateModificationType(final ModificationType type) {
         modificationType = type;
         clearSnapshot();
     }
index a2a706a..339d9cb 100644 (file)
@@ -43,7 +43,7 @@ public class TreeNodeUtils {
 
     public static <T extends StoreTreeNode<T>> T findNodeChecked(final T tree, final InstanceIdentifier path) {
         T current = tree;
-        List<PathArgument> nested = new ArrayList<>(path.getPath());
+        List<PathArgument> nested = new ArrayList<>(path.getPath().size());
         for(PathArgument pathArg : path.getPath()) {
             Optional<T> potential = current.getChild(pathArg);
             nested.add(pathArg);
@@ -80,11 +80,17 @@ public class TreeNodeUtils {
             final InstanceIdentifier currentPath = new InstanceIdentifier(path.getPath().subList(0, nesting));
             return new SimpleEntry<InstanceIdentifier,T>(currentPath,current.get());
         }
-        // Nesting minus one is safe, since current is allways present when nesting = 0
-        // so this prat of code is never triggered, in cases nesting == 0;
+
+        /*
+         * Subtracting 1 from nesting level at this point is safe, because we
+         * cannot reach here with nesting == 0: that would mean the above check
+         * for current.isPresent() failed, which it cannot, as current is always
+         * present. At any rate we check state just to be on the safe side.
+         */
+        Preconditions.checkState(nesting > 0);
         final InstanceIdentifier parentPath = new InstanceIdentifier(path.getPath().subList(0, nesting - 1));
-        return new SimpleEntry<InstanceIdentifier,T>(parentPath,parent.get());
 
+        return new SimpleEntry<InstanceIdentifier,T>(parentPath,parent.get());
     }
 
     public static <T extends StoreTreeNode<T>> Optional<T> getChild(final Optional<T> parent,final PathArgument child) {
index 64de868..0ed14c1 100644 (file)
@@ -7,13 +7,11 @@
  */
 package org.opendaylight.controller.sal.dom.broker;
 
+import com.google.common.util.concurrent.ListenableFuture
 import java.util.Collections
 import java.util.HashSet
 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.Consumer
 import org.opendaylight.controller.sal.core.api.Provider
@@ -26,7 +24,6 @@ import org.opendaylight.controller.sal.dom.broker.spi.RpcRouter
 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
 import org.opendaylight.controller.sal.core.api.RoutedRpcDefaultImplementation
@@ -39,12 +36,9 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
     private val Set<ProviderContextImpl> providerSessions = Collections.synchronizedSet(
         new HashSet<ProviderContextImpl>());
 
-    // Implementation specific
-    @Property
-    private var ExecutorService executor = Executors.newFixedThreadPool(5);
     @Property
     private var BundleContext bundleContext;
-    
+
     @Property
     private var AutoCloseable deactivator;
 
@@ -69,9 +63,8 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
         return session;
     }
 
-    protected def Future<RpcResult<CompositeNode>> invokeRpcAsync(QName rpc, CompositeNode input) {
-        val result = executor.submit([|router.invokeRpc(rpc, input)] as Callable<RpcResult<CompositeNode>>);
-        return result;
+    protected def ListenableFuture<RpcResult<CompositeNode>> invokeRpcAsync(QName rpc, CompositeNode input) {
+        return router.invokeRpc(rpc, input);
     }
 
     // Validation
@@ -111,15 +104,15 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
         sessions.remove(consumerContextImpl);
         providerSessions.remove(consumerContextImpl);
     }
-    
+
     override close() throws Exception {
         deactivator?.close();
     }
-    
+
     override addRpcImplementation(QName rpcType, RpcImplementation implementation) throws IllegalArgumentException {
         router.addRpcImplementation(rpcType,implementation);
     }
-    
+
     override addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
         router.addRoutedRpcImplementation(rpcType,implementation);
     }
@@ -131,17 +124,17 @@ public class BrokerImpl implements Broker, RpcProvisionRegistry, AutoCloseable {
     override addRpcRegistrationListener(RpcRegistrationListener listener) {
         return router.addRpcRegistrationListener(listener);
     }
-    
+
     override <L extends RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> registerRouteChangeListener(L listener) {
         return router.registerRouteChangeListener(listener);
     }
 
-    override invokeRpc(QName rpc,CompositeNode input){
-        return router.invokeRpc(rpc,input)
-    }
-
     override getSupportedRpcs() {
         return router.getSupportedRpcs();
     }
-    
+
+    override invokeRpc(QName rpc, CompositeNode input) {
+        return router.invokeRpc(rpc,input)
+    }
+
 }
index f9f977e..263f050 100644 (file)
@@ -123,9 +123,8 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv
         return rpcs.getSupportedRpcs();
     }
 
-
     @Override
-    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
         return rpcs.invokeRpc(rpc, input);
     }
 
@@ -134,7 +133,6 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv
         return rpcs.addRpcRegistrationListener(listener);
     }
 
-
     @Override
     public ListenableFuture<RpcResult<CompositeNode>> rpc(QName type, CompositeNode input) {
         return null;
@@ -228,6 +226,4 @@ public class MountPointImpl implements MountProvisionInstance, SchemaContextProv
             L listener) {
         return rpcs.registerRouteChangeListener(listener);
     }
-
-
 }
index 598361c..3e7b115 100644 (file)
@@ -46,6 +46,7 @@ import com.google.common.base.Optional;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.ListenableFuture;
 
 public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, RoutedRpcDefaultImplementation {
 
@@ -85,16 +86,16 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
         this.schemaProvider = schemaProvider;
     }
 
-  public RoutedRpcDefaultImplementation getRoutedRpcDefaultDelegate() {
-    return defaultDelegate;
-  }
+    public RoutedRpcDefaultImplementation getRoutedRpcDefaultDelegate() {
+        return defaultDelegate;
+    }
 
     @Override
-  public void setRoutedRpcDefaultDelegate(RoutedRpcDefaultImplementation defaultDelegate) {
-    this.defaultDelegate = defaultDelegate;
-  }
+    public void setRoutedRpcDefaultDelegate(RoutedRpcDefaultImplementation defaultDelegate) {
+        this.defaultDelegate = defaultDelegate;
+    }
 
-  @Override
+    @Override
     public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation) {
         checkArgument(rpcType != null, "RPC Type should not be null");
         checkArgument(implementation != null, "RPC Implementatoin should not be null");
@@ -163,7 +164,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
     }
 
     @Override
-    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
         return findRpcImplemention(rpc).invokeRpc(rpc, input);
     }
 
@@ -235,7 +236,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
     }
 
     @Override
-    public RpcResult<CompositeNode> invokeRpc(QName rpc, InstanceIdentifier identifier, CompositeNode input) {
+    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, InstanceIdentifier identifier, CompositeNode input) {
       checkState(defaultDelegate != null);
       return defaultDelegate.invokeRpc(rpc, identifier, input);
     }
@@ -319,7 +320,7 @@ public class SchemaAwareRpcBroker implements RpcRouter, Identifiable<String>, Ro
         }
 
         @Override
-        public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
+        public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
             CompositeNode inputContainer = input.getFirstCompositeByName(QName.create(rpc,"input"));
             checkArgument(inputContainer != null, "Rpc payload must contain input element");
             SimpleNode<?> routeContainer = inputContainer.getFirstSimpleByName(strategy.getLeaf());
index 40842c0..6e44cba 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.controller.sal.dom.broker.osgi;
 
+import java.util.Set;
+
 import org.opendaylight.controller.md.sal.common.api.routing.RouteChangeListener;
 import org.opendaylight.controller.sal.core.api.*;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
@@ -17,7 +19,7 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.osgi.framework.ServiceReference;
 
-import java.util.Set;
+import com.google.common.util.concurrent.ListenableFuture;
 
 public class RpcProvisionRegistryProxy extends AbstractBrokerServiceProxy<RpcProvisionRegistry>
                                        implements RpcProvisionRegistry {
@@ -41,24 +43,23 @@ public class RpcProvisionRegistryProxy extends AbstractBrokerServiceProxy<RpcPro
         return getDelegate().addRoutedRpcImplementation(rpcType, implementation);
     }
 
-  @Override
-  public void setRoutedRpcDefaultDelegate(RoutedRpcDefaultImplementation defaultImplementation) {
-    getDelegate().setRoutedRpcDefaultDelegate(defaultImplementation);
-  }
+    @Override
+    public void setRoutedRpcDefaultDelegate(RoutedRpcDefaultImplementation defaultImplementation) {
+        getDelegate().setRoutedRpcDefaultDelegate(defaultImplementation);
+    }
 
-  @Override
+    @Override
     public <L extends RouteChangeListener<RpcRoutingContext, InstanceIdentifier>> ListenerRegistration<L> registerRouteChangeListener(L listener) {
         return getDelegate().registerRouteChangeListener(listener);
     }
 
+    @Override
+    public Set<QName> getSupportedRpcs() {
+        return getDelegate().getSupportedRpcs();
+    }
 
-  @Override
-  public Set<QName> getSupportedRpcs() {
-    return getDelegate().getSupportedRpcs();
-  }
-
-  @Override
-  public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input) {
-    return getDelegate().invokeRpc(rpc,input);
-  }
+    @Override
+    public ListenableFuture<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
+        return getDelegate().invokeRpc(rpc, input);
+    }
 }
index 02419ff..2976c76 100644 (file)
@@ -8,27 +8,20 @@
 package org.opendaylight.controller.sal.dom.broker.spi;
 
 import java.util.Map;
-import java.util.Set;
 
 import org.opendaylight.controller.sal.core.api.Broker.RoutedRpcRegistration;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
 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;
 
 public interface RoutedRpcProcessor extends RpcImplementation {
 
-    public RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation);
+    RoutedRpcRegistration addRoutedRpcImplementation(QName rpcType, RpcImplementation implementation);
 
-    public Set<QName> getSupportedRpcs();
-
-    public QName getRpcType();
-    
-    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input);
+    QName getRpcType();
 
     Map<InstanceIdentifier,RpcImplementation> getRoutes();
-    
+
     RpcImplementation getDefaultRoute();
 
 }
index d1523a0..b19dac5 100644 (file)
@@ -14,8 +14,6 @@ import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration;
 import org.opendaylight.controller.sal.core.api.RpcImplementation;
 import org.opendaylight.controller.sal.core.api.RpcProvisionRegistry;
 import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
 public interface RpcRouter extends RpcProvisionRegistry, RpcImplementation {
 
@@ -28,7 +26,4 @@ public interface RpcRouter extends RpcProvisionRegistry, RpcImplementation {
 
     @Override
     public Set<QName> getSupportedRpcs();
-
-    @Override
-    public RpcResult<CompositeNode> invokeRpc(QName rpc, CompositeNode input);
 }
index 182441d..ae819b0 100644 (file)
                                     <codeGeneratorClass>
                                         org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
                                     </codeGeneratorClass>
-                                    <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
+                                    <outputBaseDir>${jmxGeneratorPath}</outputBaseDir>
                                     <additionalConfiguration>
                                         <namespaceToPackage1>
                                             urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
                 </dependencies>
             </plugin>
 
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <version>1.8</version>
-                <executions>
-                    <execution>
-                        <id>add-source</id>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>add-source</goal>
-                        </goals>
-                        <configuration>
-                            <sources>
-                                <source>${project.build.directory}/generated-sources/config</source>
-                                <source>src/main/xtend-gen</source>
-                            </sources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-
             <plugin>
                 <groupId>org.eclipse.xtend</groupId>
                 <artifactId>xtend-maven-plugin</artifactId>
index 5c6702a..e6dc59c 100644 (file)
@@ -14,9 +14,11 @@ import java.util.Date;
 
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class InventoryUtils {
-
+    private static final Logger LOG = LoggerFactory.getLogger(InventoryUtils.class);
     private static final URI INVENTORY_NAMESPACE = URI.create("urn:opendaylight:inventory");
     private static final URI NETCONF_INVENTORY_NAMESPACE = URI.create("urn:opendaylight:netconf-node-inventory");
     private static final Date INVENTORY_REVISION = dateFromString("2013-08-19");
@@ -33,18 +35,23 @@ public class InventoryUtils {
             .toInstance();
     public static final QName NETCONF_INVENTORY_MOUNT = null;
 
+    private InventoryUtils() {
+        throw new UnsupportedOperationException("Utility class cannot be instantiated");
+    }
+
     /**
      * Converts date in string format yyyy-MM-dd to java.util.Date.
-     * 
+     *
      * @return java.util.Date conformant to string formatted date yyyy-MM-dd.
      */
     private static Date dateFromString(final String date) {
+        // We do not reuse the formatter because it's not thread-safe
         SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
         try {
             return formatter.parse(date);
         } catch (ParseException e) {
-            e.printStackTrace();
+            LOG.error("Failed to parse date {}", date, e);
+            return null;
         }
-        return null;
     }
 }
index 4ae84c7..12e8b55 100644 (file)
@@ -13,19 +13,18 @@ import io.netty.util.concurrent.EventExecutor
 import java.io.InputStream
 import java.net.InetSocketAddress
 import java.net.URI
+import java.util.ArrayList
+import java.util.Collection
 import java.util.Collections
 import java.util.List
 import java.util.Set
 import java.util.concurrent.ExecutorService
-import java.util.concurrent.Future
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler
 import org.opendaylight.controller.md.sal.common.api.data.DataModification
 import org.opendaylight.controller.md.sal.common.api.data.DataReader
-import org.opendaylight.controller.netconf.api.NetconfMessage
-import org.opendaylight.controller.netconf.client.NetconfClient
 import org.opendaylight.controller.netconf.client.NetconfClientDispatcher
-import org.opendaylight.controller.netconf.util.xml.XmlUtil
 import org.opendaylight.controller.sal.core.api.Broker.ProviderSession
+import org.opendaylight.controller.sal.core.api.Broker.RpcRegistration
 import org.opendaylight.controller.sal.core.api.Provider
 import org.opendaylight.controller.sal.core.api.RpcImplementation
 import org.opendaylight.controller.sal.core.api.data.DataBrokerService
@@ -45,7 +44,6 @@ import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
 import org.opendaylight.yangtools.yang.model.api.SchemaContext
 import org.opendaylight.yangtools.yang.model.util.repo.AbstractCachingSchemaSourceProvider
 import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider
-import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProviders
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl
 import org.opendaylight.yangtools.yang.parser.impl.util.YangSourceContext
 import org.slf4j.Logger
@@ -56,14 +54,12 @@ import static org.opendaylight.controller.sal.connect.netconf.InventoryUtils.*
 
 import static extension org.opendaylight.controller.sal.connect.netconf.NetconfMapping.*
 
-class NetconfDevice implements Provider, // 
+class NetconfDevice implements Provider, //
 DataReader<InstanceIdentifier, CompositeNode>, //
 DataCommitHandler<InstanceIdentifier, CompositeNode>, //
 RpcImplementation, //
 AutoCloseable {
 
-    var NetconfClient client;
-
     @Property
     var InetSocketAddress socketAddress;
 
@@ -93,15 +89,12 @@ AutoCloseable {
     Registration<DataReader<InstanceIdentifier, CompositeNode>> operReaderReg
     Registration<DataReader<InstanceIdentifier, CompositeNode>> confReaderReg
     Registration<DataCommitHandler<InstanceIdentifier, CompositeNode>> commitHandlerReg
+    List<RpcRegistration> rpcReg
 
+    @Property
     val String name
-    MountProvisionService mountService
 
-    int messegeRetryCount = 5;
-
-    int messageTimeoutCount = 5 * 1000;
-
-    Set<QName> cachedCapabilities
+    MountProvisionService mountService
 
     @Property
     var NetconfClientDispatcher dispatcher
@@ -110,11 +103,13 @@ AutoCloseable {
 
     @Property
     var SchemaSourceProvider<InputStream> remoteSourceProvider
-    
+
     DataBrokerService dataBroker
 
+    var NetconfDeviceListener listener;
+
     public new(String name) {
-        this.name = name;
+        this._name = name;
         this.logger = LoggerFactory.getLogger(NetconfDevice.name + "#" + name);
         this.path = InstanceIdentifier.builder(INVENTORY_PATH).nodeWithKey(INVENTORY_NODE,
             Collections.singletonMap(INVENTORY_ID, name)).toInstance;
@@ -125,10 +120,11 @@ AutoCloseable {
         checkState(schemaSourceProvider != null, "Schema Source Provider must be set.")
         checkState(eventExecutor != null, "Event executor must be set.");
 
-        val listener = new NetconfDeviceListener(this);
-        val task = startClientTask(dispatcher, listener)
-        return processingExecutor.submit(task) as Future<Void>;
+        listener = new NetconfDeviceListener(this);
+
+        logger.info("Starting NETCONF Client {} for address {}", name, socketAddress);
 
+        dispatcher.createClient(socketAddress, listener, reconnectStrategy);
     }
 
     def Optional<SchemaContext> getSchemaContext() {
@@ -138,59 +134,65 @@ AutoCloseable {
         return deviceContextProvider.currentContext;
     }
 
-    private def Runnable startClientTask(NetconfClientDispatcher dispatcher, NetconfDeviceListener listener) {
-        return [ |
-            try {
-                logger.info("Starting Netconf Client on: {}", socketAddress);
-                client = NetconfClient.clientFor(name, socketAddress, reconnectStrategy, dispatcher, listener);
-                logger.debug("Initial capabilities {}", initialCapabilities);
-                var SchemaSourceProvider<String> delegate;
-                if (NetconfRemoteSchemaSourceProvider.isSupportedFor(initialCapabilities)) {
-                    delegate = new NetconfRemoteSchemaSourceProvider(this);
-                }  else if(client.capabilities.contains(NetconfRemoteSchemaSourceProvider.IETF_NETCONF_MONITORING.namespace.toString)) {
-                    delegate = new NetconfRemoteSchemaSourceProvider(this);
-                } else {
-                    logger.info("Netconf server {} does not support IETF Netconf Monitoring", socketAddress);
-                    delegate = SchemaSourceProviders.<String>noopProvider();
-                }
-                remoteSourceProvider = schemaSourceProvider.createInstanceFor(delegate);
-                deviceContextProvider = new NetconfDeviceSchemaContextProvider(this, remoteSourceProvider);
-                deviceContextProvider.createContextFromCapabilities(initialCapabilities);
-                if (mountInstance != null && schemaContext.isPresent) {
-                    mountInstance.schemaContext = schemaContext.get();
-                    val operations = schemaContext.get().operations;
-                    for (rpc : operations) {
-                        mountInstance.addRpcImplementation(rpc.QName, this);
-                    }
-                }
-                updateDeviceState()
-                if (mountInstance != null && confReaderReg == null && operReaderReg == null) {
-                    confReaderReg = mountInstance.registerConfigurationReader(ROOT_PATH, this);
-                    operReaderReg = mountInstance.registerOperationalReader(ROOT_PATH, this);
-                    commitHandlerReg = mountInstance.registerCommitHandler(ROOT_PATH, this);
-                }
-            } catch (Exception e) {
-                logger.error("Netconf client NOT started. ", e)
+    def bringDown() {
+        if (rpcReg != null) {
+            for (reg : rpcReg) {
+                reg.close()
             }
-        ]
+            rpcReg = null
+        }
+        confReaderReg?.close()
+        confReaderReg = null
+        operReaderReg?.close()
+        operReaderReg = null
+        commitHandlerReg?.close()
+        commitHandlerReg = null
+
+        updateDeviceState(false, Collections.emptySet())
     }
 
-    private def updateDeviceState() {
+    def bringUp(SchemaSourceProvider<String> delegate, Set<QName> capabilities) {
+        remoteSourceProvider = schemaSourceProvider.createInstanceFor(delegate);
+        deviceContextProvider = new NetconfDeviceSchemaContextProvider(this, remoteSourceProvider);
+        deviceContextProvider.createContextFromCapabilities(capabilities);
+        if (mountInstance != null && schemaContext.isPresent) {
+            mountInstance.schemaContext = schemaContext.get();
+        }
+
+        updateDeviceState(true, capabilities)
+
+        if (mountInstance != null) {
+            confReaderReg = mountInstance.registerConfigurationReader(ROOT_PATH, this);
+            operReaderReg = mountInstance.registerOperationalReader(ROOT_PATH, this);
+            commitHandlerReg = mountInstance.registerCommitHandler(ROOT_PATH, this);
+
+            val rpcs = new ArrayList<RpcRegistration>();
+            for (rpc : mountInstance.schemaContext.operations) {
+                rpcs.add(mountInstance.addRpcImplementation(rpc.QName, this));
+            }
+            rpcReg = rpcs
+        }
+    }
+
+    private def updateDeviceState(boolean up, Set<QName> capabilities) {
         val transaction = dataBroker.beginTransaction
 
         val it = ImmutableCompositeNode.builder
         setQName(INVENTORY_NODE)
         addLeaf(INVENTORY_ID, name)
-        addLeaf(INVENTORY_CONNECTED, client.clientSession.up)
+        addLeaf(INVENTORY_CONNECTED, up)
 
-        logger.debug("Client capabilities {}", client.capabilities)
-        for (capability : client.capabilities) {
+        logger.debug("Client capabilities {}", capabilities)
+        for (capability : capabilities) {
             addLeaf(NETCONF_INVENTORY_INITIAL_CAPABILITY, capability)
         }
 
         logger.debug("Update device state transaction " + transaction.identifier + " putting operational data started.")
+        transaction.removeOperationalData(path)
         transaction.putOperationalData(path, it.toInstance)
         logger.debug("Update device state transaction " + transaction.identifier + " putting operational data ended.")
+
+        // FIXME: this has to be asynchronous
         val transactionStatus = transaction.commit.get;
 
         if (transactionStatus.successful) {
@@ -203,13 +205,13 @@ AutoCloseable {
 
     override readConfigurationData(InstanceIdentifier path) {
         val result = invokeRpc(NETCONF_GET_CONFIG_QNAME,
-            wrap(NETCONF_GET_CONFIG_QNAME, CONFIG_SOURCE_RUNNING, path.toFilterStructure()));
+            wrap(NETCONF_GET_CONFIG_QNAME, CONFIG_SOURCE_RUNNING, path.toFilterStructure())).get();
         val data = result.result.getFirstCompositeByName(NETCONF_DATA_QNAME);
         return data?.findNode(path) as CompositeNode;
     }
 
     override readOperationalData(InstanceIdentifier path) {
-        val result = invokeRpc(NETCONF_GET_QNAME, wrap(NETCONF_GET_QNAME, path.toFilterStructure()));
+        val result = invokeRpc(NETCONF_GET_QNAME, wrap(NETCONF_GET_QNAME, path.toFilterStructure())).get();
         val data = result.result.getFirstCompositeByName(NETCONF_DATA_QNAME);
         return data?.findNode(path) as CompositeNode;
     }
@@ -218,30 +220,8 @@ AutoCloseable {
         Collections.emptySet;
     }
 
-    def createSubscription(String streamName) {
-        val it = ImmutableCompositeNode.builder()
-        QName = NETCONF_CREATE_SUBSCRIPTION_QNAME
-        addLeaf("stream", streamName);
-        invokeRpc(QName, toInstance())
-    }
-
     override invokeRpc(QName rpc, CompositeNode input) {
-        try {
-            val message = rpc.toRpcMessage(input,schemaContext);
-            val result = sendMessageImpl(message, messegeRetryCount, messageTimeoutCount);
-            return result.toRpcResult(rpc, schemaContext);
-
-        } catch (Exception e) {
-            logger.error("Rpc was not processed correctly.", e)
-            throw e;
-        }
-    }
-
-    def NetconfMessage sendMessageImpl(NetconfMessage message, int retryCount, int timeout) {
-        logger.debug("Send message {}",XmlUtil.toString(message.document))
-        val result = client.sendMessage(message, retryCount, timeout);
-        NetconfMapping.checkValidReply(message, result)
-        return result;
+        return listener.sendRequest(rpc.toRpcMessage(input,schemaContext));
     }
 
     override getProviderFunctionality() {
@@ -284,7 +264,7 @@ AutoCloseable {
                 return null;
             } else if (current instanceof CompositeNode) {
                 val currentComposite = (current as CompositeNode);
-                
+
                 current = currentComposite.getFirstCompositeByName(arg.nodeType);
                 if(current == null) {
                     current = currentComposite.getFirstCompositeByName(arg.nodeType.withoutRevision());
@@ -303,18 +283,13 @@ AutoCloseable {
     }
 
     override requestCommit(DataModification<InstanceIdentifier, CompositeNode> modification) {
-        val twoPhaseCommit = new NetconfDeviceTwoPhaseCommitTransaction(this, modification);
+        val twoPhaseCommit = new NetconfDeviceTwoPhaseCommitTransaction(this, modification, true);
         twoPhaseCommit.prepare()
         return twoPhaseCommit;
     }
 
-    def getInitialCapabilities() {
-        val capabilities = client?.capabilities;
-        if (capabilities == null) {
-            return null;
-        }
-        if (cachedCapabilities == null) {
-            cachedCapabilities = FluentIterable.from(capabilities).filter[
+    def getCapabilities(Collection<String> capabilities) {
+        return FluentIterable.from(capabilities).filter[
                 contains("?") && contains("module=") && contains("revision=")].transform [
                 val parts = split("\\?");
                 val namespace = parts.get(0);
@@ -333,16 +308,11 @@ AutoCloseable {
                 }
                 return QName.create(namespace, revision, moduleName);
             ].toSet();
-        }
-        return cachedCapabilities;
     }
 
     override close() {
-        confReaderReg?.close()
-        operReaderReg?.close()
-        client?.close()
+        bringDown()
     }
-
 }
 
 package class NetconfDeviceSchemaContextProvider {
index 13cd5db..d5e1d35 100644 (file)
  */
 package org.opendaylight.controller.sal.connect.netconf;
 
+import io.netty.util.concurrent.Future;
+import io.netty.util.concurrent.FutureListener;
+
+import java.util.ArrayDeque;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Queue;
+import java.util.Set;
+
 import org.opendaylight.controller.netconf.api.NetconfMessage;
-import org.opendaylight.controller.netconf.client.AbstractNetconfClientNotifySessionListener;
+import org.opendaylight.controller.netconf.api.NetconfTerminationReason;
 import org.opendaylight.controller.netconf.client.NetconfClientSession;
+import org.opendaylight.controller.netconf.client.NetconfClientSessionListener;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.controller.sal.common.util.Rpcs;
 import org.opendaylight.controller.sal.core.api.mount.MountProvisionInstance;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
+import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProviders;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+class NetconfDeviceListener implements NetconfClientSessionListener {
+    private static final class Request {
+        final UncancellableFuture<RpcResult<CompositeNode>> future;
+        final NetconfMessage request;
+
+        private Request(UncancellableFuture<RpcResult<CompositeNode>> future, NetconfMessage request) {
+            this.future = future;
+            this.request = request;
+        }
+    }
 
-class NetconfDeviceListener extends AbstractNetconfClientNotifySessionListener {
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfDeviceListener.class);
+    private final Queue<Request> requests = new ArrayDeque<>();
     private final NetconfDevice device;
+    private NetconfClientSession session;
 
     public NetconfDeviceListener(final NetconfDevice device) {
         this.device = Preconditions.checkNotNull(device);
     }
 
-    /**
-     * Method intended to customize notification processing.
-     * 
-     * @param session
-     *            {@see
-     *            NetconfClientSessionListener#onMessage(NetconfClientSession,
-     *            NetconfMessage)}
-     * @param message
-     *            {@see
-     *            NetconfClientSessionListener#onMessage(NetconfClientSession,
-     *            NetconfMessage)}
-     */
     @Override
-    public void onNotification(final NetconfClientSession session, final NetconfMessage message) {
-        this.device.logger.debug("Received NETCONF notification.", message);
-        CompositeNode domNotification = null;
-        if (message != null) {
-            domNotification = NetconfMapping.toNotificationNode(message, device.getSchemaContext());
-        }
-        if (domNotification != null) {
-            MountProvisionInstance _mountInstance = null;
-            if (this.device != null) {
-                _mountInstance = this.device.getMountInstance();
+    public synchronized void onSessionUp(final NetconfClientSession session) {
+        LOG.debug("Session with {} established as address {} session-id {}",
+                device.getName(), device.getSocketAddress(), session.getSessionId());
+
+        final Set<QName> caps = device.getCapabilities(session.getServerCapabilities());
+        LOG.trace("Server {} advertized capabilities {}", device.getName(), caps);
+
+        // Select the appropriate provider
+        final SchemaSourceProvider<String> delegate;
+        if (NetconfRemoteSchemaSourceProvider.isSupportedFor(caps)) {
+            delegate = new NetconfRemoteSchemaSourceProvider(device);
+        } else if(caps.contains(NetconfRemoteSchemaSourceProvider.IETF_NETCONF_MONITORING.getNamespace().toString())) {
+            delegate = new NetconfRemoteSchemaSourceProvider(device);
+        } else {
+            LOG.info("Netconf server {} does not support IETF Netconf Monitoring", device.getName());
+            delegate = SchemaSourceProviders.<String>noopProvider();
+        }
+
+        device.bringUp(delegate, caps);
+
+        this.session = session;
+    }
+
+    private synchronized void tearDown(final Exception e) {
+        session = null;
+
+        /*
+         * Walk all requests, check if they have been executing
+         * or cancelled and remove them from the queue.
+         */
+        final Iterator<Request> it = requests.iterator();
+        while (it.hasNext()) {
+            final Request r = it.next();
+            if (r.future.isUncancellable()) {
+                // FIXME: add a RpcResult instead?
+                r.future.setException(e);
+                it.remove();
+            } else if (r.future.isCancelled()) {
+                // This just does some house-cleaning
+                it.remove();
             }
-            if (_mountInstance != null) {
-                _mountInstance.publish(domNotification);
+        }
+
+        device.bringDown();
+    }
+
+    @Override
+    public void onSessionDown(final NetconfClientSession session, final Exception e) {
+        LOG.debug("Session with {} went down", device.getName(), e);
+        tearDown(e);
+    }
+
+    @Override
+    public void onSessionTerminated(final NetconfClientSession session, final NetconfTerminationReason reason) {
+        LOG.debug("Session with {} terminated {}", session, reason);
+        tearDown(new RuntimeException(reason.getErrorMessage()));
+    }
+
+    @Override
+    public void onMessage(final NetconfClientSession session, final NetconfMessage message) {
+        /*
+         * Dispatch between notifications and messages. Messages need to be processed
+         * with lock held, notifications do not.
+         */
+        if (isNotification(message)) {
+            processNotification(message);
+        } else {
+            processMessage(message);
+        }
+    }
+
+    private synchronized void processMessage(final NetconfMessage message) {
+        final Request r = requests.peek();
+        if (r.future.isUncancellable()) {
+            requests.poll();
+            LOG.debug("Matched {} to {}", r.request, message);
+
+            // FIXME: this can throw exceptions, which should result
+            // in the future failing
+            NetconfMapping.checkValidReply(r.request, message);
+            r.future.set(Rpcs.getRpcResult(true, NetconfMapping.toNotificationNode(message, device.getSchemaContext()),
+                    Collections.<RpcError>emptyList()));
+        } else {
+            LOG.warn("Ignoring unsolicited message", message);
+        }
+    }
+
+    synchronized ListenableFuture<RpcResult<CompositeNode>> sendRequest(final NetconfMessage message) {
+        if (session == null) {
+            LOG.debug("Session to {} is disconnected, failing RPC request {}", device.getName(), message);
+            return Futures.<RpcResult<CompositeNode>>immediateFuture(new RpcResult<CompositeNode>() {
+                @Override
+                public boolean isSuccessful() {
+                    return false;
+                }
+
+                @Override
+                public CompositeNode getResult() {
+                    return null;
+                }
+
+                @Override
+                public Collection<RpcError> getErrors() {
+                    // FIXME: indicate that the session is down
+                    return Collections.emptySet();
+                }
+            });
+        }
+
+        final Request req = new Request(new UncancellableFuture<RpcResult<CompositeNode>>(true), message);
+        requests.add(req);
+
+        session.sendMessage(req.request).addListener(new FutureListener<Void>() {
+            @Override
+            public void operationComplete(final Future<Void> future) throws Exception {
+                if (!future.isSuccess()) {
+                    // We expect that a session down will occur at this point
+                    LOG.debug("Failed to send request {}", req.request, future.cause());
+                    req.future.setException(future.cause());
+                } else {
+                    LOG.trace("Finished sending request {}", req.request);
+                }
             }
+        });
+
+        return req.future;
+    }
+
+    /**
+     * Process an incoming notification.
+     *
+     * @param notification Notification message
+     */
+    private void processNotification(final NetconfMessage notification) {
+        this.device.logger.debug("Received NETCONF notification.", notification);
+        CompositeNode domNotification = NetconfMapping.toNotificationNode(notification, device.getSchemaContext());
+        if (domNotification == null) {
+            return;
+        }
+
+        MountProvisionInstance mountInstance =  this.device.getMountInstance();
+        if (mountInstance != null) {
+            mountInstance.publish(domNotification);
         }
     }
+
+    private static boolean isNotification(final NetconfMessage message) {
+        final XmlElement xmle = XmlElement.fromDomDocument(message.getDocument());
+        return XmlNetconfConstants.NOTIFICATION_ELEMENT_NAME.equals(xmle.getName()) ;
+    }
 }
index c5390e5..5f14c26 100644 (file)
@@ -15,14 +15,17 @@ import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NET
 import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_RUNNING_QNAME;
 import static org.opendaylight.controller.sal.connect.netconf.NetconfMapping.NETCONF_TARGET_QNAME;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.concurrent.ExecutionException;
 
 import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.DataModification;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
@@ -31,51 +34,52 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 
-public class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransaction<InstanceIdentifier, CompositeNode> {
-
-    private final NetconfDevice device;
+class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransaction<InstanceIdentifier, CompositeNode> {
+    private static final Logger LOG = LoggerFactory.getLogger(NetconfDeviceTwoPhaseCommitTransaction.class);
     private final DataModification<InstanceIdentifier, CompositeNode> modification;
-    private final boolean candidateSupported = true;
+    private final NetconfDevice device;
+    private final boolean candidateSupported;
 
     public NetconfDeviceTwoPhaseCommitTransaction(NetconfDevice device,
-            DataModification<InstanceIdentifier, CompositeNode> modification) {
-        super();
-        this.device = device;
-        this.modification = modification;
+            DataModification<InstanceIdentifier, CompositeNode> modification,
+            boolean candidateSupported) {
+        this.device = Preconditions.checkNotNull(device);
+        this.modification = Preconditions.checkNotNull(modification);
+        this.candidateSupported = candidateSupported;
     }
 
-    public void prepare() {
+    void prepare() throws InterruptedException, ExecutionException {
         for (InstanceIdentifier toRemove : modification.getRemovedConfigurationData()) {
             sendDelete(toRemove);
         }
         for(Entry<InstanceIdentifier, CompositeNode> toUpdate : modification.getUpdatedConfigurationData().entrySet()) {
             sendMerge(toUpdate.getKey(),toUpdate.getValue());
         }
-
     }
 
-    private void sendMerge(InstanceIdentifier key, CompositeNode value) {
+    private void sendMerge(InstanceIdentifier key, CompositeNode value) throws InterruptedException, ExecutionException {
         sendEditRpc(createEditStructure(key, Optional.<String>absent(), Optional.of(value)));
     }
 
-    private void sendDelete(InstanceIdentifier toDelete) {
+    private void sendDelete(InstanceIdentifier toDelete) throws InterruptedException, ExecutionException {
         sendEditRpc(createEditStructure(toDelete, Optional.of("delete"), Optional.<CompositeNode> absent()));
     }
 
-    private void sendEditRpc(CompositeNode editStructure) {
+    private void sendEditRpc(CompositeNode editStructure) throws InterruptedException, ExecutionException {
         CompositeNodeBuilder<ImmutableCompositeNode> builder = configurationRpcBuilder();
         builder.setQName(NETCONF_EDIT_CONFIG_QNAME);
         builder.add(editStructure);
 
-        RpcResult<CompositeNode> rpcResult = device.invokeRpc(NETCONF_EDIT_CONFIG_QNAME, builder.toInstance());
+        RpcResult<CompositeNode> rpcResult = device.invokeRpc(NETCONF_EDIT_CONFIG_QNAME, builder.toInstance()).get();
         Preconditions.checkState(rpcResult.isSuccessful(),"Rpc Result was unsuccessful");
-
     }
 
     private CompositeNodeBuilder<ImmutableCompositeNode> configurationRpcBuilder() {
@@ -135,8 +139,45 @@ public class NetconfDeviceTwoPhaseCommitTransaction implements DataCommitTransac
     public RpcResult<Void> finish() {
         CompositeNodeBuilder<ImmutableCompositeNode> commitInput = ImmutableCompositeNode.builder();
         commitInput.setQName(NETCONF_COMMIT_QNAME);
-        RpcResult<?> rpcResult = device.invokeRpc(NetconfMapping.NETCONF_COMMIT_QNAME, commitInput.toInstance());
-        return (RpcResult<Void>) rpcResult;
+        try {
+            final RpcResult<?> rpcResult = device.invokeRpc(NetconfMapping.NETCONF_COMMIT_QNAME, commitInput.toInstance()).get();
+            return new RpcResult<Void>() {
+
+                @Override
+                public boolean isSuccessful() {
+                    return rpcResult.isSuccessful();
+                }
+
+                @Override
+                public Void getResult() {
+                    return null;
+                }
+
+                @Override
+                public Collection<RpcError> getErrors() {
+                    return rpcResult.getErrors();
+                }
+            };
+        } catch (final InterruptedException | ExecutionException e) {
+            LOG.warn("Failed to finish operation", e);
+            return new RpcResult<Void>() {
+                @Override
+                public boolean isSuccessful() {
+                    return false;
+                }
+
+                @Override
+                public Void getResult() {
+                    return null;
+                }
+
+                @Override
+                public Collection<RpcError> getErrors() {
+                    // FIXME: wrap the exception
+                    return Collections.emptySet();
+                }
+            };
+        }
     }
 
     @Override
index bae0f08..b68f18f 100644 (file)
@@ -11,18 +11,19 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 
 public class NetconfInventoryUtils {
-
-    
     public static final QName NETCONF_MOUNT = null;
     public static final QName NETCONF_ENDPOINT = null;
     public static final QName NETCONF_ENDPOINT_ADDRESS = null;
     public static final QName NETCONF_ENDPOINT_PORT = null;
 
+    private NetconfInventoryUtils() {
+        throw new UnsupportedOperationException("Utility class cannot be instantiated");
+    }
 
     public static String getEndpointAddress(CompositeNode node) {
         return node.getCompositesByName(NETCONF_ENDPOINT).get(0).getFirstSimpleByName(NETCONF_ENDPOINT_ADDRESS).getValue().toString();
     }
-    
+
     public static String getEndpointPort(CompositeNode node) {
         return node.getCompositesByName(NETCONF_ENDPOINT).get(0).getFirstSimpleByName(NETCONF_ENDPOINT_PORT).getValue().toString();
     }
index e5a24fc..228a01e 100644 (file)
@@ -39,8 +39,8 @@ class NetconfMapping {
     public static val NETCONF_URI = URI.create("urn:ietf:params:xml:ns:netconf:base:1.0")
     public static val NETCONF_MONITORING_URI = "urn:ietf:params:xml:ns:yang:ietf-netconf-monitoring"
     public static val NETCONF_NOTIFICATION_URI = URI.create("urn:ietf:params:xml:ns:netconf:notification:1.0")
-    
-    
+
+
     public static val NETCONF_QNAME = QName.create(NETCONF_URI, null, "netconf");
     public static val NETCONF_RPC_QNAME = QName.create(NETCONF_QNAME, "rpc");
     public static val NETCONF_GET_QNAME = QName.create(NETCONF_QNAME, "get");
@@ -51,15 +51,15 @@ class NetconfMapping {
     public static val NETCONF_DELETE_CONFIG_QNAME = QName.create(NETCONF_QNAME, "delete-config");
     public static val NETCONF_OPERATION_QNAME = QName.create(NETCONF_QNAME, "operation");
     public static val NETCONF_COMMIT_QNAME = QName.create(NETCONF_QNAME, "commit");
-    
+
     public static val NETCONF_CONFIG_QNAME = QName.create(NETCONF_QNAME, "config");
     public static val NETCONF_SOURCE_QNAME = QName.create(NETCONF_QNAME, "source");
     public static val NETCONF_TARGET_QNAME = QName.create(NETCONF_QNAME, "target");
-    
+
     public static val NETCONF_CANDIDATE_QNAME = QName.create(NETCONF_QNAME, "candidate");
     public static val NETCONF_RUNNING_QNAME = QName.create(NETCONF_QNAME, "running");
-    
-    
+
+
     public static val NETCONF_RPC_REPLY_QNAME = QName.create(NETCONF_QNAME, "rpc-reply");
     public static val NETCONF_OK_QNAME = QName.create(NETCONF_QNAME, "ok");
     public static val NETCONF_DATA_QNAME = QName.create(NETCONF_QNAME, "data");
@@ -78,7 +78,7 @@ class NetconfMapping {
         if(identifier.path.empty) {
             return null;
         }
-        
+
         for (component : identifier.path.reverseView) {
             val Node<?> current = component.toNode(previous);
             previous = current;
@@ -106,11 +106,11 @@ class NetconfMapping {
     }
 
     static def CompositeNode toCompositeNode(NetconfMessage message,Optional<SchemaContext> ctx) {
-        //TODO: implement general normalization to normalize incoming Netconf Message 
+        //TODO: implement general normalization to normalize incoming Netconf Message
         // for Schema Context counterpart
         return null
     }
-    
+
     static def CompositeNode toNotificationNode(NetconfMessage message,Optional<SchemaContext> ctx) {
         if (ctx.present) {
             val schemaContext = ctx.get
@@ -127,56 +127,53 @@ class NetconfMapping {
         w3cPayload.documentElement.setAttribute("message-id", "m-" + messageId.andIncrement)
         return new NetconfMessage(w3cPayload);
     }
-    
+
     def static flattenInput(CompositeNode node) {
         val inputQName = QName.create(node.nodeType,"input");
         val input = node.getFirstCompositeByName(inputQName);
         if(input == null) return node;
         if(input instanceof CompositeNode) {
-            
+
             val nodes = ImmutableList.builder() //
                 .addAll(input.children) //
                 .addAll(node.children.filter[nodeType != inputQName]) //
                 .build()
             return ImmutableCompositeNode.create(node.nodeType,nodes);
-        } 
-        
+        }
+
     }
 
     static def RpcResult<CompositeNode> toRpcResult(NetconfMessage message,QName rpc,Optional<SchemaContext> context) {
         var CompositeNode rawRpc;
         if(context.present) {
             if(isDataRetrievalReply(rpc)) {
-                
+
                 val xmlData = message.document.dataSubtree
                 val dataNodes = XmlDocumentUtils.toDomNodes(xmlData, Optional.of(context.get.dataDefinitions))
-                
+
                 val it = ImmutableCompositeNode.builder()
                 setQName(NETCONF_RPC_REPLY_QNAME)
                 add(ImmutableCompositeNode.create(NETCONF_DATA_QNAME, dataNodes));
-                
+
                 rawRpc = it.toInstance;
                 //sys(xmlData)
             } else {
                 val rpcSchema = context.get.operations.findFirst[QName == rpc]
                 rawRpc = message.document.toCompositeNode() as CompositeNode;
             }
-            
-            
-            
         } else {
             rawRpc = message.document.toCompositeNode() as CompositeNode;
         }
         //rawRpc.
         return Rpcs.getRpcResult(true, rawRpc, Collections.emptySet());
     }
-    
+
     def static Element getDataSubtree(Document doc) {
         doc.getElementsByTagNameNS(NETCONF_URI.toString,"data").item(0) as Element
     }
-    
+
     def static boolean isDataRetrievalReply(QName it) {
-        return NETCONF_URI == namespace && ( localName == NETCONF_GET_CONFIG_QNAME.localName || localName == NETCONF_GET_QNAME.localName) 
+        return NETCONF_URI == namespace && ( localName == NETCONF_GET_CONFIG_QNAME.localName || localName == NETCONF_GET_QNAME.localName)
     }
 
     static def wrap(QName name, Node<?> node) {
@@ -209,12 +206,12 @@ class NetconfMapping {
     public static def Node<?> toCompositeNode(Document document) {
         return XmlDocumentUtils.toDomNode(document) as Node<?>
     }
-    
+
     public static def checkValidReply(NetconfMessage input, NetconfMessage output) {
         val inputMsgId = input.document.documentElement.getAttribute("message-id")
         val outputMsgId = output.document.documentElement.getAttribute("message-id")
         Preconditions.checkState(inputMsgId == outputMsgId,"Rpc request and reply message IDs must be same.");
-        
+
     }
-    
+
 }
index fa6b6f7..c734e80 100644 (file)
@@ -7,7 +7,8 @@
  */
 package org.opendaylight.controller.sal.connect.netconf;
 
-import java.util.Set;
+import java.util.Collection;
+import java.util.concurrent.ExecutionException;
 
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -18,6 +19,7 @@ import org.opendaylight.yangtools.yang.data.impl.util.CompositeNodeBuilder;
 import org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceProvider;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
 class NetconfRemoteSchemaSourceProvider implements SchemaSourceProvider<String> {
 
@@ -26,11 +28,10 @@ class NetconfRemoteSchemaSourceProvider implements SchemaSourceProvider<String>
     public static final QName GET_SCHEMA_QNAME = QName.create(IETF_NETCONF_MONITORING, "get-schema");
     public static final QName GET_DATA_QNAME = QName.create(IETF_NETCONF_MONITORING, "data");
 
-    NetconfDevice device;
+    private final NetconfDevice device;
 
     public NetconfRemoteSchemaSourceProvider(NetconfDevice device) {
-        super();
-        this.device = device;
+        this.device = Preconditions.checkNotNull(device);
     }
 
     @Override
@@ -44,15 +45,19 @@ class NetconfRemoteSchemaSourceProvider implements SchemaSourceProvider<String>
         }
 
         device.logger.trace("Loading YANG schema source for {}:{}", moduleName, revision);
-        RpcResult<CompositeNode> schemaReply = device.invokeRpc(GET_SCHEMA_QNAME, request.toInstance());
-        if (schemaReply.isSuccessful()) {
-            String schemaBody = getSchemaFromRpc(schemaReply.getResult());
-            if (schemaBody != null) {
-                device.logger.trace("YANG Schema successfully retrieved from remote for {}:{}", moduleName, revision);
-                return Optional.of(schemaBody);
+        try {
+            RpcResult<CompositeNode> schemaReply = device.invokeRpc(GET_SCHEMA_QNAME, request.toInstance()).get();
+            if (schemaReply.isSuccessful()) {
+                String schemaBody = getSchemaFromRpc(schemaReply.getResult());
+                if (schemaBody != null) {
+                    device.logger.trace("YANG Schema successfully retrieved from remote for {}:{}", moduleName, revision);
+                    return Optional.of(schemaBody);
+                }
             }
+            device.logger.warn("YANG shcema was not successfully retrieved.");
+        } catch (InterruptedException | ExecutionException e) {
+            device.logger.warn("YANG shcema was not successfully retrieved.", e);
         }
-        device.logger.warn("YANG shcema was not successfully retrieved.");
         return Optional.absent();
     }
 
@@ -68,7 +73,7 @@ class NetconfRemoteSchemaSourceProvider implements SchemaSourceProvider<String>
         return null;
     }
 
-    public static final boolean isSupportedFor(Set<QName> capabilities) {
+    public static final boolean isSupportedFor(Collection<QName> capabilities) {
         return capabilities.contains(IETF_NETCONF_MONITORING);
     }
 }
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/UncancellableFuture.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/UncancellableFuture.java
new file mode 100644 (file)
index 0000000..c353f86
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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.connect.netconf;
+
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.GuardedBy;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.AbstractFuture;
+
+final class UncancellableFuture<V> extends AbstractFuture<V> {
+    @GuardedBy("this")
+    private boolean uncancellable = false;
+
+    public UncancellableFuture(boolean uncancellable) {
+        this.uncancellable = uncancellable;
+    }
+
+    public synchronized boolean setUncancellable() {
+        if (isCancelled()) {
+            return false;
+        }
+
+        uncancellable = true;
+        return true;
+    }
+
+    public synchronized boolean isUncancellable() {
+        return uncancellable;
+    }
+
+    @Override
+    public synchronized boolean cancel(boolean mayInterruptIfRunning) {
+        if (uncancellable) {
+            return false;
+        }
+
+        return super.cancel(mayInterruptIfRunning);
+    }
+
+    @Override
+    public synchronized boolean set(@Nullable V value) {
+        Preconditions.checkState(uncancellable == true);
+        return super.set(value);
+    }
+
+    @Override
+    protected boolean setException(Throwable throwable) {
+        Preconditions.checkState(uncancellable == true);
+        return super.setException(throwable);
+    }
+}
diff --git a/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/YangModelInputStreamAdapter.java b/opendaylight/md-sal/sal-netconf-connector/src/main/java/org/opendaylight/controller/sal/connect/netconf/YangModelInputStreamAdapter.java
deleted file mode 100644 (file)
index 23892e1..0000000
+++ /dev/null
@@ -1,104 +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.connect.netconf;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.opendaylight.yangtools.concepts.Delegator;
-import org.opendaylight.yangtools.yang.common.QName;
-
-import com.google.common.base.Charsets;
-
-/**
- *
- *
- */
-public class YangModelInputStreamAdapter extends InputStream implements Delegator<InputStream> {
-
-    final String source;
-    final QName moduleIdentifier;
-    final InputStream delegate;
-
-    private YangModelInputStreamAdapter(String source, QName moduleIdentifier, InputStream delegate) {
-        super();
-        this.source = source;
-        this.moduleIdentifier = moduleIdentifier;
-        this.delegate = delegate;
-    }
-
-    @Override
-    public int read() throws IOException {
-        return delegate.read();
-    }
-
-    @Override
-    public int hashCode() {
-        return delegate.hashCode();
-    }
-
-    @Override
-    public int read(byte[] b) throws IOException {
-        return delegate.read(b);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        return delegate.equals(obj);
-    }
-
-    @Override
-    public int read(byte[] b, int off, int len) throws IOException {
-        return delegate.read(b, off, len);
-    }
-
-    @Override
-    public long skip(long n) throws IOException {
-        return delegate.skip(n);
-    }
-
-    @Override
-    public int available() throws IOException {
-        return delegate.available();
-    }
-
-    @Override
-    public void close() throws IOException {
-        delegate.close();
-    }
-
-    @Override
-    public void mark(int readlimit) {
-        delegate.mark(readlimit);
-    }
-
-    @Override
-    public void reset() throws IOException {
-        delegate.reset();
-    }
-
-    @Override
-    public boolean markSupported() {
-        return delegate.markSupported();
-    }
-
-    @Override
-    public InputStream getDelegate() {
-        return delegate;
-    }
-
-    @Override
-    public String toString() {
-        return "YangModelInputStreamAdapter [moduleIdentifier=" + moduleIdentifier + ", delegate=" + delegate + "]";
-    }
-
-    public static YangModelInputStreamAdapter create(QName name, String module) {
-        return new YangModelInputStreamAdapter(null, name, new ByteArrayInputStream(module.getBytes(Charsets.UTF_8)));
-    }
-}
index 15bd2e7..0c06b44 100644 (file)
                     </dependency>
                 </dependencies>
             </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <version>1.8</version>
-                <executions>
-                    <execution>
-                        <id>add-source</id>
-                        <phase>generate-sources</phase>
-                        <goals>
-                            <goal>add-source</goal>
-                        </goals>
-                        <configuration>
-                            <sources>
-                                <source>${project.build.directory}/generated-sources/</source>
-                            </sources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
         </plugins>
     </build>
 </project>
index 415ae5a..0c817d2 100644 (file)
                                     <codeGeneratorClass>
                                         org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
                                     </codeGeneratorClass>
-