Cleaned-up templates and added package.html files.
diff --git a/net/api/src/main/java/org/onlab/onos/event/AbstractListenerManager.java b/net/api/src/main/java/org/onlab/onos/event/AbstractListenerManager.java
index d063b59..0ca3b8e 100644
--- a/net/api/src/main/java/org/onlab/onos/event/AbstractListenerManager.java
+++ b/net/api/src/main/java/org/onlab/onos/event/AbstractListenerManager.java
@@ -1,13 +1,13 @@
package org.onlab.onos.event;
import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
/**
* Base implementation of a manager capable of tracking listeners and
@@ -16,7 +16,7 @@
public class AbstractListenerManager<E extends Event, L extends EventListener<E>>
implements EventSink<E> {
- protected Logger log = LoggerFactory.getLogger(AbstractListenerManager.class);
+ private final Logger log = getLogger(getClass());
private final Set<L> listeners = new CopyOnWriteArraySet<>();
diff --git a/net/api/src/main/javadoc/org/onlab/onos/package.html b/net/api/src/main/javadoc/org/onlab/onos/package.html
new file mode 100644
index 0000000..cda72f5
--- /dev/null
+++ b/net/api/src/main/javadoc/org/onlab/onos/package.html
@@ -0,0 +1,3 @@
+<body>
+ONOS Core API definitions.
+</body>
\ No newline at end of file
diff --git a/net/core/trivial/src/main/java/org/onlab/onos/event/impl/SimpleEventDispatcher.java b/net/core/trivial/src/main/java/org/onlab/onos/event/impl/SimpleEventDispatcher.java
index 67cbc73..7ef8735 100644
--- a/net/core/trivial/src/main/java/org/onlab/onos/event/impl/SimpleEventDispatcher.java
+++ b/net/core/trivial/src/main/java/org/onlab/onos/event/impl/SimpleEventDispatcher.java
@@ -1,46 +1,93 @@
package org.onlab.onos.event.impl;
+import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Service;
+import org.onlab.onos.event.AbstractEvent;
+import org.onlab.onos.event.DefaultEventSinkBroker;
import org.onlab.onos.event.Event;
import org.onlab.onos.event.EventDispatchService;
import org.onlab.onos.event.EventSink;
+import org.slf4j.Logger;
-import java.util.Set;
+import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import static java.util.concurrent.Executors.newSingleThreadExecutor;
+import static org.onlab.util.Tools.namedThreads;
+import static org.slf4j.LoggerFactory.getLogger;
/**
* Simple implementation of an event dispatching service.
*/
@Component(immediate = true)
@Service
-public class SimpleEventDispatcher implements EventDispatchService {
+public class SimpleEventDispatcher extends DefaultEventSinkBroker
+ implements EventDispatchService {
- private final ExecutorService executor = Executors.newSingleThreadExecutor();
+ private final Logger log = getLogger(getClass());
+
+ private final ExecutorService executor =
+ newSingleThreadExecutor(namedThreads("event-dispatch-%d"));
+
+ @SuppressWarnings("unchecked")
+ private static final Event KILL_PILL = new AbstractEvent(null, 0) {
+ };
+
+ private final BlockingQueue<Event> events = new LinkedBlockingQueue<>();
+
+ private volatile boolean stopped = false;
@Override
public void post(Event event) {
-
+ events.add(event);
}
- @Override
- public <E extends Event> void addSink(Class<E> eventClass, EventSink<E> sink) {
-
+ @Activate
+ public void activate() {
+ stopped = false;
+ executor.execute(new DispatchLoop());
+ log.info("Started");
}
- @Override
- public <E extends Event> void removeSink(Class<E> eventClass) {
-
+ @Deactivate
+ public void deactivate() {
+ stopped = true;
+ post(KILL_PILL);
+ log.info("Stopped");
}
- @Override
- public <E extends Event> EventSink<E> getSink(Class<E> eventClass) {
- return null;
+ // Auxiliary event dispatching loop that feeds off the events queue.
+ private class DispatchLoop implements Runnable {
+ @Override
+ @SuppressWarnings("unchecked")
+ public void run() {
+ log.info("Dispatch loop initiated");
+ while (!stopped) {
+ try {
+ // Fetch the next event and if it is the kill-pill, bail
+ Event event = events.take();
+ if (event == KILL_PILL) {
+ break;
+ }
+
+ // Locate the sink for the event class and use it to
+ // process the event
+ EventSink sink = getSink(event.getClass());
+ if (sink != null) {
+ sink.process(event);
+ } else {
+ log.warn("No sink registered for event class {}",
+ event.getClass());
+ }
+ } catch (Throwable e) {
+ log.warn("Error encountered while dispatching event:", e);
+ }
+ }
+ log.info("Dispatch loop terminated");
+ }
}
- @Override
- public Set<Class<? extends Event>> getSinks() {
- return null;
- }
}
diff --git a/net/core/trivial/src/main/java/org/onlab/onos/impl/GreetManager.java b/net/core/trivial/src/main/java/org/onlab/onos/impl/GreetManager.java
index 4f4ba68..e5baf0e 100644
--- a/net/core/trivial/src/main/java/org/onlab/onos/impl/GreetManager.java
+++ b/net/core/trivial/src/main/java/org/onlab/onos/impl/GreetManager.java
@@ -7,12 +7,12 @@
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.GreetService;
import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.util.HashSet;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
/**
* Trivial implementation of the seed service to demonstrate component and
@@ -22,7 +22,7 @@
@Service
public class GreetManager implements GreetService {
- private final Logger log = LoggerFactory.getLogger(getClass());
+ private final Logger log = getLogger(getClass());
private final Set<String> names = new HashSet<>();
diff --git a/net/core/trivial/src/main/java/org/onlab/onos/impl/SomeOtherComponent.java b/net/core/trivial/src/main/java/org/onlab/onos/impl/SomeOtherComponent.java
index 6cb0bfe..627573f 100644
--- a/net/core/trivial/src/main/java/org/onlab/onos/impl/SomeOtherComponent.java
+++ b/net/core/trivial/src/main/java/org/onlab/onos/impl/SomeOtherComponent.java
@@ -7,7 +7,8 @@
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.onos.GreetService;
import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import static org.slf4j.LoggerFactory.getLogger;
/**
* Example of a component that does not provide any service, but consumes one.
@@ -15,7 +16,7 @@
@Component(immediate = true)
public class SomeOtherComponent {
- private final Logger log = LoggerFactory.getLogger(SomeOtherComponent.class);
+ private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected GreetService service;
diff --git a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleDeviceManager.java b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleDeviceManager.java
index 7038284..a293183 100644
--- a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleDeviceManager.java
+++ b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleDeviceManager.java
@@ -3,6 +3,8 @@
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.onos.event.AbstractListenerManager;
import org.onlab.onos.event.EventDispatchService;
@@ -22,11 +24,11 @@
import org.onlab.onos.net.provider.AbstractProviderBroker;
import org.onlab.onos.net.provider.AbstractProviderService;
import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
/**
* Provides basic implementation of the device SB & NB APIs.
@@ -42,24 +44,25 @@
public static final String DEVICE_DESCRIPTION_NULL = "Device description cannot be null";
public static final String PORT_DESCRIPTION_NULL = "Port description cannot be null";
- private Logger log = LoggerFactory.getLogger(SimpleDeviceManager.class);
+ private final Logger log = getLogger(getClass());
private final AbstractListenerManager<DeviceEvent, DeviceListener>
listenerManager = new AbstractListenerManager<>();
- private EventDispatchService eventDispatcher;
-
private final DeviceStore store = new DeviceStore();
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private EventDispatchService eventDispatcher;
+
@Activate
public void activate() {
-// eventDispatcher.addSink(DeviceEvent.class, listenerManager);
+ eventDispatcher.addSink(DeviceEvent.class, listenerManager);
log.info("Started");
}
@Deactivate
public void deactivate() {
-// eventDispatcher.removeSink(DeviceEvent.class);
+ eventDispatcher.removeSink(DeviceEvent.class);
log.info("Stopped");
}
diff --git a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleHostManager.java b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleHostManager.java
index 81397cf..0c0c983 100644
--- a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleHostManager.java
+++ b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleHostManager.java
@@ -3,55 +3,56 @@
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
+import org.onlab.onos.event.AbstractListenerManager;
+import org.onlab.onos.event.EventDispatchService;
import org.onlab.onos.net.host.HostDescription;
+import org.onlab.onos.net.host.HostEvent;
+import org.onlab.onos.net.host.HostListener;
import org.onlab.onos.net.host.HostProvider;
import org.onlab.onos.net.host.HostProviderBroker;
import org.onlab.onos.net.host.HostProviderService;
import org.onlab.onos.net.provider.AbstractProviderBroker;
import org.onlab.onos.net.provider.AbstractProviderService;
import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import static org.slf4j.LoggerFactory.getLogger;
/**
* Provides basic implementation of the host SB & NB APIs.
*/
@Component(immediate = true)
@Service
-public class SimpleHostManager implements HostProviderBroker {
+public class SimpleHostManager
+ extends AbstractProviderBroker<HostProvider, HostProviderService>
+ implements HostProviderBroker {
- private Logger log = LoggerFactory.getLogger(SimpleHostManager.class);
+ private final Logger log = getLogger(getClass());
- private final HostProviderBroker broker = new InternalBroker();
+ private final AbstractListenerManager<HostEvent, HostListener>
+ listenerManager = new AbstractListenerManager<>();
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private EventDispatchService eventDispatcher;
+
@Activate
public void activate() {
+ eventDispatcher.addSink(HostEvent.class, listenerManager);
log.info("Started");
}
@Deactivate
public void deactivate() {
+ eventDispatcher.removeSink(HostEvent.class);
log.info("Stopped");
}
@Override
- public HostProviderService register(HostProvider provider) {
- return broker.register(provider);
- }
-
- @Override
- public void unregister(HostProvider provider) {
- broker.unregister(provider);
- }
-
- // Internal delegate for tracking various providers and issuing them a
- // personalized provider service.
- private class InternalBroker extends AbstractProviderBroker<HostProvider, HostProviderService>
- implements HostProviderBroker {
- @Override
- protected HostProviderService createProviderService(HostProvider provider) {
- return new InternalHostProviderService(provider);
- }
+ protected HostProviderService createProviderService(HostProvider provider) {
+ return new InternalHostProviderService(provider);
}
// Personalized host provider service issued to the supplied provider.
diff --git a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleLinkManager.java b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleLinkManager.java
index 6283e0b..73fedab 100644
--- a/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleLinkManager.java
+++ b/net/core/trivial/src/main/java/org/onlab/onos/net/trivial/impl/SimpleLinkManager.java
@@ -3,55 +3,55 @@
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
+import org.onlab.onos.event.AbstractListenerManager;
+import org.onlab.onos.event.EventDispatchService;
import org.onlab.onos.net.link.LinkDescription;
+import org.onlab.onos.net.link.LinkEvent;
+import org.onlab.onos.net.link.LinkListener;
import org.onlab.onos.net.link.LinkProvider;
import org.onlab.onos.net.link.LinkProviderBroker;
import org.onlab.onos.net.link.LinkProviderService;
import org.onlab.onos.net.provider.AbstractProviderBroker;
import org.onlab.onos.net.provider.AbstractProviderService;
import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import static org.slf4j.LoggerFactory.getLogger;
/**
* Provides basic implementation of the link SB & NB APIs.
*/
@Component(immediate = true)
@Service
-public class SimpleLinkManager implements LinkProviderBroker {
+public class SimpleLinkManager
+ extends AbstractProviderBroker<LinkProvider, LinkProviderService>
+ implements LinkProviderBroker {
- private Logger log = LoggerFactory.getLogger(SimpleLinkManager.class);
+ private final Logger log = getLogger(getClass());
- private final LinkProviderBroker broker = new InternalBroker();
+ private final AbstractListenerManager<LinkEvent, LinkListener>
+ listenerManager = new AbstractListenerManager<>();
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private EventDispatchService eventDispatcher;
@Activate
public void activate() {
+ eventDispatcher.addSink(LinkEvent.class, listenerManager);
log.info("Started");
}
@Deactivate
public void deactivate() {
+ eventDispatcher.removeSink(LinkEvent.class);
log.info("Stopped");
}
@Override
- public LinkProviderService register(LinkProvider provider) {
- return broker.register(provider);
- }
-
- @Override
- public void unregister(LinkProvider provider) {
- broker.unregister(provider);
- }
-
- // Internal delegate for tracking various providers and issuing them a
- // personalized provider service.
- private class InternalBroker extends AbstractProviderBroker<LinkProvider, LinkProviderService>
- implements LinkProviderBroker {
- @Override
- protected LinkProviderService createProviderService(LinkProvider provider) {
- return new InternalLinkProviderService(provider);
- }
+ protected LinkProviderService createProviderService(LinkProvider provider) {
+ return new InternalLinkProviderService(provider);
}
// Personalized link provider service issued to the supplied provider.
diff --git a/net/core/trivial/src/main/javadoc/org/onlab/onos/event/impl/package.html b/net/core/trivial/src/main/javadoc/org/onlab/onos/event/impl/package.html
new file mode 100644
index 0000000..a22d62d
--- /dev/null
+++ b/net/core/trivial/src/main/javadoc/org/onlab/onos/event/impl/package.html
@@ -0,0 +1,3 @@
+<body>
+ONOS local event dispatching mechanism.
+</body>
\ No newline at end of file
diff --git a/net/core/trivial/src/main/javadoc/org/onlab/onos/impl/package.html b/net/core/trivial/src/main/javadoc/org/onlab/onos/impl/package.html
new file mode 100644
index 0000000..087085c
--- /dev/null
+++ b/net/core/trivial/src/main/javadoc/org/onlab/onos/impl/package.html
@@ -0,0 +1,3 @@
+<body>
+ONOS Core infrastructure implementations.
+</body>
\ No newline at end of file
diff --git a/net/pom.xml b/net/pom.xml
index bd4fa6e..fa146d9 100644
--- a/net/pom.xml
+++ b/net/pom.xml
@@ -26,6 +26,11 @@
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>org.onlab.onos</groupId>
+ <artifactId>onlab-misc</artifactId>
+ </dependency>
</dependencies>
<build>
diff --git a/pom.xml b/pom.xml
index 9ff1197..207a44f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -112,6 +112,12 @@
<!-- ONOS related -->
<dependency>
<groupId>org.onlab.onos</groupId>
+ <artifactId>onlab-misc</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onlab.onos</groupId>
<artifactId>onos-api</artifactId>
<version>${project.version}</version>
</dependency>
@@ -260,13 +266,13 @@
<group>
<title>Network Model & Services</title>
<packages>
- org.onlab.onos.*
+ org.onlab.onos:org.onlab.onos.*
</packages>
</group>
<group>
<title>Core Subsystems</title>
<packages>
- org.onlab.onos.net.trivial.impl:org.onlab.onos.net.*.impl
+ org.onlab.onos.net.trivial.impl:org.onlab.onos.net.*.impl:org.onlab.onos.impl:org.onlab.onos.event.impl
</packages>
</group>
<group>
diff --git a/providers/of/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java b/providers/of/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
index e601ac7..5977848 100644
--- a/providers/of/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
+++ b/providers/of/device/src/main/java/org/onlab/onos/provider/of/device/impl/OpenFlowDeviceProvider.java
@@ -12,8 +12,10 @@
import org.onlab.onos.net.device.DeviceProviderService;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
+import org.onlab.onos.of.controller.OpenFlowController;
import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import static org.slf4j.LoggerFactory.getLogger;
/**
* Provider which uses an OpenFlow controller to detect network
@@ -22,17 +24,16 @@
@Component(immediate = true)
public class OpenFlowDeviceProvider extends AbstractProvider implements DeviceProvider {
- private final Logger log = LoggerFactory.getLogger(OpenFlowDeviceProvider.class);
+ private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceProviderBroker providerBroker;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected OpenFlowController controller;
+
private DeviceProviderService providerService;
-// @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-// protected OpenFlowController controller;
-
-
/**
* Creates an OpenFlow device provider.
*/
diff --git a/providers/of/host/src/main/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProvider.java b/providers/of/host/src/main/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProvider.java
index ff7837a..2faeb43 100644
--- a/providers/of/host/src/main/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProvider.java
+++ b/providers/of/host/src/main/java/org/onlab/onos/provider/of/host/impl/OpenFlowHostProvider.java
@@ -11,8 +11,10 @@
import org.onlab.onos.net.host.HostProviderService;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
+import org.onlab.onos.of.controller.OpenFlowController;
import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import static org.slf4j.LoggerFactory.getLogger;
/**
* Provider which uses an OpenFlow controller to detect network
@@ -21,15 +23,15 @@
@Component(immediate = true)
public class OpenFlowHostProvider extends AbstractProvider implements HostProvider {
- private final Logger log = LoggerFactory.getLogger(OpenFlowHostProvider.class);
+ private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostProviderBroker providerBroker;
- private HostProviderService providerService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected OpenFlowController controller;
-// @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-// protected OpenFlowController controller;
+ private HostProviderService providerService;
/**
* Creates an OpenFlow host provider.
diff --git a/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java b/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
index 88b5874..dacf3a8 100644
--- a/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
+++ b/providers/of/link/src/main/java/org/onlab/onos/provider/of/link/impl/OpenFlowLinkProvider.java
@@ -10,8 +10,10 @@
import org.onlab.onos.net.link.LinkProviderService;
import org.onlab.onos.net.provider.AbstractProvider;
import org.onlab.onos.net.provider.ProviderId;
+import org.onlab.onos.of.controller.OpenFlowController;
import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+
+import static org.slf4j.LoggerFactory.getLogger;
/**
* Provider which uses an OpenFlow controller to detect network
@@ -20,15 +22,15 @@
@Component(immediate = true)
public class OpenFlowLinkProvider extends AbstractProvider implements LinkProvider {
- private final Logger log = LoggerFactory.getLogger(OpenFlowLinkProvider.class);
+ private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkProviderBroker providerBroker;
- private LinkProviderService providerService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected OpenFlowController controller;
-// @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-// protected OpenFlowController controller;
+ private LinkProviderService providerService;
/**
* Creates an OpenFlow link provider.
diff --git a/providers/pom.xml b/providers/pom.xml
index 71f6f0d..fc73d3b 100644
--- a/providers/pom.xml
+++ b/providers/pom.xml
@@ -24,7 +24,11 @@
<dependency>
<groupId>org.onlab.onos</groupId>
<artifactId>onos-api</artifactId>
- <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onlab.onos</groupId>
+ <artifactId>onlab-misc</artifactId>
</dependency>
<dependency>
diff --git a/utils/misc/pom.xml b/utils/misc/pom.xml
new file mode 100644
index 0000000..5862727
--- /dev/null
+++ b/utils/misc/pom.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onlab.onos</groupId>
+ <artifactId>onlab-utils</artifactId>
+ <version>1.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onlab-misc</artifactId>
+ <packaging>bundle</packaging>
+
+ <description>Miscellaneous ON.Lab utilities</description>
+
+ <dependencies>
+ </dependencies>
+
+</project>
diff --git a/utils/misc/src/main/java/org/onlab/util/Foo.java b/utils/misc/src/main/java/org/onlab/util/Foo.java
deleted file mode 100644
index 8113e1f..0000000
--- a/utils/misc/src/main/java/org/onlab/util/Foo.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package org.onlab.util;
-
-public class Foo {
-}
diff --git a/utils/misc/src/main/java/org/onlab/util/Tools.java b/utils/misc/src/main/java/org/onlab/util/Tools.java
new file mode 100644
index 0000000..e1e9ed7
--- /dev/null
+++ b/utils/misc/src/main/java/org/onlab/util/Tools.java
@@ -0,0 +1,23 @@
+package org.onlab.util;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+
+import java.util.concurrent.ThreadFactory;
+
+public abstract class Tools {
+
+ private Tools() {
+ }
+
+ /**
+ * Returns a thread factory that produces threads named according to the
+ * supplied name pattern.
+ *
+ * @param pattern name pattern
+ * @return thread factory
+ */
+ public static ThreadFactory namedThreads(String pattern) {
+ return new ThreadFactoryBuilder().setNameFormat(pattern).build();
+ }
+
+}