Device driver framework enhancements and CLI.

Change-Id: I5dea67620259797eff89a985718934034a86d63e
diff --git a/cli/src/main/java/org/onosproject/cli/net/DriverNameCompleter.java b/cli/src/main/java/org/onosproject/cli/net/DriverNameCompleter.java
new file mode 100644
index 0000000..2ba8a20
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/DriverNameCompleter.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cli.net;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.driver.DriverAdminService;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Device driver name completer.
+ */
+public class DriverNameCompleter implements Completer {
+    @Override
+    public int complete(String buffer, int cursor, List<String> candidates) {
+        // Delegate string completer
+        StringsCompleter delegate = new StringsCompleter();
+        SortedSet<String> strings = delegate.getStrings();
+
+        // Fetch our service and feed it's offerings to the string completer
+        DriverAdminService service = AbstractShellCommand.get(DriverAdminService.class);
+        service.getDrivers().forEach(d -> strings.add(d.name()));
+
+        // Now let the completer do the work for figuring out what to offer.
+        return delegate.complete(buffer, cursor, candidates);
+    }
+
+}
diff --git a/cli/src/main/java/org/onosproject/cli/net/DriversListCommand.java b/cli/src/main/java/org/onosproject/cli/net/DriversListCommand.java
new file mode 100644
index 0000000..fd4c96c
--- /dev/null
+++ b/cli/src/main/java/org/onosproject/cli/net/DriversListCommand.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cli.net;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverAdminService;
+
+/**
+ * Lists device drivers.
+ */
+@Command(scope = "onos", name = "drivers",
+        description = "Lists device drivers")
+public class DriversListCommand extends AbstractShellCommand {
+
+    private static final String FMT = "driver=%s, mfr=%s, hw=%s, sw=%s";
+    private static final String FMT_B = "   %s via %s";
+    private static final String FMT_P = "   %s=%s";
+
+    @Argument(index = 0, name = "driverName", description = "Driver name",
+            required = false, multiValued = false)
+    String driverName = null;
+
+    @Override
+    protected void execute() {
+        DriverAdminService service = get(DriverAdminService.class);
+
+        if (driverName != null) {
+            printDriver(service.getDriver(driverName));
+        } else {
+            service.getDrivers().forEach(this::printDriver);
+        }
+    }
+
+    private void printDriver(Driver driver) {
+        print(FMT, driver.name(), driver.manufacturer(),
+              driver.hwVersion(), driver.swVersion());
+        driver.behaviours().forEach(b -> print(FMT_B, b.getCanonicalName(),
+                                               driver.implementation(b).getCanonicalName()));
+        driver.properties().forEach((k, v) -> print(FMT_P, k, v));
+    }
+
+}
diff --git a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 5fefe45..8234462 100644
--- a/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -71,6 +71,14 @@
         </command>
 
         <command>
+            <action class="org.onosproject.cli.net.DriversListCommand"/>
+            <completers>
+                <ref component-id="driverNameCompleter"/>
+                <null/>
+            </completers>
+        </command>
+
+        <command>
             <action class="org.onosproject.cli.net.DevicesListCommand"/>
         </command>
         <command>
@@ -316,5 +324,6 @@
     <bean id="nullCompleter" class="org.apache.karaf.shell.console.completer.NullCompleter"/>
     <bean id="ethTypeCompleter" class="org.onosproject.cli.net.EthTypeCompleter"/>
     <bean id="ipProtocolCompleter" class="org.onosproject.cli.net.IpProtocolCompleter"/>
+    <bean id="driverNameCompleter" class="org.onosproject.cli.net.DriverNameCompleter"/>
 
 </blueprint>