import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-abstract public class ClusterManagerCommon implements IClusterServicesCommon {
+public abstract class ClusterManagerCommon implements IClusterServicesCommon {
protected String containerName = null;
private IClusterServices clusterService = null;
protected static final Logger logger = LoggerFactory
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-abstract public class ClusterManagerCommon implements IClusterServicesCommon {
+public abstract class ClusterManagerCommon implements IClusterServicesCommon {
protected String containerName = "";
protected static final Logger logger = LoggerFactory
.getLogger(ClusterManagerCommon.class);
<artifactId>jersey-json</artifactId>
<version>${jersey.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-all</artifactId>
+ <version>4.1</version>
+ </dependency>
</dependencies>
</project>
<!-- Northbound bundles -->
<module>../../northbound/commons</module>
+ <module>../../northbound/bundlescanner/api</module>
+ <module>../../northbound/bundlescanner/implementation</module>
<module>../../northbound/topology</module>
<module>../../northbound/staticrouting</module>
<module>../../northbound/statistics</module>
private final FlowEntry original;
private final ContainerFlow cFlow;
private final FlowEntry install;
- transient private long requestId; // async request id
- transient private boolean deletePending;
+ private transient long requestId; // async request id
+ private transient boolean deletePending;
public FlowEntryInstall(FlowEntry original, ContainerFlow cFlow) {
this.original = original;
* Serialization UID
*/
private static final long serialVersionUID = 416280377113255147L;
- final private FlowEntryInstall entry;
- final private UpdateType upType;
- final private InetAddress requestorController;
+ private final FlowEntryInstall entry;
+ private final UpdateType upType;
+ private final InetAddress requestorController;
/**
* @return the entry
addStaticFlowInternal(allowARP, true); // skip validation on internal static flow name
}
+ /**
+ * (non-Javadoc)
+ *
+ * @see org.opendaylight.controller.switchmanager.ISwitchManagerAware#modeChangeNotify(org.opendaylight.controller.sal.core.Node,
+ * boolean)
+ *
+ * This method can be called from within the OSGi framework context,
+ * given the programming operation can take sometime, it not good
+ * pratice to have in it's context operations that can take time,
+ * hence moving off to a different thread for async processing.
+ */
@Override
- public void modeChangeNotify(Node node, boolean proactive) {
- List<FlowConfig> defaultConfigs = new ArrayList<FlowConfig>();
-
- List<String> puntAction = new ArrayList<String>();
- puntAction.add(ActionType.CONTROLLER.toString());
-
- FlowConfig allowARP = new FlowConfig();
- allowARP.setInstallInHw(true);
- allowARP.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Punt ARP" + FlowConfig.INTERNALSTATICFLOWEND);
- allowARP.setPriority("1");
- allowARP.setNode(node);
- allowARP.setEtherType("0x" + Integer.toHexString(EtherTypes.ARP.intValue()).toUpperCase());
- allowARP.setActions(puntAction);
- defaultConfigs.add(allowARP);
-
- FlowConfig allowLLDP = new FlowConfig();
- allowLLDP.setInstallInHw(true);
- allowLLDP.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Punt LLDP" + FlowConfig.INTERNALSTATICFLOWEND);
- allowLLDP.setPriority("1");
- allowLLDP.setNode(node);
- allowLLDP.setEtherType("0x" + Integer.toHexString(EtherTypes.LLDP.intValue()).toUpperCase());
- allowLLDP.setActions(puntAction);
- defaultConfigs.add(allowLLDP);
-
- List<String> dropAction = new ArrayList<String>();
- dropAction.add(ActionType.DROP.toString());
-
- FlowConfig dropAllConfig = new FlowConfig();
- dropAllConfig.setInstallInHw(true);
- dropAllConfig.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Catch-All Drop" + FlowConfig.INTERNALSTATICFLOWEND);
- dropAllConfig.setPriority("0");
- dropAllConfig.setNode(node);
- dropAllConfig.setActions(dropAction);
- defaultConfigs.add(dropAllConfig);
-
- log.info("Forwarding mode for node {} set to {}", node, (proactive ? "proactive" : "reactive"));
- for (FlowConfig fc : defaultConfigs) {
- Status status = (proactive) ? addStaticFlowInternal(fc, false) : removeStaticFlow(fc);
- if (status.isSuccess()) {
- log.info("{} Proactive Static flow: {}", (proactive ? "Installed" : "Removed"), fc.getName());
- } else {
- log.warn("Failed to {} Proactive Static flow: {}", (proactive ? "install" : "remove"), fc.getName());
+ public void modeChangeNotify(final Node node, final boolean proactive) {
+ Callable<Status> modeChangeCallable = new Callable<Status>() {
+ @Override
+ public Status call() throws Exception {
+ List<FlowConfig> defaultConfigs = new ArrayList<FlowConfig>();
+
+ List<String> puntAction = new ArrayList<String>();
+ puntAction.add(ActionType.CONTROLLER.toString());
+
+ FlowConfig allowARP = new FlowConfig();
+ allowARP.setInstallInHw(true);
+ allowARP.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Punt ARP" + FlowConfig.INTERNALSTATICFLOWEND);
+ allowARP.setPriority("1");
+ allowARP.setNode(node);
+ allowARP.setEtherType("0x" + Integer.toHexString(EtherTypes.ARP.intValue())
+ .toUpperCase());
+ allowARP.setActions(puntAction);
+ defaultConfigs.add(allowARP);
+
+ FlowConfig allowLLDP = new FlowConfig();
+ allowLLDP.setInstallInHw(true);
+ allowLLDP.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Punt LLDP" + FlowConfig.INTERNALSTATICFLOWEND);
+ allowLLDP.setPriority("1");
+ allowLLDP.setNode(node);
+ allowLLDP.setEtherType("0x" + Integer.toHexString(EtherTypes.LLDP.intValue())
+ .toUpperCase());
+ allowLLDP.setActions(puntAction);
+ defaultConfigs.add(allowLLDP);
+
+ List<String> dropAction = new ArrayList<String>();
+ dropAction.add(ActionType.DROP.toString());
+
+ FlowConfig dropAllConfig = new FlowConfig();
+ dropAllConfig.setInstallInHw(true);
+ dropAllConfig.setName(FlowConfig.INTERNALSTATICFLOWBEGIN + "Catch-All Drop"
+ + FlowConfig.INTERNALSTATICFLOWEND);
+ dropAllConfig.setPriority("0");
+ dropAllConfig.setNode(node);
+ dropAllConfig.setActions(dropAction);
+ defaultConfigs.add(dropAllConfig);
+
+ log.info("Forwarding mode for node {} set to {}", node, (proactive ? "proactive" : "reactive"));
+ for (FlowConfig fc : defaultConfigs) {
+ Status status = (proactive) ? addStaticFlowInternal(fc, false) : removeStaticFlow(fc);
+ if (status.isSuccess()) {
+ log.info("{} Proactive Static flow: {}", (proactive ? "Installed" : "Removed"), fc.getName());
+ } else {
+ log.warn("Failed to {} Proactive Static flow: {}", (proactive ? "install" : "remove"),
+ fc.getName());
+ }
+ }
+ return new Status(StatusCode.SUCCESS);
}
- }
+ };
+
+ /*
+ * Execute the work outside the caller context, this could be an
+ * expensive operation and we don't want to block the caller for it.
+ */
+ this.executor.submit(modeChangeCallable);
}
/**
--- /dev/null
+<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>commons.opendaylight</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../../../commons/opendaylight</relativePath>
+ </parent>
+
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+ </scm>
+
+ <artifactId>bundlescanner</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.6</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ org.osgi.framework,
+ org.slf4j,
+ javax.ws.rs,
+ javax.ws.rs.core,
+ javax.xml.bind.annotation,
+ javax.xml.bind,
+ </Import-Package>
+ <Export-Package>
+ org.opendaylight.controller.northbound.bundlescanner
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.northbound.bundlescanner;
+
+import java.util.List;
+
+import org.osgi.framework.BundleContext;
+
+/**
+ * The bundle scan service provides services which allow introspection of
+ * bundle classes for detecting annotated classes. The scanning is performed
+ * when a bundle is RESOLVED.
+ */
+public interface IBundleScanService {
+ /**
+ * The list of annotations to be scanned
+ */
+ public final String[] ANNOTATIONS_TO_SCAN = {
+ "javax.xml.bind.annotation.*", // JAXB annotatinos
+ "javax.ws.rs.*" // JAX-RS annotatinos
+ };
+
+
+ public List<Class<?>> getAnnotatedClasses(
+ BundleContext context,
+ String[] annotations,
+ boolean includeDependentBundleClasses);
+}
--- /dev/null
+<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>commons.opendaylight</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../../../commons/opendaylight</relativePath>
+ </parent>
+
+ <scm>
+ <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+ <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+ <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:Main</url>
+ </scm>
+
+ <artifactId>bundlescanner.implementation</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.3.6</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ org.apache.felix.dm,
+ org.objectweb.asm,
+ org.opendaylight.controller.sal.core,
+ org.opendaylight.controller.northbound.bundlescanner,
+ org.osgi.framework,
+ org.slf4j,
+ javax.ws.rs,
+ javax.ws.rs.core,
+ javax.xml.bind.annotation,
+ javax.xml.bind,
+ </Import-Package>
+ <Bundle-Activator>
+ org.opendaylight.controller.northbound.bundlescanner.internal.Activator
+ </Bundle-Activator>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-all</artifactId>
+ <version>4.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.osgi</groupId>
+ <artifactId>spring-osgi-mock</artifactId>
+ <version>1.2.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>bundlescanner</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal</artifactId>
+ <version>0.5.0-SNAPSHOT</version>
+ <type>bundle</type>
+ </dependency>
+ </dependencies>
+</project>
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.northbound.bundlescanner.internal;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.northbound.bundlescanner.IBundleScanService;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+
+/**
+ * The activator registers the BundleScanner.
+ */
+public class Activator extends ComponentActivatorAbstractBase {
+
+ @Override
+ protected void init() {
+ }
+
+ @Override
+ protected void destroy() {
+ }
+
+ @Override
+ protected Object[] getGlobalImplementations() {
+ return new Object[] { BundleScanServiceImpl.class };
+ }
+
+ @Override
+ protected void configureGlobalInstance(Component c, Object imp) {
+ if (!imp.equals(BundleScanServiceImpl.class)) return;
+ // export service
+ c.setInterface(
+ new String[] { IBundleScanService.class.getName() },
+ null);
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.northbound.bundlescanner.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * BundleInfo holds information related to the bundle obtained during the
+ * bundle scan process.
+ */
+/*package*/ class BundleInfo {
+ private static final Logger LOGGER = LoggerFactory.getLogger(BundleInfo.class);
+
+ private final Bundle bundle;
+ private final Map<String, Set<String>> annotatedClasses;
+ private final Set<String> exportPkgs;
+ private final Set<String> importPkgs;
+
+ public BundleInfo(Bundle bundle, Map<String, Set<String>> classes) {
+ this.bundle = bundle;
+ this.annotatedClasses = classes;
+ Dictionary<String, String> dict = bundle.getHeaders();
+ this.importPkgs = parsePackages(dict.get(Constants.IMPORT_PACKAGE));
+ this.exportPkgs = parsePackages(dict.get(Constants.EXPORT_PACKAGE));
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(super.toString());
+ sb.append("{name:").append(bundle.getSymbolicName())
+ .append(" id:").append(getId())
+ .append(" annotated-classes:").append(annotatedClasses)
+ .append(" imports:").append(importPkgs)
+ .append(" exports:").append(exportPkgs).append("}");
+ return sb.toString();
+ }
+
+ public Bundle getBundle() {
+ return bundle;
+ }
+
+ public long getId() {
+ return bundle.getBundleId();
+ }
+
+ public List<Class<?>> getAnnotatedClasses(Pattern pattern) {
+ List<String> result = new ArrayList<String>();
+ for (Map.Entry<String, Set<String>> entry : annotatedClasses.entrySet()) {
+ if (matches(pattern, entry.getValue())) {
+ result.add(entry.getKey());
+ }
+ }
+ return BundleScanner.loadClasses(bundle, result);
+ }
+
+ private boolean matches(Pattern pattern, Set<String> values) {
+ if (pattern == null) return true;
+ //LOGGER.debug("Matching: {} {}", pattern.toString(), values);
+ for (String s : values) {
+ if (pattern.matcher(s).find()) return true;
+ }
+ return false;
+ }
+
+ public List<Class<?>> getAnnotatedClasses(
+ Collection<BundleInfo> allbundles,
+ Pattern pattern)
+ {
+ List<Class<?>> classes = getAnnotatedClasses(pattern);
+ processAnnotatedClassesInternal(this, allbundles, pattern,
+ new HashSet<BundleInfo>(), classes);
+ return classes;
+ }
+
+ private List<String> getExportedAnnotatedClasses(Pattern pattern) {
+ List<String> classes = new ArrayList<String>();
+ for (Map.Entry<String, Set<String>> entry : annotatedClasses.entrySet()) {
+ String cls = entry.getKey();
+ int idx = cls.lastIndexOf(".");
+ String pkg = (idx == -1 ? "" : cls.substring(0, idx));
+ // for a class to match, the package has to be exported and
+ // annotations should match the given pattern
+ if (exportPkgs.contains(pkg) && matches(pattern, entry.getValue())) {
+ classes.add(cls);
+ }
+ }
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Found in bundle:{} exported classes:[{}]",
+ getBundle().getSymbolicName(), classes);
+ }
+ return classes;
+ }
+
+ private static void processAnnotatedClassesInternal(
+ BundleInfo target,
+ Collection<BundleInfo> bundlesToScan,
+ Pattern pattern,
+ Collection<BundleInfo> visited,
+ List<Class<?>> classes)
+ {
+ for (BundleInfo other : bundlesToScan) {
+ if (other.getId() == target.getId()) continue;
+ if (target.isDependantOn(other)) {
+ if (!visited.contains(other)) {
+ classes.addAll(BundleScanner.loadClasses(other.getBundle(),
+ other.getExportedAnnotatedClasses(pattern)));
+ visited.add(other);
+ processAnnotatedClassesInternal(other, bundlesToScan,
+ pattern, visited, classes);
+ }
+ }
+ }
+ }
+
+ private boolean isDependantOn(BundleInfo other) {
+ for (String pkg : importPkgs) {
+ if (other.exportPkgs.contains(pkg)) return true;
+ }
+ return false;
+ }
+
+ public List<BundleInfo> getDependencies(Collection<BundleInfo> bundles) {
+ List<BundleInfo> result = new ArrayList<BundleInfo>();
+ for(BundleInfo bundle : bundles) {
+ if (isDependantOn(bundle)) result.add(bundle);
+ }
+ return result;
+ }
+
+
+ private static Set<String> parsePackages(String packageString) {
+ if (packageString == null) return Collections.emptySet();
+ String[] packages = packageString.split(",");
+ Set<String> result = new HashSet<String>();
+ for (int i=0; i<packages.length; i++) {
+ String[] nameAndAttrs = packages[i].split(";");
+ String packageName = nameAndAttrs[0].trim();
+ result.add(packageName);
+ }
+ return result;
+ }
+
+}
--- /dev/null
+package org.opendaylight.controller.northbound.bundlescanner.internal;
+
+import java.util.List;
+
+import org.opendaylight.controller.northbound.bundlescanner.IBundleScanService;
+import org.osgi.framework.BundleContext;
+
+public class BundleScanServiceImpl implements IBundleScanService {
+
+ public BundleScanServiceImpl() {}
+
+
+ @Override
+ public List<Class<?>> getAnnotatedClasses(BundleContext context,
+ String[] annotations,
+ boolean includeDependentBundleClasses)
+ {
+ return BundleScanner.getInstance().getAnnotatedClasses(
+ context, annotations, includeDependentBundleClasses);
+ }
+
+}
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.northbound.bundlescanner.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Opcodes;
+import org.opendaylight.controller.northbound.bundlescanner.IBundleScanService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.SynchronousBundleListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The custom bundle scanner scans annotations on bundles and is used for
+ * constructing JAXBContext instances. It listens for bundle events and updates
+ * the metadata in realtime.
+ */
+/*package*/ class BundleScanner implements SynchronousBundleListener {
+ private static final Logger LOGGER = LoggerFactory.getLogger(BundleScanner.class);
+ private static BundleScanner INSTANCE; // singleton
+
+ private final Pattern annotationPattern;
+ private final Map<Long,BundleInfo> bundleAnnotations =
+ new HashMap<Long, BundleInfo>();
+
+ public static synchronized BundleScanner getInstance() {
+ if (INSTANCE == null) {
+ INSTANCE = new BundleScanner();
+ }
+ return INSTANCE;
+ }
+
+ /*package*/ BundleScanner(Bundle[] bundles) {
+ annotationPattern = mergePatterns(IBundleScanService.ANNOTATIONS_TO_SCAN, true);
+ init(bundles);
+ }
+
+ /*package*/ BundleScanner() {
+ this(FrameworkUtil.getBundle(BundleScanner.class).getBundleContext().getBundles());
+ }
+
+ public List<Class<?>> getAnnotatedClasses(BundleContext context,
+ String[] annotations,
+ boolean includeDependentBundleClasses)
+ {
+ BundleInfo info = bundleAnnotations.get(context.getBundle().getBundleId());
+ if (info == null) return Collections.emptyList();
+ Pattern pattern = mergePatterns(annotations, false);
+ List<Class<?>> result = null;
+ if (includeDependentBundleClasses) {
+ result = info.getAnnotatedClasses(bundleAnnotations.values(), pattern);
+ } else {
+ result = info.getAnnotatedClasses(pattern);
+ }
+ LOGGER.debug("Annotated classes detected: {} matching: {}", result, pattern);
+ return result;
+ }
+
+ ////////////////////////////////////////////////////////////////
+ // SynchronousBundleListener implementation
+ ////////////////////////////////////////////////////////////////
+
+ @Override
+ public void bundleChanged(BundleEvent event) {
+ Bundle bundle = event.getBundle();
+ long id = bundle.getBundleId();
+ switch(event.getType()) {
+ case BundleEvent.RESOLVED :
+ scan(bundle);
+ return;
+ case BundleEvent.UNRESOLVED :
+ case BundleEvent.UNINSTALLED :
+ bundleAnnotations.remove(id);
+ return;
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////
+ // ClassVisitor implementation
+ ////////////////////////////////////////////////////////////////
+
+ private static class AnnotationDetector extends ClassVisitor {
+ private final Map<String, Set<String>> matchedClasses =
+ new HashMap<String, Set<String>>();
+
+ private final Pattern annotationsPattern;
+ private Set<String> annotations;
+ private String className;
+ private boolean accessible;
+ private boolean matchedAnnotation;
+
+ public AnnotationDetector(Pattern pattern) {
+ super(Opcodes.ASM4);
+ this.annotationsPattern = pattern;
+ }
+
+ public Map<String, Set<String>> getMatchedClasses() {
+ return new HashMap<String, Set<String>>(matchedClasses);
+ }
+
+ @Override
+ public void visit(int version, int access, String name, String signature,
+ String superName, String[] interfaces)
+ {
+ //LOGGER.debug("Visiting class:" + name);
+ className = name;
+ accessible = ((access & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC);
+ matchedAnnotation = false;
+ annotations = new HashSet<String>();
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ //LOGGER.debug("Visiting annotation:" + desc);
+ annotations.add(signature2class(desc));
+ if (!matchedAnnotation) {
+ matchedAnnotation = (annotationsPattern == null ||
+ annotationsPattern.matcher(desc).find());
+ }
+ return null;
+ }
+
+ @Override
+ public void visitEnd() {
+ if (matchedAnnotation && accessible) {
+ className = path2class(className);
+ matchedClasses.put(className, new HashSet<String>(annotations));
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////
+ // Helpers
+ ////////////////////////////////////////////////////////////////
+
+ private synchronized void init(Bundle[] bundles) {
+ for (Bundle bundle : bundles) {
+ int state = bundle.getState();
+ if (state == Bundle.RESOLVED ||
+ state == Bundle.STARTING ||
+ state == Bundle.ACTIVE)
+ {
+ scan(bundle);
+ }
+ }
+ }
+
+ private static String path2class(String path) {
+ return path.replace(".class", "").replaceAll("/", ".");
+ }
+
+ private static String class2path(String clz) {
+ return clz.replaceAll("\\.", "/");
+ }
+
+ @SuppressWarnings("unused")
+ private static String class2signature(String clz) {
+ return "L" + class2path(clz) + ";";
+ }
+
+ private static String signature2class(String sig) {
+ if (sig.startsWith("L") && sig.endsWith(";")) {
+ sig = sig.substring(1, sig.length()-1);
+ }
+ return path2class(sig);
+ }
+
+ private static List<URL> getBundleClasses(Bundle bundle, String[] pkgs) {
+ List<URL> result = new ArrayList<URL>();
+ boolean recurse = false;
+ if (pkgs == null) {
+ recurse = true;
+ pkgs = new String[] { "/" } ;
+ }
+ for (String pkg : pkgs) {
+ pkg = class2path(pkg);
+ final Enumeration<URL> e = bundle.findEntries(pkg, "*.class", recurse);
+ if (e != null) {
+ while (e.hasMoreElements()) {
+ URL url = e.nextElement();
+ result.add(url);
+ }
+ }
+ }
+ return result;
+ }
+
+ private synchronized void scan(Bundle bundle) {
+ AnnotationDetector detector = new AnnotationDetector(annotationPattern);
+ try {
+ for (URL u : getBundleClasses(bundle, null)) {
+ InputStream is = u.openStream();
+ new ClassReader(is).accept(detector, 0);
+ is.close();
+ }
+ } catch (IOException ioe) {
+ LOGGER.error("Error scanning classes in bundle: {}", bundle.getSymbolicName(), ioe);
+ }
+ Map<String, Set<String>> classes = detector.getMatchedClasses();
+ if (classes != null && classes.size() > 0) {
+ BundleInfo info = new BundleInfo(bundle, classes);
+ bundleAnnotations.put(bundle.getBundleId(),info);
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("bindings found in bundle: {}[{}] " +
+ "dependencies {} classes {}", bundle.getSymbolicName(),
+ bundle.getBundleId(),
+ info.getDependencies(bundleAnnotations.values()),
+ classes);
+ }
+ }
+ // find bundle dependencies
+ }
+
+ public static List<Class<?>> loadClasses(Bundle bundle,
+ Collection<String> annotatedClasses)
+ {
+ List<Class<?>> result = new ArrayList<Class<?>>();
+ for (String name : annotatedClasses) {
+ try {
+ result.add(bundle.loadClass(name));
+ } catch (Exception e) {
+ LOGGER.error("Unable to load class: {}", name, e);
+ }
+ }
+ return result;
+ }
+
+ public static Pattern mergePatterns(String[] patterns, boolean convert2signature) {
+ if (patterns == null || patterns.length == 0) {
+ return null;
+ }
+ StringBuilder regex = new StringBuilder();
+ for (String c : patterns) {
+ if (c.endsWith("*")) {
+ c = c.substring(0, c.length() - 1);
+ }
+ if (regex.length() > 0) regex.append("|");
+ regex.append("^");
+ if (convert2signature) {
+ regex.append("L").append(c.replaceAll("\\.", "/"));
+ } else {
+ regex.append(c);
+ }
+ }
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Merged regex: [{}]", regex.toString());
+ }
+ return Pattern.compile(regex.toString());
+ }
+
+}
--- /dev/null
+package bundle_base;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public abstract class Animal { }
--- /dev/null
+package bundle_base;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSeeAlso;
+
+@XmlRootElement
+public class BasePerson { }
\ No newline at end of file
--- /dev/null
+package bundle_base;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class Mammal extends Animal { }
--- /dev/null
+package bundle_base;
+
+public class NoAnnotation { }
--- /dev/null
+package bundle_base;
+
+@Deprecated
+public class NonRelevantAnnotation {
+
+}
--- /dev/null
+package bundle_base;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+@XmlTransient
+@Deprecated
+public class Person extends BasePerson {
+
+ @XmlElement
+ protected String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @XmlRootElement
+ public static class Info { }
+
+ @XmlRootElement
+ private static class PrivateInfo { }
+}
--- /dev/null
+package bundle_misc;
+import javax.xml.bind.annotation.XmlRootElement;
+
+@XmlRootElement
+public class Misc {
+
+}
--- /dev/null
+package bundle_sub1;
+
+public class NoAnnotation {
+
+}
--- /dev/null
+package bundle_sub1;
+
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import bundle_base.Animal;
+import bundle_base.Mammal;
+
+
+@XmlRootElement
+public class Zoo {
+ private Animal creature;
+
+ @XmlElementRef
+ public Animal getCreature() {
+ return creature;
+ }
+
+ public void setCreature(Animal creature) {
+ this.creature = creature;
+ }
+
+ public Zoo() {
+ creature = new Mammal();
+ }
+}
--- /dev/null
+package bundle_sub2;
+
+import javax.xml.bind.annotation.XmlRootElement;
+
+import bundle_base.Person;
+
+
+@XmlRootElement
+public class Agent extends Person {
+
+}
\ No newline at end of file
--- /dev/null
+package bundle_sub2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import bundle_base.BasePerson;
+import bundle_base.Person;
+
+
+@XmlRootElement
+public class Customer extends Person {
+
+ private String password;
+ private List<String> phoneNumbers;
+ @XmlElementRef
+ @XmlElementWrapper
+ private final List<BasePerson> agents = new ArrayList<BasePerson>();
+
+ @XmlTransient
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ @XmlElement(name = "phone-number")
+ public List<String> getPhoneNumbers() {
+ return phoneNumbers;
+ }
+
+ public void setPhoneNumbers(List<String> phoneNumbers) {
+ this.phoneNumbers = phoneNumbers;
+ }
+
+ public void addAgent(Person mgr) {
+ this.agents.add(mgr);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder(super.toString());
+ sb.append(" password:").append(password);
+ sb.append(" phoneNumbers:").append(phoneNumbers);
+ sb.append(" agents:").append(agents);
+ return sb.toString();
+ }
+}
+
--- /dev/null
+package bundle_sub2;
+
+public class NoAnnotation {
+
+}
--- /dev/null
+package org.opendaylight.controller.northbound.bundlescanner.internal;
+
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.JAXBException;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+import org.opendaylight.controller.northbound.bundlescanner.IBundleScanService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Constants;
+import org.springframework.osgi.mock.MockBundle;
+import org.springframework.osgi.mock.MockBundleContext;
+import org.springframework.osgi.mock.MockFrameworkUtil;
+
+public class BundleScannerTest {
+
+ private static BundleScanner bundleScanner;
+ private static List<Bundle> bundles;
+ @Rule
+ public final TestName testName = new TestName();
+
+ @BeforeClass
+ public static void init() throws Exception {
+ bundles = makeMockBundles();
+ bundleScanner = new BundleScanner(bundles.toArray(new Bundle[bundles.size()]));
+ }
+
+ @AfterClass
+ public static void destroy() throws Exception {
+ }
+
+ @Before
+ public void setup() {
+ System.out.println("==== " + testName.getMethodName());
+ }
+
+ @Test
+ public void testValidateBundles() {
+ assertNotNull(bundleScanner);
+ BundleContext context = bundles.get(0).getBundleContext();
+ assertNotNull(context.getBundle());
+ assertNotNull(context.getBundles());
+ assertNotNull(context.getBundles().length >= 4);
+ }
+
+ @Test
+ public void testBundleEvents() throws Exception {
+ MockBundle newBundle = new TestMockBundle("misc", "", "bundle_misc");
+ assertTrue(bundleScanner.getAnnotatedClasses(
+ newBundle.getBundleContext(), null, false).size() == 0);
+ BundleEvent event = new BundleEvent(BundleEvent.RESOLVED, newBundle);
+ bundleScanner.bundleChanged(event);
+ assertTrue(bundleScanner.getAnnotatedClasses(
+ newBundle.getBundleContext(), null, false).size() == 1);
+ }
+
+ @Test
+ public void testAnnotatedClassesWithDependencies() throws Exception {
+ for (Bundle bundle : bundles) {
+ List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
+ bundle.getBundleContext(), null, true);
+ String name = bundle.getSymbolicName();
+ System.out.println("name:" + name + " classes:" + classes.size());
+ if ("misc".equals(name)) {
+ assertTrue(classes.size() == 1);
+ } else if ("base".equals(name)) {
+ assertTrue(classes.size() == 5);
+ } else if ("sub1".equals(name)) {
+ assertTrue(classes.size() == 6);
+ } else if ("sub2".equals(name)) {
+ assertTrue(classes.size() == 7);
+ }
+ }
+ }
+
+ @Test
+ public void testExactFiltering() {
+ Bundle bundle = findBundle("sub1");
+ String[] annos = { "javax.xml.bind.annotation.XmlTransient" };
+ List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
+ bundle.getBundleContext(), annos, true);
+ assertTrue(classes.size() == 1);
+ }
+
+ @Test
+ public void testNonExactFiltering() {
+ Bundle bundle = findBundle("sub1");
+ String[] annos = { "javax.xml.bind.annotation.*" };
+ List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
+ bundle.getBundleContext(), annos, true);
+ assertTrue(classes.size() == 6);
+ }
+
+ @Test
+ public void testFilteringUnmatched() {
+ Bundle bundle = findBundle("sub1");
+ String[] annos = { "non.existent.pkg" };
+ List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
+ bundle.getBundleContext(), annos, true);
+ assertTrue(classes.size() == 0);
+ }
+
+ @Test
+ public void testRegexMerge() {
+ Pattern pattern = BundleScanner.mergePatterns(
+ new String[] {
+ "javax.xml.bind.annotation.*",
+ "javax.ws.rs.Path"
+ },
+ true
+ );
+ assertTrue(pattern.matcher("Ljavax/xml/bind/annotation/FOO;").find());
+ assertFalse(pattern.matcher("Ljavax/servlet/FOO;").find());
+ }
+
+ private static Bundle findBundle(String symName) {
+ for (Bundle bundle : bundles) {
+ if (bundle.getSymbolicName().equals(symName)) return bundle;
+ }
+ return null;
+ }
+
+ private static List<Bundle> makeMockBundles() throws Exception {
+ List<Bundle> result = new ArrayList<Bundle>();
+ result.add(new MockBundle());
+ result.add(new TestMockBundle("base", "", "bundle_base"));
+ result.add(new TestMockBundle("sub1", "bundle_base", "bundle_sub1"));
+ result.add(new TestMockBundle("sub2", "bundle_base", "bundle_sub2"));
+ return result;
+ }
+
+ private static List<URL> findClasses(String pkg) throws URISyntaxException {
+ if (pkg == null) return Collections.EMPTY_LIST;
+ String npkg = pkg.replaceAll("\\.", "/");
+ URL dirUrl = BundleScannerTest.class.getClassLoader().getResource(npkg);
+ final List<URL> result = new ArrayList<URL>();
+ File dir = new File(dirUrl.toURI());
+ dir.listFiles(new FileFilter() {
+
+ @Override
+ public boolean accept(File file) {
+ if (file.isFile() && file.getName().endsWith(".class")) {
+ try {
+ result.add(file.toURI().toURL());
+ } catch (MalformedURLException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return false;
+ }
+
+ });
+ return result;
+ }
+
+ public static class TestMockBundle extends MockBundle {
+ List<URL> classes;
+ public TestMockBundle(String name, String imports, String exports) throws Exception {
+ super(name, makeHeaders(name, imports, exports), new MockBundleContext() {
+ @Override
+ public Bundle[] getBundles() {
+ return bundles.toArray(new Bundle[bundles.size()]);
+ }
+ });
+ MockBundleContext ctx = (MockBundleContext) this.getBundleContext();
+ ctx.setBundle(this);
+ this.classes = findClasses(exports);
+ }
+
+ private static Dictionary<String,String> makeHeaders(
+ String name, String imports, String exports)
+ {
+ Dictionary<String,String> headers = new Hashtable<String,String>();
+ headers.put(Constants.IMPORT_PACKAGE, imports);
+ headers.put(Constants.EXPORT_PACKAGE, exports);
+ headers.put(Constants.BUNDLE_SYMBOLICNAME, name);
+ return headers;
+ }
+
+ @Override
+ public Enumeration findEntries(String path, String filePattern, boolean recurse) {
+ return Collections.enumeration(classes);
+ }
+
+ @Override
+ public long getBundleId() {
+ return hashCode();
+ }
+ }
+}
</Export-Package>
<Import-Package>
javax.ws.rs,
+ javax.ws.rs.ext,
javax.ws.rs.core,
+ javax.xml.bind,
javax.xml.bind.annotation,
+ org.objectweb.asm,
org.opendaylight.controller.sal.utils,
org.opendaylight.controller.sal.authorization,
org.opendaylight.controller.containermanager,
org.opendaylight.controller.usermanager,
+ org.opendaylight.controller.northbound.bundlescanner,
+ org.osgi.framework,
+ org.osgi.service.packageadmin,
+ org.osgi.util.tracker,
javax.servlet.http,
+ org.codehaus.jackson.jaxrs,
org.slf4j
</Import-Package>
</instructions>
<artifactId>usermanager</artifactId>
<version>0.4.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>bundlescanner</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
</dependencies>
</project>
--- /dev/null
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.northbound.commons;
+
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.ws.rs.core.Application;
+import javax.ws.rs.ext.ContextResolver;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
+import org.opendaylight.controller.northbound.bundlescanner.IBundleScanService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleReference;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceException;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Instance of javax.ws.rs.core.Application used to return the classes
+ * that will be instantiated for JAXRS processing. This hooks onto the
+ * bundle scanner service to provide JAXB classes to JAX-RS for prorcessing.
+ */
+@SuppressWarnings("unchecked")
+public class NorthboundApplication extends Application {
+ public static final String JAXRS_RESOURCES_MANIFEST_NAME = "Jaxrs-Resources";
+ private static final Logger LOGGER = LoggerFactory.getLogger(NorthboundApplication.class);
+
+ ////////////////////////////////////////////////////////////////
+ // Application overrides
+ ////////////////////////////////////////////////////////////////
+
+ @Override
+ public Set<Object> getSingletons() {
+ Set<Object> singletons = new HashSet<Object>();
+ singletons.add(new ContextResolver<JAXBContext>() {
+ @Override
+ public JAXBContext getContext(Class<?> type) {
+ return newJAXBContext();
+ }
+
+ } );
+ singletons.add(new JacksonJaxbJsonProvider());
+ return singletons;
+ }
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ Set<Class<?>> result = new HashSet<Class<?>>();
+ result.addAll(findJAXRSResourceClasses());
+ return result;
+ }
+
+ private BundleContext getBundleContext() {
+ ClassLoader tlcl = Thread.currentThread().getContextClassLoader();
+ Bundle bundle = null;
+
+ if (tlcl instanceof BundleReference) {
+ bundle = ((BundleReference) tlcl).getBundle();
+ } else {
+ LOGGER.warn("Unable to determine the bundle context based on " +
+ "thread context classloader.");
+ bundle = FrameworkUtil.getBundle(this.getClass());
+ }
+ return (bundle == null ? null : bundle.getBundleContext());
+ }
+
+ private static final IBundleScanService lookupBundleScanner(BundleContext ctx) {
+ ServiceReference svcRef = ctx.getServiceReference(IBundleScanService.class);
+ if (svcRef == null) {
+ throw new ServiceException("Unable to lookup IBundleScanService");
+ }
+ return IBundleScanService.class.cast(ctx.getService(svcRef));
+ }
+
+ private final JAXBContext newJAXBContext() {
+ BundleContext ctx = getBundleContext();
+ IBundleScanService svc = lookupBundleScanner(ctx);
+ try {
+ List<Class<?>> cls = svc.getAnnotatedClasses(ctx,
+ new String[] { XmlRootElement.class.getPackage().getName() },
+ true);
+ return JAXBContext.newInstance(cls.toArray(new Class[cls.size()]));
+ } catch (JAXBException je) {
+ LOGGER.error("Error creating JAXBContext", je);
+ return null;
+ }
+ }
+
+ private final Set<Class<?>> findJAXRSResourceClasses() {
+ BundleContext ctx = getBundleContext();
+ String bundleName = ctx.getBundle().getSymbolicName();
+ Set<Class<?>> result = new HashSet<Class<?>>();
+ ServiceException recordException = null;
+ try {
+ IBundleScanService svc = lookupBundleScanner(ctx);
+ result.addAll(svc.getAnnotatedClasses(ctx,
+ new String[] { javax.ws.rs.Path.class.getName() }, false));
+ } catch (ServiceException se) {
+ recordException = se;
+ LOGGER.debug("Error finding JAXRS resource annotated classes in " +
+ "bundle: {} error: {}.", bundleName, se.getMessage());
+ // the bundle scan service cannot be lookedup. Lets attempt to
+ // lookup the resources from the bundle manifest header
+ Dictionary<String,String> headers = ctx.getBundle().getHeaders();
+ String header = headers.get(JAXRS_RESOURCES_MANIFEST_NAME);
+ if (header != null) {
+ for (String s : header.split(",")) {
+ s = s.trim();
+ if (s.length() > 0) {
+ try {
+ result.add(ctx.getBundle().loadClass(s));
+ } catch (ClassNotFoundException cnfe) {
+ LOGGER.error("Cannot load class: {} in bundle: {} " +
+ "defined as MANIFEST JAX-RS resource", s, bundleName, cnfe);
+ }
+ }
+ }
+ }
+
+ }
+
+ if (result.size() == 0) {
+ if (recordException != null) {
+ throw recordException;
+ } else {
+ throw new ServiceException("No resource classes found in bundle:" +
+ ctx.getBundle().getSymbolicName());
+ }
+ }
+ return result;
+ }
+
+}
!org.codehaus.enunciate.jaxrs
</Import-Package>
<Web-ContextPath>/controller/nb/v2/containermanager</Web-ContextPath>
+ <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
</instructions>
</configuration>
</plugin>
<Export-Package>
</Export-Package>
<Web-ContextPath>/controller/nb/v2/flowprogrammer</Web-ContextPath>
+ <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
</instructions>
<manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
</configuration>
+++ /dev/null
-
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.flowprogrammer.northbound;
-
-import java.util.HashSet;
-import java.util.Set;
-import javax.ws.rs.core.Application;
-
-import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
-
-/**
- * Instance of javax.ws.rs.core.Application used to return the classes
- * that will be instantiated for JAXRS processing, this is necessary
- * because the package scanning in jersey doesn't yet work in OSGi
- * environment.
- *
- */
-public class FlowProgrammerNorthboundRSApplication extends Application {
- @Override
- public Set<Class<?>> getClasses() {
- Set<Class<?>> classes = new HashSet<Class<?>>();
- classes.add(FlowProgrammerNorthbound.class);
- classes.add(JacksonJaxbJsonProvider.class);
- return classes;
- }
-}
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
- <param-value>org.opendaylight.controller.flowprogrammer.northbound.FlowProgrammerNorthboundRSApplication</param-value>
+ <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
!org.codehaus.enunciate.jaxrs
</Import-Package>
<Web-ContextPath>/controller/nb/v2/hosttracker</Web-ContextPath>
+ <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
</instructions>
<manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
</configuration>
+++ /dev/null
-
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.hosttracker.northbound;
-
-import java.util.HashSet;
-import java.util.Set;
-import javax.ws.rs.core.Application;
-
-import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
-
-/**
- * This class is an instance of javax.ws.rs.core.Application used to return the classes
- * that will be instantiated for JAXRS processing, this is necessary
- * because the package scanning in jersey doesn't yet work in OSGi
- * environment.
- *
- */
-public class HostTrackerNorthboundRSApplication extends Application {
- @Override
- public Set<Class<?>> getClasses() {
- Set<Class<?>> classes = new HashSet<Class<?>>();
- classes.add(HostTrackerNorthbound.class);
- classes.add(JacksonJaxbJsonProvider.class);
- return classes;
- }
-}
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
- <param-value>org.opendaylight.controller.hosttracker.northbound.HostTrackerNorthboundRSApplication</param-value>
+ <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<version>0.4.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>bundlescanner</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>bundlescanner.implementation</artifactId>
+ <version>0.4.0-SNAPSHOT</version>
+ </dependency>
<dependency>
<groupId>org.codehaus.enunciate</groupId>
<version>${url.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-all</artifactId>
+ <version>4.1</version>
+ </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.asm</artifactId>
mavenBundle("org.opendaylight.controller", "logging.bridge").versionAsInProject(),
// mavenBundle("org.opendaylight.controller", "clustering.test").versionAsInProject(),
mavenBundle("org.opendaylight.controller", "forwarding.staticrouting").versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "bundlescanner").versionAsInProject(),
+ mavenBundle("org.opendaylight.controller", "bundlescanner.implementation").versionAsInProject(),
// Northbound bundles
mavenBundle("org.opendaylight.controller", "commons.northbound").versionAsInProject(),
mavenBundle("org.ops4j.pax.exam", "pax-exam-link-mvn").versionAsInProject(),
mavenBundle("org.ops4j.pax.url", "pax-url-aether").versionAsInProject(),
+ mavenBundle("org.ow2.asm", "asm-all").versionAsInProject(),
+
mavenBundle("org.springframework", "org.springframework.asm").versionAsInProject(),
mavenBundle("org.springframework", "org.springframework.aop").versionAsInProject(),
mavenBundle("org.springframework", "org.springframework.context").versionAsInProject(),
<Export-Package>
</Export-Package>
<Web-ContextPath>/controller/nb/v2/networkconfig/bridgedomain</Web-ContextPath>
+ <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
</instructions>
<manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
</configuration>
+++ /dev/null
-
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.networkconfig.bridgedomain.northbound;
-
-import java.util.HashSet;
-import java.util.Set;
-import javax.ws.rs.core.Application;
-
-import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
-
-/**
- * Instance of javax.ws.rs.core.Application used to return the classes
- * that will be instantiated for JAXRS processing, this is necessary
- * because the package scanning in jersey doesn't yet work in OSGi
- * environment.
- *
- */
-public class BridgeDomainNorthboundApplication extends Application {
- @Override
- public Set<Class<?>> getClasses() {
- Set<Class<?>> classes = new HashSet<Class<?>>();
- classes.add(BridgeDomainNorthbound.class);
- classes.add(JacksonJaxbJsonProvider.class);
- return classes;
- }
-}
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
- <param-value>org.opendaylight.controller.networkconfig.bridgedomain.northbound.BridgeDomainNorthboundApplication</param-value>
+ <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<Export-Package>
</Export-Package>
<Web-ContextPath>/controller/nb/v2/staticroute</Web-ContextPath>
+ <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
</instructions>
<manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
</configuration>
+++ /dev/null
-
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.forwarding.staticrouting.northbound;
-
-import java.util.HashSet;
-import java.util.Set;
-import javax.ws.rs.core.Application;
-
-import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
-
-/**
- * Instance of javax.ws.rs.core.Application used to return the classes
- * that will be instantiated for JAXRS processing, this is necessary
- * because the package scanning in jersey doesn't yet work in OSGi
- * environment.
- *
- */
-public class StaticRoutingNorthboundRSApplication extends Application {
- @Override
- public Set<Class<?>> getClasses() {
- Set<Class<?>> classes = new HashSet<Class<?>>();
- classes.add(StaticRoutingNorthbound.class);
- classes.add(JacksonJaxbJsonProvider.class);
- return classes;
- }
-}
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
- <param-value>org.opendaylight.controller.forwarding.staticrouting.northbound.StaticRoutingNorthboundRSApplication</param-value>
+ <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<Export-Package>
</Export-Package>
<Web-ContextPath>/controller/nb/v2/statistics</Web-ContextPath>
+ <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
</instructions>
<manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
</configuration>
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.statistics.northbound;
-
-import java.util.HashSet;
-import java.util.Set;
-import javax.ws.rs.core.Application;
-
-import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
-
-/**
- * Instance of javax.ws.rs.core.Application used to return the classes
- * that will be instantiated for JAXRS processing, this is necessary
- * because the package scanning in jersey doesn't yet work in OSGi
- * environment.
- *
- */
-public class StatisticsNorthboundRSApplication extends Application {
- @Override
- public Set<Class<?>> getClasses() {
- Set<Class<?>> classes = new HashSet<Class<?>>();
- classes.add(StatisticsNorthbound.class);
- classes.add(JacksonJaxbJsonProvider.class);
- return classes;
- }
-}
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
- <param-value>org.opendaylight.controller.statistics.northbound.StatisticsNorthboundRSApplication</param-value>
+ <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<Export-Package>
</Export-Package>
<Web-ContextPath>/controller/nb/v2/subnetservice</Web-ContextPath>
+ <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
</instructions>
<manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
</configuration>
+++ /dev/null
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.subnets.northbound;
-
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.ws.rs.core.Application;
-
-import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
-
-/**
- * Instance of javax.ws.rs.core.Application used to return the classes
- * that will be instantiated for JAXRS processing, this is necessary
- * because the package scanning in jersey doesn't yet work in OSGi
- * environment.
- *
- */
-public class SubnetsNorthboundRSApplication extends Application {
- @Override
- public Set<Class<?>> getClasses() {
- Set<Class<?>> classes = new HashSet<Class<?>>();
- classes.add(SubnetsNorthbound.class);
- classes.add(JacksonJaxbJsonProvider.class);
- return classes;
- }
-}
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
- <param-value>org.opendaylight.controller.subnets.northbound.SubnetsNorthboundRSApplication</param-value>
+ <param-value> org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
!org.codehaus.enunciate.jaxrs
</Import-Package>
<Web-ContextPath>/controller/nb/v2/switchmanager</Web-ContextPath>
+ <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
</instructions>
<manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
</configuration>
+++ /dev/null
-
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.switchmanager.northbound;
-
-import java.util.HashSet;
-import java.util.Set;
-import javax.ws.rs.core.Application;
-
-import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
-
-/**
- * Instance of javax.ws.rs.core.Application used to return the classes
- * that will be instantiated for JAXRS processing, this is necessary
- * because the package scanning in jersey doesn't yet work in OSGi
- * environment.
- *
- */
-public class SwitchNorthboundRSApplication extends Application {
- @Override
- public Set<Class<?>> getClasses() {
- Set<Class<?>> classes = new HashSet<Class<?>>();
- classes.add(SwitchNorthbound.class);
- classes.add(JacksonJaxbJsonProvider.class);
- return classes;
- }
-}
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
- <param-value>org.opendaylight.controller.switchmanager.northbound.SwitchNorthboundRSApplication</param-value>
+ <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
!org.codehaus.enunciate.jaxrs
</Import-Package>
<Web-ContextPath>/controller/nb/v2/topology</Web-ContextPath>
+ <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
</instructions>
<manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
</configuration>
+++ /dev/null
-
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.topology.northbound;
-
-import java.util.HashSet;
-import java.util.Set;
-import javax.ws.rs.core.Application;
-
-import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
-
-/**
- * Instance of javax.ws.rs.core.Application used to return the classes
- * that will be instantiated for JAXRS processing, this is necessary
- * because the package scanning in jersey doesn't yet work in OSGi
- * environment.
- *
- */
-public class TopologyNorthboundRSApplication extends Application {
- @Override
- public Set<Class<?>> getClasses() {
- Set<Class<?>> classes = new HashSet<Class<?>>();
- classes.add(TopologyNorthboundJAXRS.class);
- classes.add(JacksonJaxbJsonProvider.class);
- return classes;
- }
-}
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
- <param-value>org.opendaylight.controller.topology.northbound.TopologyNorthboundRSApplication</param-value>
+ <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
!org.codehaus.enunciate.jaxrs
</Import-Package>
<Web-ContextPath>/one/nb/v2/lb</Web-ContextPath>
+ <Jaxrs-Resources>,${classes;ANNOTATION;javax.ws.rs.Path}</Jaxrs-Resources>
</instructions>
<manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
</configuration>
+++ /dev/null
-/*
- * Copyright IBM Corporation, 2013. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.samples.loadbalancer.northbound;
-
-import java.util.HashSet;
-import java.util.Set;
-import javax.ws.rs.core.Application;
-
-import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
-
-/**
- * This class is an instance of javax.ws.rs.core.Application and is used to return the classes
- * that will be instantiated for JAXRS processing. This is necessary
- * because package scanning in jersey doesn't yet work in OSGi environment.
- *
- */
-public class LoadBalancerNorthboundRSApplication extends Application {
- @Override
- public Set<Class<?>> getClasses() {
- Set<Class<?>> classes = new HashSet<Class<?>>();
- classes.add(LoadBalancerNorthbound.class);
- classes.add(JacksonJaxbJsonProvider.class);
- return classes;
- }
-}
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
- <param-value>org.opendaylight.controller.samples.loadbalancer.northbound.LoadBalancerNorthboundRSApplication</param-value>
+ <param-value>org.opendaylight.controller.northbound.commons.NorthboundApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
org.opendaylight.controller.usermanager,
org.opendaylight.controller.web,
com.google.gson,
+ com.google.gson.reflect,
javax.annotation,
javax.naming,
javax.servlet,
package org.opendaylight.controller.devices.web;
+import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import org.springframework.web.bind.annotation.ResponseBody;
import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
@Controller
@RequestMapping("/")
// Add switch portName value (non-configuration field)
config.put("nodeName",
getNodeDesc(config_data.get("nodeId"), containerName));
+ NodeConnector spanPortNodeConnector = NodeConnector.fromString(config_data.get("spanPort"));
+ Name ncName = ((Name) switchManager.getNodeConnectorProp(spanPortNodeConnector,
+ Name.NamePropName));
+ String spanPortName = (ncName != null) ? ncName.getValue() : "";
+ config.put("spanPortName", spanPortName);
}
config.put("json", config_json);
spanConfigs.add(config);
Gson gson = new Gson();
ISwitchManager switchManager = (ISwitchManager) ServiceHelper
.getInstance(ISwitchManager.class, containerName, this);
- String[] spans = spanPortsToDelete.split("###");
- resultBean.setStatus(true);
- resultBean.setMessage("SPAN Port(s) deleted successfully");
- for (String span : spans) {
- if (!span.isEmpty()) {
- SpanConfig cfgObject = gson
- .fromJson(span, SpanConfig.class);
- Status result = switchManager.removeSpanConfig(cfgObject);
- if (!result.isSuccess()) {
- resultBean.setStatus(false);
- resultBean.setMessage(result.getDescription());
- break;
- }
- DaylightWebUtil.auditlog("SPAN Port", userName, "removed", cfgObject.getNodeId(), containerName);
+ Type collectionType = new TypeToken<List<SpanPortJsonBean>>() {}.getType();
+ List<SpanPortJsonBean> jsonBeanList = gson.fromJson(spanPortsToDelete, collectionType);
+ for (SpanPortJsonBean jsonBean : jsonBeanList) {
+ SpanConfig cfgObject = gson
+ .fromJson(gson.toJson(jsonBean), SpanConfig.class);
+ Status result = switchManager.removeSpanConfig(cfgObject);
+ if (!result.isSuccess()) {
+ resultBean.setStatus(false);
+ resultBean.setMessage(result.getDescription());
+ break;
}
+ DaylightWebUtil.auditlog("SPAN Port", userName, "removed", cfgObject.getNodeId(), containerName);
}
+ resultBean.setStatus(true);
+ resultBean.setMessage("SPAN Port(s) deleted successfully");
} catch (Exception e) {
resultBean.setStatus(false);
resultBean.setMessage("Error occurred while deleting span port. "
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.devices.web;
+
+public class SpanPortJsonBean {
+
+ private String nodeId;
+ private String spanPort;
+
+ public String getNodeId() {
+ return nodeId;
+ }
+
+ public void setNodeId(String nodeId) {
+ this.nodeId = nodeId;
+ }
+
+ public String getSpanPort() {
+ return spanPort;
+ }
+
+ public void setSpanPort(String spanPort) {
+ this.spanPort = spanPort;
+ }
+
+}
return false;
}
checkedCheckBoxes.each(function(index, value) {
- spanPortsToDelete.push(decodeURIComponent(checkedCheckBoxes[index].getAttribute("spanPort")));
+ var spanPortObj = {};
+ spanPortObj['spanPortJson'] = decodeURIComponent(checkedCheckBoxes[index].getAttribute("spanPort"));
+ spanPortObj['spanPortNodeName'] = checkedCheckBoxes[index].getAttribute("spanPortNode");
+ spanPortObj['spanPortPortName'] = checkedCheckBoxes[index].getAttribute("spanPortPort");
+
+ spanPortsToDelete.push(spanPortObj);
});
one.f.switchmanager.spanPortConfig.modal.removeMultiple.dialog(spanPortsToDelete);
});
// bind remove rule button
$('#'+one.f.switchmanager.spanPortConfig.id.modal.remove, $modal).click(this, function(e) {
var requestData = {};
- var spanPorts="";
- $(spanPortsToDelete).each(function(){
- spanPorts = spanPorts + "###" + this.toString();
+ var spanPorts = [];
+ $(spanPortsToDelete).each(function(index, spanPort) {
+ spanPorts.push(JSON.parse(spanPort.spanPortJson));
});
- requestData["spanPortsToDelete"] = spanPorts.slice(3,spanPorts.length);
-
+ requestData["spanPortsToDelete"] = JSON.stringify(spanPorts);
+
var url = one.f.switchmanager.rootUrl + "/spanPorts/delete";
one.f.switchmanager.spanPortConfig.ajax.main(url, requestData, function(response) {
$modal.modal('hide');
var p = 'Remove the following Span Port(s)?';
//creata a BS label for each rule and append to list
- var spanPortList = JSON.parse("["+spanPortToDelete.toString()+"]");
- $(spanPortList).each(function(){
+ $(spanPortToDelete).each(function(index, spanPortItem) {
var $span = $(document.createElement('span'));
- $span.append(this.nodeId+"-"+this.spanPort);
+ $span.append(this.spanPortNodeName+"-"+this.spanPortPortName);
p += '<br/>' + $span[0].outerHTML;
});
$p.append(p);
sortable: true
},
{
- property: 'spanPort',
+ property: 'spanPortName',
label: 'SPAN Port',
sortable: true
},
data: data.nodeData,
formatter: function(items) {
$.each(items, function(index, item) {
- item["selector"] = '<input type="checkbox" class="spanPortConfig" spanPort=' + encodeURIComponent(item["json"]) + '></input>';
+ item["selector"] = '<input type="checkbox" class="spanPortConfig" spanPort=' + encodeURIComponent(item["json"]) + ' spanPortNode=' + item["nodeName"] + ' spanPortPort=' + item["spanPortName"] + '></input>';
});
},
delay: 0
},
flows: function(nodeId) {
try {
+ if(one.f.troubleshooting === undefined){
+ return;
+ }
clearTimeout(one.f.troubleshooting.existingNodes.registry.refreshTimer);
$.getJSON(one.main.constants.address.prefix + "/troubleshoot/flowStats?nodeId=" + nodeId, function(content) {
$rightBottomDashlet = one.f.troubleshooting.rightBottomDashlet.get();
},
ports: function(nodeId) {
try {
+ if(one.f.troubleshooting === undefined){
+ return;
+ }
clearTimeout(one.f.troubleshooting.existingNodes.registry.refreshTimer);
$.getJSON(one.main.constants.address.prefix + "/troubleshoot/portStats?nodeId=" + nodeId, function(content) {
$rightBottomDashlet = one.f.troubleshooting.rightBottomDashlet.get();
* @param i OpenFlow wire protocol type
* @param t type
*/
- static public void addMapping(byte i, OFType t) {
+ public static void addMapping(byte i, OFType t) {
if (mapping == null)
mapping = new OFType[32];
OFType.mapping[i] = t;
*
* @param i OpenFlow wire protocol type
*/
- static public void removeMapping(byte i) {
+ public static void removeMapping(byte i) {
OFType.mapping[i] = null;
}
* @return OFType enum type
*/
- static public OFType valueOf(Byte i) {
+ public static OFType valueOf(Byte i) {
return OFType.mapping[i];
}