From: Ed Warnicke Date: Mon, 11 Nov 2013 12:30:54 +0000 (+0000) Subject: Merge "Unified Two Phase Commit implementation, fixed BA to BI connection" X-Git-Tag: jenkins-controller-bulk-release-prepare-only-2-1~436 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=582da55f82ee5d83af2e7a327044c62ef3a76285;hp=b3e0b00065cf40a359d4fd295b14d89c838f54e5 Merge "Unified Two Phase Commit implementation, fixed BA to BI connection" --- diff --git a/opendaylight/distribution/opendaylight/pom.xml b/opendaylight/distribution/opendaylight/pom.xml index a9a62098ec..abfc0648af 100644 --- a/opendaylight/distribution/opendaylight/pom.xml +++ b/opendaylight/distribution/opendaylight/pom.xml @@ -286,17 +286,27 @@ org.opendaylight.yangtools - binding-generator-util + binding-generator-spi ${yangtools.binding.version} org.opendaylight.yangtools - binding-model-api + binding-generator-api ${yangtools.binding.version} org.opendaylight.yangtools - binding-generator-spi + binding-generator-impl + ${yangtools.binding.version} + + + org.opendaylight.yangtools + binding-generator-util + ${yangtools.binding.version} + + + org.opendaylight.yangtools + binding-model-api ${yangtools.binding.version} diff --git a/opendaylight/md-sal/sal-binding-broker/pom.xml b/opendaylight/md-sal/sal-binding-broker/pom.xml index b0e2023f1f..35264e74e6 100644 --- a/opendaylight/md-sal/sal-binding-broker/pom.xml +++ b/opendaylight/md-sal/sal-binding-broker/pom.xml @@ -16,6 +16,7 @@ + org.opendaylight.yangtools yang-maven-plugin @@ -51,6 +52,7 @@ + org.codehaus.mojo build-helper-maven-plugin @@ -146,6 +148,7 @@ org.osgi org.osgi.core ${osgi.core.version} + provided com.google.guava @@ -161,6 +164,28 @@ javassist 3.17.1-GA + + org.opendaylight.yangtools + binding-generator-impl + 0.6.0-SNAPSHOT + + + org.opendaylight.yangtools + yang-parser-impl + 0.5.9-SNAPSHOT + test + + + org.opendaylight.controller + sal-core-api + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-broker-impl + 1.0-SNAPSHOT + runtime + junit junit @@ -175,10 +200,38 @@ org.eclipse.xtend org.eclipse.xtend.lib + + org.eclipse.xtend + org.eclipse.xtend.standalone + 2.4.3 + runtime + org.opendaylight.controller sal-binding-config 1.0-SNAPSHOT + + org.opendaylight.controller.model + model-flow-service + 1.0-SNAPSHOT + test + + + org.opendaylight.yangtools + yang-data-impl + 0.5.9-SNAPSHOT + + + org.opendaylight.yangtools + yang-model-util + 0.5.9-SNAPSHOT + + + org.slf4j + slf4j-simple + ${slf4j.version} + test + diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend index 87cc42c6e4..ea6dc131c6 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/codegen/impl/RuntimeCodeGenerator.xtend @@ -33,7 +33,7 @@ import java.util.Arrays import static extension org.opendaylight.controller.sal.binding.codegen.YangtoolsMappingHelper.* import static extension org.opendaylight.controller.sal.binding.codegen.RuntimeCodeSpecification.* import java.util.HashSet -import static org.opendaylight.controller.sal.binding.impl.osgi.ClassLoaderUtils.* +import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.* import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory import org.opendaylight.controller.sal.binding.spi.NotificationInvokerFactory.NotificationInvoker import java.util.Set diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend index d9a3dd547f..31d5d0126f 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/BindingAwareBrokerImpl.xtend @@ -40,10 +40,11 @@ import org.opendaylight.yangtools.concepts.AbstractObjectRegistration import org.opendaylight.yangtools.yang.binding.BaseIdentity import com.google.common.collect.Multimap import com.google.common.collect.HashMultimap -import static org.opendaylight.controller.sal.binding.impl.osgi.ClassLoaderUtils.* +import static org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils.* import java.util.concurrent.Executors import java.util.Collections import org.opendaylight.yangtools.yang.binding.DataObject +import org.opendaylight.controller.sal.binding.impl.connect.dom.ConnectorActivator class BindingAwareBrokerImpl implements BindingAwareBroker, AutoCloseable { private static val log = LoggerFactory.getLogger(BindingAwareBrokerImpl) @@ -86,7 +87,8 @@ class BindingAwareBrokerImpl implements BindingAwareBroker, AutoCloseable { ServiceRegistration dataConsumerRegistration - private HashMapDataStore store = new HashMapDataStore(); + ConnectorActivator connectorActivator + public new(BundleContext bundleContext) { _brokerBundleContext = bundleContext; @@ -115,11 +117,9 @@ class BindingAwareBrokerImpl implements BindingAwareBroker, AutoCloseable { notifyConsumerRegistration = brokerBundleContext.registerService(NotificationService, notifyBroker, brokerProperties) dataProviderRegistration = brokerBundleContext.registerService(DataProviderService, dataBroker, brokerProperties) dataConsumerRegistration = brokerBundleContext.registerService(DataBrokerService, dataBroker, brokerProperties) - - - getDataBroker().registerDataReader(root, store); - getDataBroker().registerCommitHandler(root, store) - + + connectorActivator = new ConnectorActivator(dataBroker,brokerBundleContext); + connectorActivator.start(); log.info("MD-SAL: Binding Aware Broker Started"); } diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.java new file mode 100644 index 0000000000..7a1ca11fb6 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.java @@ -0,0 +1,93 @@ +package org.opendaylight.controller.sal.binding.impl; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import org.opendaylight.controller.md.sal.common.api.data.DataReader; +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.controller.sal.common.DataStoreIdentifier; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.DataRoot; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; + + +public class DataBrokerImpl extends AbstractDataBroker, DataObject, DataChangeListener> implements + DataProviderService { + + public DataBrokerImpl() { + setDataReadRouter(new BindingAwareDataReaderRouter()); + } + + @Override + public DataTransactionImpl beginTransaction() { + return new DataTransactionImpl(this); + } + + @Override + public T getData(DataStoreIdentifier store, Class rootType) { + // TODO Auto-generated method stub + return null; + } + + @Override + public T getData(DataStoreIdentifier store, T filter) { + // TODO Auto-generated method stub + return null; + } + + @Override + public T getCandidateData(DataStoreIdentifier store, Class rootType) { + // TODO Auto-generated method stub + return null; + } + + @Override + public T getCandidateData(DataStoreIdentifier store, T filter) { + // TODO Auto-generated method stub + return null; + } + + @Override + public RpcResult editCandidateData(DataStoreIdentifier store, DataRoot changeSet) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Future> commit(DataStoreIdentifier store) { + // TODO Auto-generated method stub + return null; + } + + @Override + public DataObject getData(InstanceIdentifier data) { + // TODO Auto-generated method stub + return null; + } + + @Override + public DataObject getConfigurationData(InstanceIdentifier data) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void registerChangeListener(InstanceIdentifier path, DataChangeListener changeListener) { + // TODO Auto-generated method stub + + } + + @Override + public void unregisterChangeListener(InstanceIdentifier path, + DataChangeListener changeListener) { + // TODO Auto-generated method stub + + } + + +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend deleted file mode 100644 index 6ed63b21dd..0000000000 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataBrokerImpl.xtend +++ /dev/null @@ -1,175 +0,0 @@ -package org.opendaylight.controller.sal.binding.impl - -import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler -import org.opendaylight.controller.sal.binding.api.data.DataChangeListener -import org.opendaylight.controller.sal.binding.api.data.DataProviderService -import org.opendaylight.yangtools.yang.binding.DataObject -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.controller.md.sal.common.api.TransactionStatus -import org.opendaylight.controller.md.sal.common.api.data.DataReader -import org.opendaylight.yangtools.concepts.AbstractObjectRegistration -import org.opendaylight.yangtools.concepts.ListenerRegistration -import com.google.common.collect.Multimap -import static com.google.common.base.Preconditions.*; -import java.util.List -import com.google.common.collect.HashMultimap -import java.util.concurrent.ExecutorService -import java.util.concurrent.Callable -import org.opendaylight.yangtools.yang.common.RpcResult -import org.opendaylight.controller.sal.common.util.Rpcs -import java.util.Collections -import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction -import java.util.ArrayList -import org.opendaylight.controller.sal.binding.impl.util.BindingAwareDataReaderRouter -import org.opendaylight.yangtools.concepts.CompositeObjectRegistration -import java.util.Arrays - -class DataBrokerImpl extends DeprecatedDataAPISupport implements DataProviderService { - - @Property - var ExecutorService executor; - - val dataReadRouter = new BindingAwareDataReaderRouter; - - Multimap listeners = HashMultimap.create(); - Multimap commitHandlers = HashMultimap.create(); - - override beginTransaction() { - return new DataTransactionImpl(this); - } - - override readConfigurationData(InstanceIdentifier path) { - return dataReadRouter.readConfigurationData(path); - } - - override readOperationalData(InstanceIdentifier path) { - return dataReadRouter.readOperationalData(path); - } - - override registerCommitHandler(InstanceIdentifier path, - DataCommitHandler, DataObject> commitHandler) { - val registration = new DataCommitHandlerRegistration(path,commitHandler,this); - commitHandlers.put(path,registration) - return registration; - } - - override registerDataChangeListener(InstanceIdentifier path, DataChangeListener listener) { - val reg = new DataChangeListenerRegistration(path, listener, this); - listeners.put(path, reg); - return reg; - } - - override registerDataReader(InstanceIdentifier path,DataReader,DataObject> reader) { - - val confReg = dataReadRouter.registerConfigurationReader(path,reader); - val dataReg = dataReadRouter.registerOperationalReader(path,reader); - - return new CompositeObjectRegistration(reader,Arrays.asList(confReg,dataReg)); - } - - protected def removeListener(DataChangeListenerRegistration registration) { - listeners.remove(registration.path, registration); - } - - protected def removeCommitHandler(DataCommitHandlerRegistration registration) { - commitHandlers.remove(registration.path, registration); - } - - protected def getActiveCommitHandlers() { - return commitHandlers.entries.map[ value.instance].toSet - } - - protected def commit(DataTransactionImpl transaction) { - checkNotNull(transaction); - transaction.changeStatus(TransactionStatus.SUBMITED); - val task = new TwoPhaseCommit(transaction, this); - return executor.submit(task); - } - -} - -package class DataChangeListenerRegistration extends AbstractObjectRegistration implements ListenerRegistration { - - DataBrokerImpl dataBroker; - - @Property - val InstanceIdentifier path; - - new(InstanceIdentifier path, DataChangeListener instance, DataBrokerImpl broker) { - super(instance) - dataBroker = broker; - _path = path; - } - - override protected removeRegistration() { - dataBroker.removeListener(this); - dataBroker = null; - } - -} - -package class DataCommitHandlerRegistration // -extends AbstractObjectRegistration, DataObject>> { - - DataBrokerImpl dataBroker; - - @Property - val InstanceIdentifier path; - - new(InstanceIdentifier path, DataCommitHandler, DataObject> instance, - DataBrokerImpl broker) { - super(instance) - dataBroker = broker; - _path = path; - } - - override protected removeRegistration() { - dataBroker.removeCommitHandler(this); - dataBroker = null; - } - -} - -package class TwoPhaseCommit implements Callable> { - - val DataTransactionImpl transaction; - val DataBrokerImpl dataBroker; - - new(DataTransactionImpl transaction, DataBrokerImpl broker) { - this.transaction = transaction; - this.dataBroker = broker; - } - - override call() throws Exception { - - val Iterable, DataObject>> commitHandlers = dataBroker.activeCommitHandlers; - - // requesting commits - val List, DataObject>> handlerTransactions = new ArrayList(); - try { - for (handler : commitHandlers) { - handlerTransactions.add(handler.requestCommit(transaction)); - } - } catch (Exception e) { - return rollback(handlerTransactions,e); - } - val List> results = new ArrayList(); - try { - for (subtransaction : handlerTransactions) { - results.add(subtransaction.finish()); - } - } catch (Exception e) { - return rollback(handlerTransactions,e); - } - - return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.emptySet()); - } - - def rollback(List, DataObject>> transactions,Exception e) { - for (transaction : transactions) { - transaction.rollback() - } - // FIXME return encoutered error. - return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet()); - } -} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java index c970fc5e92..f7967beaae 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/DataTransactionImpl.java @@ -1,89 +1,22 @@ package org.opendaylight.controller.sal.binding.impl; -import java.util.concurrent.Future; - import org.opendaylight.controller.md.sal.common.api.TransactionStatus; -import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification; -import org.opendaylight.controller.md.sal.common.impl.ListenerRegistry; +import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; +import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction.DataTransactionListener; import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.concepts.util.ListenerRegistry; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; -import org.opendaylight.yangtools.yang.common.RpcResult; - -public class DataTransactionImpl extends AbstractDataModification, DataObject> - implements DataModificationTransaction { - - private final Object identifier; - - private TransactionStatus status; - private ListenerRegistry listeners; - - final DataBrokerImpl broker; +public class DataTransactionImpl extends AbstractDataTransaction, DataObject> + implements DataModificationTransaction { + private final ListenerRegistry listeners = new ListenerRegistry(); + + + public DataTransactionImpl(DataBrokerImpl dataBroker) { super(dataBroker); - identifier = new Object(); - broker = dataBroker; - status = TransactionStatus.NEW; - listeners = new ListenerRegistry<>(); - } - - @Override - public Future> commit() { - return broker.commit(this); - } - - @Override - public DataObject readConfigurationData( - org.opendaylight.yangtools.yang.binding.InstanceIdentifier path) { - return broker.readConfigurationData(path); - } - - @Override - public DataObject readOperationalData(InstanceIdentifier path) { - return broker.readOperationalData(path); - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((broker == null) ? 0 : broker.hashCode()); - result = prime * result + ((identifier == null) ? 0 : identifier.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - DataTransactionImpl other = (DataTransactionImpl) obj; - if (broker == null) { - if (other.broker != null) - return false; - } else if (!broker.equals(other.broker)) - return false; - if (identifier == null) { - if (other.identifier != null) - return false; - } else if (!identifier.equals(other.identifier)) - return false; - return true; - } - - @Override - public TransactionStatus getStatus() { - return status; - } - - @Override - public Object getIdentifier() { - return identifier; } @Override @@ -91,11 +24,9 @@ public class DataTransactionImpl extends AbstractDataModification> listenersToNotify = listeners.getListeners(); - for (ListenerRegistration listenerRegistration : listenersToNotify) { + protected void onStatusChange(TransactionStatus status) { + for (ListenerRegistration listenerRegistration : listeners) { listenerRegistration.getInstance().onStatusUpdated(this, status); } } -} +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java new file mode 100644 index 0000000000..ff897aa41d --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentDataServiceConnector.java @@ -0,0 +1,151 @@ +package org.opendaylight.controller.sal.binding.impl.connect.dom; + +import java.util.Collections; +import java.util.Map.Entry; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +import org.opendaylight.controller.config.api.jmx.CommitStatus; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +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.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction; +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; +import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider; +import org.opendaylight.controller.sal.common.util.Rpcs; +import org.opendaylight.controller.sal.core.api.data.DataBrokerService; +import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcError; +import org.opendaylight.yangtools.yang.common.RpcResult; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; + +import com.google.common.base.Preconditions; + +public class BindingIndependentDataServiceConnector implements // + RuntimeDataProvider, // + DataCommitHandler, DataObject> { + + private static final InstanceIdentifier ROOT = InstanceIdentifier.builder().toInstance(); + + private BindingIndependentMappingService mappingService; + + private DataBrokerService biDataService; + + private DataProviderService baDataService; + + @Override + public DataObject readOperationalData(InstanceIdentifier path) { + // TODO Auto-generated method stub + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path); + CompositeNode result = biDataService.readOperationalData(biPath); + return mappingService.dataObjectFromDataDom(path, result); + } + + @Override + public DataObject readConfigurationData(InstanceIdentifier path) { + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biPath = mappingService.toDataDom(path); + CompositeNode result = biDataService.readConfigurationData(biPath); + return mappingService.dataObjectFromDataDom(path, result); + } + + @Override + public org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction, DataObject> requestCommit( + DataModification, DataObject> modification) { + + DataModificationTransaction translated = translateTransaction(modification); + return new WrappedTransaction(translated, modification); + } + + private DataModificationTransaction translateTransaction( + DataModification, DataObject> source) { + DataModificationTransaction target = biDataService.beginTransaction(); + for (Entry, DataObject> entry : source.getUpdatedConfigurationData() + .entrySet()) { + Entry biEntry = mappingService + .toDataDom(entry); + target.putConfigurationData(biEntry.getKey(), biEntry.getValue()); + } + for (Entry, DataObject> entry : source.getUpdatedOperationalData() + .entrySet()) { + Entry biEntry = mappingService + .toDataDom(entry); + target.putOperationalData(biEntry.getKey(), biEntry.getValue()); + } + for(InstanceIdentifier entry : source.getRemovedConfigurationData()) { + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry); + target.removeConfigurationData(biEntry); + } + for(InstanceIdentifier entry : source.getRemovedOperationalData()) { + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier biEntry = mappingService.toDataDom(entry); + target.removeOperationalData(biEntry); + } + return target; + } + + private class WrappedTransaction implements + DataCommitTransaction, DataObject> { + + private DataModificationTransaction backing; + private DataModification, DataObject> modification; + + public WrappedTransaction(DataModificationTransaction backing, + DataModification, DataObject> modification) { + this.backing = backing; + this.modification = modification; + } + + @Override + public DataModification, DataObject> getModification() { + return modification; + } + + @Override + public RpcResult finish() throws IllegalStateException { + Future> result = backing.commit(); + try { + RpcResult biresult = result.get(); + } catch (InterruptedException e) { + throw new IllegalStateException("", e); + } catch (ExecutionException e) { + throw new IllegalStateException("", e); + } + return Rpcs. getRpcResult(true, null, Collections. emptySet()); + } + + @Override + public RpcResult rollback() throws IllegalStateException { + // backing.cancel(); + return Rpcs. getRpcResult(true, null, Collections. emptySet()); + } + + } + + public DataBrokerService getBiDataService() { + return biDataService; + } + + public void setBiDataService(DataBrokerService biDataService) { + this.biDataService = biDataService; + } + + public DataProviderService getBaDataService() { + return baDataService; + } + + public void setBaDataService(DataProviderService baDataService) { + this.baDataService = baDataService; + } + + public void start() { + baDataService.registerDataReader(ROOT, this); + baDataService.registerCommitHandler(ROOT, this); + } + + public void setMappingService(BindingIndependentMappingService mappingService) { + this.mappingService = mappingService; + } + +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java new file mode 100644 index 0000000000..d8fbc70f8e --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentMappingService.java @@ -0,0 +1,19 @@ +package org.opendaylight.controller.sal.binding.impl.connect.dom; + +import java.util.Map.Entry; + +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; + +public interface BindingIndependentMappingService { + + CompositeNode toDataDom(DataObject data); + + Entry toDataDom( + Entry, DataObject> entry); + + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom(InstanceIdentifier path); + + DataObject dataObjectFromDataDom(InstanceIdentifier path, CompositeNode result); +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentRpcConnector.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentRpcConnector.java new file mode 100644 index 0000000000..d22da3038c --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingIndependentRpcConnector.java @@ -0,0 +1,5 @@ +package org.opendaylight.controller.sal.binding.impl.connect.dom; + +public class BindingIndependentRpcConnector { + +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend new file mode 100644 index 0000000000..9a6330ea0f --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/BindingMapping.xtend @@ -0,0 +1,402 @@ +package org.opendaylight.controller.sal.binding.impl.connect.dom + +import org.opendaylight.yangtools.yang.common.QName +import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext +import java.util.List +import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder +import org.opendaylight.yangtools.sal.binding.model.api.Type +import org.opendaylight.yangtools.yang.model.api.SchemaNode +import java.util.Map +import org.opendaylight.yangtools.yang.model.api.SchemaPath +import org.opendaylight.yangtools.yang.model.api.SchemaContext +import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil +import org.opendaylight.yangtools.binding.generator.util.Types +import java.util.HashMap +import org.opendaylight.yangtools.yang.data.api.CompositeNode +import org.opendaylight.yangtools.yang.binding.DataContainer +import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl +import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty +import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType +import java.util.Collections +import java.util.ArrayList +import org.opendaylight.yangtools.yang.data.api.Node +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode +import org.opendaylight.yangtools.yang.model.api.ChoiceNode +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode +import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl +import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl +import org.opendaylight.yangtools.yang.model.api.NotificationDefinition +import org.opendaylight.yangtools.yang.model.api.TypeDefinition +import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition +import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import org.opendaylight.yangtools.yang.binding.DataObject +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates +import org.opendaylight.yangtools.yang.model.util.ExtendedType +import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject +import com.google.common.collect.FluentIterable +import org.opendaylight.yangtools.yang.data.api.SimpleNode +import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil +import org.opendaylight.controller.sal.binding.impl.util.ClassLoaderUtils +import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition + +class BindingMapping { + + val Map typeToDefinition = new HashMap(); + val Map typeToSchemaNode = new HashMap(); + + def QName getSchemaNode(Class cls) { + val ref = Types.typeForClass(cls); + return typeToSchemaNode.get(ref)?.QName; + } + + def void updateBinding(SchemaContext schemaContext, ModuleContext moduleBindingContext) { + updateBindingFor(moduleBindingContext.childNodes, schemaContext); + + } + + def org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom( + InstanceIdentifier obj) { + val pathArguments = obj.path; + var Class parent; + val dataDomArgs = new ArrayList(); + for (pathArgument : pathArguments) { + dataDomArgs.add(pathArgument.toDataDomPathArgument(parent)); + parent = pathArgument.type; + } + + return new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier(dataDomArgs); + } + + + + def DataObject dataObjectFromDataDom(InstanceIdentifier identifier, CompositeNode node) { + if (node == null) { + return null; + } + val targetClass = identifier.targetType; + val classLoader = targetClass.classLoader; + val ref = Types.typeForClass(targetClass); + val targetType = typeToDefinition.get(ref); + val targetSchema = typeToSchemaNode.get(ref); + return node.toDataObject(classLoader, targetType.toInstance, targetSchema); + + } + + def dispatch PathArgument toDataDomPathArgument(IdentifiableItem argument, Class parent) { + val Class rawType = argument.type; + val ref = Types.typeForClass(rawType); + val schemaType = typeToSchemaNode.get(ref); + val qname = schemaType.QName + + val Object key = argument.key; + val predicates = key.toPredicates(schemaType as ListSchemaNode); + + return new NodeIdentifierWithPredicates(qname, predicates); + } + + def dispatch PathArgument toDataDomPathArgument(Item argument, Class parent) { + val ref = Types.typeForClass(argument.type); + val qname = typeToSchemaNode.get(ref).QName + return new NodeIdentifier(qname); + } + + def Map toPredicates(Object identifier, ListSchemaNode node) { + val keyDefinitions = node.keyDefinition; + val map = new HashMap(); + for (keydef : keyDefinitions) { + val keyNode = node.getDataChildByName(keydef) as LeafSchemaNode; + val value = identifier.getSimpleValue(keydef, keyNode.type); + map.put(keydef, value.value); + } + return map; + } + + def void updateBindingFor(Map map, SchemaContext module) { + for (entry : map.entrySet) { + val schemaNode = SchemaContextUtil.findDataSchemaNode(module, entry.key); + typeToDefinition.put(entry.value, entry.value); + typeToSchemaNode.put(entry.value, schemaNode) + } + } + + def CompositeNode toCompositeNode(DataContainer data) { + val type = data.implementedInterface; + val typeRef = Types.typeForClass(type); + val schemaNode = typeToSchemaNode.get(typeRef); + val generatedType = typeToDefinition.get(typeRef); + + return data.toDataDom(schemaNode, generatedType); + } + + private def dispatch CompositeNode toDataDom(DataContainer data, ContainerSchemaNode node, + GeneratedTypeBuilder builder) { + val subnodes = data.toDataDomComponents(node); + return new CompositeNodeTOImpl(node.QName, null, subnodes); + } + + private def dispatch CompositeNode toDataDom(DataContainer data, NotificationDefinition node, + GeneratedTypeBuilder builder) { + val subnodes = data.toDataDomComponents(node); + return new CompositeNodeTOImpl(node.QName, null, subnodes); + } + + private def dispatch CompositeNode toDataDom(DataContainer data, ListSchemaNode node, + GeneratedTypeBuilder builder) { + val subnodes = data.toDataDomComponents(node); + return new CompositeNodeTOImpl(node.QName, null, subnodes); + } + + private def List> toDataDomComponents(DataContainer data, DataNodeContainer node) { + val subnodes = new ArrayList>(); + for (childNode : node.childNodes) { + val value = childNode.dataDomFromParent(data); + if (value !== null) { + subnodes.addAll(value); + } + } + return subnodes; + } + + private def List> dataDomFromParent(DataSchemaNode node, DataContainer container) { + if (node.augmenting) { + return Collections.emptyList(); + } + return dataDomFromParentImpl(node, container); + } + + private def dispatch List> dataDomFromParentImpl(LeafSchemaNode node, DataContainer container) { + val value = container.getSimpleValue(node.QName, node.type); + if (value !== null) { + return Collections.>singletonList(value); + } + return Collections.emptyList(); + } + + private def dispatch List> dataDomFromParentImpl(LeafListSchemaNode node, DataContainer container) { + val values = container.getSimpleValues(node); + if (values !== null) { + //val it = new ArrayList>(); + //for (value : values) { + //} + + } + return Collections.emptyList(); + } + + def getSimpleValues(DataContainer container, LeafListSchemaNode node) { + return Collections.emptyList(); + } + + private def dispatch List> dataDomFromParentImpl(ListSchemaNode node, DataContainer container) { + val qname = node.QName; + val values = container.getValue(qname, List) as List; + if (values === null) { + return Collections.emptyList; + } + val it = new ArrayList>(); + for (value : values) { + add(value.toCompositeNode()); + } + + return it; + } + + private def dispatch List> dataDomFromParentImpl(ChoiceNode node, DataContainer container) { + } + + private def dispatch List> serializeValueImpl(List list, GeneratedTypeBuilder builder, + ListSchemaNode node) { + val it = new ArrayList>(); + for (value : list) { + + val serVal = value.serializeValueImpl(builder, node); + if (serVal !== null) { + addAll(serVal); + } + } + return it; + } + + private def dispatch Node getSimpleValue(Object container, QName name, ExtendedType type) { + getSimpleValue(container, name, type.baseType); + } + + private def dispatch Node getSimpleValue(Object container, QName name, StringTypeDefinition type) { + val value = container.getValue(name, String); + if(value === null) return null; + return new SimpleNodeTOImpl(name, null, value); + } + + private def dispatch Node getSimpleValue(Object container, QName name, TypeDefinition type) { + val value = container.getValue(name, Object); + if(value === null) return null; + return new SimpleNodeTOImpl(name, null, value); + } + + private def dispatch Node getSimpleValue(Object container, QName name, BooleanTypeDefinition type) { + val value = container.getValue(name, Boolean); + if(value === null) return null; + return new SimpleNodeTOImpl(name, null, value); + } + + private def dispatch Node getSimpleValue(Object container, QName name, BinaryTypeDefinition type) { + val Object value = container.getValue(name, Object); //Constants.BYTES_CLASS); + if(value === null) return null; + return new SimpleNodeTOImpl(name, null, value); + } + + private def T getValue(Object object, QName node, Class type) { + val methodName = BindingGeneratorImpl.getterMethodName(node.localName, Types.typeForClass(type)); + var clz = object.class; + if (object instanceof DataContainer) { + clz = (object as DataContainer).implementedInterface; + } + val method = clz.getMethod(methodName); + if (method === null) { + return null; + } + val value = method.invoke(object); + if (value === null) { + return null; + } + if (type.isAssignableFrom(value.class)) { + return value as T; + } + return value.getEncapsulatedValue(type); + } + + private def T getEncapsulatedValue(Object value, Class type) { + val method = value.class.getMethod("getValue"); + if (method !== null && type.isAssignableFrom(method.returnType)) { + return method.invoke(value) as T; + } + return null; + } + + private def dispatch List> serializeValueImpl(DataContainer data, GeneratedTypeBuilder builder, + SchemaNode node) { + return Collections.>singletonList(data.toDataDom(node, builder)); + } + + private def dispatch List> serializeValueImpl(Object object, GeneratedTypeBuilder builder, + SchemaNode node) { + } + + def DataObject toDataObject(CompositeNode node, ClassLoader loader, GeneratedType type, SchemaNode schema) { + + // Nasty reflection hack (for now) + val builderClass = loader.loadClass(type.builderFQN); + val builder = builderClass.newInstance; + val buildMethod = builderClass.getMethod("build"); + + node.fillDataObject(builder, loader, type, schema); + + return buildMethod.invoke(builder) as DataObject; + } + + def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type, + ListSchemaNode schema) { + + if (schema.keyDefinition !== null && !schema.keyDefinition.empty) { + + val value = node.keyToBindingKey(loader, type, schema); + builder.setProperty("key", value); + } + } + + def dispatch void fillDataObject(CompositeNode node, Object builder, ClassLoader loader, GeneratedType type, + ContainerSchemaNode schema) { + } + + + def Object keyToBindingKey(CompositeNode node, ClassLoader loader, GeneratedType type, ListSchemaNode schema) { + val keyClass = loader.loadClass(type.keyFQN); + val constructor = keyClass.constructors.get(0); + val keyType = type.keyTypeProperties; + val args = new ArrayList(); + for (key : schema.keyDefinition) { + val keyProperty = keyType.get(BindingGeneratorUtil.parseToClassName(key.localName)); + val domKeyValue = node.getFirstSimpleByName(key); + val keyValue = domKeyValue.deserializeSimpleValue(loader, keyProperty.returnType, + schema.getDataChildByName(key)); + args.add(keyValue); + } + return ClassLoaderUtils.construct(constructor, args); + } + + def dispatch Object deserializeSimpleValue(SimpleNode node, ClassLoader loader, Type type, + LeafSchemaNode node2) { + deserializeSimpleValueImpl(node, loader, type, node2.type); + } + + def dispatch Object deserializeSimpleValue(SimpleNode node, ClassLoader loader, Type type, + LeafListSchemaNode node2) { + deserializeSimpleValueImpl(node, loader, type, node2.type); + } + + def dispatch Object deserializeSimpleValueImpl(SimpleNode node, ClassLoader loader, Type type, + ExtendedType definition) { + deserializeSimpleValueImpl(node, loader, type, definition.baseType); + } + + def dispatch Object deserializeSimpleValueImpl(SimpleNode node, ClassLoader loader, Type type, + StringTypeDefinition definition) { + if (type instanceof GeneratedTransferObject) { + val cls = loader.getClassForType(type); + val const = cls.getConstructor(String); + val str = String.valueOf(node.value); + return const.newInstance(str); + } + return node.value; + } + + def Class getClassForType(ClassLoader loader, Type type) { + loader.loadClass(type.fullyQualifiedName); + } + + def dispatch Object deserializeSimpleValueImpl(SimpleNode node, ClassLoader loader, Type type, + TypeDefinition definition) { + throw new UnsupportedOperationException("TODO: auto-generated method stub") + } + + def Map getKeyTypeProperties(GeneratedType type) { + val method = FluentIterable.from(type.methodDefinitions).findFirst[name == "getKey"] + val key = method.returnType as GeneratedTransferObject; + val ret = new HashMap(); + for (prop : key.properties) { + ret.put(prop.name, prop); + } + return ret; + } + + def void setProperty(Object object, String property, Object value) { + val cls = object.class; + val valMethod = cls.getMethod("set" + property.toFirstUpper, value.class); + if (valMethod != null) + valMethod.invoke(object, value); + } + + def String getBuilderFQN(Type type) '''«type.fullyQualifiedName»Builder''' + + def String getKeyFQN(Type type) '''«type.fullyQualifiedName»Key''' + +} + +@Data +class PropertyCapture { + + @Property + val Type returnType; + @Property + val String name; + +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/ConnectorActivator.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/ConnectorActivator.java new file mode 100644 index 0000000000..c96835bd94 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/ConnectorActivator.java @@ -0,0 +1,73 @@ +package org.opendaylight.controller.sal.binding.impl.connect.dom; + +import java.util.Collection; +import java.util.Collections; + +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; +import org.opendaylight.controller.sal.core.api.Broker; +import org.opendaylight.controller.sal.core.api.Provider; +import org.opendaylight.controller.sal.core.api.Broker.ProviderSession; +import org.opendaylight.controller.sal.core.api.data.DataBrokerService; +import org.opendaylight.controller.sal.core.api.model.SchemaService; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.util.tracker.ServiceTracker; +import org.osgi.util.tracker.ServiceTrackerCustomizer; + +public class ConnectorActivator implements Provider, ServiceTrackerCustomizer { + + BindingIndependentDataServiceConnector dataConnector; + BindingIndependentMappingService mappingService; + + private final DataProviderService baDataService; + private BundleContext context; + + private ServiceTracker brokerTracker; + + public ConnectorActivator(DataProviderService dataService, BundleContext context) { + baDataService = dataService; + this.context = context; + brokerTracker = new ServiceTracker<>(context, Broker.class, this); + } + + @Override + public Collection getProviderFunctionality() { + return Collections.emptySet(); + } + + @Override + public void onSessionInitiated(ProviderSession session) { + + MappingServiceImpl mappingImpl = new MappingServiceImpl(); + mappingImpl.setSchemaService(session.getService(SchemaService.class)); + mappingImpl.start(); + + mappingService = mappingImpl; + dataConnector = new BindingIndependentDataServiceConnector(); + dataConnector.setBaDataService(baDataService); + dataConnector.setBiDataService(session.getService(DataBrokerService.class)); + dataConnector.setMappingService(mappingService); + dataConnector.start(); + } + + @Override + public Broker addingService(ServiceReference reference) { + Broker br= context.getService(reference); + br.registerProvider(this, context); + return br; + } + + @Override + public void modifiedService(ServiceReference reference, Broker service) { + // NOOP + } + + @Override + public void removedService(ServiceReference reference, Broker service) { + // NOOP + } + + public void start() { + brokerTracker.open(); + } +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/Constants.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/Constants.java new file mode 100644 index 0000000000..1c9a59d414 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/Constants.java @@ -0,0 +1,5 @@ +package org.opendaylight.controller.sal.binding.impl.connect.dom; + +public class Constants { + public static final Class BYTES_CLASS = byte[].class; +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/MappingServiceImpl.xtend b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/MappingServiceImpl.xtend new file mode 100644 index 0000000000..84a0065ea1 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/connect/dom/MappingServiceImpl.xtend @@ -0,0 +1,68 @@ +package org.opendaylight.controller.sal.binding.impl.connect.dom + +import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener +import org.opendaylight.yangtools.yang.model.api.SchemaContext +import org.opendaylight.yangtools.sal.binding.model.api.CodeGenerator +import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl +import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator +import org.opendaylight.yangtools.yang.data.api.CompositeNode +import org.opendaylight.yangtools.yang.binding.DataObject +import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl +import java.util.Collections +import java.util.Map.Entry +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier +import java.util.AbstractMap.SimpleEntry +import org.opendaylight.controller.sal.core.api.model.SchemaService + +class MappingServiceImpl implements SchemaServiceListener, BindingIndependentMappingService { + + var extension BindingMapping mapping = new BindingMapping; + + @Property + BindingGeneratorImpl binding; + + @Property + SchemaService schemaService; + + override onGlobalContextUpdated(SchemaContext arg0) { + recreateBindingContext(arg0); + } + + def recreateBindingContext(SchemaContext schemaContext) { + val newBinding = new BindingGeneratorImpl(); + newBinding.generateTypes(schemaContext); + val newMapping = new BindingMapping(); + for (entry : newBinding.moduleContexts.entrySet) { + val module = entry.key; + val context = entry.value; + + newMapping.updateBinding(schemaContext, context); + } + mapping = newMapping + } + + override CompositeNode toDataDom(DataObject data) { + mapping.toCompositeNode(data); + } + + override Entry toDataDom( + Entry, DataObject> entry) { + val key = mapping.toDataDom(entry.key); + val data = mapping.toCompositeNode(entry.value); + return new SimpleEntry(key, data); + } + + override org.opendaylight.yangtools.yang.data.api.InstanceIdentifier toDataDom( + InstanceIdentifier path) { + return mapping.toDataDom(path); + } + + override dataObjectFromDataDom(InstanceIdentifier path, CompositeNode result) { + return mapping.dataObjectFromDataDom(path,result); + } + + public def void start() { + schemaService.registerSchemaServiceListener(this); + recreateBindingContext(schemaService.globalContext); + } +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/ClassLoaderUtils.java b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/ClassLoaderUtils.java similarity index 56% rename from opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/ClassLoaderUtils.java rename to opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/ClassLoaderUtils.java index ad0473e8a2..ccf99dfe37 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/osgi/ClassLoaderUtils.java +++ b/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/util/ClassLoaderUtils.java @@ -1,10 +1,17 @@ -package org.opendaylight.controller.sal.binding.impl.osgi; +package org.opendaylight.controller.sal.binding.impl.util; import java.util.concurrent.Callable; + import static com.google.common.base.Preconditions.*; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; + +import org.opendaylight.yangtools.yang.binding.Identifier; + public class ClassLoaderUtils { public static V withClassLoader(ClassLoader cls,Callable function) throws Exception { @@ -21,4 +28,9 @@ public class ClassLoaderUtils { throw new Exception(e); } } + + public static Object construct(Constructor constructor, ArrayList objects) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Object[] initargs = objects.toArray(new Object[]{}); + return constructor.newInstance(initargs); + } } \ No newline at end of file diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java new file mode 100644 index 0000000000..0448238665 --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/BrokerIntegrationTest.java @@ -0,0 +1,136 @@ +package org.opendaylight.controller.sal.binding.test.connect.dom; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; +import org.opendaylight.controller.sal.binding.api.data.DataProviderService; +import org.opendaylight.controller.sal.binding.impl.DataBrokerImpl; +import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentDataServiceConnector; +import org.opendaylight.controller.sal.binding.impl.connect.dom.MappingServiceImpl; +import org.opendaylight.controller.sal.core.api.data.DataBrokerService; +import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.RpcResult; + +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; + +public class BrokerIntegrationTest { + + DataBrokerService biDataService; + DataProviderService baDataService; + private MappingServiceImpl mappingServiceImpl; + private MappingServiceImpl mappingService; + private DataBrokerImpl baDataImpl; + private org.opendaylight.controller.sal.dom.broker.DataBrokerImpl biDataImpl; + private ListeningExecutorService executor; + private BindingIndependentDataServiceConnector connectorServiceImpl; + private HashMapDataStore dataStore; + + + @Before + public void setUp() { + executor = MoreExecutors.sameThreadExecutor(); + baDataImpl = new DataBrokerImpl(); + baDataService = baDataImpl; + baDataImpl.setExecutor(executor); + + biDataImpl = new org.opendaylight.controller.sal.dom.broker.DataBrokerImpl(); + biDataService = biDataImpl; + biDataImpl.setExecutor(executor); + + dataStore = new HashMapDataStore(); + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier treeRoot = org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.builder().toInstance(); + biDataImpl.registerConfigurationReader(treeRoot, dataStore); + biDataImpl.registerOperationalReader(treeRoot, dataStore); + biDataImpl.registerCommitHandler(treeRoot, dataStore); + + mappingServiceImpl = new MappingServiceImpl(); + mappingService = mappingServiceImpl; + + + connectorServiceImpl = new BindingIndependentDataServiceConnector(); + connectorServiceImpl.setBaDataService(baDataService); + connectorServiceImpl.setBiDataService(biDataService); + connectorServiceImpl.setMappingService(mappingServiceImpl); + connectorServiceImpl.start(); + + String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang", + "node-inventory.yang" }; + + mappingService.onGlobalContextUpdated(MappingServiceTest.getContext(yangFiles)); + } + + @Test + public void simpleModifyOperation() throws Exception { + + DataModificationTransaction transaction = baDataService.beginTransaction(); + assertNotNull(transaction); + + NodeRef node1 = createNodeRef("0"); + DataObject node = baDataService.readConfigurationData(node1.getValue()); + assertNull(node); + Node nodeData1 = createNode("0"); + + transaction.putConfigurationData(node1.getValue(), nodeData1); + Future> commitResult = transaction.commit(); + assertNotNull(commitResult); + + RpcResult result = commitResult.get(); + + assertNotNull(result); + assertNotNull(result.getResult()); + assertEquals(TransactionStatus.COMMITED, result.getResult()); + + Node readedData = (Node) baDataService.readConfigurationData(node1.getValue()); + assertNotNull(readedData); + assertEquals(nodeData1.getKey(), readedData.getKey()); + + + DataModificationTransaction transaction2 = baDataService.beginTransaction(); + assertNotNull(transaction); + + transaction2.removeConfigurationData(node1.getValue()); + + Future> commitResult2 = transaction2.commit(); + assertNotNull(commitResult2); + + RpcResult result2 = commitResult2.get(); + + assertNotNull(result2); + assertNotNull(result2.getResult()); + assertEquals(TransactionStatus.COMMITED, result2.getResult()); + + DataObject readedData2 = baDataService.readConfigurationData(node1.getValue()); + assertNull(readedData2); + } + + private static NodeRef createNodeRef(String string) { + NodeKey key = new NodeKey(new NodeId(string)); + InstanceIdentifier path = InstanceIdentifier.builder().node(Nodes.class).node(Node.class, key) + .toInstance(); + return new NodeRef(path); + } + + private static Node createNode(String string) { + NodeBuilder ret = new NodeBuilder(); + ret.setId(new NodeId(string)); + ret.setKey(new NodeKey(ret.getId())); + return ret.build(); + } +} diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MappingServiceTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MappingServiceTest.java new file mode 100644 index 0000000000..b0c2e7529a --- /dev/null +++ b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/sal/binding/test/connect/dom/MappingServiceTest.java @@ -0,0 +1,118 @@ +package org.opendaylight.controller.sal.binding.test.connect.dom; + +import static org.junit.Assert.*; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.junit.Before; +import org.junit.Test; +import org.opendaylight.controller.sal.binding.impl.connect.dom.BindingIndependentMappingService; +import org.opendaylight.controller.sal.binding.impl.connect.dom.MappingServiceImpl; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; +import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext; +import org.opendaylight.yangtools.yang.binding.Augmentation; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; + +public class MappingServiceTest { + + private static final QName NODES = QName.create("urn:opendaylight:inventory", "2013-08-19", "nodes"); + private static final QName NODE = QName.create(NODES,"node"); + private static final QName ID = QName.create(NODES,"id"); + + BindingIndependentMappingService service; + private MappingServiceImpl impl; + + @Before + public void setUp() { + impl = new MappingServiceImpl(); + service = impl; + } + + @Test + public void baDataToBiData() throws Exception { + + String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang", + "node-inventory.yang" }; + + SchemaContext ctx = getContext(yangFiles); + + impl.onGlobalContextUpdated(ctx); + + NodesBuilder nodes = new NodesBuilder(); + + List nodeList = new ArrayList<>(); + nodeList.add(createChildNode("foo")); + nodeList.add(createChildNode("bar")); + + nodes.setNode(nodeList); + Nodes nodesTO = nodes.build(); + CompositeNode xmlNodes = service.toDataDom(nodesTO); + assertNotNull(xmlNodes); + List invNodes = xmlNodes.getCompositesByName(NODE); + assertNotNull(invNodes); + assertEquals(2, invNodes.size()); + } + + @Test + public void instanceIdentifierTest() throws Exception { + + String[] yangFiles = new String[] { "yang-ext.yang", "ietf-inet-types.yang", "ietf-yang-types.yang", + "node-inventory.yang" }; + SchemaContext ctx = getContext(yangFiles); + impl.onGlobalContextUpdated(ctx); + + NodeKey nodeKey = new NodeKey(new NodeId("foo")); + InstanceIdentifier path = InstanceIdentifier.builder().node(Nodes.class).child(Node.class, nodeKey).toInstance(); + org.opendaylight.yangtools.yang.data.api.InstanceIdentifier result = service.toDataDom(path); + assertNotNull(result); + assertEquals(2, result.getPath().size()); + } + + public static SchemaContext getContext(String[] yangFiles) { + + ClassLoader loader = MappingServiceTest.class.getClassLoader(); + + List streams = new ArrayList<>(); + for (String string : yangFiles) { + InputStream stream = loader.getResourceAsStream("META-INF/yang/" + string); + streams.add(stream); + + } + YangParserImpl parser = new YangParserImpl(); + + Set modules = parser.parseYangModelsFromStreams(streams); + return parser.resolveSchemaContext(modules); + } + + private Node createChildNode(String id) { + NodeBuilder node = new NodeBuilder(); + NodeId nodeId = new NodeId(id); + + node.setId(nodeId); + node.setKey(new NodeKey(nodeId)); + + FlowCapableNodeBuilder aug = new FlowCapableNodeBuilder(); + aug.setManufacturer(id); + node.addAugmentation(FlowCapableNode.class, aug.build()); + + return node.build(); + } + +} diff --git a/opendaylight/md-sal/sal-binding-it/pom.xml b/opendaylight/md-sal/sal-binding-it/pom.xml index a20491b6be..e242b9ecee 100644 --- a/opendaylight/md-sal/sal-binding-it/pom.xml +++ b/opendaylight/md-sal/sal-binding-it/pom.xml @@ -206,5 +206,10 @@ 1.0-SNAPSHOT provided + + org.opendaylight.yangtools.thirdparty + antlr4-runtime-osgi-nohead + 4.0 + diff --git a/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java b/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java index 3e3ee3a874..2f9c397632 100644 --- a/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java +++ b/opendaylight/md-sal/sal-binding-it/src/main/java/org/opendaylight/controller/test/sal/binding/it/TestHelper.java @@ -25,6 +25,7 @@ public class TestHelper { mavenBundle(CONTROLLER, "sal-common-api").versionAsInProject(), // mavenBundle(CONTROLLER, "sal-common-impl").versionAsInProject(), // + mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(), mavenBundle("com.google.guava", "guava").versionAsInProject(), // mavenBundle(YANGTOOLS + ".thirdparty", "xtend-lib-osgi").versionAsInProject() // ); @@ -44,8 +45,32 @@ public class TestHelper { mavenBundle(CONTROLLER, "sal-binding-config").versionAsInProject(), mavenBundle(CONTROLLER, "sal-binding-broker-impl").versionAsInProject(), // mavenBundle("org.javassist", "javassist").versionAsInProject(), // - mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject() // - ); + mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject(), // + + mavenBundle(YANGTOOLS, "yang-data-api").versionAsInProject(), // + mavenBundle(YANGTOOLS, "yang-data-impl").versionAsInProject(), // + mavenBundle(YANGTOOLS, "yang-model-api").versionAsInProject(), // + mavenBundle(YANGTOOLS, "yang-model-util").versionAsInProject(), // + mavenBundle(YANGTOOLS, "yang-parser-api").versionAsInProject(), + mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(), + + + mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(), // + mavenBundle(YANGTOOLS, "binding-model-api").versionAsInProject(), // + mavenBundle(YANGTOOLS, "binding-generator-util").versionAsInProject(), + mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(), + mavenBundle(YANGTOOLS, "binding-type-provider").versionAsInProject(), + mavenBundle(YANGTOOLS, "binding-generator-api").versionAsInProject(), + mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(), + mavenBundle(YANGTOOLS, "binding-generator-impl").versionAsInProject(), + + + mavenBundle(CONTROLLER, "sal-core-api").versionAsInProject().update(), // + mavenBundle(CONTROLLER, "sal-broker-impl").versionAsInProject(), // + mavenBundle(CONTROLLER, "sal-core-spi").versionAsInProject().update(), // + + mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject() // + ); } diff --git a/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/DataServiceTest.java b/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/DataServiceTest.java index d26f2e7aa1..e1f109b88d 100644 --- a/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/DataServiceTest.java +++ b/opendaylight/md-sal/sal-binding-it/src/test/java/org/opendaylight/controller/test/sal/binding/it/DataServiceTest.java @@ -11,6 +11,7 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer; import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext; import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction; +import org.opendaylight.controller.sal.core.api.Broker; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; @@ -21,9 +22,15 @@ import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; +import com.google.inject.Inject; + public class DataServiceTest extends AbstractTest { protected DataBrokerService consumerDataService; + + + @Inject + Broker broker2; @Before public void setUp() throws Exception { @@ -61,9 +68,9 @@ public class DataServiceTest extends AbstractTest { assertNotNull(result.getResult()); assertEquals(TransactionStatus.COMMITED, result.getResult()); - DataObject readedData = consumerDataService.readConfigurationData(node1.getValue()); + Node readedData = (Node) consumerDataService.readConfigurationData(node1.getValue()); assertNotNull(readedData); - assertEquals(nodeData1, readedData); + assertEquals(nodeData1.getKey(), readedData.getKey()); DataModificationTransaction transaction2 = consumerDataService.beginTransaction(); @@ -97,7 +104,9 @@ public class DataServiceTest extends AbstractTest { private static Node createNode(String string) { NodeBuilder ret = new NodeBuilder(); - ret.setId(new NodeId(string)); + NodeId id = new NodeId(string); + ret.setKey(new NodeKey(id)); + ret.setId(id); return ret.build(); } } diff --git a/opendaylight/md-sal/sal-common-impl/pom.xml b/opendaylight/md-sal/sal-common-impl/pom.xml index 3bd51ec7d8..7fb05806df 100644 --- a/opendaylight/md-sal/sal-common-impl/pom.xml +++ b/opendaylight/md-sal/sal-common-impl/pom.xml @@ -1,50 +1,59 @@ - 4.0.0 - - org.opendaylight.controller - sal-parent - 1.0-SNAPSHOT - - sal-common-impl - bundle - - scm:git:ssh://git.opendaylight.org:29418/controller.git - scm:git:ssh://git.opendaylight.org:29418/controller.git - https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + org.opendaylight.controller + sal-parent + 1.0-SNAPSHOT + + sal-common-impl + bundle + + scm:git:ssh://git.opendaylight.org:29418/controller.git + scm:git:ssh://git.opendaylight.org:29418/controller.git + https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL + - - - org.opendaylight.controller - sal-common-api - 1.0-SNAPSHOT - - - com.google.guava - guava - - - org.eclipse.xtend - org.eclipse.xtend.lib - - + + + org.opendaylight.controller + sal-common-api + 1.0-SNAPSHOT + + + org.opendaylight.controller + sal-common-util + 1.0-SNAPSHOT + + + com.google.guava + guava + + + org.eclipse.xtend + org.eclipse.xtend.lib + + - - - - org.apache.felix - maven-bundle-plugin - - - - org.opendaylight.controller.md.sal.common.impl, - org.opendaylight.controller.md.sal.common.impl.* - - - - - - + + + + org.apache.felix + maven-bundle-plugin + + + + org.opendaylight.controller.md.sal.common.impl, + org.opendaylight.controller.md.sal.common.impl.* + + + + + + org.eclipse.xtend + xtend-maven-plugin + + + diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java index 531ce224e6..d6b3c5334a 100644 --- a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/routing/AbstractDataReadRouter.java @@ -35,7 +35,7 @@ public abstract class AbstractDataReadRouter

, D> implements Da @Override public D readOperationalData(P path) { FluentIterable dataBits = FluentIterable // - .from(getReaders(configReaders, path)).transform(operationalRead(path)); + .from(getReaders(operationalReaders, path)).transform(operationalRead(path)); return merge(path,dataBits); } diff --git a/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend new file mode 100644 index 0000000000..b878071183 --- /dev/null +++ b/opendaylight/md-sal/sal-common-impl/src/main/java/org/opendaylight/controller/md/sal/common/impl/service/AbstractDataBroker.xtend @@ -0,0 +1,259 @@ +package org.opendaylight.controller.md.sal.common.impl.service + +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler +import org.opendaylight.controller.md.sal.common.api.TransactionStatus +import org.opendaylight.controller.md.sal.common.api.data.DataReader +import org.opendaylight.yangtools.concepts.AbstractObjectRegistration +import org.opendaylight.yangtools.concepts.ListenerRegistration +import com.google.common.collect.Multimap +import static com.google.common.base.Preconditions.*; +import java.util.List +import com.google.common.collect.HashMultimap +import java.util.concurrent.ExecutorService +import java.util.concurrent.Callable +import org.opendaylight.yangtools.yang.common.RpcResult +import java.util.Collections +import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction +import java.util.ArrayList +import org.opendaylight.yangtools.concepts.CompositeObjectRegistration +import java.util.Arrays +import org.opendaylight.controller.md.sal.common.api.data.DataProvisionService +import org.opendaylight.controller.md.sal.common.api.data.DataModificationTransactionFactory +import org.opendaylight.controller.md.sal.common.api.data.DataChangePublisher +import org.opendaylight.controller.md.sal.common.api.data.DataChangeListener +import org.opendaylight.controller.sal.common.util.Rpcs +import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification +import java.util.concurrent.Future +import org.opendaylight.controller.md.sal.common.impl.routing.AbstractDataReadRouter +import org.opendaylight.yangtools.concepts.Path +import org.slf4j.LoggerFactory + +abstract class AbstractDataBroker

,D,DCL extends DataChangeListener> implements +DataModificationTransactionFactory, // +DataReader, // +DataChangePublisher, // +DataProvisionService { + + @Property + var ExecutorService executor; + + @Property + var AbstractDataReadRouter dataReadRouter; + + Multimap> listeners = HashMultimap.create(); + Multimap> commitHandlers = HashMultimap.create(); + + + public new() { + + } + + override final readConfigurationData(P path) { + return dataReadRouter.readConfigurationData(path); + } + + override final readOperationalData(P path) { + return dataReadRouter.readOperationalData(path); + } + + override final registerCommitHandler(P path, + DataCommitHandler commitHandler) { + val registration = new DataCommitHandlerRegistration(path,commitHandler,this); + commitHandlers.put(path,registration) + return registration; + } + + override final def registerDataChangeListener(P path, DCL listener) { + val reg = new DataChangeListenerRegistration(path, listener, this); + listeners.put(path, reg); + return reg; + } + + final def registerDataReader(P path,DataReader reader) { + + val confReg = dataReadRouter.registerConfigurationReader(path,reader); + val dataReg = dataReadRouter.registerOperationalReader(path,reader); + + return new CompositeObjectRegistration(reader,Arrays.asList(confReg,dataReg)); + } + + protected final def removeListener(DataChangeListenerRegistration registration) { + listeners.remove(registration.path, registration); + } + + protected final def removeCommitHandler(DataCommitHandlerRegistration registration) { + commitHandlers.remove(registration.path, registration); + } + + protected final def getActiveCommitHandlers() { + return commitHandlers.entries.map[ value.instance].toSet + } + + package final def Future> commit(AbstractDataTransaction transaction) { + checkNotNull(transaction); + transaction.changeStatus(TransactionStatus.SUBMITED); + val task = new TwoPhaseCommit(transaction, this); + return executor.submit(task); + } + +} + +package class DataChangeListenerRegistration

,D,DCL extends DataChangeListener> extends AbstractObjectRegistration implements ListenerRegistration { + + AbstractDataBroker dataBroker; + + @Property + val P path; + + new(P path, DCL instance, AbstractDataBroker broker) { + super(instance) + dataBroker = broker; + _path = path; + } + + override protected removeRegistration() { + dataBroker.removeListener(this); + dataBroker = null; + } + +} + +package class DataCommitHandlerRegistration

,D> +extends AbstractObjectRegistration> { + + AbstractDataBroker dataBroker; + + @Property + val P path; + + new(P path, DataCommitHandler instance, + AbstractDataBroker broker) { + super(instance) + dataBroker = broker; + _path = path; + } + + override protected removeRegistration() { + dataBroker.removeCommitHandler(this); + dataBroker = null; + } + +} + +package class TwoPhaseCommit

,D> implements Callable> { + + private static val log = LoggerFactory.getLogger(TwoPhaseCommit); + + val AbstractDataTransaction transaction; + val AbstractDataBroker dataBroker; + + new(AbstractDataTransaction transaction, AbstractDataBroker broker) { + this.transaction = transaction; + this.dataBroker = broker; + } + + override call() throws Exception { + + val Iterable> commitHandlers = dataBroker.activeCommitHandlers; + + // requesting commits + val List> handlerTransactions = new ArrayList(); + try { + for (handler : commitHandlers) { + handlerTransactions.add(handler.requestCommit(transaction)); + } + } catch (Exception e) { + log.error("Request Commit failded",e); + return rollback(handlerTransactions,e); + } + val List> results = new ArrayList(); + try { + for (subtransaction : handlerTransactions) { + results.add(subtransaction.finish()); + } + } catch (Exception e) { + log.error("Finish Commit failed",e); + return rollback(handlerTransactions,e); + } + + return Rpcs.getRpcResult(true, TransactionStatus.COMMITED, Collections.emptySet()); + } + + def rollback(List> transactions,Exception e) { + for (transaction : transactions) { + transaction.rollback() + } + // FIXME return encountered error. + return Rpcs.getRpcResult(false, TransactionStatus.FAILED, Collections.emptySet()); + } +} + +public abstract class AbstractDataTransaction

, D> extends AbstractDataModification { + + @Property + private val Object identifier; + + + var TransactionStatus status; + + + var AbstractDataBroker broker; + + protected new (AbstractDataBroker dataBroker) { + super(dataBroker); + _identifier = new Object(); + broker = dataBroker; + status = TransactionStatus.NEW; + //listeners = new ListenerRegistry<>(); + } + + override commit() { + return broker.commit(this); + } + + override readConfigurationData(P path) { + return broker.readConfigurationData(path); + } + + override readOperationalData(P path) { + return broker.readOperationalData(path); + } + + override hashCode() { + return identifier.hashCode; + } + + override equals(Object obj) { + if (this === obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + val other = (obj as AbstractDataTransaction) ; + if (broker == null) { + if (other.broker != null) + return false; + } else if (!broker.equals(other.broker)) + return false; + if (identifier == null) { + if (other.identifier != null) + return false; + } else if (!identifier.equals(other.identifier)) + return false; + return true; + } + + override TransactionStatus getStatus() { + return status; + } + + + protected abstract def void onStatusChange(TransactionStatus status); + + public def changeStatus(TransactionStatus status) { + this.status = status; + onStatusChange(status); + } + +} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerActivator.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerActivator.java index e49cb4bb0a..3af645a2b8 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerActivator.java +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/BrokerActivator.java @@ -8,6 +8,8 @@ import org.opendaylight.controller.sal.core.api.data.DataProviderService; import org.opendaylight.controller.sal.core.api.model.SchemaService; import org.opendaylight.controller.sal.core.api.mount.MountProvisionService; import org.opendaylight.controller.sal.core.api.mount.MountService; +import org.opendaylight.controller.sal.dom.broker.impl.HashMapDataStore; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; @@ -15,6 +17,7 @@ import org.osgi.framework.ServiceRegistration; public class BrokerActivator implements BundleActivator { + private static final InstanceIdentifier ROOT = InstanceIdentifier.builder().toInstance(); BrokerImpl broker; private ServiceRegistration brokerReg; private ServiceRegistration schemaReg; @@ -25,13 +28,14 @@ public class BrokerActivator implements BundleActivator { private MountPointManagerImpl mountService; private ServiceRegistration mountReg; private ServiceRegistration mountProviderReg; + private HashMapDataStore hashMapStore; @Override public void start(BundleContext context) throws Exception { Hashtable emptyProperties = new Hashtable(); broker = new BrokerImpl(); broker.setBundleContext(context); - brokerReg = context.registerService(Broker.class, broker, emptyProperties); + schemaService = new SchemaServiceImpl(); schemaService.setContext(context); @@ -40,14 +44,24 @@ public class BrokerActivator implements BundleActivator { schemaReg = context.registerService(SchemaService.class, schemaService, new Hashtable()); dataService = new DataBrokerImpl(); + dataService.setExecutor(broker.getExecutor()); + dataReg = context.registerService(DataBrokerService.class, dataService, emptyProperties); dataProviderReg = context.registerService(DataProviderService.class, dataService, emptyProperties); + hashMapStore = new HashMapDataStore(); + + dataService.registerConfigurationReader(ROOT, hashMapStore); + dataService.registerCommitHandler(ROOT, hashMapStore); + dataService.registerOperationalReader(ROOT, hashMapStore); + mountService = new MountPointManagerImpl(); mountService.setDataBroker(dataService); mountReg = context.registerService(MountService.class, mountService, emptyProperties); mountProviderReg = context.registerService(MountProvisionService.class, mountService, emptyProperties); + + brokerReg = context.registerService(Broker.class, broker, emptyProperties); } @Override diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java new file mode 100644 index 0000000000..d95fdcc53d --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.java @@ -0,0 +1,66 @@ +package org.opendaylight.controller.sal.dom.broker; + +import org.opendaylight.controller.md.sal.common.api.data.DataReader; +import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataBroker; +import org.opendaylight.controller.sal.common.DataStoreIdentifier; +import org.opendaylight.controller.sal.core.api.data.DataChangeListener; +import org.opendaylight.controller.sal.core.api.data.DataProviderService; +import org.opendaylight.controller.sal.core.api.data.DataValidator; +import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter; +import org.opendaylight.yangtools.concepts.Registration; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; + +public class DataBrokerImpl extends AbstractDataBroker implements + DataProviderService { + + public DataBrokerImpl() { + setDataReadRouter(new DataReaderRouter()); + } + + @Override + public DataTransactionImpl beginTransaction() { + return new DataTransactionImpl(this); + } + + @Override + public Registration> registerConfigurationReader( + InstanceIdentifier path, DataReader reader) { + return getDataReadRouter().registerConfigurationReader(path, reader); + } + + @Override + public Registration> registerOperationalReader( + InstanceIdentifier path, DataReader reader) { + return getDataReadRouter().registerOperationalReader(path, reader); + } + + @Deprecated + @Override + public void addValidator(DataStoreIdentifier store, DataValidator validator) { + // TODO Auto-generated method stub + + } + + @Deprecated + @Override + public void removeValidator(DataStoreIdentifier store, DataValidator validator) { + // TODO Auto-generated method stub + + } + + @Deprecated + @Override + public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) { + // TODO Auto-generated method stub + + } + + @Deprecated + @Override + public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) { + // TODO Auto-generated method stub + + } + +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.xtend deleted file mode 100644 index 8a17c83e6c..0000000000 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataBrokerImpl.xtend +++ /dev/null @@ -1,63 +0,0 @@ -package org.opendaylight.controller.sal.dom.broker - -import org.opendaylight.controller.sal.core.api.data.DataProviderService -import org.opendaylight.controller.sal.common.DataStoreIdentifier -import org.opendaylight.controller.sal.core.api.data.DataProviderService.DataRefresher -import org.opendaylight.controller.sal.core.api.data.DataValidator -import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier -import org.opendaylight.controller.sal.dom.broker.impl.DataReaderRouter -import org.opendaylight.controller.sal.core.api.data.DataChangeListener -import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler -import org.opendaylight.yangtools.yang.data.api.CompositeNode -import org.opendaylight.controller.md.sal.common.api.data.DataReader - -class DataBrokerImpl implements DataProviderService { - - val readRouter = new DataReaderRouter(); - - override addRefresher(DataStoreIdentifier store, DataRefresher refresher) { - // NOOP - } - - override addValidator(DataStoreIdentifier store, DataValidator validator) { - // NOOP - } - - override beginTransaction() { - // NOOP - } - - override readConfigurationData(InstanceIdentifier path) { - readRouter.readConfigurationData(path) - } - - override readOperationalData(InstanceIdentifier path) { - readRouter.readOperationalData(path) - } - - override registerConfigurationReader(InstanceIdentifier path, DataReader reader) { - readRouter.registerConfigurationReader(path, reader); - } - - override registerOperationalReader(InstanceIdentifier path, DataReader reader) { - readRouter.registerOperationalReader(path, reader); - } - - override removeRefresher(DataStoreIdentifier store, DataRefresher refresher) { - // NOOP - } - - override removeValidator(DataStoreIdentifier store, DataValidator validator) { - // NOOP - } - - override registerDataChangeListener(InstanceIdentifier path, DataChangeListener listener) { - // NOOP - } - - override registerCommitHandler(InstanceIdentifier path, - DataCommitHandler commitHandler) { - // NOOP - } - -} diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataTransactionImpl.java b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataTransactionImpl.java new file mode 100644 index 0000000000..5cb01c9a10 --- /dev/null +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/DataTransactionImpl.java @@ -0,0 +1,31 @@ +package org.opendaylight.controller.sal.dom.broker; + +import org.opendaylight.controller.md.sal.common.api.TransactionStatus; +import org.opendaylight.controller.md.sal.common.impl.service.AbstractDataTransaction; +import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.concepts.util.ListenerRegistry; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; + +public class DataTransactionImpl extends AbstractDataTransaction + implements DataModificationTransaction { + private final ListenerRegistry listeners = new ListenerRegistry(); + + + + public DataTransactionImpl(DataBrokerImpl dataBroker) { + super(dataBroker); + } + + @Override + public ListenerRegistration registerListener(DataTransactionListener listener) { + return listeners.register(listener); + } + + protected void onStatusChange(TransactionStatus status) { + for (ListenerRegistration listenerRegistration : listeners) { + listenerRegistration.getInstance().onStatusUpdated(this, status); + } + } +} \ No newline at end of file diff --git a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend index b0c61c920f..fbed2ca113 100644 --- a/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/DataReaderRouter.xtend @@ -8,7 +8,11 @@ import org.opendaylight.controller.md.sal.common.api.data.DataReader class DataReaderRouter extends AbstractDataReadRouter { override protected merge(InstanceIdentifier path, Iterable data) { - return data.iterator.next + val iterator = data.iterator; + if(iterator.hasNext) { + return data.iterator.next + } + return null; } } diff --git a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/HashMapDataStore.xtend b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend similarity index 52% rename from opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/HashMapDataStore.xtend rename to opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend index 2356468f5b..404842c1dc 100644 --- a/opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/sal/binding/impl/HashMapDataStore.xtend +++ b/opendaylight/md-sal/sal-dom-broker/src/main/java/org/opendaylight/controller/sal/dom/broker/impl/HashMapDataStore.xtend @@ -1,10 +1,7 @@ -package org.opendaylight.controller.sal.binding.impl +package org.opendaylight.controller.sal.dom.broker.impl import org.opendaylight.controller.md.sal.common.api.data.DataReader -import org.opendaylight.controller.sal.binding.api.data.RuntimeDataProvider import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler -import org.opendaylight.yangtools.yang.binding.InstanceIdentifier -import org.opendaylight.yangtools.yang.binding.DataObject import org.opendaylight.controller.md.sal.common.api.data.DataModification import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler.DataCommitTransaction import org.opendaylight.yangtools.yang.common.RpcResult @@ -12,58 +9,58 @@ import java.util.Map import java.util.concurrent.ConcurrentHashMap import org.opendaylight.controller.sal.common.util.Rpcs import java.util.Collections +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier +import org.opendaylight.yangtools.yang.data.api.CompositeNode class HashMapDataStore // implements // -RuntimeDataProvider, DataCommitHandler, DataObject> { +DataReader, DataCommitHandler { - val Map,DataObject> configuration = new ConcurrentHashMap(); - val Map,DataObject> operational = new ConcurrentHashMap(); + val Map configuration = new ConcurrentHashMap(); + val Map operational = new ConcurrentHashMap(); - - override readConfigurationData(InstanceIdentifier path) { + override readConfigurationData(InstanceIdentifier path) { configuration.get(path); } - override readOperationalData(InstanceIdentifier path) { + override readOperationalData(InstanceIdentifier path) { operational.get(path); } - override requestCommit(DataModification, DataObject> modification) { - return new HashMapDataStoreTransaction(modification,this); + override requestCommit(DataModification modification) { + return new HashMapDataStoreTransaction(modification, this); } - + def RpcResult rollback(HashMapDataStoreTransaction transaction) { - return Rpcs.getRpcResult(true,null,Collections.emptySet); + return Rpcs.getRpcResult(true, null, Collections.emptySet); } - + def RpcResult finish(HashMapDataStoreTransaction transaction) { val modification = transaction.modification; configuration.putAll(modification.updatedConfigurationData); operational.putAll(modification.updatedOperationalData); - - for(removal : modification.removedConfigurationData) { + + for (removal : modification.removedConfigurationData) { configuration.remove(removal); } - for(removal : modification.removedOperationalData) { + for (removal : modification.removedOperationalData) { operational.remove(removal); } - return Rpcs.getRpcResult(true,null,Collections.emptySet); + return Rpcs.getRpcResult(true, null, Collections.emptySet); } } class HashMapDataStoreTransaction implements // -DataCommitTransaction, DataObject> { +DataCommitTransaction { @Property - val DataModification, DataObject> modification + val DataModification modification @Property val HashMapDataStore datastore; - - + new( - DataModification, DataObject> modify, + DataModification modify, HashMapDataStore store ) { _modification = modify; diff --git a/opendaylight/md-sal/samples/toaster-it/pom.xml b/opendaylight/md-sal/samples/toaster-it/pom.xml index 6f53bcd2c4..a1925a53b5 100644 --- a/opendaylight/md-sal/samples/toaster-it/pom.xml +++ b/opendaylight/md-sal/samples/toaster-it/pom.xml @@ -167,5 +167,10 @@ logback-classic 1.0.9 + + org.opendaylight.yangtools.thirdparty + antlr4-runtime-osgi-nohead + 4.0 + diff --git a/opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java b/opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java index 7cd4fa52c6..337648ab03 100644 --- a/opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java +++ b/opendaylight/md-sal/samples/toaster-it/src/test/java/org/opendaylight/controller/sample/toaster/it/ToasterTest.java @@ -23,6 +23,10 @@ public class ToasterTest { public static final String ODL = "org.opendaylight.controller"; public static final String YANG = "org.opendaylight.yangtools"; + public static final String CONTROLLER = "org.opendaylight.controller"; + public static final String YANGTOOLS = "org.opendaylight.yangtools"; + + public static final String SAMPLE = "org.opendaylight.controller.samples"; @Test @@ -50,9 +54,6 @@ public class ToasterTest { mavenBundle("org.slf4j", "log4j-over-slf4j").versionAsInProject(), // mavenBundle("ch.qos.logback", "logback-core").versionAsInProject(), // mavenBundle("ch.qos.logback", "logback-classic").versionAsInProject(), // - mavenBundle(ODL, "sal-binding-api").versionAsInProject(), // - mavenBundle(ODL, "sal-binding-config").versionAsInProject(), - mavenBundle(ODL, "sal-binding-broker-impl").versionAsInProject(), // mavenBundle(ODL, "sal-common").versionAsInProject(), // mavenBundle(ODL, "sal-common-api").versionAsInProject(),// @@ -62,7 +63,37 @@ public class ToasterTest { mavenBundle(ODL, "config-api").versionAsInProject(), // mavenBundle(ODL, "config-manager").versionAsInProject(), // mavenBundle("commons-io", "commons-io").versionAsInProject(), + mavenBundle("org.apache.commons", "commons-lang3").versionAsInProject(), + mavenBundle(CONTROLLER, "sal-binding-api").versionAsInProject(), // + mavenBundle(CONTROLLER, "sal-binding-config").versionAsInProject(), + mavenBundle(CONTROLLER, "sal-binding-broker-impl").versionAsInProject(), // + mavenBundle("org.javassist", "javassist").versionAsInProject(), // + mavenBundle(CONTROLLER, "sal-common-util").versionAsInProject(), // + + mavenBundle(YANGTOOLS, "yang-data-api").versionAsInProject(), // + mavenBundle(YANGTOOLS, "yang-data-impl").versionAsInProject(), // + mavenBundle(YANGTOOLS, "yang-model-api").versionAsInProject(), // + mavenBundle(YANGTOOLS, "yang-model-util").versionAsInProject(), // + mavenBundle(YANGTOOLS, "yang-parser-api").versionAsInProject(), + mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(), + + + mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(), // + mavenBundle(YANGTOOLS, "binding-model-api").versionAsInProject(), // + mavenBundle(YANGTOOLS, "binding-generator-util").versionAsInProject(), + mavenBundle(YANGTOOLS, "yang-parser-impl").versionAsInProject(), + mavenBundle(YANGTOOLS, "binding-type-provider").versionAsInProject(), + mavenBundle(YANGTOOLS, "binding-generator-api").versionAsInProject(), + mavenBundle(YANGTOOLS, "binding-generator-spi").versionAsInProject(), + mavenBundle(YANGTOOLS, "binding-generator-impl").versionAsInProject(), + + + mavenBundle(CONTROLLER, "sal-core-api").versionAsInProject().update(), // + mavenBundle(CONTROLLER, "sal-broker-impl").versionAsInProject(), // + mavenBundle(CONTROLLER, "sal-core-spi").versionAsInProject().update(), // + + mavenBundle(YANGTOOLS + ".thirdparty", "antlr4-runtime-osgi-nohead").versionAsInProject(), // mavenBundle(SAMPLE, "sample-toaster").versionAsInProject(), // mavenBundle(SAMPLE, "sample-toaster-consumer").versionAsInProject(), //