Committed the initial version of the UPnP Tester bundle (FELIX-52).
It requires org.osgi.core, org.osgi.compendium and org.apache.felix.upnp.extra.
The tester acts as Generic Control Point useful to monitor the registered UPnPDevice services.
git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@391455 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/Activator.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/Activator.java
new file mode 100644
index 0000000..4a0a8f7
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/Activator.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester;
+
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class Activator implements BundleActivator {
+
+ public static BundleContext context;
+
+ private ControlPoint cp;
+
+ /**
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ Activator.context = context;
+ cp = new ControlPoint();
+ }
+
+ /**
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+ cp.close();
+ Activator.context=null;
+ }
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/ControlPoint.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/ControlPoint.java
new file mode 100644
index 0000000..cf9bdd7
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/ControlPoint.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester;
+
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.net.URL;
+
+import javax.swing.AbstractAction;
+import javax.swing.ButtonGroup;
+import javax.swing.ImageIcon;
+import javax.swing.JFrame;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JRadioButtonMenuItem;
+import javax.swing.JSplitPane;
+import javax.swing.event.PopupMenuEvent;
+import javax.swing.event.PopupMenuListener;
+
+import org.apache.felix.upnp.tester.discovery.DriverProxy;
+import org.apache.felix.upnp.tester.discovery.RootDeviceListener;
+import org.apache.felix.upnp.tester.gui.LogPanel;
+import org.apache.felix.upnp.tester.gui.PropertiesViewer;
+import org.apache.felix.upnp.tester.gui.TreeViewer;
+import org.apache.felix.upnp.tester.gui.Util;
+import org.osgi.framework.BundleException;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class ControlPoint implements PopupMenuListener {
+ RootDeviceListener x;
+ RootDeviceListener listener;
+ TreeViewer viewer;
+ PropertiesViewer properties;
+ JFrame frame;
+
+
+ public ControlPoint() {
+ frame = new JFrame("OSGi UPnP Device Tester");
+ try {
+ URL eventIconUrl = Util.class.getResource("IMAGES/logo.gif");
+ ImageIcon icon= new ImageIcon(eventIconUrl,"logo");
+ frame.setIconImage(icon.getImage());
+ }
+ catch (Exception ex){
+ System.out.println("Resource: IMAGES/logo.gif not found : " + ex.toString());
+ }
+ //frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+
+ frame.addWindowListener(new WindowAdapter(){
+ public void windowClosing(WindowEvent e){
+ try {
+ Activator.context.getBundle().stop();
+ } catch (BundleException ex) {
+ ex.printStackTrace();
+ }
+ }
+
+ });
+ frame.setBounds(0,0,300,200);
+
+
+ doMenuBar(frame);
+ doControlPanel();
+ Mediator.setControlPoint(this);
+ Mediator.setMainFrame(frame);
+ Mediator.setRootDeviceListener(listener);
+ listener = new RootDeviceListener();
+ Mediator.setRootDeviceListener(listener);
+ listener.setDeviceNodeListener(viewer);
+
+ frame.pack();
+ frame.setVisible(true);
+
+ DriverProxy driverProxy = new DriverProxy();
+ Mediator.setDriverProxy(driverProxy);
+
+ listener.activate();
+ }
+
+ public void close(){
+ listener.deactive();
+ frame.dispose();
+ Mediator.getDriverProxy().close();
+ }
+
+ private void doControlPanel(){
+ JPanel panel = new JPanel(new BorderLayout());
+ viewer = new TreeViewer();
+ viewer.setPreferredSize(new Dimension(180,450));
+ properties = new PropertiesViewer();
+ Mediator.setPropertiesViewer(properties);
+
+ JSplitPane treeSplitter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,viewer,properties);
+ JPanel logPanel = new LogPanel();
+ logPanel.setPreferredSize(new Dimension(180,100));
+ JSplitPane logSplitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT,treeSplitter,logPanel);
+ panel.add(logSplitter);
+ frame.getContentPane().add(panel);
+
+
+ }
+
+ /////////////////////////// MENU /////////////////////////////
+ JMenu searchMenu,loggerMenu,cyberMenu;
+ public void doMenuBar(JFrame frame) {
+
+ JMenuBar menuBar = new JMenuBar();
+
+ //////////////// FILE
+ JMenu file_menu = new JMenu("File");
+ file_menu.setMnemonic(KeyEvent.VK_F);
+
+ searchMenu = new JMenu("Search");
+ final String ALL_DEVICE = "ssdp:all";
+ final String ROOT_DEVICE = "upnp:rootdevice";
+ searchMenu.setMnemonic(KeyEvent.VK_L);
+ searchMenu.setEnabled(false);
+ AbstractAction searchAction = new AbstractAction(){
+ public void actionPerformed(ActionEvent e) {
+ DriverProxy controller = Mediator.getDriverProxy();
+ if (e.getActionCommand().equals(ALL_DEVICE))
+ controller.doSearch(ALL_DEVICE);
+ else if (e.getActionCommand().equals(ROOT_DEVICE))
+ controller.doSearch(ROOT_DEVICE);
+ }
+ };
+
+ JMenuItem rootDeviceItem = new JMenuItem("Root Devices");
+ rootDeviceItem.setMnemonic(KeyEvent.VK_R);
+ rootDeviceItem.addActionListener(searchAction);
+ rootDeviceItem.setActionCommand(ROOT_DEVICE);
+ searchMenu.add(rootDeviceItem);
+
+ JMenuItem allDeviceItem = new JMenuItem("All Devices");
+ allDeviceItem .setMnemonic(KeyEvent.VK_A);
+ allDeviceItem .addActionListener(searchAction);
+ allDeviceItem .setActionCommand(ALL_DEVICE);
+ searchMenu.add(allDeviceItem);
+
+
+ JMenuItem checkIncompleteItem = new JMenuItem("Print Pending Devices");
+ checkIncompleteItem.setMnemonic(KeyEvent.VK_I);
+ checkIncompleteItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ Mediator.getRootDeviceListener().checkIncompleteDevice();
+ }
+ });
+
+ JMenuItem checkErrataItem = new JMenuItem("Check Errata UPnPDevices");
+ checkErrataItem.setMnemonic(KeyEvent.VK_E);
+ checkErrataItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ RootDeviceListener.checkErrataDevice();}
+ });
+
+
+ loggerMenu = new JMenu("Domoware Logger");
+ final String NO_LOGGING ="No Logging";
+ final String ERROR ="Error";
+ final String WARNING ="Warning";
+ final String INFO ="Info";
+ final String DEBUG ="Debug";
+
+ loggerMenu.getPopupMenu().addPopupMenuListener(this);
+ loggerMenu.setMnemonic(KeyEvent.VK_L);
+ loggerMenu.setEnabled(false);
+ AbstractAction loggerAction = new AbstractAction(){
+ public void actionPerformed(ActionEvent e) {
+ DriverProxy controller = Mediator.getDriverProxy();
+ if (e.getActionCommand().equals(NO_LOGGING))
+ controller.setLogLevel(0);
+ else if (e.getActionCommand().equals(ERROR))
+ controller.setLogLevel(1);
+ else if (e.getActionCommand().equals(WARNING))
+ controller.setLogLevel(2);
+ else if (e.getActionCommand().equals(INFO))
+ controller.setLogLevel(3);
+ else if (e.getActionCommand().equals(DEBUG))
+ controller.setLogLevel(4);
+ }
+ };
+
+ ButtonGroup group = new ButtonGroup();
+
+ JRadioButtonMenuItem rbMenuItem = new JRadioButtonMenuItem(NO_LOGGING);
+ rbMenuItem.setSelected(true);
+ rbMenuItem.setMnemonic(KeyEvent.VK_N);
+ rbMenuItem.setActionCommand(NO_LOGGING);
+ rbMenuItem.addActionListener(loggerAction);
+ group.add(rbMenuItem);
+ loggerMenu.add(rbMenuItem);
+ loggerMenu.addSeparator();
+
+ rbMenuItem = new JRadioButtonMenuItem(ERROR);
+ rbMenuItem.setMnemonic(KeyEvent.VK_E);
+ rbMenuItem.setActionCommand(ERROR);
+ rbMenuItem.addActionListener(loggerAction);
+ group.add(rbMenuItem);
+ loggerMenu.add(rbMenuItem);
+
+ rbMenuItem = new JRadioButtonMenuItem(WARNING);
+ rbMenuItem.setMnemonic(KeyEvent.VK_W);
+ rbMenuItem.setActionCommand(WARNING);
+ rbMenuItem.addActionListener(loggerAction);
+ group.add(rbMenuItem);
+ loggerMenu.add(rbMenuItem);
+
+ rbMenuItem = new JRadioButtonMenuItem(INFO);
+ rbMenuItem.setMnemonic(KeyEvent.VK_I);
+ rbMenuItem.setActionCommand(INFO);
+ rbMenuItem.addActionListener(loggerAction);
+ group.add(rbMenuItem);
+ loggerMenu.add(rbMenuItem);
+
+ rbMenuItem = new JRadioButtonMenuItem(DEBUG);
+ rbMenuItem.setMnemonic(KeyEvent.VK_D);
+ rbMenuItem.setActionCommand(DEBUG);
+ rbMenuItem.addActionListener(loggerAction);
+ group.add(rbMenuItem);
+ loggerMenu.add(rbMenuItem);
+
+ final String ON ="On";
+ final String OFF ="Off";
+ cyberMenu = new JMenu("Cyber Debugger");
+ cyberMenu.getPopupMenu().addPopupMenuListener(this);
+ cyberMenu.setMnemonic(KeyEvent.VK_C);
+ cyberMenu.setEnabled(false);
+ AbstractAction cyberAction = new AbstractAction(){
+ public void actionPerformed(ActionEvent e) {
+ DriverProxy controller = Mediator.getDriverProxy();
+ if (e.getActionCommand().equals(ON))
+ controller.setCyberDebug(true);
+ else if (e.getActionCommand().equals(OFF))
+ controller.setCyberDebug(false);
+ }
+ };
+
+
+ ButtonGroup cyberGroup = new ButtonGroup();
+ rbMenuItem = new JRadioButtonMenuItem(ON);
+ rbMenuItem.setSelected(true);
+ rbMenuItem.setMnemonic(KeyEvent.VK_O);
+ rbMenuItem.setActionCommand(ON);
+ rbMenuItem.addActionListener(cyberAction);
+ cyberGroup.add(rbMenuItem);
+ cyberMenu.add(rbMenuItem);
+
+ rbMenuItem = new JRadioButtonMenuItem(OFF);
+ rbMenuItem.setMnemonic(KeyEvent.VK_F);
+ rbMenuItem.setActionCommand(OFF);
+ rbMenuItem.addActionListener(cyberAction);
+ cyberGroup.add(rbMenuItem);
+ cyberMenu.add(rbMenuItem);
+
+ /*
+ JMenuItem clearSubscriptionItem = new JMenuItem("Clear Subscriptions");
+ clearSubscriptionItem.setMnemonic(KeyEvent.VK_S);
+ clearSubscriptionItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+// to do
+ }
+ });
+ */
+
+ JMenuItem exitItem = new JMenuItem("Exit");
+ exitItem.setMnemonic(KeyEvent.VK_X);
+ exitItem.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ try {
+ Activator.context.getBundle().stop();
+ }catch (Exception ex){
+ ex.printStackTrace();
+ }
+ }
+ });
+
+
+ file_menu.add(searchMenu);
+ file_menu.addSeparator();
+ file_menu.add(loggerMenu);
+ file_menu.add(cyberMenu);
+ file_menu.addSeparator();
+ file_menu.add(checkIncompleteItem);
+ file_menu.add(checkErrataItem);
+ //file_menu.addSeparator();
+ //file_menu.add(clearSubscriptionItem);
+ file_menu.addSeparator();
+ file_menu.add(exitItem);
+
+ menuBar.add(file_menu);
+ frame.setJMenuBar(menuBar);
+
+ }
+
+
+ public void enableMenus(boolean driverAvailable,int logLevel,boolean cyberDebug) {
+ searchMenu.setEnabled(driverAvailable);
+ Component[] items = searchMenu.getPopupMenu().getComponents();
+ for (int i=0;i < items.length;i++)
+ items[i].setEnabled(driverAvailable);
+
+ loggerMenu.setEnabled(driverAvailable);
+ items = loggerMenu.getPopupMenu().getComponents();
+ for (int i=0;i < items.length;i++)
+ items[i].setEnabled(driverAvailable);
+ if (driverAvailable){
+ ((JRadioButtonMenuItem)items[logLevel>0?logLevel+1:0]).setSelected(true);
+ }
+ cyberMenu.setEnabled(driverAvailable);
+ items = cyberMenu.getPopupMenu().getComponents();
+ for (int i=0;i < items.length;i++)
+ items[i].setEnabled(driverAvailable);
+ if (driverAvailable){
+ if (cyberDebug)
+ ((JRadioButtonMenuItem)items[0]).setSelected(true);
+ else
+ ((JRadioButtonMenuItem)items[1]).setSelected(true);
+ }
+ }
+
+ public void popupMenuCanceled(PopupMenuEvent e) { }
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { }
+
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+ JPopupMenu loggerPopup = loggerMenu.getPopupMenu();
+ JPopupMenu cyberPopup = cyberMenu.getPopupMenu();
+ if (e.getSource()==loggerPopup){
+ int logLevel = Mediator.getDriverProxy().getLogLevel();
+ Component[] items = loggerPopup.getComponents();
+ ((JRadioButtonMenuItem)items[logLevel>0?logLevel+1:0]).setSelected(true);
+ }
+ else if (e.getSource()==cyberPopup){
+ boolean cyberDebug = Mediator.getDriverProxy().getCyberDebug();
+ Component[] items = cyberPopup.getComponents();
+ if (cyberDebug)
+ ((JRadioButtonMenuItem)items[0]).setSelected(true);
+ else
+ ((JRadioButtonMenuItem)items[1]).setSelected(true);
+ }
+
+
+ }
+
+
+
+
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/Mediator.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/Mediator.java
new file mode 100644
index 0000000..7a7c3da
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/Mediator.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester;
+
+
+import javax.swing.*;
+
+import org.apache.felix.upnp.tester.discovery.*;
+import org.apache.felix.upnp.tester.gui.*;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class Mediator {
+ static PropertiesViewer props;
+ static JTree tree;
+ static JFrame frame;
+ static DriverProxy driverProxy;
+ static RootDeviceListener rootDeviceListener;
+ static ControlPoint controlPoint;
+ static TreeViewer treeViewer;
+
+
+ public static void setPropertiesViewer(PropertiesViewer props){
+ Mediator.props=props;
+ }
+ public static PropertiesViewer getPropertiesViewer(){
+ return props;
+ }
+
+ public static void setUPnPDeviceTree(JTree tree){
+ Mediator.tree=tree;
+ }
+ public static JTree getUPnPDeviceTree(){
+ return tree;
+ }
+
+ public static void setTreeViewer(TreeViewer treeViewer){
+ Mediator.treeViewer=treeViewer;
+ }
+ public static TreeViewer getTreeViewer(){
+ return treeViewer;
+ }
+
+ public static void setMainFrame(JFrame frame){
+ Mediator.frame=frame;
+ }
+ public static JFrame getMainFrame(){
+ return frame;
+ }
+ public static void setControlPoint(ControlPoint controlPoint){
+ Mediator.controlPoint=controlPoint;
+ }
+ public static ControlPoint getControlPoint(){
+ return controlPoint;
+ }
+
+ public static void setDriverProxy(DriverProxy driverProxy) {
+ Mediator.driverProxy = driverProxy;
+ }
+
+ public static DriverProxy getDriverProxy(){
+ return driverProxy;
+ }
+
+ public static void setRootDeviceListener(RootDeviceListener listener) {
+ Mediator.rootDeviceListener = listener;
+ }
+
+ public static RootDeviceListener getRootDeviceListener(){
+ return rootDeviceListener;
+ }
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/UPnPSubscriber.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/UPnPSubscriber.java
new file mode 100644
index 0000000..27ae36f
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/UPnPSubscriber.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester;
+
+import java.util.*;
+
+import org.osgi.framework.*;
+import org.osgi.service.upnp.*;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class UPnPSubscriber {
+ private BundleContext context;
+ private UPnPEventListener listener;
+ private HashMap hash;
+
+ private class Subscription implements UPnPEventListener{
+ ServiceRegistration registration;
+
+ Subscription(String keys){
+ try {
+ Filter filter = context.createFilter(keys);
+ Properties props = new Properties();
+ props.put(UPnPEventListener.UPNP_FILTER, filter);
+ registration = context.registerService(UPnPEventListener.class.getName(), this, props);
+ }catch (Exception ex){
+ System.out.println(ex);
+ }
+ }
+
+ public void unsubscribe(){
+ registration.unregister();
+ }
+
+ public void notifyUPnPEvent(String arg0, String arg1, Dictionary arg2) {
+ listener.notifyUPnPEvent( arg0, arg1, arg2);
+ }
+ }
+
+
+ public UPnPSubscriber(BundleContext context,UPnPEventListener listener){
+ this.context = context;
+ this.listener = listener;
+ hash = new HashMap();
+ }
+
+ public void subscribe(String deviceId, String serviceId){
+ String keys = "(&(" + UPnPDevice.ID + "="+ deviceId + ")(" + UPnPService.ID + "=" + serviceId + "))";
+ if (hash.get(keys) == null){
+ hash.put(keys, new Subscription(keys));
+ }
+ }
+
+ public void unsubscribe(String deviceId, String serviceId){
+ String keys = "(&(" + UPnPDevice.ID + "="+ deviceId + ")(" + UPnPService.ID + "=" + serviceId + "))";
+ if (hash.containsKey(keys)) {
+ Subscription subscription = (Subscription) hash.get(keys);
+ subscription.unsubscribe();
+ hash.remove(keys);
+ }
+ }
+
+
+
+
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DeviceChangeListener.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DeviceChangeListener.java
new file mode 100644
index 0000000..5999ddd
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DeviceChangeListener.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.discovery;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public interface DeviceChangeListener {
+
+ public void addedDevice(DeviceNode dn);
+
+ public void removedDevice(DeviceNode dn);
+
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DeviceNode.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DeviceNode.java
new file mode 100644
index 0000000..fd24dd2
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DeviceNode.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.discovery;
+import java.util.*;
+
+import org.osgi.framework.*;
+import org.osgi.service.upnp.*;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class DeviceNode {
+
+ private ServiceReference sr;
+ private boolean isRootNode;
+ private String udn ;
+ private boolean hasChild;
+ private int numberOfSons;
+ private ArrayList children;
+ private DeviceNode parent;
+
+ public DeviceNode(ServiceReference sr){
+ //PRE: argument is always UPnPDevice service reference
+ if (sr == null)
+ throw new IllegalArgumentException("null is not a valid arg in DeviceNode constructor");
+ this.sr = sr;
+ udn = (String) sr.getProperty(UPnPDevice.UDN);
+ parent=null;
+ isRootNode = (sr.getProperty(UPnPDevice.PARENT_UDN) == null);
+ String[] sons = ((String[]) sr.getProperty(UPnPDevice.CHILDREN_UDN));
+ hasChild = (sons != null);
+ if (hasChild) {
+ children = new ArrayList();
+ numberOfSons = sons.length;
+ }
+ /*
+ //Operation to let DeviceNode::isComplete() O(1)
+ isComplete = !hasChild;
+ */
+ }
+
+ public ServiceReference getReference(){
+ return sr;
+ }
+ public UPnPDevice getDevice(BundleContext ctx){
+ return (UPnPDevice)ctx.getService(sr);
+ }
+
+ public void attach(DeviceNode node){
+ if (node == null)
+ throw new IllegalArgumentException("null is not a valid arg in DeviceNode.attach() method");
+ node.parent = this;
+ /*
+ //Operation to let DeviceNode::isComplete() O(1)
+ if((numberOfSons==children.size()-1)
+ &&(node.isComplete())){
+ this.isComplete = true;
+ }
+ */
+ children.add(node);
+ }
+
+ public DeviceNode dethatch(String name){
+ DeviceNode dn = this.search(name);
+ if(dn==null)
+ return null;
+
+ if(dn.parent!=null){
+ Iterator list = dn.parent.children.iterator();
+ while (list.hasNext()) {
+ DeviceNode x = (DeviceNode) list.next();
+ if(x.udn.equals(name)){
+ list.remove();
+ /*
+ //Operation to let DeviceNode::isComplete() O(1)
+ dn.parent.isComplete=false;
+ */
+ break;
+ }
+ }
+ }
+ dn.parent=null;
+ return dn;
+ }
+
+ public Collection getAllChildren(){
+ if((this.children==null)||(this.children.size()==0))
+ return new ArrayList();
+
+ Vector v = new Vector(this.children);
+ Iterator list = this.children.iterator();
+ while (list.hasNext()) {
+ DeviceNode x = (DeviceNode) list.next();
+ Collection c = x.getAllChildren();
+ if(c==null) continue;
+ v.addAll(c);
+ }
+ return v;
+ }
+
+ public Collection getChildren(){
+ if((this.children==null)||(this.children.size()==0))
+ return new ArrayList();
+ return this.children;
+ }
+
+ /**
+ * @param name <code>String</code> that contain the UDN to look for
+ * @return return a <code>DeviceNode</code> that have the UDN equals to name and <br>
+ * if there is any <code>DeviceNode</code> with the proper UDN value return <code>null</code>
+ */
+ public DeviceNode search(String name){
+ if (name == null)
+ throw new IllegalArgumentException("null is not a valid arg in DeviceNode.search() method");
+ if (name.equals(udn))
+ return this;
+ else if (hasChild){
+ Iterator list = children.iterator();
+ while (list.hasNext()){
+ DeviceNode child = (DeviceNode)list.next();
+ DeviceNode node = child.search(name);
+ if (node != null) return node;
+ }
+ }
+ return null;
+ }
+
+ /**
+ *
+ * @param udn
+ * @return <code>true</code> if and only if this <code>DeviceNode</code>
+ * contains a DeviceNode with UDN equals to passed argument or if
+ * its USN is equal to passed argument
+ */
+ public boolean contains(String udn){
+ return this.search(udn)!=null;
+ }
+
+ public boolean isComplete(){
+ /*
+ //Operation to let DeviceNode::isComplete() O(1)
+ return isComplete;
+ */
+ if (! hasChild) return true;
+ if (numberOfSons != children.size())return false;
+ Iterator list = children.iterator();
+ while (list.hasNext()){
+ DeviceNode child = (DeviceNode)list.next();
+ if (! child.isComplete()) return false;
+ }
+ return true;
+ }
+
+ public DeviceNode isAttachable(DeviceNode node){
+ if (node == null)
+ throw new IllegalArgumentException("null is not a valid arg in DeviceNode.isAttachable() method");
+ String parentUDN=(String) node.getReference().getProperty(UPnPDevice.PARENT_UDN);
+ if(parentUDN==null) return null;
+ return search(parentUDN);
+ }
+
+ public boolean isRoot(){
+ return isRootNode;
+ }
+
+ public boolean equals(String udn){
+ return this.udn.equals(udn);
+ }
+
+ public String toString(){
+ return udn;
+ }
+ public boolean isLeaf() {
+ return !hasChild;
+ }
+
+ public void print(){
+ System.out.println("####Device Node");
+ String[] props = sr.getPropertyKeys();
+ for (int i=0;i< props.length;i++){
+ Object prop= sr.getProperty(props[i]);
+ if (prop instanceof String[]){
+ System.out.println(props[i]+ "=");
+ String[] multiple = (String[])prop;
+ for (int j=0;j< multiple.length;j++){
+ System.out.println(multiple[j]+ ";");
+ }
+
+ }
+ else System.out.println(props[i]+ "="+ prop);
+ }
+ System.out.println("####Device Node");
+ }
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DeviceNodeListener.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DeviceNodeListener.java
new file mode 100644
index 0000000..d9becb3
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DeviceNodeListener.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.discovery;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public interface DeviceNodeListener {
+ public void deviceDetected(DeviceNode d);
+ public void rootDeviceUnplugged(String udn);
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DevicesList.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DevicesList.java
new file mode 100644
index 0000000..fcfe4b3
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DevicesList.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.discovery;
+
+import java.util.*;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class DevicesList {
+
+ ArrayList devices;
+ DeviceChangeListener listener = null;
+
+ public DevicesList(){
+ devices = new ArrayList();
+ }
+
+
+ public boolean add(DeviceNode dev) {
+ if(listener!=null)
+ listener.addedDevice(dev);
+ return devices.add(dev);
+ }
+
+ public Iterator iterator() {
+ return devices.iterator();
+ }
+
+ public boolean remove(DeviceNode dev) {
+ if(listener!=null)
+ listener.removedDevice(dev);
+ return devices.remove(dev);
+ }
+
+ public DeviceChangeListener getChangeListener() {
+ return listener;
+ }
+
+ public void setChangeListener(DeviceChangeListener listener) {
+ this.listener = listener;
+ }
+
+
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DriverProxy.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DriverProxy.java
new file mode 100644
index 0000000..fce3e03
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/DriverProxy.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.discovery;
+
+import org.apache.felix.upnp.extra.controller.*;
+import org.apache.felix.upnp.tester.*;
+
+import org.osgi.framework.*;
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class DriverProxy implements ServiceListener {
+ private DevicesInfo devicesInfo;
+ private DriverController drvController;
+ public DriverProxy(){
+ ServiceReference sr = Activator.context.getServiceReference(DevicesInfo.class.getName());
+ if (sr != null){
+ devicesInfo = (DevicesInfo)Activator.context.getService(sr);
+ drvController = (DriverController) devicesInfo;
+ Mediator.getControlPoint().enableMenus(true,getLogLevel(),getCyberDebug());
+ Mediator.getTreeViewer().setPopupMenuEnabled(true);
+ }
+ String filter = "(" + Constants.OBJECTCLASS + "=" + DevicesInfo.class.getName() + ")" ;
+ try {
+ Activator.context.addServiceListener(this,filter);
+ } catch (Exception ignored){};
+ }
+
+ public boolean isDriverAvailable(){
+ return (drvController != null);
+ }
+
+ public String getDeviceDescriptionURI(String udn){
+ if (devicesInfo != null)
+ return devicesInfo.getLocationURL(udn);
+ return "";
+ }
+
+ public String getServiceDescriptionURI(String udn,String serviceId){
+ if (devicesInfo != null)
+ return devicesInfo.getSCPDURL(udn,serviceId);
+ return null;
+ }
+
+ public String resolveRelativeUrl(String udn,String link){
+ if (devicesInfo != null)
+ return devicesInfo.resolveRelativeUrl(udn,link);
+ return null;
+ }
+
+ public boolean getCyberDebug(){
+ if (drvController != null)
+ return drvController.getCyberDebug();
+ return false;
+ }
+ public void setCyberDebug(boolean b){
+ if (drvController != null)
+ drvController.setCyberDebug(b);
+ }
+ public int getLogLevel(){
+ if (drvController != null)
+ return drvController.getLogLevel();
+ return 0;
+ }
+
+ public void setLogLevel(int value){
+ if (drvController != null)
+ drvController.setLogLevel(value);
+ }
+ public void doSearch(String target){
+ if (drvController != null)
+ drvController.search(target);
+ }
+
+
+ public void serviceChanged(ServiceEvent e) {
+ switch(e.getType()){
+ case ServiceEvent.REGISTERED:{
+ Object service = Activator.context.getService(e.getServiceReference());
+ if (service != null){
+ devicesInfo = (DevicesInfo) service;
+ drvController = (DriverController) devicesInfo;
+ Mediator.getControlPoint().enableMenus(true,getLogLevel(),getCyberDebug());
+ Mediator.getTreeViewer().setPopupMenuEnabled(true);
+ }
+ };break;
+ case ServiceEvent.UNREGISTERING:{
+ devicesInfo = null;
+ drvController =null;
+ Mediator.getControlPoint().enableMenus(false,0,false);
+ Mediator.getTreeViewer().setPopupMenuEnabled(false);
+ };break;
+ }
+ }
+
+ public void close(){
+ Activator.context.removeServiceListener(this);
+ }
+
+
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/RootDeviceListener.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/RootDeviceListener.java
new file mode 100644
index 0000000..12d62a1
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/discovery/RootDeviceListener.java
@@ -0,0 +1,295 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.discovery;
+
+
+import java.util.*;
+
+import org.apache.felix.upnp.tester.Activator;
+import org.apache.felix.upnp.tester.gui.*;
+import org.osgi.framework.*;
+import org.osgi.service.upnp.*;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class RootDeviceListener implements ServiceListener {
+
+ //This list contains all partial tree of UPnP Device
+ //when a device is complete it will be removed from the list
+ private ArrayList devices;
+
+ private DeviceNodeListener listener;
+
+ public RootDeviceListener(){
+ devices = new ArrayList();
+
+ }
+
+ public void setDeviceNodeListener(DeviceNodeListener listener){
+ this.listener = listener;
+ }
+
+ public synchronized void addNewDevice(ServiceReference sr){
+ LogPanel.log("adding device:"+sr.getProperty(UPnPDevice.FRIENDLY_NAME));
+ DeviceNode node = new DeviceNode(sr);
+ //node.print();
+ if(node.isRoot() && node.isLeaf()){
+ //Obiovsly
+ listener.deviceDetected(node);
+ return;
+ }
+
+ if(!node.isLeaf()){
+ //I look if there is some partial tree that is child
+ //of my new node. This operation may complete the tree
+ Iterator list = devices.iterator();
+ DeviceNode handle = null;
+ while(list.hasNext()){
+ DeviceNode tree = (DeviceNode) list.next();
+ if((handle = node.isAttachable(tree)) != null){
+ handle.attach(tree);
+ list.remove();
+ monitorDevices();
+ if(node.isRoot() && node.isComplete()){
+ listener.deviceDetected(node);
+// removeChildren(node);
+ return;
+ }
+ }
+ }
+ }
+
+ if(!node.isRoot()){
+ //I look if there is some partial tree that should own
+ //my new node. This operation may complete the tree
+ Iterator list = devices.iterator();
+ DeviceNode handle = null;
+ while(list.hasNext()){
+ DeviceNode tree = (DeviceNode) list.next();
+ if((handle = tree.isAttachable(node)) != null){
+ handle.attach(node);
+ if(tree.isRoot() && tree.isComplete()){
+ list.remove();
+ monitorDevices();
+ listener.deviceDetected(tree);
+// removeChildren(tree);
+ }
+ return;
+ }
+ }
+ }
+
+ devices.add(node);
+ monitorDevices();
+ }
+
+ private void monitorDevices() {
+ LogPanel.status("Pending Devices: " + devices.size() );
+ }
+
+ public void removeDevice(ServiceReference sr){
+ DeviceNode node = new DeviceNode(sr);
+ if (node.isRoot()) {
+ LogPanel.log("removing root device ..."+sr.getProperty(UPnPDevice.FRIENDLY_NAME));
+ listener.rootDeviceUnplugged(node.toString());
+ return;
+ }
+
+ }
+ /**
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent e) {
+ switch(e.getType()){
+ case ServiceEvent.REGISTERED:{
+ addNewDevice(e.getServiceReference());
+ };break;
+
+ case ServiceEvent.MODIFIED:{
+ };break;
+
+ case ServiceEvent.UNREGISTERING:{
+ removeDevice(e.getServiceReference());
+ };break;
+
+ }
+ }
+
+
+ /**
+ * Register this object to listen to all "well registered" UPnPDevice<br>
+ * that should be Exported<br>
+ * And look for all the already registered UPnPDevice to be exported
+ *
+ */
+ public void activate() {
+ /*
+ * I listen for the UPnPDevice service that are Root
+ * that should be exported to UPnP Network.
+ */
+ try {
+ Activator.context.addServiceListener(this,
+ "(&"+
+ "("+Constants.OBJECTCLASS+"="+UPnPDevice.class.getName()+")"+
+ "("+UPnPDevice.UDN+"=*)"+
+ ")"
+ );
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ ServiceReference[] roots = null;
+ try {
+ roots = Activator.context.getServiceReferences(
+ UPnPDevice.class.getName(),
+ "(&"+
+ "("+Constants.OBJECTCLASS+"="+UPnPDevice.class.getName()+")"+
+ "("+UPnPDevice.UDN+"=*)"+
+ ")"
+ );
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ if(roots!=null){
+ for (int i = 0; i < roots.length; i++) {
+ addNewDevice(roots[i]);
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ public void deactive() {
+ Activator.context.removeServiceListener(this);
+ }
+
+
+
+
+
+
+ public void checkIncompleteDevice() {
+ if (devices.size() == 0){
+ LogPanel.log("[check incomplete device] no pending devices !" );
+ return;
+ }
+ Iterator list = devices.iterator();
+ while(list.hasNext()){
+ LogPanel.log("[check incomplete device] " );
+ LogPanel.log("------- device -------- " );
+ DeviceNode tree = (DeviceNode) list.next();
+ printProperties(tree.getReference());
+ }
+
+ }
+
+ public static void checkErrataDevice() {
+ ServiceReference[] allUPnPDevice = null;
+ ServiceReference[] UPnPbaseDriverDevice = null;
+ try {
+ allUPnPDevice = Activator.context.getServiceReferences(
+ UPnPDevice.class.getName(),
+ "(&" + "(" + UPnPDevice.UPNP_EXPORT + "=*)"
+ + "("+Constants.OBJECTCLASS+"="+UPnPDevice.class.getName()+")"
+ + ")"
+ );
+ // filter used by UPnP base Driver
+ UPnPbaseDriverDevice = Activator.context.getServiceReferences(UPnPDevice.class.getName(),
+ "(&" + "(" + UPnPDevice.UPNP_EXPORT + "=*)" +
+ "(DEVICE_CATEGORY=UPnP)" +
+ "(" + UPnPDevice.UDN + "=*)" +
+ "(" + UPnPDevice.FRIENDLY_NAME + "=*)" +
+ "(" + UPnPDevice.MANUFACTURER + "=*)" +
+ "(" + UPnPDevice.MODEL_NAME + "=*)" +
+ "(" + UPnPDevice.TYPE + "=*)" +
+ "(!("+ UPnPDevice.PARENT_UDN + "=*))" +
+ ")");
+
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ if (allUPnPDevice!=null){
+ if (UPnPbaseDriverDevice!= null){
+ if (allUPnPDevice.length == UPnPbaseDriverDevice.length){
+ LogPanel.log("---- Check Errata Device ----");
+ LogPanel.log("All registered Devices have mandatory properties specified");
+ LogPanel.log("-------- End Check --------");
+ }
+ else if (allUPnPDevice.length > UPnPbaseDriverDevice.length)
+ printErrataDevice(allUPnPDevice,UPnPbaseDriverDevice) ;
+ }
+ else {
+ printErrataDevice(allUPnPDevice,UPnPbaseDriverDevice) ;
+ }
+ }
+
+ }
+
+ public static void printErrataDevice(ServiceReference[] allUPnPDevice,ServiceReference[] UPnPbaseDriverDevice) {
+ LogPanel.log("---- Check Errata Device ----");
+ for (int i =0;i< allUPnPDevice.length;i++){
+ if (! isPresent(allUPnPDevice[i],UPnPbaseDriverDevice)){
+ LogPanel.log("---- Device ----");
+ printProperties(allUPnPDevice[i]);
+ }
+ }
+ LogPanel.log("-------- End Check --------");
+ }
+
+ public static boolean isPresent(ServiceReference sr, ServiceReference[] list) {
+ Object s = Activator.context.getService(sr);
+ for(int i = 0; i<list.length;i++){
+ Object item =Activator.context.getService(list[i]);
+ if (s == item) {
+ Activator.context.ungetService(sr);
+ Activator.context.ungetService(list[i]);
+ return true;
+ }
+ Activator.context.ungetService(list[i]);
+ }
+ Activator.context.ungetService(sr);
+ return false;
+ }
+
+ public static void printProperties(ServiceReference service){
+ String[] properties = service.getPropertyKeys();
+ if (properties == null)
+ LogPanel.log("properties are null");
+ else {
+ for(int j =0;j<properties.length;j++)
+ LogPanel.log(properties[j] + "=" + Util.justString(service.getProperty(properties[j])));
+ }
+
+ if ( service.getProperty(UPnPDevice.UDN)== null)
+ LogPanel.log("[Warning] missing property: "+UPnPDevice.UDN);
+ if ( service.getProperty(UPnPDevice.FRIENDLY_NAME)== null)
+ LogPanel.log("[Warning] missing property: "+UPnPDevice.FRIENDLY_NAME);
+ if ( service.getProperty(UPnPDevice.MANUFACTURER)== null)
+ LogPanel.log("[Warning] missing property: "+UPnPDevice.MANUFACTURER);
+ if ( service.getProperty(UPnPDevice.MODEL_NAME)== null)
+ LogPanel.log("[Warning] missing property: "+UPnPDevice.MODEL_NAME);
+ if ( service.getProperty(UPnPDevice.TYPE)== null)
+ LogPanel.log("[Warning] missing property: "+UPnPDevice.TYPE);
+
+ }
+
+
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/ActionPanel.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/ActionPanel.java
new file mode 100644
index 0000000..2c61c99
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/ActionPanel.java
@@ -0,0 +1,365 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.swing.AbstractAction;
+import javax.swing.AbstractCellEditor;
+import javax.swing.DefaultCellEditor;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSlider;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.SwingConstants;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import javax.swing.event.TableModelEvent;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableModel;
+
+import org.apache.felix.upnp.extra.util.Converter;
+import org.apache.felix.upnp.extra.util.UPnPException;
+import org.apache.felix.upnp.tester.Mediator;
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class ActionPanel extends JPanel {
+
+ UPnPAction action;
+ ArgumentsModel argsModel;
+ MyTable table;
+ JPanel buttonPanel;
+
+ OutputArgumentsModel outArgsModel;
+ JTable outTable;
+
+ /**
+ *
+ */
+ public ActionPanel() {
+ super(new GridBagLayout());
+ buildButtonPanel();
+ buildTable();
+ add(new JScrollPane(table),Util.setConstrains(0,0,1,1,100,100));
+ add(new JScrollPane(outTable),Util.setConstrains(0,1,1,1,100,100));
+ add(buttonPanel,Util.setConstrains(1,0,1,1,1,1));
+ }
+
+ private void buildButtonPanel(){
+ buttonPanel = new JPanel();
+ JButton doAction = new JButton("Do Action");
+ doAction.addActionListener(new AbstractAction(){
+ public void actionPerformed(ActionEvent e) {
+ outArgsModel.clearData();
+
+ Dictionary params = null;
+ Dictionary result = null;
+ if (argsModel.getRowCount()!= 0){
+ if (table.isEditing()) table.getCellEditor().stopCellEditing();
+ params = new Hashtable();
+ for (int i =0;i<argsModel.getRowCount();i++){
+ String name = (String) argsModel.getValueAt(i,0);
+ String value = (String)argsModel.getValueAt(i,3);
+ try {
+ params.put(
+ name,
+ Converter.parseString(
+ value,
+ action.getStateVariable(name).getUPnPDataType()));
+ } catch (Exception ex) {
+ LogPanel.log("Error invoking action (bad parameter)");
+ return ;
+ }
+ }
+ }
+ try {result = action.invoke(params);}
+ catch (UPnPException ex){
+ String error =
+ "===== Action Failed =====" +
+ "\nUPnP Error Code::\n " +ex.getErrorCode() +
+ "\nUPnP Error Description::\n " +ex.getErrorDescription();
+ printReport(params,error);
+ JOptionPane.showMessageDialog(
+ Mediator.getPropertiesViewer(),error);
+ }
+ catch (Exception ex){
+ printReport(params,ex.getMessage());
+ JOptionPane.showMessageDialog(
+ Mediator.getPropertiesViewer(),
+ ex.getMessage()
+ );
+ }
+ if (result != null) {
+ printReport(params,result);
+ outArgsModel.setData(action,result);
+ JOptionPane.showMessageDialog(
+ Mediator.getPropertiesViewer(),
+ "Action invoked!"
+ );
+
+ }
+ }
+ private void printReport(Dictionary params,Object result) {
+ String input = "";
+ String output = "";
+ if (params != null) input = params.toString();
+ if (output != null) output = result.toString();
+ String method = action.getName();
+ String report = "\n==== Action:: " + method + " ====\n"
+ + input
+ + "\n----------- result ----------\n"
+ + output
+ + "\n-----------------------------";
+ LogPanel.log(report);
+ }
+ });
+ buttonPanel.add(doAction);
+ }
+
+ private void buildTable(){
+ argsModel = new ArgumentsModel();
+ table = new MyTable(argsModel);
+ argsModel.setTable(table);
+
+ outArgsModel = new OutputArgumentsModel();
+ outTable = new JTable(outArgsModel);
+ }
+
+ public void setArguments(UPnPAction action){
+ this.action = action;
+ argsModel.setData(action);
+ outArgsModel.clearData();
+ }
+
+}
+
+//thanks to Thomas Wagner 18/10/2005
+class OutputArgumentsModel extends ArgumentsModel {
+
+ public OutputArgumentsModel() {
+ super();
+ header = new String[]{"output arg name","related Var","Java \\ UpnP type","value"};
+ }
+
+ public void clearData() {
+ names = new String[]{""};
+ related = new String[]{""};
+ types = new String[]{""};
+ values = new String[]{""};
+ size=0;
+ this.fireTableChanged(new TableModelEvent(this));
+ }
+
+ public void setData(UPnPAction action, Object result){
+
+ Hashtable res = (Hashtable) result;
+
+ String[] names = action.getOutputArgumentNames();
+ size = 0;
+ this.names = names;
+ if (names!=null){
+ values = new String[names.length];
+ types = new String[names.length];
+ related = new String[names.length];
+ for (int i=0;i<names.length;i++) {
+ UPnPStateVariable currentStateVar = action.getStateVariable(names[i]);
+
+ Object value = res.get(names[i]);
+ values[i]=value.toString();
+ related[i] = currentStateVar.getName();
+
+ String javaType =currentStateVar.getJavaDataType().toString();
+ javaType = javaType.substring(javaType.lastIndexOf('.')+1);
+ String upnpType = currentStateVar.getUPnPDataType();
+ types[i] = javaType + " \\ " + upnpType;
+ }
+ size = names.length;
+ }
+ this.fireTableChanged(new TableModelEvent(this));
+ }
+}
+
+//thanks to Thomas Wagner 12/10/2005
+class ArgumentsModel extends AbstractTableModel {
+ int size = 0;
+ private MyTable table;
+ String[] names = new String[]{""};
+ String[] related = new String[]{""};
+ String[] types = new String[]{""};
+ String[] values = new String[]{""};
+ String[] header = new String[]{"arg name","related Var","Java \\ UpnP type","value"};
+
+ public void setTable(MyTable table) {
+ this.table = table;
+ }
+
+ public int getColumnCount() { return 4; }
+ public int getRowCount() { return size;}
+ public String getColumnName(int col) { return header[col]; }
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return (columnIndex ==3);
+ }
+ public Object getValueAt(int row, int col) {
+ if (col == 0) return names[row];
+ else if (col == 1) return related[row];
+ else if (col == 2) return types[row];
+ else if (col == 3) return values[row];
+ return null;
+ }
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ values[rowIndex]= (String) aValue;
+ }
+
+ public void setData(UPnPAction action){
+
+ table.deleteMyCellEditors();
+
+
+ String[] names = action.getInputArgumentNames();
+ size = 0;
+ this.names = names;
+ if (names!=null){
+ values = new String[names.length];
+ related = new String[names.length];
+ types = new String[names.length];
+ for (int i=0;i<names.length;i++) {
+ values[i]="";
+ UPnPStateVariable currentStateVar = action.getStateVariable(names[i]);
+ related[i] = currentStateVar.getName();
+ String javaType = currentStateVar.getJavaDataType().toString();
+ javaType = javaType.substring(javaType.lastIndexOf('.')+1);
+ String upnpType = currentStateVar.getUPnPDataType();
+ types[i] = javaType + " \\ " + upnpType;
+
+ //handle allowed value list
+ if ( currentStateVar.getAllowedValues() != null) {
+ String av[] = currentStateVar.getAllowedValues();
+ JComboBox comboBox = new JComboBox();
+ for (int j = 0; j < av.length; j++) {
+ comboBox.addItem(av[j]);
+ }
+ values[i] = av[0]; //preset the first value from list
+ table.setMyCellEditor(new DefaultCellEditor(comboBox),i);
+ }
+
+ //handle default value
+ if (currentStateVar.getDefaultValue() != null) {
+ String val = currentStateVar.getDefaultValue().toString();
+ if(val.length() > 0)
+ values[i] = val;
+ }
+
+ //handle range values
+ if ((currentStateVar.getMaximum()!= null)
+ &&(currentStateVar.getMinimum()!= null)){
+ int max = currentStateVar.getMaximum().intValue();
+ int min = currentStateVar.getMinimum().intValue();
+ int value = min;
+ try { value = Integer.parseInt(values[i]);}
+ catch (NumberFormatException ignored){}
+ table.setMyCellEditor(new SliderEditor(min,max,value),i);
+ }
+
+ }
+ size = names.length;
+ }
+ this.fireTableChanged(new TableModelEvent(this));
+ this.fireTableStructureChanged();
+ }
+}
+
+// thanks to Thomas Wagner 12/10/2005
+class MyTable extends JTable {
+
+ private Hashtable cellEditors;
+
+ public MyTable(TableModel dm) {
+ super(dm);
+ cellEditors = new Hashtable();
+ }
+
+ public void setMyCellEditor(TableCellEditor editor,int col){
+ cellEditors.put(new Integer(col),editor);
+ }
+
+ public void deleteMyCellEditors(){
+ cellEditors.clear();
+ }
+
+ //overwritten JTable method
+ public TableCellEditor getCellEditor(int row,int col) {
+ TableCellEditor tce = (TableCellEditor) cellEditors.get(new Integer(row));
+ if( tce != null) {
+ return tce;
+ } else {
+ return super.getCellEditor(row,col);
+ }
+ }
+}
+
+class SliderEditor extends AbstractCellEditor implements TableCellEditor
+{
+ JPanel editor;
+ JTextField text;
+ JSlider slider;
+ public SliderEditor(int min, int max, int value){
+ editor = new JPanel(new BorderLayout());
+ //editor.setBorder(new EmptyBorder(1,0,1,0));
+ text = new JTextField(Integer.toString(max).length());
+ slider = new JSlider(SwingConstants.HORIZONTAL,min,max,value);
+ editor.add(text,BorderLayout.WEST);
+ editor.add(slider);
+ slider.addChangeListener(new ChangeListener(){
+ public void stateChanged(ChangeEvent e) {
+ //if (! replSlider.getValueIsAdjusting()){
+ text.setText(new Integer(slider.getValue()).toString());
+ //}
+ }
+ });
+
+ }
+
+ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+ text.setText((String) value);
+ try {
+ slider.setValue(Integer.parseInt((String)value));
+ } catch (NumberFormatException ignored) {}
+ return editor;
+ }
+
+ public Object getCellEditorValue() {
+ return text.getText();
+ }
+}
+
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/LogPanel.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/LogPanel.java
new file mode 100644
index 0000000..9300686
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/LogPanel.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.gui;
+
+import java.awt.BorderLayout;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollBar;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class LogPanel extends JPanel {
+ private static JTextArea logArea = new JTextArea(4,50);
+ private static JPanel statusBar = new JPanel(new BorderLayout());
+ private static JLabel statusText = new JLabel();
+
+ private static JScrollPane scroll = new JScrollPane(logArea);
+
+ public LogPanel() {
+ super(new BorderLayout());
+ logArea.setText("");
+ //add(new JScrollPane(new JTextArea(4,80)));
+ add(scroll);
+ statusBar.add(statusText,BorderLayout.EAST);
+ add(statusBar,BorderLayout.SOUTH);
+ }
+
+ /* public static void log(String msg) {
+ logArea.append(msg + "\n\r");
+ JScrollBar scrBar = scroll.getVerticalScrollBar();
+ int maxPos = scrBar.getMaximum();
+ scrBar.setValue(maxPos);
+ }*/
+
+ public static void log(final String msg){
+ synchronized (logArea) {
+ logArea.append(msg );
+ logArea.append("\n\r");
+ }
+ JScrollBar scrBar = scroll.getVerticalScrollBar();
+ int maxPos = scrBar.getMaximum();
+ scrBar.setValue(maxPos);
+ }
+
+ public static void status(final String msg){
+ statusText.setText(msg);
+ }
+
+ public static void clear(String msg) {
+ logArea.setText("");
+ }
+
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/PropertiesViewer.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/PropertiesViewer.java
new file mode 100644
index 0000000..917bbb7
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/PropertiesViewer.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.gui;
+
+
+
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.GridBagLayout;
+import java.awt.Point;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTree;
+import javax.swing.event.TableModelEvent;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.DefaultTableCellRenderer;
+
+import org.apache.felix.upnp.tester.Mediator;
+import org.apache.felix.upnp.tester.discovery.DeviceNode;
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPDevice;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class PropertiesViewer extends JPanel {
+
+ ActionPanel actionsPanel;
+ SubscriptionPanel subscriptionPanel;
+ DataModel dataModel;
+ JTable table;
+
+ public PropertiesViewer(){
+ super(new GridBagLayout());
+ buildTable();
+ actionsPanel = new ActionPanel();
+ subscriptionPanel = new SubscriptionPanel();
+
+ JScrollPane scroll = new JScrollPane(table);
+ scroll.setPreferredSize(new Dimension(500,200));
+ //actionsPanel.setPreferredSize(new Dimension(500,100)); twa
+ actionsPanel.setPreferredSize(new Dimension(500,200));
+ add(scroll,Util.setConstrains(0,0,6,2,100,50));
+ add(actionsPanel,Util.setConstrains(0,2,6,1,100,20));
+ add(subscriptionPanel,Util.setConstrains(0,3,6,1,100,5));
+ showActionPanel(false);
+ showSubscriptionPanel(false);
+
+ table.addMouseMotionListener(new MouseMotionListener(){
+ private final Cursor handCursor = new Cursor(Cursor.HAND_CURSOR);
+
+ public void mouseDragged(MouseEvent e) {}
+ public void mouseMoved(MouseEvent e) {
+ String link = getDataLink(e.getPoint());
+ if (link != null)
+ table.setCursor(handCursor);
+ else
+ table.setCursor(Cursor.getDefaultCursor());
+ }
+
+ });
+
+ table.addMouseListener(new MouseAdapter(){
+ public void mouseClicked(MouseEvent e){
+ String link = getDataLink(e.getPoint());
+ if (link != null)
+ Util.openUrl(link);
+ }
+ });
+
+ }
+
+ public String getDataLink(Point p) {
+ int col = table.columnAtPoint(p);
+ if (col != 1)
+ return null;
+ else {
+ int row = table.rowAtPoint(p);
+ String data = (String) dataModel.getValueAt(row,col);
+ if (data == null) return null;
+ if (data.length()<4) return null;
+ String begin = data.substring(0,4);
+ if (begin.equalsIgnoreCase("http"))
+ return data;
+ else {
+ String propertyName= (String) dataModel.getValueAt(row,0);
+ if (propertyName.equalsIgnoreCase(UPnPDevice.PRESENTATION_URL)
+ ||propertyName.equalsIgnoreCase(UPnPDevice.MANUFACTURER_URL)
+ ||propertyName.equalsIgnoreCase(UPnPDevice.MODEL_URL) )
+ {
+ JTree tree = Mediator.getUPnPDeviceTree();
+ UPnPDeviceTreeNode selectedNode = (UPnPDeviceTreeNode)tree.getLastSelectedPathComponent();
+ String url = "";
+ if (selectedNode.category.equals(UPnPDeviceTreeNode.DEVICE)){
+ UPnPDeviceTreeNode parent = (UPnPDeviceTreeNode)selectedNode.getParent();
+ while (parent.category!=UPnPDeviceTreeNode.ROOT_DEVICE)
+ parent = (UPnPDeviceTreeNode)parent.getParent();
+ DeviceNode device = (DeviceNode) parent.getUserObject();
+ String udn = (String)device.getReference().getProperty(UPnPDevice.UDN);
+ url = Mediator.getDriverProxy().resolveRelativeUrl(udn,data);
+ return url;
+ }
+ else if (selectedNode.category.equals(UPnPDeviceTreeNode.ROOT_DEVICE))
+ {
+ DeviceNode node = (DeviceNode) selectedNode.getUserObject();
+ String udn = (String)node.getReference().getProperty(UPnPDevice.UDN);
+ url = Mediator.getDriverProxy().resolveRelativeUrl(udn,data);
+ return url;
+ }
+ }
+ return null;
+ }
+ }
+ }
+
+ public void setProperties(String[]name,String[]values){
+ dataModel.setData(name,values);
+ }
+
+ public void setAction(UPnPAction action){
+ actionsPanel.setArguments(action);
+
+ }
+
+ public void showActionPanel(boolean show){
+ actionsPanel.setVisible(show);
+ }
+
+ public void showSubscriptionPanel(boolean show){
+ subscriptionPanel.setVisible(show);
+ }
+
+ private void buildTable(){
+ dataModel = new DataModel();
+ table = new JTable(dataModel);
+ table.setDefaultRenderer(table.getColumnClass(1), new LinkCellRenderer());
+ }
+
+
+}
+
+class DataModel extends AbstractTableModel {
+ int size = 0;
+ String[] names = new String[]{""};
+ String[] values = new String[]{""};
+ String[] header = new String[]{"property key","value"};
+
+ public String getColumnName(int col) { return header[col]; }
+ public int getColumnCount() { return 2; }
+ public int getRowCount() { return size;}
+ public Object getValueAt(int row, int col) {
+ if (col==0) return names[row];
+ else return values[row];
+ }
+
+ /*
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return false;
+ }
+ */
+
+ public void setData(String[]names,String[]values){
+ String[] lowerNames = new String[names.length];
+ for (int i=0;i<names.length;i++)
+ lowerNames[i]= names[i].toLowerCase();
+ this.names=lowerNames;
+ this.values=values;
+ size = names.length;
+ this.fireTableChanged(new TableModelEvent(this));
+ }
+
+}
+
+class LinkCellRenderer extends DefaultTableCellRenderer
+{
+ public LinkCellRenderer(){
+ super();
+ }
+
+ public Component getTableCellRendererComponent(JTable table, Object value,
+ boolean isSelected, boolean hasFocus, int row, int column) {
+ super.getTableCellRendererComponent(table,value,isSelected,hasFocus,row,column);
+ if (column==1){
+ String propertyName = (String)table.getModel().getValueAt(row,0);
+ if (propertyName.equalsIgnoreCase(UPnPDevice.PRESENTATION_URL)
+ ||propertyName.equalsIgnoreCase(UPnPDevice.MODEL_URL)
+ ||propertyName.equalsIgnoreCase(UPnPDevice.MANUFACTURER_URL))
+ {
+ if (!value.equals(""))
+ setValue("<html><a href=''>"+value+"</a></html>");
+ return this;
+ }
+ if (((String) value).length()<4) return this;
+ String begin = ((String) value).substring(0,4);
+ if (begin.equalsIgnoreCase("http"))
+ setValue("<html><a href=''>"+value+"</a></html>");
+ }
+ return this;
+ }
+
+}
+
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/SubscriptionPanel.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/SubscriptionPanel.java
new file mode 100644
index 0000000..18476f8
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/SubscriptionPanel.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.gui;
+
+
+
+import java.awt.event.ActionEvent;
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JTree;
+import javax.swing.SwingUtilities;
+
+import org.apache.felix.upnp.tester.Activator;
+import org.apache.felix.upnp.tester.Mediator;
+import org.apache.felix.upnp.tester.UPnPSubscriber;
+import org.apache.felix.upnp.tester.discovery.DeviceNode;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPEventListener;
+import org.osgi.service.upnp.UPnPService;
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class SubscriptionPanel extends JPanel implements UPnPEventListener{
+ public SubscriptionPanel() {
+ super();
+ buildButtonPanel();
+ }
+
+ private void buildButtonPanel(){
+ JButton subscribeBtn = new JButton("Subscribe");
+ subscribeBtn.addActionListener(new AbstractAction(){
+ public void actionPerformed(ActionEvent e) {
+ //System.out.println("subscribing ...");
+ doSubscribe();
+ }
+ });
+ JButton unsubscribeBtn = new JButton("Unsubscribe");
+ unsubscribeBtn.addActionListener(new AbstractAction(){
+ public void actionPerformed(ActionEvent e) {
+ //System.out.println("unsubscribing ...");
+ doUnsubscribe();
+ }
+ });
+ add(subscribeBtn);
+ add(unsubscribeBtn);
+ }
+
+ UPnPSubscriber subscriber;
+ public void doSubscribe()
+ {
+ if (subscriber == null)
+ subscriber = new UPnPSubscriber(Activator.context,this);
+
+ UPnPDeviceTreeNode selectedNode = getSelectedNode();
+ String serviceId = getServiceId(selectedNode);
+ String parentId = getDeviceId(selectedNode);
+ LogPanel.log("subscribing ... "+ "ServiceId ["+serviceId+"] of DeviceId ["+parentId +"]");
+ subscriber.subscribe(parentId,serviceId);
+ setSubscribedVariableOf(selectedNode);
+ }
+
+ public void doUnsubscribe(){
+ UPnPDeviceTreeNode selectedNode = getSelectedNode();
+ String serviceId = getServiceId(selectedNode);
+ String parentId = getDeviceId(selectedNode);
+ LogPanel.log("unsubscribing ... "+ "ServiceId ["+serviceId+"] of DeviceId ["+parentId +"]");
+ subscriber.unsubscribe(parentId,serviceId);
+ setUnubscribedVariableOf(selectedNode);
+ }
+
+ public void notifyUPnPEvent(final String deviceId, final String serviceId, final Dictionary events) {
+ // UPnP base driver notify are synchronous !!
+ Runnable doShowMsg = new Runnable() {
+ public void run() {
+ LogPanel.log("notifyUPnPEvent::[DeviceID "+deviceId+"][ServiceId "+serviceId+"]");
+ Enumeration elements = events.keys();
+ while (elements.hasMoreElements()){
+ Object key = elements.nextElement();
+ Object value = events.get(key);
+ LogPanel.log("["+key+"][value "+value+"]");
+ }
+ }
+ };
+ SwingUtilities.invokeLater(doShowMsg);
+
+ }
+
+ private void setSubscribedVariableOf(UPnPDeviceTreeNode selectedNode){
+ Enumeration list = selectedNode.children();
+ while (list.hasMoreElements()){
+ UPnPDeviceTreeNode node = (UPnPDeviceTreeNode) list.nextElement();
+ if (node.category == UPnPDeviceTreeNode.EVENTED_STATE)
+ node.category = UPnPDeviceTreeNode.SUBSCRIBED_STATE;
+ }
+ JTree tree = Mediator.getUPnPDeviceTree();
+ tree.validate();
+ tree.repaint();
+ }
+
+ private void setUnubscribedVariableOf(UPnPDeviceTreeNode selectedNode){
+ Enumeration list = selectedNode.children();
+ while (list.hasMoreElements()){
+ UPnPDeviceTreeNode node = (UPnPDeviceTreeNode) list.nextElement();
+ if (node.category == UPnPDeviceTreeNode.SUBSCRIBED_STATE)
+ node.category = UPnPDeviceTreeNode.EVENTED_STATE;
+ }
+ JTree tree = Mediator.getUPnPDeviceTree();
+ tree.validate();
+ tree.repaint();
+ }
+
+ private UPnPDeviceTreeNode getSelectedNode(){
+ JTree tree = Mediator.getUPnPDeviceTree();
+ UPnPDeviceTreeNode selectedNode = (UPnPDeviceTreeNode)tree.getLastSelectedPathComponent();
+ return selectedNode;
+ }
+ private String getServiceId (UPnPDeviceTreeNode selectedNode){
+ Object userObj = selectedNode.getUserObject();
+ String serviceId = ((UPnPService) userObj).getId();
+ return serviceId;
+ }
+ private String getDeviceId (UPnPDeviceTreeNode selectedNode){
+ UPnPDeviceTreeNode parent = (UPnPDeviceTreeNode)selectedNode.getParent();
+ DeviceNode node =(DeviceNode)parent.getUserObject();
+ String parentId = (String) node.getReference().getProperty(UPnPDevice.ID);
+ return parentId;
+ }
+
+
+
+}
+
+
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/TreeViewer.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/TreeViewer.java
new file mode 100644
index 0000000..403533e
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/TreeViewer.java
@@ -0,0 +1,323 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.gui;
+
+
+import java.awt.BorderLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+import javax.swing.AbstractAction;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JScrollPane;
+import javax.swing.JTree;
+import javax.swing.SwingUtilities;
+import javax.swing.ToolTipManager;
+import javax.swing.event.PopupMenuEvent;
+import javax.swing.event.PopupMenuListener;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreePath;
+
+import org.apache.felix.upnp.tester.Activator;
+import org.apache.felix.upnp.tester.Mediator;
+import org.apache.felix.upnp.tester.discovery.DeviceNode;
+import org.apache.felix.upnp.tester.discovery.DeviceNodeListener;
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPService;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class TreeViewer extends JPanel implements DeviceNodeListener
+{
+
+ private UPnPDeviceTreeNode root;
+ private DefaultTreeModel treeModel;
+ private JTree tree;
+ final TreePopup popup ;
+ public TreeViewer(){
+ super(new BorderLayout());
+ Mediator.setTreeViewer(this);
+ root = new UPnPDeviceTreeNode("UPnP Devices");
+ treeModel= new DefaultTreeModel(root);
+ tree = new JTree(treeModel);
+ Mediator.setUPnPDeviceTree(tree);
+ tree.setCellRenderer(new TreeNodeCellRenderer() );
+ tree.putClientProperty("JTree.lineStyle", "Angled");
+ add(new JScrollPane(tree));
+ addTreeSelectionListener();
+
+
+ popup = new TreePopup(tree);
+ popup.setEnabled(false);
+ tree.addMouseListener(new MouseAdapter(){
+ public void mouseClicked(MouseEvent e){
+ if (SwingUtilities.isRightMouseButton(e)){
+ TreePath path = tree.getClosestPathForLocation(e.getX(), e.getY());
+ tree.setSelectionPath(path);
+ tree.scrollPathToVisible(path);
+ popup.show(tree, e.getX(), e.getY());
+ }
+ }
+ });
+ ToolTipManager.sharedInstance().registerComponent(tree);
+
+
+ }
+
+ public void setPopupMenuEnabled(boolean driverControllerAvailable){
+ popup.getComponent(0).setEnabled(driverControllerAvailable);
+ }
+ /* (non-Javadoc)
+ * @see org.apache.felix.sample.upnp.DeviceNodeListener#deviceDetected(it.cnr.isti.niche.osgi.upnpbase.export.DeviceNode)
+ */
+ public void deviceDetected(DeviceNode node) {
+ root.add(new UPnPDeviceTreeNode(node,Activator.context));
+ treeModel.nodeStructureChanged(root);
+ }
+
+ public void rootDeviceUnplugged(String udn){
+ Enumeration list = root.children();
+ while (list.hasMoreElements()){
+ UPnPDeviceTreeNode node= (UPnPDeviceTreeNode)list.nextElement();
+ DeviceNode device = (DeviceNode)node.getUserObject();
+ if (udn.equals(device.toString())) {
+ node.removeFromParent();
+ treeModel.nodeStructureChanged(root);
+ }
+ }
+ }
+
+ private void addTreeSelectionListener(){
+ tree.addTreeSelectionListener(new TreeSelectionListener(){
+ public void valueChanged(TreeSelectionEvent e){
+ UPnPDeviceTreeNode selectedNode = (UPnPDeviceTreeNode)tree.getLastSelectedPathComponent();
+ doNodeAction(selectedNode);
+ }
+ });
+ }
+
+ private void doNodeAction(UPnPDeviceTreeNode node){
+ if (node == null) {
+ clearPropertiesViewer();
+ return;
+ }
+ if (node.category.equals(UPnPDeviceTreeNode.ACTION))
+ Mediator.getPropertiesViewer().showActionPanel(true);
+ else
+ Mediator.getPropertiesViewer().showActionPanel(false);
+
+ if (node.category.equals(UPnPDeviceTreeNode.SERVICE))
+ Mediator.getPropertiesViewer().showSubscriptionPanel(true);
+ else
+ Mediator.getPropertiesViewer().showSubscriptionPanel(false);
+
+ if ( node.category.equals(UPnPDeviceTreeNode.DEVICE)
+ ||node.category.equals(UPnPDeviceTreeNode.ROOT_DEVICE)){
+ DeviceNode device = (DeviceNode) node.getUserObject();
+ UPnPDevice upnpDevice = device.getDevice(Activator.context);
+ makeProperties(upnpDevice);
+ }
+ else if (node.category.equals(UPnPDeviceTreeNode.SERVICE)){
+ UPnPService service = (UPnPService) node.getUserObject();
+ makeProperties(service);
+ }
+ else if (node.category.equals(UPnPDeviceTreeNode.ACTION)){
+ UPnPAction action = (UPnPAction) node.getUserObject();
+ makeProperties(action);
+ Mediator.getPropertiesViewer().setAction(action);
+ }
+ else if (node.category.equals(UPnPDeviceTreeNode.STATE)
+ ||node.category.equals(UPnPDeviceTreeNode.EVENTED_STATE)
+ ||node.category.equals(UPnPDeviceTreeNode.SUBSCRIBED_STATE)){
+ UPnPStateVariable state = (UPnPStateVariable) node.getUserObject();
+ makeProperties(state);
+ }
+
+ }
+
+ private void clearPropertiesViewer(){
+ String[] names = new String[]{};
+ String[] values = new String[]{};
+ PropertiesViewer viewer = Mediator.getPropertiesViewer();
+ viewer.setProperties(names,values);
+ viewer.showActionPanel(false);
+ viewer.showSubscriptionPanel(false);
+ }
+
+ private void makeProperties(UPnPDevice upnpDevice){
+ Dictionary dict = upnpDevice.getDescriptions(null);
+ int size = dict.size();
+ String[] names = new String[size];
+ String[] values = new String[size];
+ Enumeration keys = dict.keys();
+ for (int i=0;i<size;i++){
+ names[i]= (String) keys.nextElement();
+ values[i]= Util.justString(dict.get(names[i]));
+ }
+ Mediator.getPropertiesViewer().setProperties(names,values);
+ }
+
+ private void makeProperties(UPnPService service){
+ String[] names = new String[]{"Id","Type","Version"};
+ String[] values = new String[]{service.getId(),service.getType(),service.getType()};
+ Mediator.getPropertiesViewer().setProperties(names,values);
+ }
+
+ private void makeProperties(UPnPAction action){
+ ArrayList names = new ArrayList();
+ ArrayList values = new ArrayList();
+ names.add("Name");
+ values.add(action.getName());
+
+ String returnName = action.getReturnArgumentName();
+ if (returnName != null){
+ names.add("Return value name");
+ values.add(returnName);
+ }
+ String[] inArg = action.getInputArgumentNames();
+ if (inArg != null){
+ for (int i = 0; i<inArg.length;i++){
+ names.add("Input arg["+ (i+1)+"]");
+ values.add(inArg[i]);
+ }
+ }
+ String[] outArg = action.getOutputArgumentNames();
+ if (outArg != null){
+ for (int i = 0; i<outArg.length;i++){
+ names.add("Output arg["+ (i+1)+"]");
+ values.add(outArg[i]);
+ }
+ }
+
+ Mediator.getPropertiesViewer().setProperties(
+ (String[])names.toArray(new String[]{}),
+ (String[])values.toArray(new String[]{})
+ );
+
+ }
+
+ private void makeProperties(UPnPStateVariable state){
+ ArrayList names = new ArrayList();
+ ArrayList values = new ArrayList();
+ names.add("Name");
+ values.add(state.getName());
+ names.add("Evented");
+ values.add(state.sendsEvents()? "yes":"no");
+ names.add("Default Value");
+ values.add(Util.justString(state.getDefaultValue()));
+ names.add("Java Data Type");
+ values.add(state.getJavaDataType().getName());
+ names.add("Java UPnP Type");
+ values.add(state.getUPnPDataType());
+ names.add("Minimum");
+ values.add(Util.justString(state.getMinimum()));
+ names.add("Maximum");
+ values.add(Util.justString(state.getMaximum()));
+ names.add("Step");
+ values.add(Util.justString(state.getStep()));
+ String[] allowed = state.getAllowedValues();
+ if (allowed!=null){
+ for (int i=0;i<allowed.length;i++){
+ names.add("Allowed value["+i+1+"]");
+ values.add(allowed[i]);
+ }
+ }
+ Mediator.getPropertiesViewer().setProperties(
+ (String[])names.toArray(new String[]{}),
+ (String[])values.toArray(new String[]{})
+ );
+ }
+
+
+}
+
+class TreePopup extends JPopupMenu implements PopupMenuListener {
+ JTree tree;
+ JMenuItem item;
+
+ public TreePopup(final JTree tree){
+ super();
+ this.tree = tree;
+ (item = add(new AbstractAction(){
+ public void actionPerformed(ActionEvent e){
+ UPnPDeviceTreeNode selectedNode = (UPnPDeviceTreeNode)tree.getLastSelectedPathComponent();
+ String url = "";
+ if (selectedNode.category.equals(UPnPDeviceTreeNode.DEVICE)){
+ UPnPDeviceTreeNode parent = (UPnPDeviceTreeNode)selectedNode.getParent();
+ while (parent.category!=UPnPDeviceTreeNode.ROOT_DEVICE)
+ parent = (UPnPDeviceTreeNode)parent.getParent();
+ DeviceNode device = (DeviceNode) parent.getUserObject();
+ String udn = (String)device.getReference().getProperty(UPnPDevice.UDN);
+ url = Mediator.getDriverProxy().getDeviceDescriptionURI(udn);
+ }
+
+ else if (selectedNode.category.equals(UPnPDeviceTreeNode.ROOT_DEVICE))
+ {
+ DeviceNode node = (DeviceNode) selectedNode.getUserObject();
+ String udn = (String)node.getReference().getProperty(UPnPDevice.UDN);
+ url = Mediator.getDriverProxy().getDeviceDescriptionURI(udn);
+ }
+ else if (selectedNode.category.equals(UPnPDeviceTreeNode.SERVICE))
+ {
+ UPnPDeviceTreeNode parent = (UPnPDeviceTreeNode)selectedNode.getParent();
+ while (parent.category!=UPnPDeviceTreeNode.ROOT_DEVICE)
+ parent = (UPnPDeviceTreeNode)parent.getParent();
+ DeviceNode device = (DeviceNode) parent.getUserObject();
+ String udn = (String)device.getReference().getProperty(UPnPDevice.UDN);
+ UPnPService service = (UPnPService) selectedNode.getUserObject();
+ url = Mediator.getDriverProxy().getServiceDescriptionURI(udn,service.getId());
+ }
+ Util.openUrl(url);
+ }
+ })).setText("Show Description");
+ addPopupMenuListener(this);
+
+ }
+
+ public void popupMenuCanceled(PopupMenuEvent e){}
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e){}
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e){
+ if (Mediator.getDriverProxy().isDriverAvailable()){
+ UPnPDeviceTreeNode selectedNode = (UPnPDeviceTreeNode)tree.getLastSelectedPathComponent();
+ if (selectedNode.category.equals(UPnPDeviceTreeNode.DEVICE)
+ ||selectedNode.category.equals(UPnPDeviceTreeNode.ROOT_DEVICE)
+ ||selectedNode.category.equals(UPnPDeviceTreeNode.SERVICE))
+ {
+ item.setEnabled(true);
+ }
+ else
+ item.setEnabled(false);
+ }
+ else
+ item.setEnabled(false);
+
+ }
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/UPnPDeviceTreeNode.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/UPnPDeviceTreeNode.java
new file mode 100644
index 0000000..ecda361
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/UPnPDeviceTreeNode.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.gui;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.image.ImageObserver;
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JToolTip;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import org.apache.felix.upnp.tester.discovery.DeviceNode;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPService;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class UPnPDeviceTreeNode extends DefaultMutableTreeNode {
+ public final static String ROOT_DEVICE = "RootDeviceNode";
+ public final static String DEVICE = "DeviceNode";
+ public final static String SERVICE = "UPnPService";
+ public final static String ACTION = "UPnPAction";
+ public final static String STATE = "UPnPStateVariable";
+ public final static String EVENTED_STATE = "EventedStateVariable";
+ public final static String SUBSCRIBED_STATE = "SubscribedStateVariable";
+
+ protected String category;
+ public UPnPDeviceTreeNode(String obj) {
+ super(obj);
+ category = obj.getClass().getName();
+ }
+
+ public UPnPDeviceTreeNode(DeviceNode obj, BundleContext ctx) {
+ super(obj);
+
+ if (obj.isRoot()) category = ROOT_DEVICE;
+ else category = DEVICE;
+
+ UPnPDevice device = (UPnPDevice)ctx.getService(obj.getReference());
+ UPnPService[] services = device.getServices();
+
+ Collection nodeChildren = obj.getChildren();
+ if (nodeChildren != null){
+ Iterator list = nodeChildren.iterator();
+ while (list.hasNext()){
+ DeviceNode node = (DeviceNode)list.next();
+ this.add(new UPnPDeviceTreeNode(node,ctx));
+ }
+ }
+ if (services != null){
+ for (int i=0;i<services.length;i++)
+ this.add(new UPnPDeviceTreeNode(services[i]));
+ }
+
+ }
+
+ public UPnPDeviceTreeNode(UPnPService obj) {
+ super(obj);
+ category = SERVICE;
+ UPnPStateVariable[] variables = obj.getStateVariables();
+ if (variables != null){
+ for (int i=0;i<variables.length;i++)
+ this.add(new UPnPDeviceTreeNode(variables[i]));
+ }
+ UPnPAction[] actions = obj.getActions();
+ if (actions != null){
+ for (int i=0;i<actions.length;i++)
+ this.add(new UPnPDeviceTreeNode(actions[i]));
+ }
+ }
+ public UPnPDeviceTreeNode(UPnPAction obj) {
+ super(obj);
+ category = ACTION;
+ }
+
+ public UPnPDeviceTreeNode(UPnPStateVariable obj) {
+ super(obj);
+ if (obj.sendsEvents()) category = EVENTED_STATE;
+ else category = STATE;
+ }
+
+ public String toString() {
+ if (category.equals(DEVICE)||category.equals(ROOT_DEVICE)){
+ DeviceNode node = (DeviceNode) getUserObject();
+ return node.toString();
+ }
+ else if (category.equals(SERVICE)){
+ UPnPService node = (UPnPService) getUserObject();
+ return node.getType();
+ }
+ else if (category.equals(ACTION)){
+ UPnPAction node = (UPnPAction) getUserObject();
+ return node.getName();
+ }
+ else if (category.equals(STATE) ||category.equals(EVENTED_STATE)||category.equals(SUBSCRIBED_STATE)){
+ UPnPStateVariable node = (UPnPStateVariable) getUserObject();
+ return node.getName();
+ }
+ else
+ return getUserObject().toString();
+ }
+}
+
+// local class for JTree icon renderer
+class TreeNodeCellRenderer extends DefaultTreeCellRenderer implements ImageObserver{
+
+ private HashMap icons ;
+ ImageIcon image;
+ public TreeNodeCellRenderer() {
+ super();
+ icons = new HashMap();
+ try {
+ icons.put(UPnPDeviceTreeNode.EVENTED_STATE, loadIcon(UPnPDeviceTreeNode.EVENTED_STATE));
+ image = loadIcon(UPnPDeviceTreeNode.SUBSCRIBED_STATE);
+ // to use animate gif
+ //image.setImageObserver(this);
+ icons.put(UPnPDeviceTreeNode.SUBSCRIBED_STATE, image);
+
+ icons.put(UPnPDeviceTreeNode.ROOT_DEVICE, loadIcon(UPnPDeviceTreeNode.ROOT_DEVICE));
+ icons.put(UPnPDeviceTreeNode.DEVICE, loadIcon(UPnPDeviceTreeNode.DEVICE));
+ icons.put(UPnPDeviceTreeNode.SERVICE, loadIcon(UPnPDeviceTreeNode.SERVICE));
+ icons.put(UPnPDeviceTreeNode.ACTION, loadIcon(UPnPDeviceTreeNode.ACTION));
+ icons.put(UPnPDeviceTreeNode.STATE, loadIcon(UPnPDeviceTreeNode.STATE));
+ } catch (Exception ex) {
+ System.out.println(ex);
+ }
+
+ }
+
+ public JToolTip createToolTip() {
+ JToolTip tip = super.createToolTip();
+ tip.setBackground(Color.yellow);
+ return tip;
+ }
+
+ //test to display animated gif
+ /*
+ public boolean imageUpdate(Image img, int infoflags,
+ int x, int y, int width, int height){
+ //System.out.println("image update");
+ Mediator.getUPnPDeviceTree().validate();
+ Mediator.getUPnPDeviceTree().repaint();
+ return true;
+ }
+ */
+
+ public Component getTreeCellRendererComponent(JTree tree, Object value,
+ boolean sel, boolean expanded, boolean leaf, int row,
+ boolean hasFocus) {
+ Icon icon = selectIcon((UPnPDeviceTreeNode) value);
+ setToolTip((UPnPDeviceTreeNode) value);
+ if (icon != null) {
+ setOpenIcon(icon);
+ setClosedIcon(icon);
+ setLeafIcon(icon);
+ } else {
+ setOpenIcon(getDefaultOpenIcon());
+ setClosedIcon(getDefaultClosedIcon());
+ setLeafIcon(getDefaultLeafIcon());
+ }
+ return super.getTreeCellRendererComponent(tree, value, sel, expanded,
+ leaf, row, hasFocus);
+ }
+
+ public Icon selectIcon(UPnPDeviceTreeNode node) {
+ Icon icon = null;
+ try {
+ String tag = node.category;
+ icon = (Icon) icons.get(tag);
+ } catch (Exception ex) {
+ System.out.println("getTreeCellRendererComponent Exception:" + ex);
+ }
+ return icon;
+ }
+
+ public void setToolTip(UPnPDeviceTreeNode node) {
+ String tag = node.category;
+ if (tag.equals(UPnPDeviceTreeNode.ROOT_DEVICE)
+ ||tag.equals(UPnPDeviceTreeNode.DEVICE))
+ {
+ DeviceNode device = (DeviceNode) node.getUserObject();
+ setToolTipText("<html><TABLE BORDER='0' CELLPADDING='0' CELLSPACING='0' ><TR BGCOLOR='#F9FF79' ><TD>"
+ + device.getReference().getProperty(UPnPDevice.FRIENDLY_NAME).toString()
+ +"</TD></TR></TABLE ></html>");
+ }
+ else
+ setToolTipText(null);
+ }
+
+ public static ImageIcon loadIcon(String name)
+ {
+ try {
+ /*
+ System.out.println("loading image ..."+name);
+ System.out.println("from "+"IMAGES/" + name + ".gif");
+ */
+ URL eventIconUrl = UPnPDeviceTreeNode.class.getResource("IMAGES/" + name + ".gif");
+ return new ImageIcon(eventIconUrl,name);
+ }
+ catch (Exception ex){
+ System.out.println("Resource:" + name + " not found : " + ex.toString());
+ return null;
+ }
+ }
+
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/Util.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/Util.java
new file mode 100644
index 0000000..75338ac
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/gui/Util.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester.gui;
+
+import java.awt.GridBagConstraints;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+
+public class Util {
+ final static GridBagConstraints constrains = new GridBagConstraints();
+
+ public static GridBagConstraints setConstrains(int x,int y,int w,int h,int wx, int wy)
+ {
+ constrains.insets.left=5;
+ constrains.insets.right=5;
+ constrains.insets.bottom=3;
+ constrains.fill=GridBagConstraints.BOTH;
+ constrains.anchor=GridBagConstraints.WEST;
+ constrains.gridx=x;
+ constrains.gridy=y;
+ constrains.gridwidth=w;
+ constrains.gridheight=h;
+ constrains.weightx=wx;
+ constrains.weighty=wy;
+ return constrains;
+ }
+
+ public static String justString(Object obj){
+ if (obj == null) return "";
+ else if (obj instanceof String[]){
+ String[] items = (String[])obj;
+ String tmp = "";
+ for (int i = 0; i < items.length; i++) {
+ tmp+=items[i]+"; ";
+ }
+ return tmp;
+ }
+ return obj.toString();
+ }
+
+ public static void openUrl(String url) {
+ try {
+ if (url == null) return;
+ String os=System.getProperty("os.name","").toLowerCase();
+ Process p = null;
+ if(os.indexOf("windows")!=-1){
+ String cmd = null;
+ cmd = "cmd.exe /C start "+url;
+ LogPanel.log("[Executing cmd] " +cmd);
+ p = Runtime.getRuntime().exec(cmd);
+
+ }else if(os.indexOf("linux")!=-1){
+ String[] cmd = new String[]{
+ "/bin/sh",
+ "-c",
+ "( $BROWSER " + url + " || mozilla-firefox '" + url + "' || firefox '" + url
+ + "' || mozilla '" + url + "' || konqueror '" + url + "' || opera '" + url + "' )"
+ };
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < cmd.length; i++) {
+ sb.append(" ").append(cmd[i]);
+
+ }
+ LogPanel.log("[Executing cmd] " +sb.toString());
+ p = Runtime.getRuntime().exec(cmd);
+ }
+ BufferedReader err = new BufferedReader(new InputStreamReader(p.getErrorStream()));
+ BufferedReader out = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ while (true) {
+ while(err.ready()) System.err.println(err.readLine());
+ while(out.ready()) System.out.println(out.readLine());
+ try{
+ p.exitValue();
+ break;
+ }catch (IllegalThreadStateException e) {
+ }
+ }
+ } catch (Exception ex){
+ System.out.println(ex);
+ }
+ }
+
+}
diff --git a/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/test.java b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/test.java
new file mode 100644
index 0000000..4ab9df3
--- /dev/null
+++ b/org.apache.felix.upnp.tester/src/main/java/org/apache/felix/upnp/tester/test.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2006 The Apache Software Foundation
+ *
+ * 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.apache.felix.upnp.tester;
+
+import java.awt.Image;
+import java.net.URL;
+
+import javax.swing.ImageIcon;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+public class test extends JFrame {
+
+ Image image;
+
+ public test(String filename) {
+ super(filename);
+ setDefaultCloseOperation(EXIT_ON_CLOSE);
+ //image = getToolkit().getImage(filename);
+ ImageIcon image =loadIcon("EventedStateVariable");
+ //image.setImageObserver(this);
+ JPanel panel = new JPanel();
+
+ panel.add(new JLabel(image));
+ JLabel lab = new JLabel();
+ lab.setIcon(image);
+ panel.add(lab);
+ this.getContentPane().add(panel);
+ }
+
+ /*public void paint(Graphics g) {
+ super.paint(g);
+ g.drawImage(image, 25, 25, this);
+ }*/
+
+ public static void main(String args[]) {
+ if (args.length > 0) {
+ JFrame f = new test(args[0]);
+ f.setSize(300, 300);
+ f.show();
+ } else {
+ System.err.println(
+ "You must specify an image filename to display");
+ }
+ }
+
+
+ public static ImageIcon loadIcon(String name)
+ {
+ try {
+ //System.out.println("loading image ..."+path);
+ URL eventIconUrl = test.class.getResource("images/" + name + ".gif");
+ return new ImageIcon(eventIconUrl,name);
+ }
+ catch (Exception ex){
+ System.out.println("Resource:" + name + " not found : " + ex.toString());
+ return null;
+ }
+ }
+
+}
\ No newline at end of file