import javax.management.ObjectName;
import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.yangtools.concepts.Identifiable;
/**
* Each new {@link org.opendaylight.controller.config.spi.Module} can receive
*
* @see org.opendaylight.controller.config.spi.Module
*/
-public interface DependencyResolver {
+public interface DependencyResolver extends Identifiable<ModuleIdentifier> {
/**
* To be used during validation phase to validate serice interface of
for (ModuleFactory moduleFactory : toBeAdded) {
Set<? extends Module> defaultModules = moduleFactory.getDefaultModules(dependencyResolverManager, bundleContext);
for (Module module : defaultModules) {
+ // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
+ DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(module.getIdentifier());
try {
- putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null);
+ putConfigBeanToJMXAndInternalMaps(module.getIdentifier(), module, moduleFactory, null, dependencyResolver);
} catch (InstanceAlreadyExistsException e) {
throw new IllegalStateException(e);
}
"Error while copying old configuration from %s to %s",
oldConfigBeanInfo, moduleFactory), e);
}
- putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo);
+ putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module, moduleFactory, oldConfigBeanInfo, dependencyResolver);
}
@Override
DependencyResolver dependencyResolver = dependencyResolverManager.getOrCreate(moduleIdentifier);
Module module = moduleFactory.createModule(instanceName, dependencyResolver, bundleContext);
return putConfigBeanToJMXAndInternalMaps(moduleIdentifier, module,
- moduleFactory, null);
+ moduleFactory, null, dependencyResolver);
}
private synchronized ObjectName putConfigBeanToJMXAndInternalMaps(
ModuleIdentifier moduleIdentifier, Module module,
ModuleFactory moduleFactory,
- @Nullable ModuleInternalInfo maybeOldConfigBeanInfo)
+ @Nullable ModuleInternalInfo maybeOldConfigBeanInfo, DependencyResolver dependencyResolver)
throws InstanceAlreadyExistsException {
+
logger.debug("Adding module {} to transaction {}", moduleIdentifier, this);
if (moduleIdentifier.equals(module.getIdentifier())==false) {
throw new IllegalStateException("Incorrect name reported by module. Expected "
+ moduleIdentifier + ", got " + module.getIdentifier());
}
+ if (dependencyResolver.getIdentifier().equals(moduleIdentifier) == false ) {
+ throw new IllegalStateException("Incorrect name reported by dependency resolver. Expected "
+ + moduleIdentifier + ", got " + dependencyResolver.getIdentifier());
+ }
DynamicMBean writableDynamicWrapper = new DynamicWritableWrapper(
module, moduleIdentifier, transactionIdentifier,
readOnlyAtomicBoolean, transactionsMBeanServer,
maybeOldConfigBeanInfo, transactionModuleJMXRegistration);
dependencyResolverManager.put(moduleInternalTransactionalInfo);
- // ensure default module to be registered to jmx even if its module factory does not use dependencyResolverFactory
- dependencyResolverManager.getOrCreate(moduleIdentifier);
return writableON;
}
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
-import static java.lang.String.format;
-
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.ObjectName;
-
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.JmxAttributeValidationException;
import org.opendaylight.controller.config.manager.impl.TransactionStatus;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
-import org.opendaylight.yangtools.concepts.Identifiable;
+
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.ObjectName;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static java.lang.String.format;
/**
* Protect {@link org.opendaylight.controller.config.spi.Module#getInstance()}
* during validation. Tracks dependencies for ordering purposes.
*/
final class DependencyResolverImpl implements DependencyResolver,
- Identifiable<ModuleIdentifier>, Comparable<DependencyResolverImpl> {
+ Comparable<DependencyResolverImpl> {
private final ModulesHolder modulesHolder;
private final ModuleIdentifier name;
private final TransactionStatus transactionStatus;
this.modulesHolder = modulesHolder;
}
- @Deprecated
- public ModuleIdentifier getName() {
- return name;
- }
-
/**
* {@inheritDoc}
*/
int maxDepth = 0;
LinkedHashSet<ModuleIdentifier> chainForDetectingCycles2 = new LinkedHashSet<>(
chainForDetectingCycles);
- chainForDetectingCycles2.add(impl.getName());
+ chainForDetectingCycles2.add(impl.getIdentifier());
for (ModuleIdentifier dependencyName : impl.dependencies) {
DependencyResolverImpl dependentDRI = manager
.getOrCreate(dependencyName);
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.InstanceAlreadyExistsException;
-
import org.opendaylight.controller.config.api.DependencyResolver;
import org.opendaylight.controller.config.api.DependencyResolverFactory;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* Holds information about modules being created and destroyed within this
* transaction. Observes usage of DependencyResolver within modules to figure
List<ModuleIdentifier> result = new ArrayList<>(
moduleIdentifiersToDependencyResolverMap.size());
for (DependencyResolverImpl dri : getAllSorted()) {
- ModuleIdentifier driName = dri.getName();
+ ModuleIdentifier driName = dri.getIdentifier();
result.add(driName);
}
return result;
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.annotation.concurrent.GuardedBy;
-import javax.management.InstanceAlreadyExistsException;
-
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.JmxAttributeValidationException;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
+import javax.annotation.concurrent.GuardedBy;
+import javax.management.InstanceAlreadyExistsException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
/**
* Represents modules to be committed.
*/
throws InstanceAlreadyExistsException {
if (commitMap.containsKey(moduleIdentifier)) {
throw new InstanceAlreadyExistsException(
- "There is an instance registered with name "
- + moduleIdentifier);
+ "There is an instance registered with name " + moduleIdentifier);
}
}
*/
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
-import java.util.Map;
-
-import javax.management.InstanceAlreadyExistsException;
-
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.manager.impl.CommitInfo;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
+import javax.management.InstanceAlreadyExistsException;
+import java.util.Map;
+
interface TransactionHolder {
CommitInfo toCommitInfo();
<Import-Package>
org.opendaylight.controller.sal.binding.api,
org.opendaylight.controller.sal.binding.api.data,
- org.opendaylight.controller.md.sal.common.api.data,
- org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev130819.flow,
+ org.opendaylight.controller.md.sal.common.api.data,
+ org.opendaylight.controller.sal.utils,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket,
org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819,
+ org.opendaylight.controller.clustering.services, org.opendaylight.controller.sal.core,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction,
+ org.opendaylight.controller.switchmanager,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list,
+ org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024,
org.opendaylight.yangtools.concepts,
org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819,
org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819,
package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
+import org.eclipse.osgi.framework.console.CommandProvider;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
import org.opendaylight.controller.sal.binding.api.NotificationService;
import org.opendaylight.controller.sal.binding.api.data.DataBrokerService;
import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public class FRMConsumerImpl extends AbstractBindingAwareProvider {
+public class FRMConsumerImpl extends AbstractBindingAwareProvider implements CommandProvider{
protected static final Logger logger = LoggerFactory.getLogger(FRMConsumerImpl.class);
private static ProviderContext p_session;
private static DataBrokerService dataBrokerService;
private GroupConsumerImpl groupImplRef;
private static DataProviderService dataProviderService;
+ private static IClusterContainerServices clusterContainerService = null;
+ private static ISwitchManager switchManager;
+ private static IContainer container;
+
@Override
public void onSessionInitiated(ProviderContext session) {
FRMConsumerImpl.p_session = session;
+ if (!getDependentModule()) {
+ logger.error("Unable to fetch handlers for dependent modules");
+ System.out.println("Unable to fetch handlers for dependent modules");
+ return;
+ }
+
if (null != session) {
notificationService = session.getSALService(NotificationService.class);
if (null != dataProviderService) {
flowImplRef = new FlowConsumerImpl();
- groupImplRef = new GroupConsumerImpl();
+ // groupImplRef = new GroupConsumerImpl();
+ registerWithOSGIConsole();
}
else {
logger.error("Data Provider Service is down or NULL. " +
System.out.println("Consumer session is NULL. Please check if provider is registered");
}
+ }
+
+ public static IClusterContainerServices getClusterContainerService() {
+ return clusterContainerService;
+ }
+
+ public static void setClusterContainerService(
+ IClusterContainerServices clusterContainerService) {
+ FRMConsumerImpl.clusterContainerService = clusterContainerService;
+ }
+
+ public static ISwitchManager getSwitchManager() {
+ return switchManager;
+ }
+
+ public static void setSwitchManager(ISwitchManager switchManager) {
+ FRMConsumerImpl.switchManager = switchManager;
+ }
+
+ public static IContainer getContainer() {
+ return container;
}
- public static DataProviderService getDataProviderService() {
+ public static void setContainer(IContainer container) {
+ FRMConsumerImpl.container = container;
+ }
+
+ private void registerWithOSGIConsole() {
+ BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+ bundleContext.registerService(CommandProvider.class.getName(), this, null);
+ }
+
+ private boolean getDependentModule() {
+ do {
+ clusterContainerService = (IClusterContainerServices) ServiceHelper.getGlobalInstance(IClusterContainerServices.class, this);
+ try {
+ Thread.sleep(4);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } while(clusterContainerService == null);
+
+ do {
+
+
+ container = (IContainer) ServiceHelper.getGlobalInstance(IContainer.class, this);
+ try {
+ Thread.sleep(5);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } while (container == null);
+
+ do {
+ switchManager = (ISwitchManager) ServiceHelper.getInstance(ISwitchManager.class, container.getName(), this);
+ try {
+ Thread.sleep(5);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } while(null == switchManager);
+ return true;
+ }
+
+
+
+ public static DataProviderService getDataProviderService() {
return dataProviderService;
}
public FlowConsumerImpl getFlowImplRef() {
- return flowImplRef;
+ return flowImplRef;
}
public GroupConsumerImpl getGroupImplRef() {
- return groupImplRef;
+ return groupImplRef;
}
public static ProviderContext getProviderSession() {
public static DataBrokerService getDataBrokerService() {
return dataBrokerService;
}
+
+ /*
+ * OSGI COMMANDS
+ */
+ @Override
+ public String getHelp() {
+ StringBuffer help = new StringBuffer();
+ return help.toString();
+ }
}
--- /dev/null
+package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.bucket.Actions;
+
+public class FRMUtil {
+ private static final String NAMEREGEX = "^[a-zA-Z0-9]+$";
+ public enum operation {ADD, DELETE, UPDATE, GET};
+
+
+ public static boolean isNameValid(String name) {
+
+ // Name validation
+ if (name == null || name.trim().isEmpty() || !name.matches(NAMEREGEX)) {
+ return false;
+ }
+ return true;
+
+ }
+
+ public static boolean areActionsValid(Actions actions) {
+ // List<Action> actionList;
+ // Action actionRef;
+ // if (null != actions && null != actions.getAction()) {
+ // actionList = actions.getAction();
+
+
+
+
+ // }
+
+ return true;
+ }
+}
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.Flows;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.config.rev130819.flows.Flow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInput;
+
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowInputBuilder;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.NodeFlow;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowListener;
import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
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;
}
listener = new FlowDataListener();
+
if (null == FRMConsumerImpl.getDataBrokerService().registerDataChangeListener(path, listener)) {
logger.error("Failed to listen on flow data modifcation events");
System.out.println("Consumer SAL Service is down or NULL.");
System.out.println("Consumer SAL Service is down or NULL.");
return;
}
- addFlowTest();
+ //addFlowTest();
System.out.println("-------------------------------------------------------------------");
allocateCaches();
commitHandler = new FlowDataCommitHandler();
private void addFlow(InstanceIdentifier<?> path, Flow dataObject) {
AddFlowInputBuilder input = new AddFlowInputBuilder();
+ List<Instruction> inst = (dataObject).getInstructions().getInstruction();
input.setNode((dataObject).getNode());
input.setPriority((dataObject).getPriority());
input.setMatch((dataObject).getMatch());
input.setCookie((dataObject).getCookie());
- input.setAction((dataObject).getAction());
+ input.setInstructions((dataObject).getInstructions());
+ dataObject.getMatch().getLayer3Match()
+ for (int i=0;i<inst.size();i++) {
+ System.out.println("i = "+ i + inst.get(i).getInstruction().toString());
+ System.out.println("i = "+ i + inst.get(i).toString());
+ }
+
+ System.out.println("Instruction list" + (dataObject).getInstructions().getInstruction().toString());
// We send flow to the sounthbound plugin
flowService.addFlow(input.build());
private void commitToPlugin(internalTransaction transaction) {
for(Entry<InstanceIdentifier<?>, Flow> entry :transaction.additions.entrySet()) {
+ System.out.println("Coming add cc in FlowDatacommitHandler");
addFlow(entry.getKey(),entry.getValue());
}
- for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Flow> entry :transaction.additions.entrySet()) {
+ for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Flow> entry :transaction.updates.entrySet()) {
+ System.out.println("Coming update cc in FlowDatacommitHandler");
// updateFlow(entry.getKey(),entry.getValue());
}
Flow original = originalSwView.get(key);
if (original != null) {
// It is update for us
+ System.out.println("Coming update in FlowDatacommitHandler");
updates.put(key, flow);
} else {
// It is addition for us
+ System.out.println("Coming add in FlowDatacommitHandler");
additions.put(key, flow);
}
}
for (DataObject dataObject : additions) {
if (dataObject instanceof NodeFlow) {
NodeRef nodeOne = createNodeRef("foo:node:1");
- // validating the dataObject here
+ // validating the dataObject here
AddFlowInputBuilder input = new AddFlowInputBuilder();
input.setNode(((NodeFlow) dataObject).getNode());
input.setNode(nodeOne);
return new NodeRef(path);
}
- /* private void loadFlowData() {
- DataModification modification = (DataModification) dataservice.beginTransaction();
- String id = "abc";
- FlowKey key = new FlowKey(id, new NodeRef());
- InstanceIdentifier<?> path1;
- FlowBuilder flow = new FlowBuilder();
- flow.setKey(key);
- path1 = InstanceIdentifier.builder().node(Flows.class).node(Flow.class, key).toInstance();
- DataObject cls = (DataObject) modification.readConfigurationData(path);
- modification.putConfigurationData(path, flow.build());
- modification.commit();
- }*/
}
package org.opendaylight.controller.forwardingrulesmanager_mdsal.consumer.impl;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+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.DataCommitHandler.DataCommitTransaction;
+import org.opendaylight.controller.sal.common.util.Rpcs;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.Groups;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.config.rev131024.groups.GroupKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.AddGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.GroupUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.UpdateGroupInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes.GroupType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("unused")
public class GroupConsumerImpl {
- public GroupConsumerImpl() {
-
+
+ protected static final Logger logger = LoggerFactory.getLogger(GroupConsumerImpl.class);
+ private GroupEventListener groupEventListener = new GroupEventListener();
+ private Registration<NotificationListener> groupListener;
+ private SalGroupService groupService;
+ private GroupDataCommitHandler commitHandler;
+
+ private ConcurrentMap<GroupKey, Group> originalSwGroupView;
+ private ConcurrentMap<GroupKey, Group> installedSwGroupView;
+
+ private ConcurrentMap<Node, List<Group>> nodeGroups;
+ private ConcurrentMap<GroupKey, Group> inactiveGroups;
+
+ private IClusterContainerServices clusterGroupContainerService = null;
+ private ISwitchManager switchGroupManager;
+ private IContainer container;
+
+ public GroupConsumerImpl() {
+ InstanceIdentifier<? extends DataObject> path = InstanceIdentifier.builder().node(Groups.class).toInstance();
+ groupService = FRMConsumerImpl.getProviderSession().getRpcService(SalGroupService.class);
+
+ clusterGroupContainerService = FRMConsumerImpl.getClusterContainerService();
+ switchGroupManager = FRMConsumerImpl.getSwitchManager();
+ container = FRMConsumerImpl.getContainer();
+
+ if (!(cacheStartup())) {
+ logger.error("Unanle to allocate/retrieve group cache");
+ System.out.println("Unable to allocate/retrieve group cache");
+ }
+
+ if (null == groupService) {
+ logger.error("Consumer SAL Group Service is down or NULL. FRM may not function as intended");
+ System.out.println("Consumer SAL Group Service is down or NULL.");
+ return;
+ }
+
+ // For switch events
+ groupListener = FRMConsumerImpl.getNotificationService().registerNotificationListener(groupEventListener);
+
+ if (null == groupListener) {
+ logger.error("Listener to listen on group data modifcation events");
+ System.out.println("Listener to listen on group data modifcation events.");
+ return;
+ }
+
+ commitHandler = new GroupDataCommitHandler();
+ FRMConsumerImpl.getDataProviderService().registerCommitHandler(path, commitHandler);
}
+
+ private boolean allocateGroupCaches() {
+ if (this.clusterGroupContainerService == null) {
+ logger.warn("Group: Un-initialized clusterGroupContainerService, can't create cache");
+ return false;
+ }
+
+ try {
+ clusterGroupContainerService.createCache("frm.originalSwGroupView",
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+ clusterGroupContainerService.createCache("frm.installedSwGroupView",
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+ clusterGroupContainerService.createCache("frm.inactiveGroups",
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+ clusterGroupContainerService.createCache("frm.nodeGroups",
+ EnumSet.of(IClusterServices.cacheMode.TRANSACTIONAL));
+
+//TODO for cluster mode
+ /* clusterGroupContainerService.createCache(WORK_STATUS_CACHE,
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));
+
+ clusterGroupContainerService.createCache(WORK_ORDER_CACHE,
+ EnumSet.of(IClusterServices.cacheMode.NON_TRANSACTIONAL, IClusterServices.cacheMode.ASYNC));*/
+
+ } catch (CacheConfigException cce) {
+ logger.error("Group CacheConfigException");
+ return false;
+
+ } catch (CacheExistException cce) {
+ logger.error(" Group CacheExistException");
+ }
+
+ return true;
+ }
+
+ private void nonClusterGroupObjectCreate() {
+ originalSwGroupView = new ConcurrentHashMap<GroupKey, Group>();
+ installedSwGroupView = new ConcurrentHashMap<GroupKey, Group>();
+ nodeGroups = new ConcurrentHashMap<Node, List<Group>>();
+ inactiveGroups = new ConcurrentHashMap<GroupKey, Group>();
+ }
+
+ @SuppressWarnings({ "unchecked" })
+ private boolean retrieveGroupCaches() {
+ ConcurrentMap<?, ?> map;
+
+ if (this.clusterGroupContainerService == null) {
+ logger.warn("Group: un-initialized clusterGroupContainerService, can't retrieve cache");
+ nonClusterGroupObjectCreate();
+ return false;
+ }
+
+ map = clusterGroupContainerService.getCache("frm.originalSwGroupView");
+ if (map != null) {
+ originalSwGroupView = (ConcurrentMap<GroupKey, Group>) map;
+ } else {
+ logger.error("Retrieval of cache(originalSwGroupView) failed");
+ return false;
+ }
+
+ map = clusterGroupContainerService.getCache("frm.installedSwGroupView");
+ if (map != null) {
+ installedSwGroupView = (ConcurrentMap<GroupKey, Group>) map;
+ } else {
+ logger.error("Retrieval of cache(installedSwGroupView) failed");
+ return false;
+ }
+
+ map = clusterGroupContainerService.getCache("frm.inactiveGroups");
+ if (map != null) {
+ inactiveGroups = (ConcurrentMap<GroupKey, Group>) map;
+ } else {
+ logger.error("Retrieval of cache(inactiveGroups) failed");
+ return false;
+ }
+
+ map = clusterGroupContainerService.getCache("frm.nodeGroups");
+ if (map != null) {
+ nodeGroups = (ConcurrentMap<Node, List<Group>>) map;
+ } else {
+ logger.error("Retrieval of cache(nodeGroup) failed");
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean cacheStartup() {
+ if (allocateGroupCaches()) {
+ if (retrieveGroupCaches()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public Status validateGroup(Group group, FRMUtil.operation operation) {
+ String containerName;
+ String groupName;
+ Iterator<Bucket> bucketIterator;
+ boolean returnResult;
+ Buckets groupBuckets;
+
+ if (null != group) {
+ containerName = group.getContainerName();
+
+ if (null == containerName) {
+ containerName = GlobalConstants.DEFAULT.toString();
+ }
+ else if (!FRMUtil.isNameValid(containerName)) {
+ logger.error("Container Name is invalid %s" + containerName);
+ return new Status(StatusCode.BADREQUEST, "Container Name is invalid");
+ }
+
+ groupName = group.getGroupName();
+ if (!FRMUtil.isNameValid(groupName)) {
+ logger.error("Group Name is invalid %s" + groupName);
+ return new Status(StatusCode.BADREQUEST, "Group Name is invalid");
+ }
+
+ returnResult = doesGroupEntryExists(group.getKey(), groupName, containerName);
+
+ if (FRMUtil.operation.ADD == operation && returnResult) {
+ logger.error("Record with same Group Name exists");
+ return new Status(StatusCode.BADREQUEST, "Group record exists");
+ }
+ else if (!returnResult) {
+ logger.error("Group record does not exist");
+ return new Status(StatusCode.BADREQUEST, "Group record does not exist");
+ }
+
+ if (!(group.getGroupType().getIntValue() >= GroupType.GroupAll.getIntValue() &&
+ group.getGroupType().getIntValue() <= GroupType.GroupFf.getIntValue())) {
+ logger.error("Invalid Group type %d" + group.getGroupType().getIntValue());
+ return new Status(StatusCode.BADREQUEST, "Invalid Group type");
+ }
+
+ groupBuckets = group.getBuckets();
+
+ if (null != groupBuckets && null != groupBuckets.getBucket()) {
+ bucketIterator = groupBuckets.getBucket().iterator();
+
+ while (bucketIterator.hasNext()) {
+ if(!(FRMUtil.areActionsValid(bucketIterator.next().getActions()))) {
+ logger.error("Error in action bucket");
+ return new Status(StatusCode.BADREQUEST, "Invalid Group bucket contents");
+ }
+ }
+ }
+ }
+
+ return new Status(StatusCode.SUCCESS);
+
+ }
+
+ private boolean doesGroupEntryExists(GroupKey key, String groupName, String containerName) {
+ if (! originalSwGroupView.containsKey(key)) {
+ return false;
+ }
+
+ for (ConcurrentMap.Entry<GroupKey, Group> entry : originalSwGroupView.entrySet()) {
+ if (entry.getValue().getGroupName().equals(groupName)) {
+ if (entry.getValue().getContainerName().equals(containerName)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Update Group entries to the southbound plugin/inventory and our internal database
+ *
+ * @param path
+ * @param dataObject
+ */
+ private Status updateGroup(InstanceIdentifier<?> path, Group groupUpdateDataObject) {
+ GroupKey groupKey = groupUpdateDataObject.getKey();
+ Status groupOperationStatus = validateGroup(groupUpdateDataObject, FRMUtil.operation.UPDATE);
+
+ if (!groupOperationStatus.isSuccess()) {
+ logger.error("Group data object validation failed %s" + groupUpdateDataObject.getGroupName());
+ return groupOperationStatus;
+ }
+
+ originalSwGroupView.remove(groupKey);
+ originalSwGroupView.put(groupKey, groupUpdateDataObject);
+
+ if (groupUpdateDataObject.isInstall()) {
+ UpdateGroupInputBuilder groupData = new UpdateGroupInputBuilder();
+ //TODO how to get original group and modified group.
+
+ if (installedSwGroupView.containsKey(groupKey)) {
+ installedSwGroupView.remove(groupKey);
+ }
+
+ installedSwGroupView.put(groupKey, groupUpdateDataObject);
+ groupService.updateGroup(groupData.build());
+ }
+
+ return groupOperationStatus;
+ }
+
+ /**
+ * Adds Group to the southbound plugin and our internal database
+ *
+ * @param path
+ * @param dataObject
+ */
+ private Status addGroup(InstanceIdentifier<?> path, Group groupAddDataObject) {
+ GroupKey groupKey = groupAddDataObject.getKey();
+ Status groupOperationStatus = validateGroup(groupAddDataObject, FRMUtil.operation.ADD);
+
+ if (!groupOperationStatus.isSuccess()) {
+ logger.error("Group data object validation failed %s" + groupAddDataObject.getGroupName());
+ return groupOperationStatus;
+ }
+ validateGroup(groupAddDataObject, FRMUtil.operation.ADD);
+ originalSwGroupView.put(groupKey, groupAddDataObject);
+
+ if (groupAddDataObject.isInstall()) {
+ AddGroupInputBuilder groupData = new AddGroupInputBuilder();
+ groupData.setBuckets(groupAddDataObject.getBuckets());
+ groupData.setContainerName(groupAddDataObject.getContainerName());
+ groupData.setGroupId(groupAddDataObject.getGroupId());
+ groupData.setGroupType(groupAddDataObject.getGroupType());
+ groupData.setNode(groupAddDataObject.getNode());
+ installedSwGroupView.put(groupKey, groupAddDataObject);
+ groupService.addGroup(groupData.build());
+ }
+
+ return groupOperationStatus;
+ }
+
+ private RpcResult<Void> commitToPlugin(internalTransaction transaction) {
+ for(Entry<InstanceIdentifier<?>, Group> entry :transaction.additions.entrySet()) {
+
+ if (!addGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+ return Rpcs.getRpcResult(false, null, null);
+ }
+ }
+ for(@SuppressWarnings("unused") Entry<InstanceIdentifier<?>, Group> entry :transaction.additions.entrySet()) {
+
+ if (!updateGroup(entry.getKey(),entry.getValue()).isSuccess()) {
+ return Rpcs.getRpcResult(false, null, null);
+ }
+ }
+
+ for(InstanceIdentifier<?> removal : transaction.removals) {
+ // removeFlow(removal);
+ }
+
+ return Rpcs.getRpcResult(true, null, null);
+ }
+
+ private final class GroupDataCommitHandler implements DataCommitHandler<InstanceIdentifier<?>, DataObject> {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public DataCommitTransaction requestCommit(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+ // We should verify transaction
+ System.out.println("Coming in FlowDatacommitHandler");
+ internalTransaction transaction = new internalTransaction(modification);
+ transaction.prepareUpdate();
+ return transaction;
+ }
+ }
+
+ private final class internalTransaction implements DataCommitTransaction<InstanceIdentifier<?>, DataObject> {
+
+ private final DataModification<InstanceIdentifier<?>, DataObject> modification;
+
+ @Override
+ public DataModification<InstanceIdentifier<?>, DataObject> getModification() {
+ return modification;
+ }
+
+ public internalTransaction(DataModification<InstanceIdentifier<?>, DataObject> modification) {
+ this.modification = modification;
+ }
+
+ Map<InstanceIdentifier<?>, Group> additions = new HashMap<>();
+ Map<InstanceIdentifier<?>, Group> updates = new HashMap<>();
+ Set<InstanceIdentifier<?>> removals = new HashSet<>();
+
+ /**
+ * We create a plan which flows will be added, which will be updated and
+ * which will be removed based on our internal state.
+ *
+ */
+ void prepareUpdate() {
+
+ Set<Entry<InstanceIdentifier<?>, DataObject>> puts = modification.getUpdatedConfigurationData().entrySet();
+ for (Entry<InstanceIdentifier<?>, DataObject> entry : puts) {
+ if (entry.getValue() instanceof Group) {
+ Group group = (Group) entry.getValue();
+ preparePutEntry(entry.getKey(), group);
+ }
+
+ }
+
+ removals = modification.getRemovedConfigurationData();
+ }
+
+ private void preparePutEntry(InstanceIdentifier<?> key, Group group) {
+
+ Group original = originalSwGroupView.get(key);
+ if (original != null) {
+ // It is update for us
+
+ updates.put(key, group);
+ } else {
+ // It is addition for us
+
+ additions.put(key, group);
+ }
+ }
+
+ /**
+ * We are OK to go with execution of plan
+ *
+ */
+ @Override
+ public RpcResult<Void> finish() throws IllegalStateException {
+
+ RpcResult<Void> rpcStatus = commitToPlugin(this);
+ // We return true if internal transaction is successful.
+ // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+ return rpcStatus;
+ }
+
+ /**
+ *
+ * We should rollback our preparation
+ *
+ */
+ @Override
+ public RpcResult<Void> rollback() throws IllegalStateException {
+ // NOOP - we did not modified any internal state during
+ // requestCommit phase
+ // return Rpcs.getRpcResult(true, null, Collections.emptySet());
+ return Rpcs.getRpcResult(true, null, null);
+
+ }
+
+ }
+
+
+ final class GroupEventListener implements SalGroupListener {
+
+ List<GroupAdded> addedGroups = new ArrayList<>();
+ List<GroupRemoved> removedGroups = new ArrayList<>();
+ List<GroupUpdated> updatedGroups = new ArrayList<>();
+
+
+ @Override
+ public void onGroupAdded(GroupAdded notification) {
+ System.out.println("added Group..........................");
+ addedGroups.add(notification);
+ }
+
+ @Override
+ public void onGroupRemoved(GroupRemoved notification) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onGroupUpdated(GroupUpdated notification) {
+ // TODO Auto-generated method stub
+
+ }
+ }
}
type string;
}
+ leaf barrier {
+ type boolean;
+ }
+
container buckets {
list bucket {
key "order";
type meter-id;
}
+ leaf install {
+ type boolean;
+ }
+ leaf meter-name {
+ type string;
+ }
+
+ leaf container-name {
+ type string;
+ }
+
container meter-band-headers {
list meter-band-header {
key "order";
}
typedef port-state {
- type enumeration {
- enum link-down;
- enum blocked;
- enum live;
+ type enumeration {
+ enum link-down;
+ enum blocked;
+ enum live;
}
}
uses common-port;
leaf mask {
- type uint32;
+ type port-config;
description "Bitmap of OFPPC-* flags to be changed";
}
leaf port-name {
type string;
- }
+ }
+
+ leaf barrier {
+ type boolean;
+ }
}
}
}
}
grouping meter-entry {
-
leaf node {
type inv:node-ref;
}
-
uses meter:meter;
}
--- /dev/null
+module flow-capable-transaction {
+ namespace "urn:opendaylight:flow:transaction";
+ prefix type;
+
+ import opendaylight-inventory {prefix inv; revision-date "2013-08-19";}
+ import yang-ext {prefix ext; revision-date "2013-07-09";}
+
+ revision "2013-11-03" {
+ description "Initial revision";
+ }
+
+ typedef transaction-id {
+ type uint64;
+ }
+
+ grouping transaction-aware {
+ leaf transaction-id {
+ type transaction-id;
+ }
+ }
+
+ rpc get-next-transaction-id {
+ input {
+ leaf node {
+ ext:context-reference "inv:node-context";
+ type inv:node-ref;
+ }
+ }
+ output {
+ uses transaction-aware;
+ }
+ }
+
+ // Barier request?
+ rpc finish-transaction {
+ input {
+ leaf node {
+ ext:context-reference "inv:node-context";
+ type inv:node-ref;
+ }
+ leaf transaction-id {
+ type transaction-id;
+ }
+ }
+ }
+}
\ No newline at end of file
import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
import ietf-inet-types {prefix inet;revision-date 2010-09-24;}
import opendaylight-group-types {prefix group-type;revision-date 2013-10-18;}
+ import flow-capable-transaction {prefix tr;}
revision "2013-09-18" {
description "Initial revision of group service";
}
grouping node-group {
- uses "inv:node-context-ref";
-
+ uses "inv:node-context-ref";
uses group-type:group;
}
rpc add-group {
input {
uses node-group;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
rpc remove-group {
input {
uses group-update;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
rpc update-group {
input {
uses group-update;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
import yang-ext {prefix ext; revision-date "2013-07-09";}
import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
import opendaylight-meter-types {prefix meter-type;revision-date "2013-09-18";}
+ import flow-capable-transaction {prefix tr;}
revision "2013-09-18" {
description "Initial revision of meter service";
rpc add-meter {
input {
uses node-meter;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
rpc remove-meter {
input {
uses node-meter;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
rpc update-meter {
input {
uses meter-update;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
--- /dev/null
+module sal-port {
+ namespace "urn:opendaylight:port:service";
+ prefix port;
+
+ import yang-ext {prefix ext; revision-date "2013-07-09";}
+ import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
+ import opendaylight-port-types {prefix port-type;revision-date "2013-09-25";}
+
+ revision "2013-11-07" {
+ description "Initial revision of port service";
+ }
+
+ grouping node-port {
+ uses "inv:node-context-ref";
+
+ uses port-type:ofp-port-mod;
+ }
+
+ /** Base configuration structure **/
+ grouping port-update {
+ uses "inv:node-context-ref";
+
+ container original-port {
+ uses port-type:ofp-port-mod;
+ }
+ container updated-port {
+ uses port-type:ofp-port-mod;
+ }
+ }
+
+ rpc update-port {
+ input {
+ uses port-update;
+ }
+ }
+
+ rpc get-port {
+ output {
+ uses port-type:flow-capable-port;
+ }
+ }
+
+ notification port-removed {
+ uses node-port;
+ }
+}
\ No newline at end of file
import yang-ext {prefix ext; revision-date "2013-07-09";}
import opendaylight-inventory {prefix inv;revision-date "2013-08-19";}
import opendaylight-table-types {prefix table-type;revision-date "2013-10-26";}
+ import flow-capable-transaction {prefix tr;}
revision "2013-10-26" {
description "Initial revision of table service";
- }
+ }
/** Base configuration structure **/
grouping table-update {
+ uses "inv:node-context-ref";
container original-table {
uses table-type:table-features;
}
rpc update-table {
input {
- leaf node {
- ext:context-reference "inv:node-context";
- type inv:node-ref;
- }
uses table-update;
+ uses tr:transaction-aware;
+ }
+ output {
+ uses tr:transaction-aware;
}
}
}
\ No newline at end of file
package org.opendaylight.controller.sal.core.api.model;
import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
* @return
*/
SchemaContext getGlobalContext();
+
+ ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener);
}
--- /dev/null
+package org.opendaylight.controller.sal.core.api.model;
+
+import java.util.EventListener;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public interface SchemaServiceListener extends EventListener {
+
+
+ void onGlobalContextUpdated(SchemaContext context);
+
+}
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">\r
- <modelVersion>4.0.0</modelVersion>\r
- <parent>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-parent</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </parent>\r
- <artifactId>sal-broker-impl</artifactId>\r
- <packaging>bundle</packaging>\r
- <scm>\r
- <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>\r
- <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>\r
- <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>\r
- </scm>\r
-\r
- <dependencies>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-core-api</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-common-util</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-common-impl</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-common-impl</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.opendaylight.controller</groupId>\r
- <artifactId>sal-core-spi</artifactId>\r
- <version>1.0-SNAPSHOT</version>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.slf4j</groupId>\r
- <artifactId>slf4j-api</artifactId>\r
- </dependency>\r
- <dependency>\r
- <groupId>com.google.guava</groupId>\r
- <artifactId>guava</artifactId>\r
- </dependency>\r
- <dependency>\r
- <groupId>org.eclipse.xtend</groupId>\r
- <artifactId>org.eclipse.xtend.lib</artifactId>\r
- </dependency>\r
- </dependencies>\r
-\r
- <build>\r
- <plugins>\r
- <plugin>\r
- <groupId>org.apache.felix</groupId>\r
- <artifactId>maven-bundle-plugin</artifactId>\r
- <extensions>true</extensions>\r
- <configuration>\r
- <instructions>\r
- <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>\r
- <Bundle-Activator>org.opendaylight.controller.sal.dom.broker.BrokerActivator</Bundle-Activator>\r
- <Private-Package>\r
- org.opendaylight.controller.sal.dom.broker.*\r
- </Private-Package>\r
- </instructions>\r
- </configuration>\r
- </plugin>\r
- <plugin>\r
- <groupId>org.eclipse.xtend</groupId>\r
- <artifactId>xtend-maven-plugin</artifactId>\r
- </plugin>\r
- </plugins>\r
- </build>\r
-</project>\r
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-parent</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>sal-broker-impl</artifactId>
+ <packaging>bundle</packaging>
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+ </scm>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-core-api</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-impl</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-core-spi</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>org.eclipse.xtend.lib</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>config-api</artifactId>
+ <version>0.2.2-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-parser-impl</artifactId>
+ <version>0.5.9-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+ <Bundle-Activator>org.opendaylight.controller.sal.dom.broker.BrokerActivator</Bundle-Activator>
+ <Private-Package>
+ org.opendaylight.controller.sal.dom.broker.*
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.eclipse.xtend</groupId>
+ <artifactId>xtend-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
+</project>
import java.util.Hashtable;
import org.opendaylight.controller.sal.core.api.Broker;
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
BrokerImpl broker;
private ServiceRegistration<Broker> brokerReg;
-
+ private ServiceRegistration<SchemaService> schemaReg;
+ private ServiceRegistration<DataBrokerService> dataReg;
+ private ServiceRegistration<DataProviderService> dataProviderReg;
+ private SchemaServiceImpl schemaService;
+ private DataBrokerImpl dataService;
+
@Override
public void start(BundleContext context) throws Exception {
+ Hashtable<String, String> emptyProperties = new Hashtable<String, String>();
broker = new BrokerImpl();
broker.setBundleContext(context);
- brokerReg = context.registerService(Broker.class, broker, new Hashtable<String,String>());
+ brokerReg = context.registerService(Broker.class, broker, emptyProperties);
+
+ schemaService = new SchemaServiceImpl();
+ schemaService.setContext(context);
+ schemaService.setParser(new YangParserImpl());
+ schemaService.start();
+ schemaReg = context.registerService(SchemaService.class, schemaService, new Hashtable<String, String>());
+
+ dataService = new DataBrokerImpl();
+ dataReg = context.registerService(DataBrokerService.class, dataService, emptyProperties);
+ dataProviderReg = context.registerService(DataProviderService.class, dataService, emptyProperties);
+
+
}
@Override
public void stop(BundleContext context) throws Exception {
- if(brokerReg != null) {
+ if (brokerReg != null) {
brokerReg.unregister();
}
}
private val Set<ConsumerContextImpl> sessions = Collections.synchronizedSet(new HashSet<ConsumerContextImpl>());
private val Set<ProviderContextImpl> providerSessions = Collections.synchronizedSet(
new HashSet<ProviderContextImpl>());
- private val Set<BrokerModule> modules = Collections.synchronizedSet(new HashSet<BrokerModule>());
- private val Map<Class<? extends BrokerService>, BrokerModule> serviceProviders = Collections.
- synchronizedMap(new HashMap<Class<? extends BrokerService>, BrokerModule>());
// Implementation specific
@Property
private var ExecutorService executor = Executors.newFixedThreadPool(5);
@Property
private var BundleContext bundleContext;
-
+
@Property
private var RpcRouter router;
return session;
}
- public def addModule(BrokerModule module) {
- log.info("Registering broker module " + module);
- if(modules.contains(module)) {
- log.error("Module already registered");
- throw new IllegalArgumentException("Module already exists.");
- }
-
- val provServices = module.getProvidedServices();
- for (Class<? extends BrokerService> serviceType : provServices) {
- log.info(" Registering session service implementation: " + serviceType.getCanonicalName());
- serviceProviders.put(serviceType, module);
- }
- }
-
- public def <T extends BrokerService> T serviceFor(Class<T> service, ConsumerContextImpl session) {
- val prov = serviceProviders.get(service);
- if(prov == null) {
- log.warn("Service " + service.toString() + " is not supported");
- return null;
- }
- return prov.getServiceForSession(service, session);
- }
-
protected def Future<RpcResult<CompositeNode>> invokeRpc(QName rpc, CompositeNode input) {
val result = executor.submit([|router.invokeRpc(rpc, input)] as Callable<RpcResult<CompositeNode>>);
return result;
// Validation
private def void checkPredicates(Provider prov) {
- if(prov == null)
+ if (prov == null)
throw new IllegalArgumentException("Provider should not be null.");
for (ProviderContextImpl session : providerSessions) {
- if(prov.equals(session.getProvider()))
+ if (prov.equals(session.getProvider()))
throw new IllegalStateException("Provider already registered");
}
}
private def void checkPredicates(Consumer cons) {
- if(cons == null)
+ if (cons == null)
throw new IllegalArgumentException("Consumer should not be null.");
for (ConsumerContextImpl session : sessions) {
- if(cons.equals(session.getConsumer()))
+ if (cons.equals(session.getConsumer()))
throw new IllegalStateException("Consumer already registered");
}
}
package org.opendaylight.controller.sal.dom.broker
-import java.util.Collections
import org.opendaylight.controller.sal.core.api.Broker.ConsumerSession
-import java.util.HashMap
import org.opendaylight.controller.sal.core.api.BrokerService
import org.opendaylight.controller.sal.core.api.Consumer
import org.osgi.framework.BundleContext
import org.opendaylight.yangtools.yang.common.QName
import org.opendaylight.yangtools.yang.data.api.CompositeNode
+import org.opendaylight.controller.sal.dom.broker.osgi.AbstractBrokerServiceProxy
+import com.google.common.collect.ClassToInstanceMap
+import com.google.common.collect.MutableClassToInstanceMap
+import org.opendaylight.controller.sal.dom.broker.osgi.ProxyFactory
class ConsumerContextImpl implements ConsumerSession {
@Property
private var BrokerImpl broker;
- private val instantiatedServices = Collections.synchronizedMap(
- new HashMap<Class<? extends BrokerService>, BrokerService>());
+ private val ClassToInstanceMap<BrokerService> instantiatedServices = MutableClassToInstanceMap.create();
private boolean closed = false;
private BundleContext context;
}
override <T extends BrokerService> T getService(Class<T> service) {
- val potential = instantiatedServices.get(service);
- if(potential != null) {
- val ret = potential as T;
- return ret;
+ val localProxy = instantiatedServices.getInstance(service);
+ if(localProxy != null) {
+ return localProxy;
}
- val ret = broker.serviceFor(service, this);
+ val serviceRef = context.getServiceReference(service);
+ if(serviceRef == null) {
+ return null;
+ }
+ val serviceImpl = context.getService(serviceRef);
+
+
+ val ret = ProxyFactory.createProxy(serviceRef,serviceImpl);
if(ret != null) {
- instantiatedServices.put(service, ret);
+ instantiatedServices.putInstance(service, ret);
}
return ret;
}
val toStop = instantiatedServices.values();
this.closed = true;
for (BrokerService brokerService : toStop) {
- //brokerService.closeSession();
+ if(brokerService instanceof AbstractBrokerServiceProxy<?>) {
+ (brokerService as AutoCloseable).close();
+ }
}
broker.consumerSessionClosed(this);
}
--- /dev/null
+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<InstanceIdentifier, CompositeNode> reader) {
+ readRouter.registerConfigurationReader(path, reader);
+ }
+
+ override registerOperationalReader(InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> 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<InstanceIdentifier, CompositeNode> commitHandler) {
+ // NOOP
+ }
+
+}
+++ /dev/null
-package org.opendaylight.controller.sal.dom.broker
-
-import org.opendaylight.controller.sal.core.api.data.DataBrokerService
-import org.opendaylight.controller.sal.common.DataStoreIdentifier
-import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier
-import org.opendaylight.controller.sal.core.api.data.DataChangeListener
-
-class DataConsumerServiceImpl implements DataBrokerService {
-
- override beginTransaction() {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
- override readConfigurationData(InstanceIdentifier path) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
- override readOperationalData(InstanceIdentifier path) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-
- override registerDataChangeListener(InstanceIdentifier path, DataChangeListener listener) {
- throw new UnsupportedOperationException("TODO: auto-generated method stub")
- }
-}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+import java.util.zip.Checksum;
+
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.util.ListenerRegistry;
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Sets;
+import static com.google.common.base.Preconditions.*;
+
+public class SchemaServiceImpl implements SchemaService, AutoCloseable {
+ private static final Logger logger = LoggerFactory.getLogger(SchemaServiceImpl.class);
+
+ private ListenerRegistry<SchemaServiceListener> listeners;
+ private YangModelParser parser;
+
+ private BundleContext context;
+ private BundleScanner scanner = new BundleScanner();
+
+ /**
+ * Map of currently problematic yang files that should get fixed eventually
+ * after all events are received.
+ */
+ private final Multimap<Bundle, URL> inconsistentBundlesToYangURLs = HashMultimap.create();
+ private final Multimap<Bundle, URL> consistentBundlesToYangURLs = HashMultimap.create();
+ private BundleTracker<Object> bundleTracker;
+ private final YangStoreCache cache = new YangStoreCache();
+
+ public ListenerRegistry<SchemaServiceListener> getListeners() {
+ return listeners;
+ }
+
+ public void setListeners(ListenerRegistry<SchemaServiceListener> listeners) {
+ this.listeners = listeners;
+ }
+
+ public YangModelParser getParser() {
+ return parser;
+ }
+
+ public void setParser(YangModelParser parser) {
+ this.parser = parser;
+ }
+
+ public BundleContext getContext() {
+ return context;
+ }
+
+ public void setContext(BundleContext context) {
+ this.context = context;
+ }
+
+ public void start() {
+ checkState(parser != null);
+ checkState(context != null);
+ if (listeners == null) {
+ listeners = new ListenerRegistry<>();
+ }
+
+ bundleTracker = new BundleTracker<Object>(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, scanner);
+ bundleTracker.open();
+ }
+
+ public SchemaContext getGlobalContext() {
+ return getSchemaContextSnapshot();
+ }
+
+ public synchronized SchemaContext getSchemaContextSnapshot() {
+ Optional<SchemaContext> yangStoreOpt = cache.getCachedSchemaContext(consistentBundlesToYangURLs);
+ if (yangStoreOpt.isPresent()) {
+ return yangStoreOpt.get();
+ }
+ SchemaContext snapshot = createSnapshot(parser, consistentBundlesToYangURLs);
+ updateCache(snapshot);
+ return snapshot;
+ }
+
+ @Override
+ public void addModule(Module module) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SchemaContext getSessionContext() {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void removeModule(Module module) {
+ // TODO Auto-generated method stub
+ throw new UnsupportedOperationException();
+ }
+
+
+ @Override
+ public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
+ return listeners.register(listener);
+ }
+
+ @Override
+ public void close() throws Exception {
+ bundleTracker.close();
+ // FIXME: Add listeners.close();
+
+ }
+
+ private synchronized boolean tryToUpdateState(Collection<URL> changedURLs, Multimap<Bundle, URL> proposedNewState,
+ boolean adding) {
+ Preconditions.checkArgument(changedURLs.size() > 0, "No change can occur when no URLs are changed");
+
+ try {
+ // consistent state
+ // merge into
+ SchemaContext snapshot = createSnapshot(parser, proposedNewState);
+ consistentBundlesToYangURLs.clear();
+ consistentBundlesToYangURLs.putAll(proposedNewState);
+ inconsistentBundlesToYangURLs.clear();
+ // update cache
+ updateCache(snapshot);
+ logger.info("SchemaService updated to new consistent state");
+ logger.trace("SchemaService updated to new consistent state containing {}", consistentBundlesToYangURLs);
+
+ // notifyListeners(changedURLs, adding);
+ return true;
+ } catch (Exception e) {
+ // inconsistent state
+ logger.debug(
+ "SchemaService is falling back on last consistent state containing {}, inconsistent yang files {}, reason {}",
+ consistentBundlesToYangURLs, inconsistentBundlesToYangURLs, e.toString());
+ return false;
+ }
+ }
+
+ private static Collection<InputStream> fromUrlsToInputStreams(Multimap<Bundle, URL> multimap) {
+ return Collections2.transform(multimap.values(), new Function<URL, InputStream>() {
+
+ @Override
+ public InputStream apply(URL url) {
+ try {
+ return url.openStream();
+ } catch (IOException e) {
+ logger.warn("Unable to open stream from {}", url);
+ throw new IllegalStateException("Unable to open stream from " + url, e);
+ }
+ }
+ });
+ }
+
+ private static SchemaContext createSnapshot(YangModelParser parser, Multimap<Bundle, URL> multimap) {
+ List<InputStream> models = new ArrayList<>(fromUrlsToInputStreams(multimap));
+ Set<Module> modules = parser.parseYangModelsFromStreams(models);
+ SchemaContext yangStoreSnapshot = parser.resolveSchemaContext(modules);
+ return yangStoreSnapshot;
+ }
+
+ private void updateCache(SchemaContext snapshot) {
+ cache.cacheYangStore(consistentBundlesToYangURLs, snapshot);
+ for (ListenerRegistration<SchemaServiceListener> listener : listeners) {
+ try {
+ listener.getInstance().onGlobalContextUpdated(snapshot);
+ } catch (Exception e) {
+ logger.error("Exception occured during invoking listener",e);
+ }
+ }
+ }
+
+ private class BundleScanner implements BundleTrackerCustomizer<Object> {
+ @Override
+ public Object addingBundle(Bundle bundle, BundleEvent event) {
+
+ // Ignore system bundle:
+ // system bundle might have config-api on classpath &&
+ // config-api contains yang files =>
+ // system bundle might contain yang files from that bundle
+ if (bundle.getBundleId() == 0)
+ return bundle;
+
+ Enumeration<URL> enumeration = bundle.findEntries("META-INF/yang", "*.yang", false);
+ if (enumeration != null && enumeration.hasMoreElements()) {
+ synchronized (this) {
+ List<URL> addedURLs = new ArrayList<>();
+ while (enumeration.hasMoreElements()) {
+ URL url = enumeration.nextElement();
+ addedURLs.add(url);
+ }
+ logger.trace("Bundle {} has event {}, bundle state {}, URLs {}", bundle, event, bundle.getState(),
+ addedURLs);
+ // test that yang store is consistent
+ Multimap<Bundle, URL> proposedNewState = HashMultimap.create(consistentBundlesToYangURLs);
+ proposedNewState.putAll(inconsistentBundlesToYangURLs);
+ proposedNewState.putAll(bundle, addedURLs);
+ boolean adding = true;
+ if (tryToUpdateState(addedURLs, proposedNewState, adding) == false) {
+ inconsistentBundlesToYangURLs.putAll(bundle, addedURLs);
+ }
+ }
+ }
+ return bundle;
+ }
+
+ @Override
+ public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+ logger.debug("Modified bundle {} {} {}", bundle, event, object);
+ }
+
+ /**
+ * If removing YANG files makes yang store inconsistent, method
+ * {@link #getYangStoreSnapshot()} will throw exception. There is no
+ * rollback.
+ */
+
+ @Override
+ public synchronized void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+ inconsistentBundlesToYangURLs.removeAll(bundle);
+ Collection<URL> consistentURLsToBeRemoved = consistentBundlesToYangURLs.removeAll(bundle);
+
+ if (consistentURLsToBeRemoved.isEmpty()) {
+ return; // no change
+ }
+ boolean adding = false;
+ // notifyListeners(consistentURLsToBeRemoved, adding);
+ }
+ }
+
+ private static final class YangStoreCache {
+
+ Set<URL> cachedUrls;
+ SchemaContext cachedContextSnapshot;
+
+ Optional<SchemaContext> getCachedSchemaContext(Multimap<Bundle, URL> bundlesToYangURLs) {
+ Set<URL> urls = setFromMultimapValues(bundlesToYangURLs);
+ if (cachedUrls != null && cachedUrls.equals(urls)) {
+ Preconditions.checkState(cachedContextSnapshot != null);
+ return Optional.of(cachedContextSnapshot);
+ }
+ return Optional.absent();
+ }
+
+ private static Set<URL> setFromMultimapValues(Multimap<Bundle, URL> bundlesToYangURLs) {
+ Set<URL> urls = Sets.newHashSet(bundlesToYangURLs.values());
+ Preconditions.checkState(bundlesToYangURLs.size() == urls.size());
+ return urls;
+ }
+
+ void cacheYangStore(Multimap<Bundle, URL> urls, SchemaContext ctx) {
+ this.cachedUrls = setFromMultimapValues(urls);
+ this.cachedContextSnapshot = ctx;
+ }
+
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.controller.sal.core.api.BrokerService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.osgi.framework.ServiceReference;
+import static com.google.common.base.Preconditions.*;
+
+public abstract class AbstractBrokerServiceProxy<T extends BrokerService> implements AutoCloseable, BrokerService {
+
+ private T delegate;
+ private final ServiceReference<T> reference;
+
+ public AbstractBrokerServiceProxy(ServiceReference<T> ref, T delegate) {
+ this.delegate = checkNotNull(delegate, "Delegate should not be null.");
+ this.reference = checkNotNull(ref, "Reference should not be null.");
+ }
+
+ protected final T getDelegate() {
+ checkState(delegate != null, "Proxy was closed and unregistered.");
+ return delegate;
+ }
+
+ protected final ServiceReference<T> getReference() {
+ return reference;
+ }
+
+ private Set<Registration<?>> registrations = Collections.synchronizedSet(new HashSet<Registration<?>>());
+
+ protected <R extends Registration<?>> R addRegistration(R registration) {
+ if (registration != null) {
+ registrations.add(registration);
+ }
+ return registration;
+ }
+
+ protected void closeBeforeUnregistrations() {
+ // NOOP
+ }
+
+ protected void closeAfterUnregistrations() {
+ // NOOP
+ }
+
+ @Override
+ public void close() {
+ if (delegate != null) {
+ delegate = null;
+ RuntimeException potentialException = new RuntimeException(
+ "Uncaught exceptions occured during unregistration");
+ boolean hasSuppressed = false;
+ for (Registration<?> registration : registrations) {
+ try {
+ registration.close();
+ } catch (Exception e) {
+ potentialException.addSuppressed(e);
+ hasSuppressed = true;
+ }
+ }
+ if (hasSuppressed) {
+ throw potentialException;
+ }
+ }
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.ServiceReference;
+
+public class DataBrokerServiceProxy extends AbstractBrokerServiceProxy<DataBrokerService> implements DataBrokerService {
+
+ public DataBrokerServiceProxy(ServiceReference<DataBrokerService> ref, DataBrokerService delegate) {
+ super(ref, delegate);
+ }
+
+ public ListenerRegistration<DataChangeListener> registerDataChangeListener(InstanceIdentifier path,
+ DataChangeListener listener) {
+ return addRegistration(getDelegate().registerDataChangeListener(path, listener));
+ }
+
+ public CompositeNode readConfigurationData(InstanceIdentifier path) {
+ return getDelegate().readConfigurationData(path);
+ }
+
+ public CompositeNode readOperationalData(InstanceIdentifier path) {
+ return getDelegate().readOperationalData(path);
+ }
+
+ public DataModificationTransaction beginTransaction() {
+ return getDelegate().beginTransaction();
+ }
+
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.md.sal.common.api.data.DataCommitHandler;
+import org.opendaylight.controller.md.sal.common.api.data.DataReader;
+import org.opendaylight.controller.sal.common.DataStoreIdentifier;
+import org.opendaylight.controller.sal.core.api.data.DataChangeListener;
+import org.opendaylight.controller.sal.core.api.data.DataModificationTransaction;
+import org.opendaylight.controller.sal.core.api.data.DataProviderService;
+import org.opendaylight.controller.sal.core.api.data.DataValidator;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.osgi.framework.ServiceReference;
+
+public class DataProviderServiceProxy extends AbstractBrokerServiceProxy<DataProviderService> implements
+ DataProviderService {
+
+ public DataProviderServiceProxy(ServiceReference<DataProviderService> ref, DataProviderService delegate) {
+ super(ref, delegate);
+ }
+
+ public ListenerRegistration<DataChangeListener> registerDataChangeListener(InstanceIdentifier path,
+ DataChangeListener listener) {
+ return addRegistration(getDelegate().registerDataChangeListener(path, listener));
+ }
+
+ public CompositeNode readConfigurationData(InstanceIdentifier path) {
+ return getDelegate().readConfigurationData(path);
+ }
+
+ public CompositeNode readOperationalData(InstanceIdentifier path) {
+ return getDelegate().readOperationalData(path);
+ }
+
+ public DataModificationTransaction beginTransaction() {
+ return getDelegate().beginTransaction();
+ }
+
+ @Override
+ public void addRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+ getDelegate().addRefresher(store, refresher);
+ }
+
+ @Override
+ public void addValidator(DataStoreIdentifier store, DataValidator validator) {
+ getDelegate().addValidator(store, validator);
+ }
+
+ @Override
+ public Registration<DataCommitHandler<InstanceIdentifier, CompositeNode>> registerCommitHandler(
+ InstanceIdentifier path, DataCommitHandler<InstanceIdentifier, CompositeNode> commitHandler) {
+ return addRegistration(getDelegate().registerCommitHandler(path, commitHandler));
+ }
+
+ @Override
+ public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerConfigurationReader(
+ InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+ return addRegistration(getDelegate().registerConfigurationReader(path, reader));
+ }
+
+ @Override
+ public Registration<DataReader<InstanceIdentifier, CompositeNode>> registerOperationalReader(
+ InstanceIdentifier path, DataReader<InstanceIdentifier, CompositeNode> reader) {
+ return addRegistration(getDelegate().registerOperationalReader(path, reader));
+ }
+
+ @Override
+ public void removeRefresher(DataStoreIdentifier store, DataRefresher refresher) {
+ getDelegate().removeRefresher(store, refresher);
+ }
+
+ @Override
+ public void removeValidator(DataStoreIdentifier store, DataValidator validator) {
+ getDelegate().removeValidator(store, validator);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.osgi.framework.ServiceReference;
+
+public class NotificationPublishServiceProxy extends AbstractBrokerServiceProxy<NotificationPublishService> implements NotificationPublishService {
+
+ public NotificationPublishServiceProxy(ServiceReference<NotificationPublishService> ref,
+ NotificationPublishService delegate) {
+ super(ref, delegate);
+ }
+
+ public void sendNotification(CompositeNode notification) {
+ getDelegate().sendNotification(notification);
+ }
+
+ public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+ return addRegistration(getDelegate().addNotificationListener(notification, listener));
+
+ }
+
+ public void publish(CompositeNode notification) {
+ getDelegate().publish(notification);
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.notify.NotificationListener;
+import org.opendaylight.controller.sal.core.api.notify.NotificationService;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.osgi.framework.ServiceReference;
+
+public class NotificationServiceProxy extends AbstractBrokerServiceProxy<NotificationService> implements
+ NotificationService {
+
+ public NotificationServiceProxy(ServiceReference<NotificationService> ref, NotificationService delegate) {
+ super(ref, delegate);
+ }
+
+ @Override
+ public Registration<NotificationListener> addNotificationListener(QName notification, NotificationListener listener) {
+ return addRegistration(getDelegate().addNotificationListener(notification, listener));
+ }
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi
+
+import org.opendaylight.controller.sal.core.api.BrokerService
+import org.osgi.framework.ServiceReference
+import org.opendaylight.controller.sal.core.api.data.DataBrokerService
+import org.opendaylight.controller.sal.core.api.data.DataProviderService
+import org.opendaylight.controller.sal.core.api.notify.NotificationPublishService
+import org.opendaylight.controller.sal.core.api.notify.NotificationService
+import org.opendaylight.controller.sal.core.api.model.SchemaService
+
+class ProxyFactory {
+
+ static def <T extends BrokerService> T createProxy(ServiceReference<T> serviceRef, T service) {
+ return createProxyImpl(serviceRef, service) as T;
+ }
+
+ private static def dispatch createProxyImpl(ServiceReference<?> ref, DataBrokerService service) {
+ new DataBrokerServiceProxy(ref as ServiceReference<DataBrokerService>, service);
+ }
+
+ private static def dispatch createProxyImpl(ServiceReference<?> ref, DataProviderService service) {
+ new DataProviderServiceProxy(ref as ServiceReference<DataProviderService>, service);
+ }
+
+ private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationPublishService service) {
+ new NotificationPublishServiceProxy(ref as ServiceReference<NotificationPublishService>, service);
+ }
+
+ private static def dispatch createProxyImpl(ServiceReference<?> ref, NotificationService service) {
+ new NotificationServiceProxy(ref as ServiceReference<NotificationService>, service);
+ }
+
+ private static def dispatch createProxyImpl(ServiceReference<?> ref, SchemaService service) {
+ new SchemaServiceProxy(ref as ServiceReference<SchemaService>, service);
+ }
+
+ private static def dispatch createProxyImpl(ServiceReference<?> reference, BrokerService service) {
+ throw new IllegalArgumentException("Not supported class");
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.sal.dom.broker.osgi;
+
+import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.osgi.framework.ServiceReference;
+
+public class SchemaServiceProxy extends AbstractBrokerServiceProxy<SchemaService> implements SchemaService {
+
+ public SchemaServiceProxy(ServiceReference<SchemaService> ref, SchemaService delegate) {
+ super(ref, delegate);
+ }
+
+ @Override
+ public void addModule(Module module) {
+ getDelegate().addModule(module);
+ }
+
+ @Override
+ public void removeModule(Module module) {
+ getDelegate().removeModule(module);
+ }
+
+ @Override
+ public SchemaContext getSessionContext() {
+ return null;
+ }
+
+ @Override
+ public SchemaContext getGlobalContext() {
+ return getDelegate().getGlobalContext();
+ }
+
+ @Override
+ public ListenerRegistration<SchemaServiceListener> registerSchemaServiceListener(SchemaServiceListener listener) {
+ ListenerRegistration<SchemaServiceListener> registration = getDelegate().registerSchemaServiceListener(listener);
+ addRegistration(registration);
+ return registration;
+ }
+
+
+
+}
package org.opendaylight.controller.sal.restconf.impl.test;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import javax.ws.rs.WebApplicationException;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
+import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
+import org.opendaylight.controller.sal.restconf.impl.StructuredData;
import org.opendaylight.yangtools.yang.data.api.CompositeNode;
import org.opendaylight.yangtools.yang.data.api.Node;
import org.opendaylight.yangtools.yang.data.api.SimpleNode;
import org.opendaylight.yangtools.yang.data.impl.XmlTreeBuilder;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.*;
import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
import org.slf4j.Logger;
}
}
+
+ static String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
+ String jsonResult = null;
+ Set<Module> modules = null;
+
+ try {
+ modules = TestUtils.loadModules(YangAndXmlToJsonConversionJsonReaderTest.class.getResource(yangPath).getPath());
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ assertNotNull("modules can't be null.", modules);
+
+ InputStream xmlStream = YangAndXmlToJsonConversionJsonReaderTest.class.getResourceAsStream(xmlDataPath);
+ CompositeNode compositeNode = null;
+ try {
+ compositeNode = TestUtils.loadCompositeNode(xmlStream);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ assertNotNull("Composite node can't be null", compositeNode);
+
+ StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
+ for (Module module : modules) {
+ for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+ StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+ ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+ try {
+ structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
+ } catch (WebApplicationException | IOException e) {
+ e.printStackTrace();
+ }
+ assertFalse(
+ "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
+ byteArrayOS.toString().isEmpty());
+ jsonResult = byteArrayOS.toString();
+ try {
+ outputToFile(byteArrayOS);
+ } catch (IOException e) {
+ System.out.println("Output file wasn't cloased sucessfuly.");
+ }
+ }
+ }
+ return jsonResult;
+ }
+
+ static void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
+ FileOutputStream fileOS = null;
+ try {
+ String path = YangAndXmlToJsonConversionJsonReaderTest.class.getResource("/yang-to-json-conversion/xml").getPath();
+ File outFile = new File(path + "/data.json");
+ fileOS = new FileOutputStream(outFile);
+ try {
+ fileOS.write(outputStream.toByteArray());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ fileOS.close();
+ } catch (FileNotFoundException e1) {
+ e1.printStackTrace();
+ }
+ }
+
+ static String readJsonFromFile(String path,boolean removeWhiteChars) {
+ FileReader fileReader = getFileReader(path);
+
+ StringBuilder strBuilder = new StringBuilder();
+ char[] buffer = new char[1000];
+
+ while (true) {
+ int loadedCharNum;
+ try {
+ loadedCharNum = fileReader.read(buffer);
+ } catch (IOException e) {
+ break;
+ }
+ if (loadedCharNum == -1) {
+ break;
+ }
+ strBuilder.append(buffer, 0, loadedCharNum);
+ }
+ try {
+ fileReader.close();
+ } catch (IOException e) {
+ System.out.println("The file wasn't closed");
+ }
+ String rawStr = strBuilder.toString();
+ if (removeWhiteChars) {
+ rawStr = rawStr.replace("\n", "");
+ rawStr = rawStr.replace("\r", "");
+ rawStr = rawStr.replace("\t", "");
+ rawStr = removeSpaces(rawStr);
+ }
+
+ return rawStr;
+ }
+
+ private static FileReader getFileReader(String path) {
+ String fullPath = YangAndXmlToJsonConversionJsonReaderTest.class.getResource(path).getPath();
+ assertNotNull("Path to file can't be null.", fullPath);
+ File file = new File(fullPath);
+ assertNotNull("File can't be null", file);
+ FileReader fileReader = null;
+ try {
+ fileReader = new FileReader(file);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ assertNotNull("File reader can't be null.", fileReader);
+ return fileReader;
+ }
+
+ private static String removeSpaces(String rawStr) {
+ StringBuilder strBuilder = new StringBuilder();
+ int i = 0;
+ int quoteCount = 0;
+ while (i < rawStr.length()) {
+ if (rawStr.substring(i, i + 1).equals("\"")) {
+ quoteCount++;
+ }
+
+ if (!rawStr.substring(i, i + 1).equals(" ") || (quoteCount % 2 == 1)) {
+ strBuilder.append(rawStr.charAt(i));
+ }
+ i++;
+ }
+
+ return strBuilder.toString();
+ }
+
+
}
--- /dev/null
+package org.opendaylight.controller.sal.restconf.impl.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.*;
+import java.util.*;
+
+import org.junit.Test;
+
+import com.google.gson.stream.JsonReader;
+
+public class YangAndXmlToJsonConversionJsonReaderTest {
+
+ @Test
+ public void simpleYangTypesWithJsonReaderTest() {
+ String jsonOutput;
+ jsonOutput = TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",
+ false);
+
+// jsonOutput = TestUtils.convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
+// "/yang-to-json-conversion/simple-yang-types");
+
+ StringReader strReader = new StringReader(jsonOutput);
+ JsonReader jReader = new JsonReader(strReader);
+ try {
+ checkCont1(jReader);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void checkCont1(JsonReader jReader) throws IOException {
+ jReader.beginObject();
+ assertNotNull("cont1 is missing.", jReader.hasNext());
+ jReader.nextName();
+ checkCont1Elements(jReader, prepareInputData(jReader), "cont1/");
+ jReader.endObject();
+
+ }
+
+ private Map<String, String> prepareInputData(JsonReader jReader) {
+ Map<String, String> dataMap = new HashMap<>();
+ dataMap.put("cont1/lf11", "lf");
+ dataMap.put("cont1/lflst11.1", "55");
+ dataMap.put("cont1/lflst11.2", "56");
+ dataMap.put("cont1/lflst11.3", "57");
+ dataMap.put("cont1/lflst12.1", "lflst12 str1");
+ dataMap.put("cont1/lflst12.2", "lflst12 str2");
+ dataMap.put("cont1/lflst12.3", "lflst12 str3");
+
+ dataMap.put("cont1/lst11.1/lf111", "140");
+ dataMap.put("cont1/lst11.1/lf112", "lf112 str");
+ dataMap.put("cont1/lst11.1/cont111/lf1111", "lf1111 str");
+ dataMap.put("cont1/lst11.1/cont111/lflst1111.1", "2048");
+ dataMap.put("cont1/lst11.1/cont111/lflst1111.2", "1024");
+ dataMap.put("cont1/lst11.1/cont111/lflst1111.3", "4096");
+ dataMap.put("cont1/lst11.1/cont111/lst1111.1/lf1111A", "lf1111A str11");
+ dataMap.put("cont1/lst11.1/cont111/lst1111.1/lf1111B", "4");
+ dataMap.put("cont1/lst11.1/cont111/lst1111.2/lf1111A", "lf1111A str12");
+ dataMap.put("cont1/lst11.1/cont111/lst1111.2/lf1111B", "7");
+ dataMap.put("cont1/lst11.1/lst111.1/lf1111", "65");
+ dataMap.put("cont1/lst11.1/lst112.1/lf1121", "lf1121 str11");
+
+ dataMap.put("cont1/lst11.2/lf111", "141");
+ dataMap.put("cont1/lst11.2/lf112", "lf112 str2");
+ dataMap.put("cont1/lst11.2/cont111/lf1111", "lf1111 str2");
+ dataMap.put("cont1/lst11.2/cont111/lflst1111.1", "2049");
+ dataMap.put("cont1/lst11.2/cont111/lflst1111.2", "1025");
+ dataMap.put("cont1/lst11.2/cont111/lflst1111.3", "4097");
+ dataMap.put("cont1/lst11.2/cont111/lst1111.1/lf1111A", "lf1111A str21");
+ dataMap.put("cont1/lst11.2/cont111/lst1111.1/lf1111B", "5");
+ dataMap.put("cont1/lst11.2/cont111/lst1111.2/lf1111A", "lf1111A str22");
+ dataMap.put("cont1/lst11.2/cont111/lst1111.2/lf1111B", "8");
+ dataMap.put("cont1/lst11.2/lst111.1/lf1111", "55");
+ dataMap.put("cont1/lst11.2/lst111.2/lf1111", "56");
+ dataMap.put("cont1/lst11.2/lst112.1/lf1121", "lf1121 str21");
+ dataMap.put("cont1/lst11.2/lst112.2/lf1121", "lf1121 str22");
+
+ return dataMap;
+
+ }
+
+ private void checkCont1Elements(JsonReader jReader, Map<String, String> dataMap, String pthPref) throws IOException {
+ Set<String> keys = new HashSet<>();
+ jReader.beginObject();
+ while (jReader.hasNext()) {
+ String keyName = jReader.nextName();
+ if (keyName.equals("lf11")) {
+ assertEquals("Key " + keyName + " has incorrect value.", dataMap.get(pthPref + keyName),
+ jReader.nextString());
+ keys.add(keyName);
+ } else if (keyName.equals("lflst11")) {
+ checkLflstValues(jReader, pthPref + keyName, dataMap);
+ keys.add(keyName);
+ } else if (keyName.equals("lflst12")) {
+ checkLflstValues(jReader, pthPref + keyName, dataMap);
+ keys.add(keyName);
+ } else if (keyName.equals("lst11")) {
+ checkLst11(jReader, pthPref + keyName, dataMap);
+ keys.add(keyName);
+ } else {
+ assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
+ }
+ }
+ jReader.endObject();
+ assertEquals("Incorrect number of keys in cont1", 4, keys.size());
+
+ }
+
+ private void checkLst11(JsonReader jReader, String pthPref, Map<String, String> dataMap) throws IOException {
+ jReader.beginArray();
+
+ int arrayLength = 0;
+ while (jReader.hasNext()) {
+ checkLst11Elements(jReader, pthPref + "." + ++arrayLength + "/", dataMap);
+ }
+ jReader.endArray();
+ assertEquals("Incorrect number of items in lst11 array.", 2, arrayLength);
+ }
+
+ private void checkLst11Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginObject();
+ while (jReader.hasNext()) {
+ String keyName = jReader.nextName();
+ if (keyName.equals("lf111")) {
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+ } else if (keyName.equals("lf112")) {
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+ } else if (keyName.equals("cont111")) {
+ checkCont111(jReader, pthPref + keyName, data);
+ } else if (keyName.equals("lst111")) {
+ checkLst111(jReader, pthPref + keyName, data);
+ } else if (keyName.equals("lst112")) {
+ checkLst112(jReader, pthPref + keyName, data);
+ } else {
+ assertTrue("Key " + keyName + " doesn't exists in yang file.", false);
+ }
+ }
+ jReader.endObject();
+ }
+
+ private void checkLst112(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginArray();
+ int arrayIndex = 0;
+ while (jReader.hasNext()) {
+ checkLst112Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+ }
+ jReader.endArray();
+ }
+
+ private void checkLst112Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginObject();
+ if (jReader.hasNext()) {
+ String keyName = jReader.nextName();
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+ }
+ jReader.endObject();
+
+ }
+
+ private void checkLst111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginArray();
+ int arrayIndex = 0;
+ while (jReader.hasNext()) {
+ checkLst111Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+ }
+ jReader.endArray();
+ }
+
+ private void checkLst111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginObject();
+ if (jReader.hasNext()) {
+ String keyName = jReader.nextName();
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+ }
+ jReader.endObject();
+ }
+
+ private void checkCont111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginObject();
+ checkCont111Elements(jReader, pthPref + "/", data);
+ jReader.endObject();
+ }
+
+ private void checkCont111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ while (jReader.hasNext()) {
+ String keyName = jReader.nextName();
+ if (keyName.equals("lf1111")) {
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+ } else if (keyName.equals("lflst1111")) {
+ checkLflstValues(jReader, pthPref + keyName, data);
+ } else if (keyName.equals("lst1111")) {
+ checkLst1111(jReader, pthPref + keyName, data);
+ }
+ }
+
+ }
+
+ private void checkLst1111(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginArray();
+ int arrayIndex = 0;
+ while (jReader.hasNext()) {
+ checkLst1111Elements(jReader, pthPref + "." + ++arrayIndex + "/", data);
+ }
+ jReader.endArray();
+ }
+
+ private void checkLst1111Elements(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginObject();
+ while (jReader.hasNext()) {
+ String keyName = jReader.nextName();
+ if (keyName.equals("lf1111A")) {
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+
+ } else if (keyName.equals("lf1111B")) {
+ assertEquals("Incorrect value for key " + keyName, data.get(pthPref + keyName), jReader.nextString());
+ }
+ }
+ jReader.endObject();
+ }
+
+ private void checkLflstValues(JsonReader jReader, String pthPref, Map<String, String> data) throws IOException {
+ jReader.beginArray();
+ int arrayIndex = 1;
+ String keyValue = null;
+ List<String> searchedValues = new ArrayList<>();
+ while ((keyValue = data.get(pthPref + "." + arrayIndex++)) != null) {
+ searchedValues.add(keyValue);
+ }
+
+ while (jReader.hasNext()) {
+ String value = jReader.nextString();
+ assertTrue("Value " + value + " of lflst " + pthPref + " wasn't found", searchedValues.contains(value));
+ }
+
+ jReader.endArray();
+ }
+
+
+
+}
package org.opendaylight.controller.sal.restconf.impl.test;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
-import java.io.*;
-import java.util.Set;
-import java.util.regex.*;
+import java.util.regex.Pattern;
-import javax.ws.rs.WebApplicationException;
+import org.junit.Test;
-import org.junit.*;
-import org.opendaylight.controller.sal.rest.impl.StructuredDataToJsonProvider;
-import org.opendaylight.controller.sal.restconf.impl.StructuredData;
-import org.opendaylight.yangtools.yang.model.api.*;
-import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+public class YangAndXmlToJsonConversionRegExTest {
-public class YangAndXmlToJsonConversion {
-
- @Ignore
@Test
/**
* Test for simple yang types (leaf, list, leaf-list, container and various combination of them)
public void simpleYangTypesTest() {
String jsonOutput = null;
- jsonOutput = convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
- "/yang-to-json-conversion/simple-yang-types");
+// jsonOutput = TestUtils.convertXmlDataAndYangToJson("/yang-to-json-conversion/simple-yang-types/xml/data.xml",
+// "/yang-to-json-conversion/simple-yang-types");
-// jsonOutput =
-// readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/output.json");
+ jsonOutput =
+ TestUtils.readJsonFromFile("/yang-to-json-conversion/simple-yang-types/xml/awaited_output.json",true);
verifyJsonOutputForSimpleYangTypes(jsonOutput);
-
- }
+ }
private void verifyJsonOutputForSimpleYangTypes(String jsonOutput) {
return null;
}
- private String readJsonFromFile(String path) {
- String fullPath = YangAndXmlToJsonConversion.class.getResource(path).getPath();
- assertNotNull("Path to file can't be null.", fullPath);
- File file = new File(fullPath);
- assertNotNull("File can't be null", file);
- FileReader fileReader = null;
- try {
- fileReader = new FileReader(file);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- assertNotNull("File reader can't be null.", fileReader);
-
- StringBuilder strBuilder = new StringBuilder();
- char[] buffer = new char[1000];
-
- while (true) {
- int loadedCharNum;
- try {
- loadedCharNum = fileReader.read(buffer);
- } catch (IOException e) {
- break;
- }
- if (loadedCharNum == -1) {
- break;
- }
- strBuilder.append(buffer, 0, loadedCharNum);
- }
- try {
- fileReader.close();
- } catch (IOException e) {
- System.out.println("The file wasn't closed");
- ;
- }
- String rawStr = strBuilder.toString();
- rawStr = rawStr.replace("\n", "");
- rawStr = rawStr.replace("\r", "");
- rawStr = rawStr.replace("\t", "");
- rawStr = removeSpaces(rawStr);
-
- return rawStr;
- }
-
- private String removeSpaces(String rawStr) {
- StringBuilder strBuilder = new StringBuilder();
- int i = 0;
- int quoteCount = 0;
- while (i < rawStr.length()) {
- if (rawStr.substring(i, i + 1).equals("\"")) {
- quoteCount++;
- }
- if (!rawStr.substring(i, i + 1).equals(" ") || (quoteCount % 2 == 1)) {
- strBuilder.append(rawStr.charAt(i));
- }
- i++;
- }
-
- return strBuilder.toString();
- }
- private String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
- String jsonResult = null;
- Set<Module> modules = null;
- try {
- modules = TestUtils.loadModules(YangAndXmlToJsonConversion.class.getResource(yangPath).getPath());
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- assertNotNull("modules can't be null.", modules);
-
- InputStream xmlStream = YangAndXmlToJsonConversion.class.getResourceAsStream(xmlDataPath);
- CompositeNode compositeNode = null;
- try {
- compositeNode = TestUtils.loadCompositeNode(xmlStream);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }
- assertNotNull("Composite node can't be null", compositeNode);
+// private String convertXmlDataAndYangToJson(String xmlDataPath, String yangPath) {
+// String jsonResult = null;
+// Set<Module> modules = null;
+//
+// try {
+// modules = TestUtils.loadModules(YangAndXmlToJsonConversionJsonReaderTest.class.getResource(yangPath).getPath());
+// } catch (FileNotFoundException e) {
+// e.printStackTrace();
+// }
+// assertNotNull("modules can't be null.", modules);
+//
+// InputStream xmlStream = YangAndXmlToJsonConversionJsonReaderTest.class.getResourceAsStream(xmlDataPath);
+// CompositeNode compositeNode = null;
+// try {
+// compositeNode = TestUtils.loadCompositeNode(xmlStream);
+// } catch (FileNotFoundException e) {
+// e.printStackTrace();
+// }
+// assertNotNull("Composite node can't be null", compositeNode);
+//
+// StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
+// for (Module module : modules) {
+// for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+// StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
+// ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
+// try {
+// structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
+// } catch (WebApplicationException | IOException e) {
+// e.printStackTrace();
+// }
+// assertFalse(
+// "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
+// byteArrayOS.toString().isEmpty());
+// jsonResult = byteArrayOS.toString();
+// try {
+// outputToFile(byteArrayOS);
+// } catch (IOException e) {
+// System.out.println("Output file wasn't cloased sucessfuly.");
+// }
+// }
+// }
+// return jsonResult;
+// }
+//
+// private void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
+// FileOutputStream fileOS = null;
+// try {
+// String path = YangAndXmlToJsonConversionJsonReaderTest.class.getResource("/yang-to-json-conversion/xml").getPath();
+// File outFile = new File(path + "/data.json");
+// fileOS = new FileOutputStream(outFile);
+// try {
+// fileOS.write(outputStream.toByteArray());
+// } catch (IOException e) {
+// e.printStackTrace();
+// }
+// fileOS.close();
+// } catch (FileNotFoundException e1) {
+// e1.printStackTrace();
+// }
+// }
+
- StructuredDataToJsonProvider structuredDataToJsonProvider = StructuredDataToJsonProvider.INSTANCE;
- for (Module module : modules) {
- for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
- StructuredData structuredData = new StructuredData(compositeNode, dataSchemaNode);
- ByteArrayOutputStream byteArrayOS = new ByteArrayOutputStream();
- try {
- structuredDataToJsonProvider.writeTo(structuredData, null, null, null, null, null, byteArrayOS);
- } catch (WebApplicationException | IOException e) {
- e.printStackTrace();
- }
- assertFalse(
- "Returning JSON string can't be empty for node " + dataSchemaNode.getQName().getLocalName(),
- byteArrayOS.toString().isEmpty());
- jsonResult = byteArrayOS.toString();
- try {
- outputToFile(byteArrayOS);
- } catch (IOException e) {
- System.out.println("Output file wasn't cloased sucessfuly.");
- }
- }
- }
- return jsonResult;
- }
-
- private void outputToFile(ByteArrayOutputStream outputStream) throws IOException {
- FileOutputStream fileOS = null;
- try {
- String path = YangAndXmlToJsonConversion.class.getResource("/yang-to-json-conversion/xml").getPath();
- File outFile = new File(path + "/data.json");
- fileOS = new FileOutputStream(outFile);
- try {
- fileOS.write(outputStream.toByteArray());
- } catch (IOException e) {
- e.printStackTrace();
- }
- fileOS.close();
- } catch (FileNotFoundException e1) {
- e1.printStackTrace();
- }
- }
}
"lf1111B": 7
}
]
- }
+ },
+ "lst111" : [
+ {
+ "lf1111" : 65
+ }
+ ],
+ "lst112" : [
+ {
+ "lf1121" : "lf1121 str11"
+ }
+ ]
+
},
{
"lf111":141,
"lf1111B": 8
}
]
- }
+ },
+ "lst111" : [
+ {
+ "lf1111" : 55
+ },
+ {
+ "lf1111" : 56
+ }
+ ],
}
]
+ "lst112" : [
+ {
+ "lf1121" : "lf1121 str21"
+ },
+ {
+ "lf1121" : "lf1121 str22"
+ }
+ ]
+ }
+ ]
}
}
\ No newline at end of file