Committed the initial version (R3) of the UPnP Base Driver bundle (FELIX-52).
It requires org.osgi.core, org.osgi.compendium, org.apache.felix.upnp.extra and cyberlink-patched-release.
I've installed the cyberlink-1.7-patched-release.jar on my local repository.
In order to install the library you can use the command :
mvn install:install-file -DgroupId=org.cybergarage -DartifactId=cyberlink-patched-release /
-Dversion=1.7 -Dpackaging=jar -Dfile=<basedir>\trunk\org.apache.felix.upnp.basedriver\src\main\resources\lib\cyberlink-1.7-patched-release.jar
I've added the source code in the resources dir (cyberlink-1.7-patched-debug.jar)
The basedriver doesn't compile without it, so I've commented the module related to it in the trunk/pom.xml
I need help to understand how to use an external repository.
git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@391447 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.upnp.basedriver/pom.xml b/org.apache.felix.upnp.basedriver/pom.xml
new file mode 100644
index 0000000..9fcad51
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/pom.xml
@@ -0,0 +1,73 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>felix</artifactId>
+ <version>0.8.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>osgi-bundle</packaging>
+ <groupId>org.apache.felix</groupId>
+ <name>Apache Felix UPnP Base Driver</name>
+ <artifactId>org.apache.felix.upnp.basedriver</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ <!-- <url>http://maven.apache.org</url> -->
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <version>4.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <version>4.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.upnp.extra</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.cybergarage</groupId>
+ <artifactId>cyberlink-patched-release</artifactId>
+ <version>1.7</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix.plugins</groupId>
+ <artifactId>maven-osgi-plugin</artifactId>
+ <!-- <version>${pom.version}</version> -->
+ <extensions>true</extensions>
+ <configuration>
+ <osgiManifest>
+ <bundleName>UPnPBaseDriver</bundleName>
+ <bundleVendor>Apache Software Foundation</bundleVendor>
+ <bundleVersion>1.0.0</bundleVersion>
+ <bundleDescription>
+ A Bundle implementation of the UPnP Service Specification R4 (not yet)
+ </bundleDescription>
+ <bundleSymbolicName>org.apache.felix.upnp.basedriver</bundleSymbolicName>
+ <!-- <bundleClassPath>.,lib/cyberlink-1.7-patched-release.jar</bundleClassPath> -->
+ <bundleActivator>org.apache.felix.upnp.basedriver.Activator</bundleActivator>
+ <importPackage>
+ org.osgi.framework;specification-version=1.3,org.osgi.service.device;specification-version=1.1,org.osgi.service.upnp;specification-version=1.1,org.osgi.service.log;specification-version=1.3,org.apache.felix.upnp.extra.util;specification-version=1.0,org.apache.felix.upnp.extra.controller;specification-version=1.0
+ </importPackage>
+ </osgiManifest>
+ <manifestFile>src/main/resources/META-INF/Manifest.mf</manifestFile>
+ </configuration>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ </resource>
+ </resources>
+ </build>
+</project>
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/Activator.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/Activator.java
new file mode 100644
index 0000000..3129b97
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/Activator.java
@@ -0,0 +1,136 @@
+/*
+ * 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.basedriver;
+
+import org.apache.felix.upnp.extra.controller.DevicesInfo;
+import org.apache.felix.upnp.extra.controller.DriverController;
+
+import org.cybergarage.upnp.UPnP;
+import org.cybergarage.xml.parser.JaxpParser;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+import org.apache.felix.upnp.basedriver.controller.impl.DriverControllerImpl;
+import org.apache.felix.upnp.basedriver.export.RootDeviceExportingQueue;
+import org.apache.felix.upnp.basedriver.export.RootDeviceListener;
+import org.apache.felix.upnp.basedriver.export.ThreadExporter;
+import org.apache.felix.upnp.basedriver.importer.core.MyCtrlPoint;
+import org.apache.felix.upnp.basedriver.importer.core.event.structs.Monitor;
+import org.apache.felix.upnp.basedriver.importer.core.event.structs.NotifierQueue;
+import org.apache.felix.upnp.basedriver.importer.core.event.structs.SubscriptionQueue;
+import org.apache.felix.upnp.basedriver.importer.core.event.thread.Notifier;
+import org.apache.felix.upnp.basedriver.importer.core.event.thread.SubScriber;
+import org.apache.felix.upnp.basedriver.tool.Logger;
+import org.apache.felix.upnp.basedriver.tool.Util;
+
+/**
+ * @author Stefano "Kismet" Lenzi,
+ * @author Francesco Furfari
+ *
+ */
+public class Activator implements BundleActivator {
+
+ public static BundleContext bc;
+ public static Logger logger;
+ private RootDeviceExportingQueue queue;
+ private RootDeviceListener producerDeviceToExport;
+ private ThreadExporter consumerDeviceToExport;
+
+ private MyCtrlPoint ctrl;
+ private SubScriber subScriber;
+ private Notifier notifier;
+ private NotifierQueue notifierQueue;
+ private SubscriptionQueue subQueue;
+ private Monitor monitor;
+ private DriverControllerImpl drvController;
+ private ServiceRegistration drvControllerRegistrar;
+
+ /**
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception {
+ //Setting basic variabile used by everyone
+
+ Activator.bc = context;
+
+ String levelStr = (String) Util.getPropertyDefault(context,"domoware.upnpbase.log","2");
+ Activator.logger = new Logger(levelStr);
+ String cyberLog = (String) Util.getPropertyDefault(context,"domoware.upnpbase.cyberlink.log","false");
+ Activator.logger.setCyberDebug(cyberLog);
+
+ UPnP.setXMLParser(new JaxpParser());
+
+ //Setting up Base Driver Exporter
+ this.queue = new RootDeviceExportingQueue();
+ this.producerDeviceToExport = new RootDeviceListener(queue);
+ producerDeviceToExport.activate();
+ consumerDeviceToExport = new ThreadExporter(queue);
+ new Thread(consumerDeviceToExport, "Exporter").start();
+
+ //Setting up Base Driver Importer
+ this.notifierQueue = new NotifierQueue();
+ this.subQueue = new SubscriptionQueue();
+ ctrl = new MyCtrlPoint(context, subQueue, notifierQueue);
+
+ //Enable CyberLink re-new for Event
+ ctrl.setNMPRMode(true);
+
+ this.monitor=new Monitor();
+ this.notifier = new Notifier(notifierQueue,monitor);
+ this.subScriber = new SubScriber(ctrl, subQueue,monitor);
+
+ ctrl.start();
+ subScriber.start();
+ notifier.start();
+
+ doControllerRegistration();
+
+ }
+
+ private void doControllerRegistration() {
+ drvController = new DriverControllerImpl(ctrl);
+ drvControllerRegistrar = bc.registerService(
+ new String[]{
+ DriverController.class.getName(),
+ DevicesInfo.class.getName()},
+ drvController,
+ null
+ );
+ }
+
+ /**
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception {
+
+ drvControllerRegistrar.unregister();
+
+ //Setting up Base Driver Exporter
+ consumerDeviceToExport.end();
+ consumerDeviceToExport.cleanUp();
+ producerDeviceToExport.deactive();
+
+ //Setting up Base Driver Importer
+ ctrl.stop();
+ Activator.logger.close();
+ Activator.logger=null;
+ Activator.bc = null;
+ }
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/controller/impl/DriverControllerImpl.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/controller/impl/DriverControllerImpl.java
new file mode 100644
index 0000000..49719c6
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/controller/impl/DriverControllerImpl.java
@@ -0,0 +1,126 @@
+/*
+ * 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.basedriver.controller.impl;
+
+import org.apache.felix.upnp.extra.controller.DevicesInfo;
+import org.apache.felix.upnp.extra.controller.DriverController;
+
+import org.cybergarage.upnp.Device;
+import org.cybergarage.upnp.Service;
+
+import org.apache.felix.upnp.basedriver.Activator;
+import org.apache.felix.upnp.basedriver.importer.core.MyCtrlPoint;
+import org.apache.felix.upnp.basedriver.tool.Logger;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class DriverControllerImpl implements DriverController, DevicesInfo{
+ private MyCtrlPoint myCtrl;
+ private Logger logger = Activator.logger;
+
+ public DriverControllerImpl(MyCtrlPoint myCtrl){
+ this.myCtrl = myCtrl;
+
+ }
+
+ public void setLogLevel(int n) {
+ logger.setLogLevel(n);
+ }
+
+ public int getLogLevel() {
+ return logger.getLogLevel();
+ }
+
+ public void setCyberDebug(boolean b) {
+ logger.setCyberDebug(b);
+ }
+
+ public boolean getCyberDebug() {
+ return logger.getCyberDebug();
+ }
+
+ public String getLocationURL(String udn) {
+ if (udn == null || udn.equals("")) throw new IllegalArgumentException("Invalid udn paramenter");
+ Device device = myCtrl.getDevice(udn);
+ if (device == null) logger.WARNING("getLocationURL():: No device data available for UDN:"+udn);
+ return myCtrl.getDevice(udn).getLocation();
+ }
+
+ public String getSCPDURL(String udn, String serviceId) {
+ if (udn == null || udn.equals("") ) throw new IllegalArgumentException("Invalid udn paramenter");
+ if (serviceId == null || serviceId.equals("") ) throw new IllegalArgumentException("Invalid serviceId paramenter");
+ Device device= myCtrl.getDevice(udn);
+ if (device == null) {
+ logger.WARNING("getSCPDURL():: No device data available for UDN: "+udn);
+ return null;
+ }
+ Service service = device.getService(serviceId);
+ if (service == null) {
+ logger.WARNING("getSCPDURL():: No service data available for serviceId:"+serviceId + " of UDN " + udn);
+ return null;
+ }
+ String scpd = service.getSCPDURL().trim();
+ return resolveRelativeLink(device,scpd);
+ }
+
+ public String resolveRelativeUrl(String udn, String link) {
+ if (udn == null || udn.equals("")) throw new IllegalArgumentException("Invalid udn paramenter");
+ Device device = myCtrl.getDevice(udn);
+ return resolveRelativeLink(device,link);
+ }
+
+ private String resolveRelativeLink(Device device, String link) {
+ if ( device == null || link == null) return null;
+ if (link.startsWith("http:"))
+ return link;
+ else {
+ String hostname = "";
+ String location = "";
+ String urlBase = device.getURLBase().trim();
+ //TODO Check if is more important URLBase or location
+ if (urlBase.equals("")){
+ location = device.getLocation().trim();
+ int endHostnameIdx = location.indexOf("/",7);
+ if (endHostnameIdx!=-1)
+ hostname=location.substring(0,endHostnameIdx);
+ else
+ hostname = location;
+ if (link.startsWith("/")){
+ return hostname+link;
+ }else{
+ //TODO Check for link start with .. or /
+ return location +link;
+ }
+ }
+ else {
+ return urlBase+link;
+ }
+ }
+ }
+
+ public void search(String target) {
+ myCtrl.search(target);
+ }
+
+
+
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ActionDispatcher.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ActionDispatcher.java
new file mode 100644
index 0000000..0417997
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ActionDispatcher.java
@@ -0,0 +1,46 @@
+/*
+ * 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.basedriver.export;
+
+import org.cybergarage.upnp.Action;
+import org.cybergarage.upnp.control.ActionListener;
+
+import org.osgi.framework.ServiceReference;
+
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ *
+ */
+public class ActionDispatcher implements ActionListener{
+ /**
+ *
+ */
+ public ActionDispatcher(ServiceReference sr) {
+ super();
+ }
+
+ /**
+ * @see org.cybergarage.upnp.control.ActionListener#actionControlReceived(org.cybergarage.upnp.Action)
+ */
+ public boolean actionControlReceived(Action action) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/BuildDevice.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/BuildDevice.java
new file mode 100644
index 0000000..64864eb
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/BuildDevice.java
@@ -0,0 +1,267 @@
+/*
+ * 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.basedriver.export;
+
+
+import org.cybergarage.upnp.Action;
+import org.cybergarage.upnp.AllowedValueList;
+import org.cybergarage.upnp.AllowedValueRange;
+import org.cybergarage.upnp.Argument;
+import org.cybergarage.upnp.ArgumentList;
+import org.cybergarage.upnp.Device;
+import org.cybergarage.upnp.Service;
+import org.cybergarage.upnp.StateVariable;
+import org.cybergarage.upnp.xml.DeviceData;
+import org.cybergarage.xml.Node;
+
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPService;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+import org.ungoverned.device.RootDescription;
+
+import org.apache.felix.upnp.basedriver.Activator;
+import org.apache.felix.upnp.extra.util.Converter;
+/**
+ *
+ * @author Stefano "Kismet" Lenzi
+ *
+ */
+public class BuildDevice {
+
+ private static Node buildRootNode(){
+ Node root = new Node(RootDescription.ROOT_ELEMENT);
+ root.setAttribute("xmlns",RootDescription.ROOT_ELEMENT_NAMESPACE);
+ Node spec = new Node(RootDescription.SPECVERSION_ELEMENT);
+ Node maj =new Node(RootDescription.MAJOR_ELEMENT);
+ maj.setValue("1");
+ Node min =new Node(RootDescription.MINOR_ELEMENT);
+ min.setValue("0");
+ spec.addNode(maj);
+ spec.addNode(min);
+ root.addNode(spec);
+ return root;
+ }
+
+ private static Device buildRootDeviceNode(Node root,ServiceReference sr){
+ Node dev = new Node(Device.ELEM_NAME);
+ root.addNode(dev);
+ DeviceData dd = new DeviceData();
+ dd.setDescriptionURI("/gen-desc.xml");
+ dev.setUserData(dd);
+ Device devUPnP = new Device(root,dev);
+
+
+ Object aux = sr.getProperty(UPnPDevice.TYPE);
+ if(aux==null){
+ devUPnP.setDeviceType(null);
+ }else if(aux instanceof String){
+ devUPnP.setDeviceType((String) aux);
+ }else if(aux instanceof String[]){
+ //The property key UPnP.device.type should be a String
+ String[] v = (String[]) aux;
+ int maxindex=0;
+ int max=Integer.parseInt(v[0].substring(v[0].lastIndexOf(":")+1));
+ int tmp;
+ for (int i = 1; i < v.length; i++) {
+ tmp=Integer.parseInt(v[i].substring(v[i].lastIndexOf(":")+1));
+ if(max<tmp){
+ max=tmp;
+ maxindex=i;
+ }
+ }
+ devUPnP.setDeviceType(v[maxindex]);
+ }
+
+ devUPnP.setFriendlyName((String) sr.getProperty(UPnPDevice.FRIENDLY_NAME));
+ devUPnP.setManufacture((String) sr.getProperty(UPnPDevice.MANUFACTURER));
+ devUPnP.setManufactureURL((String) sr.getProperty(UPnPDevice.MANUFACTURER_URL));
+ devUPnP.setModelDescription((String) sr.getProperty(UPnPDevice.MODEL_DESCRIPTION));
+ devUPnP.setModelName((String) sr.getProperty(UPnPDevice.MODEL_NAME));
+ devUPnP.setUDN((String) sr.getProperty(UPnPDevice.UDN));
+ devUPnP.setPresentationURL((String) sr.getProperty(UPnPDevice.PRESENTATION_URL));
+ devUPnP.setUPC((String) sr.getProperty(UPnPDevice.UPC));
+ devUPnP.setModelNumber((String) sr.getProperty(UPnPDevice.MODEL_NUMBER));
+ devUPnP.setModelURL((String) sr.getProperty(UPnPDevice.MODEL_URL));
+ devUPnP.setSerialNumber((String) sr.getProperty(UPnPDevice.SERIAL_NUMBER));
+ devUPnP.setLocation("/gen-desc.xml");
+
+ addServices("",devUPnP,sr);
+ addDevices("",devUPnP,sr);
+
+ return devUPnP;
+ }
+
+ private static void addDevices(String id,Device devUPnP, ServiceReference sr) {
+
+ String[] udns=(String[]) sr.getProperty(UPnPDevice.CHILDREN_UDN);
+ if(udns==null) {
+ return;
+ }
+ for (int i = 0; i < udns.length; i++) {
+ try {
+ ServiceReference[] aux = Activator.bc.getServiceReferences(
+ UPnPDevice.class.getName(),"("+UPnPDevice.UDN+"="+udns[i]+")"
+ );
+ if(aux==null || aux.length == 0)
+ continue;
+ //id=+"/device/"+i; // twa: wrong in recursion
+ //buildDevice(id,devUPnP,aux[0]); // twa: wrong in recursion
+ String localId = new StringBuffer(id).append("/device/").append(i).toString();
+ buildDevice(localId,devUPnP,aux[0]); // twa: better
+ } catch (InvalidSyntaxException ignored) {}
+ }
+ }
+
+ private static void buildDevice(String id,Device parent, ServiceReference sr) {
+ Node dev = new Node(Device.ELEM_NAME);
+ DeviceData dd = new DeviceData();
+ dd.setDescriptionURI(id+"/gen-desc.xml");
+ dev.setUserData(dd);
+
+ Device devUPnP = new Device(dev);
+
+ devUPnP.setFriendlyName((String) sr.getProperty(UPnPDevice.FRIENDLY_NAME));
+ devUPnP.setManufacture((String) sr.getProperty(UPnPDevice.MANUFACTURER));
+ devUPnP.setManufactureURL((String) sr.getProperty(UPnPDevice.MANUFACTURER_URL));
+ devUPnP.setModelDescription((String) sr.getProperty(UPnPDevice.MODEL_DESCRIPTION));
+ devUPnP.setModelName((String) sr.getProperty(UPnPDevice.MODEL_NAME));
+ devUPnP.setUDN((String) sr.getProperty(UPnPDevice.UDN));
+ devUPnP.setPresentationURL((String) sr.getProperty(UPnPDevice.PRESENTATION_URL));
+ devUPnP.setUPC((String) sr.getProperty(UPnPDevice.UPC));
+ devUPnP.setModelNumber((String) sr.getProperty(UPnPDevice.MODEL_NUMBER));
+ devUPnP.setModelURL((String) sr.getProperty(UPnPDevice.MODEL_URL));
+ devUPnP.setSerialNumber((String) sr.getProperty(UPnPDevice.SERIAL_NUMBER));
+ devUPnP.setLocation(id+"/gen-desc.xml");
+
+ addServices(id,devUPnP,sr);
+ addDevices(id,devUPnP,sr);
+
+ parent.addDevice(devUPnP); // twa: essential!!!!!!!
+ }
+
+ /**
+ * Method used to create a new Service in CyberLink world without creating the XML
+ *
+ * @param id ServiceId
+ * @param devUPnP the CyberLink device that where the new Service will be created
+ * @param sr ServiceReference to OSGi Device that used as source of the information
+ * for the creation of the device
+ */
+ private static void addServices(String id,Device devUPnP, ServiceReference sr) {
+ UPnPDevice devOSGi = (UPnPDevice) Activator.bc.getService(sr);
+
+ if( devOSGi == null) { //added by twa to prevent a null pointer exception
+ Activator.logger.WARNING("UPnP Device taht cotains serviceId="
+ +id+" is deregistered from the framework while is exported");
+ return;
+ }
+
+ UPnPService[] services = devOSGi.getServices();
+ if(services==null || services.length==0)
+ return;
+
+
+
+ for (int i = 0; i < services.length; i++) {
+ Service ser = new Service();
+ devUPnP.addService(ser);
+ ser.setServiceType(services[i].getType() );
+ ser.setServiceID(services[i].getId());
+ ser.setSCPDURL(id+"/service/"+i+"/gen-desc.xml");
+ ser.setDescriptionURL(id+"/service/"+i+"/gen-desc.xml");
+ ser.setControlURL(id+"/service/"+i+"/ctrl");
+ ser.setEventSubURL(id+"/service/"+i+"/event");
+
+ UPnPStateVariable[] vars = services[i].getStateVariables();
+ for (int j = 0; j < vars.length; j++) {
+ StateVariable var = new StateVariable();
+ var.setDataType(vars[j].getUPnPDataType());
+ var.setName(vars[j].getName());
+ var.setSendEvents(vars[j].sendsEvents());
+ String[] values = vars[j].getAllowedValues();
+ if(values!=null){
+ AllowedValueList avl = new AllowedValueList(values);
+ var.setAllowedValueList(avl);
+ }else if(vars[j].getMaximum()!= null){
+ AllowedValueRange avr = new AllowedValueRange(
+ vars[j].getMaximum(),
+ vars[j].getMinimum(),
+ vars[j].getStep()
+ );
+ var.setAllowedValueRange(avr);
+ }
+ if(vars[j].getDefaultValue()!=null)
+ try {
+ var.setDefaultValue(Converter.toString(
+ vars[j].getDefaultValue(),vars[j].getUPnPDataType()
+ ));
+ } catch (Exception ignored) {
+ }
+ ser.addStateVariable(var);
+ }
+
+ UPnPAction[] actions = services[i].getActions();
+ for (int j = 0; j < actions.length; j++) {
+ Action act = new Action(ser.getServiceNode());
+ act.setName(actions[j].getName());
+ ArgumentList al = new ArgumentList();
+
+ String[] names=actions[j].getInputArgumentNames();
+ if(names!=null){
+ for (int k = 0; k < names.length; k++) {
+ Argument a = new Argument();
+ a.setDirection(Argument.IN);
+ a.setName(names[k]);
+ a.setRelatedStateVariableName(
+ actions[j].getStateVariable(names[k]).getName()
+ );
+ al.add(a);
+ }
+ }
+ names=actions[j].getOutputArgumentNames();
+ if(names!=null){
+ for (int k = 0; k < names.length; k++) {
+ Argument a = new Argument();
+ a.setDirection(Argument.OUT);
+ a.setName(names[k]);
+ a.setRelatedStateVariableName(
+ actions[j].getStateVariable(names[k]).getName()
+ );
+ al.add(a);
+ }
+ }
+ act.setArgumentList(al);
+ ser.addAction(act);
+ }
+
+ Activator.bc.ungetService(sr);
+ }
+
+
+ }
+
+ public static Device createCyberLinkDevice(ServiceReference sr){
+ Node root = buildRootNode();
+ Device devUPnP = buildRootDeviceNode(root,sr);
+ return devUPnP;
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/DeviceNode.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/DeviceNode.java
new file mode 100644
index 0000000..a2c1d0c
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/DeviceNode.java
@@ -0,0 +1,183 @@
+/*
+ * 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.basedriver.export;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.upnp.UPnPDevice;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco "Sygent" 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;
+ }
+ }
+
+ 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;
+ 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();
+ break;
+ }
+ }
+ }
+ dn.parent=null;
+ return dn;
+ }
+
+ public Collection getAllChildren(){
+ if((this.children==null)||(this.children.size()==0))
+ return null;
+
+ 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 null;
+ 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(){
+ 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;
+ }
+
+ /**
+ * @return true if and only
+ * if the Device doesn't have embedded Device
+ */
+ public boolean isLeaf() {
+ return !hasChild;
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ExporterUPnPEventListener.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ExporterUPnPEventListener.java
new file mode 100644
index 0000000..b99cb17
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ExporterUPnPEventListener.java
@@ -0,0 +1,69 @@
+/*
+ * 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.basedriver.export;
+
+
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+import org.cybergarage.upnp.Device;
+import org.cybergarage.upnp.Service;
+import org.cybergarage.upnp.StateVariable;
+
+import org.osgi.service.upnp.UPnPEventListener;
+
+import org.apache.felix.upnp.extra.util.Converter;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ *
+ */
+public class ExporterUPnPEventListener implements UPnPEventListener {
+
+ private Device d;
+
+ public ExporterUPnPEventListener(Device d){
+ this.d=d;
+ }
+
+ /**
+ * @see org.osgi.service.upnp.UPnPEventListener#notifyUPnPEvent(java.lang.String, java.lang.String, java.util.Dictionary)
+ */
+ public void notifyUPnPEvent(String deviceId, String serviceId,Dictionary events) {
+ Device dAux = null;
+ if(d.getUDN().equals(deviceId)){
+ dAux=d;
+ }else{
+ dAux= d.getDevice(deviceId);
+ }
+ Service s = dAux.getService(serviceId);
+ // fix 2/9/2004 francesco
+ Enumeration e = events.keys();
+ StateVariable sv;
+ while (e.hasMoreElements()) {
+ String name = (String) e.nextElement();
+ sv=s.getStateVariable(name);
+ //sv.setValue((String) events.get(name));
+ try {
+ sv.setValue(Converter.toString(events.get(name),sv.getDataType()));
+ } catch (Exception ignored) {
+ }
+ }
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/GeneralActionListener.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/GeneralActionListener.java
new file mode 100644
index 0000000..2c90817
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/GeneralActionListener.java
@@ -0,0 +1,158 @@
+/*
+ * 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.basedriver.export;
+
+
+import java.util.Dictionary;
+import java.util.Properties;
+
+import org.cybergarage.upnp.Action;
+import org.cybergarage.upnp.Argument;
+import org.cybergarage.upnp.ArgumentList;
+import org.cybergarage.upnp.UPnPStatus;
+import org.cybergarage.upnp.control.ActionListener;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPService;
+
+import org.apache.felix.upnp.basedriver.Activator;
+import org.apache.felix.upnp.extra.util.Converter;
+import org.apache.felix.upnp.extra.util.UPnPException;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ *
+ *
+ */
+public class GeneralActionListener implements ServiceListener,ActionListener {
+
+ private ServiceReference dev;
+ private String id;
+ private boolean open;
+
+ /**
+ * @param osgiServ
+ */
+ public GeneralActionListener(ServiceReference sr, String serviceId) {
+ try {
+ Activator.bc.addServiceListener(this,
+ "("+Constants.SERVICE_ID+"="+sr.getProperty(Constants.SERVICE_ID)+")");
+ } catch (InvalidSyntaxException ingnored) {}
+ this.dev=sr;
+ this.id=serviceId;
+ this.open=true;
+ }
+
+ /**
+ * @see org.cybergarage.upnp.control.ActionListener#actionControlReceived(org.cybergarage.upnp.Action)
+ */
+ public synchronized boolean actionControlReceived(Action upnpAct) {
+ if(!open) return false;
+ UPnPService osgiServ=null;
+ try{
+ osgiServ=((UPnPDevice) Activator.bc.getService(dev)).getService(id);
+ }catch(Exception ignored){}
+
+ if(osgiServ==null)
+ return exiting(false);
+
+ UPnPAction osgiAct = osgiServ.getAction(upnpAct.getName());
+ Properties inArgs = null;
+ ArgumentList al = upnpAct.getArgumentList();
+ String[] inArg = osgiAct.getInputArgumentNames();
+ boolean invalidAction=false;
+ if(inArg!=null){
+ inArgs = new Properties();
+ Argument arg;
+ for (int j = 0; j < inArg.length; j++) {
+ arg=al.getArgument(inArg[j]);
+ try {
+ inArgs.put(
+ inArg[j],
+ Converter.parseString(
+ arg.getValue(),
+ arg.getRelatedStateVariable().getDataType()
+ /*osgiServ.getStateVariable(arg.getRelatedStateVariableName()).getUPnPDataType()*/
+ )
+ );
+ } catch (Exception e) {
+ invalidAction=true;
+ break;
+ }
+ }
+ }
+ Dictionary outArgs=null;
+ try {
+ outArgs=osgiAct.invoke(inArgs);
+ } catch (UPnPException e) {
+ //TODO Activator.logger.log()
+ upnpAct.setStatus(e.getErrorCode(),e.getErrorDescription());
+ invalidAction=true;
+ } catch (Exception e){
+ //TODO Activator.logger.log()
+ upnpAct.setStatus(UPnPStatus.ACTION_FAILED);
+ invalidAction=true;
+ }
+ if(invalidAction)
+ return exiting(false);
+ String[] outArg = osgiAct.getOutputArgumentNames();
+ if(outArg!=null){
+ Argument arg;
+ for (int j = 0; j < outArg.length; j++) {
+ arg = al.getArgument(outArg[j]);
+ try {
+ arg.setValue(
+ Converter.toString(
+ outArgs.get(outArg[j]),
+ arg.getRelatedStateVariable().getDataType()
+ /*osgiServ.getStateVariable(arg.getRelatedStateVariableName()).getUPnPDataType()*/
+ )
+ );
+ } catch (Exception e) {
+ e.printStackTrace();
+ return exiting(false);
+ }
+ }
+ }
+ return exiting(true);
+ }
+
+ /**
+ * @param b
+ * @return
+ */
+ private boolean exiting(boolean b) {
+ Activator.bc.ungetService(dev);
+ return b;
+ }
+
+ /**
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent e) {
+ if(e.getType()==ServiceEvent.UNREGISTERING){
+ Activator.bc.removeServiceListener(this);
+ }
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/RootDeviceExportingQueue.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/RootDeviceExportingQueue.java
new file mode 100644
index 0000000..5ddaf99
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/RootDeviceExportingQueue.java
@@ -0,0 +1,69 @@
+/*
+ * 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.basedriver.export;
+
+import java.util.Vector;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ *
+ */
+public class RootDeviceExportingQueue {
+
+ private Vector v;
+ private boolean waiting;
+
+ public RootDeviceExportingQueue(){
+ v = new Vector();
+ waiting=false;
+ }
+
+ public synchronized void addRootDevice(DeviceNode dev){
+ v.addElement(dev);
+ if(waiting) notify();
+ }
+
+ public synchronized DeviceNode getRootDevice(){
+ while(v.isEmpty()){
+ waiting=true;
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ DeviceNode dev = (DeviceNode) v.firstElement();
+ v.remove(0);
+ return dev;
+ }
+ /**
+ *
+ * @param udn <code>String</code> rappresentaing the UDN of the device to remove
+ * @return a root <code>DeviceNode</code> that have UDN equals to the passed
+ * udn <code>String</code> or contain a device with the spcified UDN
+ */
+ public synchronized DeviceNode removeRootDevice(String udn){
+ for (int i = 0; i < v.size(); i++) {
+ DeviceNode aux=(DeviceNode) v.elementAt(i);
+ if(aux.contains(udn)){
+ v.remove(i);
+ return aux;
+ }
+ }
+ return null;
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/RootDeviceListener.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/RootDeviceListener.java
new file mode 100644
index 0000000..4e4f73f
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/RootDeviceListener.java
@@ -0,0 +1,209 @@
+/*
+ * 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.basedriver.export;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.upnp.UPnPDevice;
+
+import org.apache.felix.upnp.basedriver.Activator;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco "Sygent" Furfari
+ */
+public class RootDeviceListener implements ServiceListener {
+
+ private RootDeviceExportingQueue queue;
+
+ private ArrayList devices;
+
+ public RootDeviceListener(RootDeviceExportingQueue queue) {
+ this.queue = queue;
+ devices = new ArrayList();
+ }
+
+ public synchronized void addDevice(ServiceReference sr) {
+ DeviceNode node = new DeviceNode(sr);
+
+ if(node.isRoot() && node.isLeaf()){
+ //Obiovsly
+ queue.addRootDevice(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();
+ if(node.isRoot() && node.isComplete()){
+ queue.addRootDevice(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();
+ queue.addRootDevice(tree);
+ }
+ return;
+ }
+ }
+ }
+
+ devices.add(node);
+
+ }
+
+ /**
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent e) {
+ switch (e.getType()) {
+ case ServiceEvent.REGISTERED: {
+ addDevice(e.getServiceReference());
+ }break;
+
+ case ServiceEvent.MODIFIED:
+ break;
+
+ case ServiceEvent.UNREGISTERING: {
+ removeDevice(e.getServiceReference());
+ }break;
+ }
+ }
+
+ /**
+ * @param serviceReference
+ */
+ public synchronized void removeDevice(ServiceReference sr) {
+ String udn = (String) sr.getProperty(UPnPDevice.UDN);
+ DeviceNode removeNode = null;
+ /*
+ * I look in the queue of complete device that will be exported
+ */
+
+ DeviceNode root=this.queue.removeRootDevice(udn);
+ if(root!=null) removeNode=root.dethatch(udn);
+
+ /*
+ * I look in the list that conatin unqueue,so no-complete Device
+ */
+ Iterator i = this.devices.iterator();
+ while (i.hasNext()) {
+ root = (DeviceNode) i.next();
+ removeNode = root.dethatch(udn);
+ }
+
+ /*
+ * if I found the device removeNode != null
+ */
+ if(removeNode==null) return;
+ /*
+ * I get all the already attached subdevice and add to
+ * unttached device list
+ */
+ Collection c=removeNode.getChildren();
+ if(c==null) return;
+ this.devices.addAll(c);
+ }
+
+ /**
+ * 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.
+ *
+ * Please Note: The following filter disable listining for bad registerd
+ * UPnPDevice
+ */
+ try {
+ Activator.bc.addServiceListener(this,
+ "(&" +
+ "(" + Constants.OBJECTCLASS + "=" + UPnPDevice.class.getName() + ")" +
+ "(" + UPnPDevice.UPNP_EXPORT + "=*)" +
+ "(DEVICE_CATEGORY=UPnP)" +
+ "(" + UPnPDevice.UDN + "=*)" +
+ "(" + UPnPDevice.FRIENDLY_NAME + "=*)" +
+ "(" + UPnPDevice.MANUFACTURER + "=*)" +
+ "(" + UPnPDevice.MODEL_NAME + "=*)" +
+ "(" + UPnPDevice.TYPE + "=*)" +
+ ")");
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ ServiceReference[] roots = null;
+ try {
+ roots = Activator.bc.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 (roots != null) {
+ for (int i = 0; i < roots.length; i++) {
+ addDevice(roots[i]);
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ public void deactive() {
+ Activator.bc.removeServiceListener(this);
+ }
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ThreadExporter.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ThreadExporter.java
new file mode 100644
index 0000000..a0a1141
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ThreadExporter.java
@@ -0,0 +1,512 @@
+/*
+ * 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.basedriver.export;
+
+
+import java.io.File;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.cybergarage.upnp.Device;
+import org.cybergarage.upnp.DeviceList;
+import org.cybergarage.upnp.ServiceList;
+import org.cybergarage.upnp.UPnP;
+
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPEventListener;
+
+import org.apache.felix.upnp.basedriver.Activator;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ *
+ */
+public class ThreadExporter implements Runnable,ServiceListener {
+
+ private boolean end;
+
+ private RootDeviceExportingQueue queueRootDevice;
+
+// private String basePath; twa: redundant
+
+// private File baseFile; twa: redundant
+
+ private Hashtable exportedDevices;
+
+ private boolean listening;
+
+ private class ExportedDeviceInfo{
+ private Device device;
+ private ServiceRegistration serviceRegistration;
+ //private DeviceNode deviceNode;
+
+
+ /**
+ * @param device
+ * @param serviceRegistration
+ * @param deviceNode
+ */
+ private ExportedDeviceInfo(Device device,
+ ServiceRegistration serviceRegistration,
+ DeviceNode deviceNode) {
+ super();
+ this.device = device;
+ this.serviceRegistration = serviceRegistration;
+ //this.deviceNode = deviceNode;
+ }
+
+
+ private Device getDevice() {
+ return this.device;
+ }
+ private ServiceRegistration getServiceRegistration() {
+ return this.serviceRegistration;
+ }
+ /*private DeviceNode getDeviceNode(){
+ return this.deviceNode;
+ }*/
+
+
+ }
+
+ /**
+ *
+ */
+ public ThreadExporter(RootDeviceExportingQueue queue) throws InvalidSyntaxException {
+ end=false;
+ queueRootDevice=queue;
+// basePath="./tmp/device"; twa: redundant
+// baseFile = Activator.bc.getDataFile("./tmp/device"); twa: redundant
+// if(!baseFile.exists()) baseFile.mkdirs(); twa: redundant
+ this.exportedDevices=new Hashtable();
+ setListening(false);
+ UPnP.setEnable(UPnP.USE_ONLY_IPV4_ADDR);
+ }
+ public void run() {
+
+ File osgiRoot = Activator.bc.getDataFile("");
+ if (osgiRoot == null) {
+ Activator.logger.ERROR("Unable to use filesystem");
+ while (true) {
+ try {
+ Activator.bc.getBundle().stop();
+ break;
+ } catch (BundleException e) {
+ e.printStackTrace();
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ex) {
+ ex.printStackTrace();
+ }
+ }
+ }
+ return;
+ }
+
+ ServiceReference rootDevice = null;
+ while (!shouldEnd()) {
+ DeviceNode dn = queueRootDevice.getRootDevice();
+ if (dn == null)
+ continue;
+ rootDevice = dn.getReference();
+ if(!getListening())
+ setListen();
+ Activator.logger.INFO("[Exporter] Exporting device "+ rootDevice.getProperty(UPnPDevice.FRIENDLY_NAME));
+ /*
+ File xml = new File(baseFile,
+ Converter.sanitizeFilename(
+ (String) rootDevice.getProperty(UPnPDevice.UDN)
+ )
+ );
+ if (xml == null)
+ continue;
+ if (!xml.exists())
+ xml.mkdir();
+
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(xml.getAbsolutePath()
+ + File.separator + "desc.xml");
+ } catch (FileNotFoundException e) {
+ Activator.logger.log(LogService.LOG_ERROR,"Unable to write:" + xml.getAbsolutePath(), e);
+ continue;
+ }
+ if (fos == null)
+ continue;*/
+ /*
+ * I don't know if the exporting should be make default language of the framework
+ * or without any lanuguages
+ Root r = new Root(rootDevice, context, context
+ .getProperty(Constants.FRAMEWORK_LANGUAGE));
+ */
+
+ synchronized (this) {
+ //Root r = new Root(rootDevice, Activator.bc, null);
+ /*
+ * Now that I have XML I'm going to exporting device
+ * so I have to avoid rece condition with deregistration
+ * of the same device
+ */
+ /*
+ try {
+ r.writeXML(fos);
+ } catch (IOException e) {
+ e.printStackTrace();
+ continue;
+ }
+ if(writeXMLService(xml.getAbsolutePath(),r.getRootDevice())){
+ Device d = null;
+ try {
+ d = new Device(xml.getAbsolutePath()
+ + File.separator + "desc.xml");
+ } catch (InvalidDescriptionException e) {
+ e.printStackTrace();
+ }*/
+ Device d = BuildDevice.createCyberLinkDevice(dn.getReference());
+ if (d != null) {
+ if(!bindInvokes(d,rootDevice)){
+ Activator.logger.DEBUG("Unable to find all the sub device or to set action listener");
+ continue;
+ }
+ ServiceRegistration listenReg = bindSubscribe(d);
+ if(listenReg==null){
+ Activator.logger.DEBUG("Unable to set action listener event listener");
+ continue;
+ }
+ //makeIcons(r.getRootDevice(),xml.getAbsolutePath());
+ d.start();
+ exportedDevices.put(
+ rootDevice.getProperty(UPnPDevice.UDN),
+ new ExportedDeviceInfo(d,listenReg,dn)
+ );
+ }
+ //}
+ }
+ }
+ }
+
+ /**
+ *
+ */
+ private void setListen() {
+ {
+ try {
+ Activator.bc.addServiceListener(
+ this,
+ // fixed by Matteo and Francesco 21/9/04
+ "(&("+Constants.OBJECTCLASS+"="+UPnPDevice.class.getName()+")"
+ + "(" + UPnPDevice.UPNP_EXPORT +"=*))"
+ );
+ } catch (InvalidSyntaxException ingnore) {}
+ }
+ }
+ /*
+ /**
+ * @param upnpDev
+ * @param refDev
+ *
+ private void makeIcons(
+ org.apache.felix.upnpbase.export.xml.Device upnpDev,
+ String path) {
+ Icon[] icons = upnpDev.getIcons();
+ if(icons!=null){
+ byte[] buf = new byte[512];
+ for (int i = 0; i < icons.length; i++) {
+ try {
+ String icoPath = path+icons[i].getUrl().replace('/',File.separatorChar);
+ InputStream is = icons[i].getInputStream();
+ Converter.makeParentPath(icoPath);
+ FileOutputStream fos = new FileOutputStream(icoPath);
+ int n=is.read(buf,0,buf.length);
+ while(n>0){
+ fos.write(buf,0,n);
+ n=is.read(buf,0,buf.length);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ org.apache.felix.upnpbase.export.xml.Device[] devs = upnpDev.getDevices();
+ if(devs==null)
+ return;
+ for (int i = 0; i < devs.length; i++) {
+ makeIcons(devs[i],path);
+ }
+ }*/
+ /**
+ * This method is used to connect all the Action that are shown to UPnP world
+ * by CyberLink UPnP Device to the real implementation that is conatined iniside
+ * the OSGi service.
+ * This method will connect even all the subdevice of te given OSGi device.
+ *
+ * @param d CyberLink Device that will be used associated to the OSGi Device
+ * @param rootDevice ServiceReference to the OSGi Device that will be used as
+ * implementation of the CyberLink Device
+ * @return true if and only if the binding off all the action of all the children
+ * device is done succesfully
+ */
+ private boolean bindInvokes(Device d, ServiceReference rootDevice) {
+ bindInvoke(d,rootDevice);
+ //Activator.bc.ungetService(rootDevice);
+ ServiceReference[] childs = null;
+ try {
+ childs = Activator.bc.getServiceReferences(
+ UPnPDevice.class.getName(),
+ "("+UPnPDevice.PARENT_UDN+"="+rootDevice.getProperty(UPnPDevice.UDN)+")"
+ );
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ String[] childsUDN = (String[]) rootDevice.getProperty(UPnPDevice.CHILDREN_UDN);
+ if((childs==null)&&(childsUDN==null)){
+ return true;
+ }else if((childs==null)||(childsUDN==null)){
+ return false;
+ }else if(childs.length==childsUDN.length){
+ /*--- your code ---
+ for (int i = 0; i < childs.length; i++) {
+ if(!bindInvokes(d,childs[i]))
+ return false;
+ }
+ ----- your code end ---*/
+ /*--- twa code ---*/
+ DeviceList dl = d.getDeviceList();
+ for (int i = 0; i < childs.length; i++) {
+ Device dev = (Device)dl.elementAt(i);
+ if(!bindInvokes(dev,childs[i]))
+ return false;
+ }
+ /*----- twa code end ---*/
+
+ return true;
+ }else{
+ return false;
+ }
+
+ }
+ /*
+ /**
+ * @param path
+ *
+ private boolean writeXMLService(String path,org.apache.felix.upnpbase.export.xml.Device d) {
+ Vector v = new Vector();
+ v.add(d);
+ while(v.size()!=0){
+ d=(org.apache.felix.upnpbase.export.xml.Device) v.elementAt(0);
+ v.remove(0);
+ Service[] servs = d.getServices();
+ if(servs==null)
+ continue;
+ for (int i = 0; i < servs.length; i++) {
+ FileOutputStream fos;
+ String xmlPath=path+servs[i].getScpdURL().replace('/',File.separatorChar);
+ if(!Converter.makeParentPath(xmlPath)) return false;
+ try {
+ fos = new FileOutputStream(xmlPath);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ return false;
+ }
+ try {
+ servs[i].writeXML(fos);
+ fos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ org.apache.felix.upnpbase.export.xml.Device[] subs = d.getDevices();
+ if(subs==null){
+ return true;
+ }else{
+ for(int i = 0; i < subs.length;i++){
+ v.add(subs[i]);
+ }
+ }
+ }
+ return true;
+ }*/
+ /**
+ * This method add an UPnPEventListener Service to the OSGi Framework so that
+ * the Base Driver can notify all the event listener registered on the CyberLink
+ * UPnP device from the UPnP World.
+ *
+ * @param d Device of CyberLink that will be notified by the changing of the StateVariable
+ * that happen on the OSGi World
+ * @return ServiceRegistration of the new registered service.
+ */
+ private ServiceRegistration bindSubscribe(Device d) {
+ ExporterUPnPEventListener eventer = new ExporterUPnPEventListener(d);
+ Properties p = new Properties();
+
+ StringBuffer sb = new StringBuffer("(|");
+ Vector v = new Vector();
+ v.add(d);
+ Device current;
+ while (v.size() != 0) {
+ current = (Device) v.elementAt(0);
+ v.remove(0);
+ DeviceList dl = current.getDeviceList();
+ for (int i = 0; i < dl.size(); i++) {
+ v.add(dl.elementAt(i));
+ }
+ sb.append("(").append(UPnPDevice.ID).append("=").append(
+ current.getUDN()).append(")");
+ }
+ sb.append(")");
+ Filter f = null;
+ try {
+ f = Activator.bc.createFilter(sb.toString());
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ return null;
+ }
+ if (f != null) p.put(UPnPEventListener.UPNP_FILTER, f);
+
+ return Activator.bc.registerService(UPnPEventListener.class.getName(), eventer, p);
+ }
+
+ /**
+ * This method do the real connection between OSGi UPnP Service action and
+ * CyberLink UPnP Device action
+ *
+ * @param upnpDev the CyberLink UPnP Device object that will be connected
+ * @param osgiDev the ServiceReference to OSGi UPnP Service that will be connected to
+ * CyberLink UPnP as implementation of the Action
+ * @return true if and only if the binding off all the action is done succesfully
+ */
+ private boolean bindInvoke(Device upnpDev,ServiceReference osgiDev) {
+ ServiceList sl = upnpDev.getServiceList();
+ int l=sl.size();
+ for (int i = 0; i < l; i++) {
+ sl.getService(i).setActionListener(
+ new GeneralActionListener(
+ osgiDev,
+ sl.getService(i).getServiceID()
+ )
+ );
+ }
+ return true;
+ }
+
+ /**
+ *
+ */
+ public synchronized void cleanUp() {
+ Activator.logger.INFO("Cleaning...");
+
+ Enumeration keys;
+
+ Activator.logger.INFO("Removing temporary listener....");
+ keys=exportedDevices.keys();
+ while (keys.hasMoreElements()) {
+ ServiceRegistration sr = ((ExportedDeviceInfo)
+ exportedDevices.get(keys.nextElement())).getServiceRegistration();
+ sr.unregister();
+ }
+ Activator.logger.INFO("Done");
+
+ Activator.logger.INFO("Removing device....");
+ keys=exportedDevices.keys();
+ while (keys.hasMoreElements()) {
+ Device dev = ((ExportedDeviceInfo)
+ exportedDevices.get(keys.nextElement())).getDevice();
+ dev.stop();
+ }
+ Activator.logger.INFO("Done");
+ }
+
+ private synchronized boolean shouldEnd() {
+ return end;
+ }
+
+ public synchronized void end() {
+ end = true;
+ queueRootDevice.addRootDevice(null);
+ }
+ /**
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent event) {
+ switch(event.getType()){
+ case ServiceEvent.REGISTERED:break;
+
+ case ServiceEvent.MODIFIED:
+ case ServiceEvent.UNREGISTERING:{
+ this.unexportDevice(event.getServiceReference());
+ if(exportedDevices.size()==0){
+ Activator.bc.removeServiceListener(this);
+ setListening(false);
+ }
+ }break;
+ }
+ }
+ /**
+ * @param b
+ */
+ private synchronized void setListening(boolean b) {
+ listening=b;
+ }
+
+ private synchronized boolean getListening(){
+ return listening;
+ }
+
+ /**
+ * @param property
+ */
+ private synchronized void unexportDevice(ServiceReference dev) {
+ String udn=(String) dev.getProperty(UPnPDevice.PARENT_UDN);
+ if(udn==null){
+ ExportedDeviceInfo edi =
+ (ExportedDeviceInfo) exportedDevices.get(
+ dev.getProperty(UPnPDevice.UDN)
+ );
+ Device d = edi.getDevice();
+ if(d!=null) {
+ Activator.logger.INFO("[Exporter] removing device:" +d.getFriendlyName());
+ d.stop();
+ exportedDevices.remove(d.getUDN());
+ }
+ ServiceRegistration srListener=edi.getServiceRegistration();
+ if(srListener!=null) srListener.unregister();
+
+ }else{
+ ServiceReference[] servs=null;
+ try {
+ servs = Activator.bc.getServiceReferences(
+ UPnPDevice.class.getName(),
+ "("+UPnPDevice.UDN+"="+udn+")"
+ );
+ } catch (InvalidSyntaxException ignored) {}
+ if(servs==null) return;
+ this.unexportDevice(servs[0]);
+ }
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/MyCtrlPoint.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/MyCtrlPoint.java
new file mode 100644
index 0000000..1c86669
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/MyCtrlPoint.java
@@ -0,0 +1,933 @@
+/*
+ * 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.basedriver.importer.core;
+
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.cybergarage.http.HTTPRequest;
+import org.cybergarage.upnp.ControlPoint;
+import org.cybergarage.upnp.Device;
+import org.cybergarage.upnp.DeviceList;
+import org.cybergarage.upnp.Service;
+import org.cybergarage.upnp.ServiceList;
+import org.cybergarage.upnp.ServiceStateTable;
+import org.cybergarage.upnp.StateVariable;
+import org.cybergarage.upnp.device.NotifyListener;
+import org.cybergarage.upnp.device.SearchResponseListener;
+import org.cybergarage.upnp.event.NotifyRequest;
+import org.cybergarage.upnp.event.Property;
+import org.cybergarage.upnp.event.PropertyList;
+import org.cybergarage.upnp.ssdp.SSDPPacket;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPEventListener;
+import org.osgi.service.upnp.UPnPService;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+import org.apache.felix.upnp.basedriver.Activator;
+import org.apache.felix.upnp.basedriver.importer.core.event.message.FirstMessage;
+import org.apache.felix.upnp.basedriver.importer.core.event.message.ListenerModified;
+import org.apache.felix.upnp.basedriver.importer.core.event.message.ListenerUnRegistration;
+import org.apache.felix.upnp.basedriver.importer.core.event.message.StateChanged;
+import org.apache.felix.upnp.basedriver.importer.core.event.structs.NotifierQueue;
+import org.apache.felix.upnp.basedriver.importer.core.event.structs.SubscriptionQueue;
+import org.apache.felix.upnp.basedriver.importer.core.upnp.UPnPDeviceImpl;
+import org.apache.felix.upnp.basedriver.importer.core.upnp.UPnPServiceImpl;
+import org.apache.felix.upnp.basedriver.importer.util.DictionaryProp;
+import org.apache.felix.upnp.basedriver.importer.util.ParseUSN;
+import org.apache.felix.upnp.extra.util.Converter;
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ *
+ */
+public class MyCtrlPoint extends ControlPoint
+ implements
+ NotifyListener,
+ SearchResponseListener,
+ ServiceListener
+{
+ private BundleContext context;
+ private Hashtable devices;//key UDN value OsgideviceInfo(Osgi)
+ private SubscriptionQueue subQueue;
+ private NotifierQueue notifierQueue;
+
+ private final String UPNP_EVENT_LISTENER_FLTR =
+ "(" + Constants.OBJECTCLASS + "=" + UPnPEventListener.class.getName() + ")";
+ private final String UPNP_DEVICE_FLTR =
+ "(" + Constants.OBJECTCLASS + "=" + UPnPDevice.class.getName() + ")";
+ private final String EXPORT_FLTR =
+ "(" + UPnPDevice.UPNP_EXPORT + "=*" + ")";
+ private final String IMPORT_FLTR =
+ "(" + org.apache.felix.upnp.extra.util.Constants.UPNP_IMPORT + "=*" + ")";
+
+
+ public MyCtrlPoint(BundleContext context, SubscriptionQueue subQueue,
+ NotifierQueue notifierQueue) {
+ super();
+ this.context = context;
+ devices = new Hashtable();
+ addNotifyListener(this);
+ addSearchResponseListener(this);
+ try {
+ context.addServiceListener(this, UPNP_EVENT_LISTENER_FLTR);
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ this.subQueue = subQueue;
+ this.notifierQueue = notifierQueue;
+ }
+
+ public void httpRequestRecieved(HTTPRequest httpReq) {
+ Activator.logger.DEBUG("[Importer] httpRequestRecieved event");
+ Activator.logger.PACKET(httpReq.toString());
+
+ if (httpReq.isNotifyRequest() == true) {
+ Activator.logger.DEBUG("[Importer] Notify Request");
+ NotifyRequest notifyReq = new NotifyRequest(httpReq);
+ String uuid = notifyReq.getSID();
+ long seq = notifyReq.getSEQ();
+ PropertyList props = notifyReq.getPropertyList();
+// int propCnt = props.size();
+// Hashtable hash = new Hashtable();
+// for (int n = 0; n < propCnt; n++) {
+// Property prop = props.getProperty(n);
+// String varName = prop.getName();
+// String varValue = prop.getValue();
+// hash.put(varName, varValue);
+// }
+ newEventArrived(uuid, seq, props);
+ httpReq.returnOK();
+ return;
+ }
+
+ Activator.logger.DEBUG("BAD Request");
+ httpReq.returnBadRequest();
+
+ }
+
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.cybergarage.upnp.ControlPoint#removeExpiredDevices()
+ *
+ */
+ public void removeExpiredDevices() {
+ DeviceList devList = getDeviceList();
+ int devCnt = devList.size();
+ for (int n = 0; n < devCnt; n++) {
+ Device dev = devList.getDevice(n);
+ if (dev.isExpired() == true) {
+ Activator.logger.DEBUG("[Importer] Expired device:"+ dev.getFriendlyName());
+ removeDevice(dev);
+ removeOSGiExpireDevice(dev);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.cybergarage.upnp.device.NotifyListener#deviceNotifyReceived(org.cybergarage.upnp.ssdp.SSDPPacket)
+ */
+ public void deviceNotifyReceived(SSDPPacket ssdpPacket) {
+ Activator.logger.DEBUG("[Importer] deviceNotifyReceived");
+ Activator.logger.PACKET(ssdpPacket.toString());
+ /*
+ * case is notify case isalive case new root crea e aggiungi il servizio
+ * in Osgi con tutta la stirpe case device or service controllo se
+ * esiste in OSGi se si nada, se no lo creo partendo dal root case
+ * byebye case root deregistro tutta la stirpe case device o service
+ * reinstanzio il root con le modifiche
+ *
+ */
+ /*
+ * if the packet is
+ * NOTIFY or ISALIVE or *new* ROOT then create and register the UPnPDevice and
+ * all the embeeded device too
+ * DEVICE or SERVICE then if they already exist in OSGi do nothing otherwise I'll create and
+ * register all the UPnPDevice need starting from the root device
+ * *root* BYEBYE then I'll unregister it and all its children from OSGi Framework
+ * *service* BYEBYE then I'll re-register the UPnPDevice that contain the service with the updated
+ * properties
+ * *device* BYEBYE then I'll re-register the UPnPDevice that contain the device with the updated
+ * properties and also unregister the UPnPDevice that has left
+ */
+ String usn = ssdpPacket.getUSN();
+ ParseUSN parseUSN = new ParseUSN(usn);
+ String udn = parseUSN.getUDN();
+
+ ServiceReference[] refs = null;
+ String filter = "(&" + UPNP_DEVICE_FLTR + EXPORT_FLTR+ ")";
+ try {
+ refs = context.getServiceReferences(UPnPDevice.class.getName(), filter);
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ if (refs != null) {
+ for (int i = 0; i < refs.length; i++) {
+ UPnPDevice dev = (UPnPDevice) context.getService(refs[i]);
+ Dictionary dic = dev.getDescriptions(null);
+ if (((String) dic.get(UPnPDevice.UDN)).equals(udn)) {
+ return;
+ }
+ }
+ }
+
+ if (ssdpPacket.isAlive()) {
+
+ Activator.logger.DEBUG("[Importer] ssdpPacket.isAlive");
+ if (devices.containsKey(udn)) {
+ Activator.logger.DEBUG("[Importer] Device already discovered");
+ if (parseUSN.isService()) {
+ doServiceUpdating(udn,parseUSN.getServiceType());
+ }
+ } else {
+ doDeviceRegistration(udn);
+ }
+
+ } else if (ssdpPacket.isByeBye()) {
+ Activator.logger.DEBUG("[Importer] ssdpPacket.isByeBye");
+
+ if (devices.containsKey(udn)) {
+ if (parseUSN.isDevice()) {
+ Activator.logger.DEBUG("[Importer] parseUSN.isDevice ...unregistering all the children devices ");
+
+ //unregistering all the children devices
+ UPnPDeviceImpl dev = ((OSGiDeviceInfo) devices.get(udn)).getOSGiDevice();
+ removeOSGiandUPnPDeviceHierarchy(dev);
+
+ } else if (parseUSN.isService()) {
+ Activator.logger.DEBUG("[Importer] parseUSN.isService ...registering modified device again ");
+ /*
+ * I have to unregister the UPnPDevice and register it again
+ * with the updated properties
+ */
+ UPnPDeviceImpl device =
+ ((OSGiDeviceInfo) devices.get(udn)).getOSGiDevice();
+ ServiceRegistration registar =
+ ((OSGiDeviceInfo) devices.get(udn)).getRegistration();
+ String[] oldServicesID =
+ (String[]) (device.getDescriptions(null).get(UPnPService.ID));
+ String[] oldServiceType =
+ (String[]) (device.getDescriptions(null).get(UPnPService.TYPE));
+
+ Device cyberDevice = findDeviceCtrl(this, udn);
+ Vector vec = new Vector();
+ for (int i = 0; i < oldServiceType.length; i++) {
+ Service ser = cyberDevice.getService(oldServicesID[i]);
+ if (!(ser.getServiceType().equals(parseUSN.getServiceType())))
+ {
+ vec.add(oldServicesID[i]);
+ }
+ }
+
+ //new serviceID
+ String[] actualServicesID = new String[vec.size()];
+ actualServicesID = (String[]) vec.toArray(new String[]{});
+
+ //new serviceType
+ String[] actualServiceType = new String[oldServiceType.length - 1];
+ vec.clear();
+ for (int i = 0; i < oldServiceType.length; i++) {
+ if (!(oldServiceType[i].equals(parseUSN.getServiceType())))
+ {
+ vec.add(oldServiceType[i]);
+ }
+ }
+ actualServiceType = (String[]) vec.toArray(new String[]{});
+
+ //unrigistering and registering again with the new properties
+ unregisterUPnPDevice(registar);
+ device.setProperty(UPnPService.ID, actualServicesID);
+ device.setProperty(UPnPService.TYPE, actualServiceType);
+ registerUPnPDevice(null, device, device.getDescriptions(null));
+ searchForListener(cyberDevice);
+ }
+ }
+ } else {
+ /*
+ * if it is a service means that it is beend delete when the
+ * owner was unregister so I can skip this bye-bye
+ */
+ }
+ }
+
+ public synchronized void removeOSGiandUPnPDeviceHierarchy(UPnPDeviceImpl dev)
+ {
+ /*
+ * remove all the UPnPDevice from the struct of local device recursively
+ */
+ String[] childrenUDN = (String[]) dev.getDescriptions(null).get(
+ UPnPDevice.CHILDREN_UDN);
+ if (childrenUDN == null) {
+ //non ha figli
+ //no children
+ unregisterUPnPDevice(((OSGiDeviceInfo) devices.get(dev
+ .getDescriptions(null).get(UPnPDevice.UDN)))
+ .getRegistration());
+ devices.remove(dev.getDescriptions(null).get(UPnPDevice.UDN));
+ return;
+ }
+ for (int i = 0; i < childrenUDN.length; i++) {
+ if (devices.get(childrenUDN[i]) == null) {
+ continue;
+ } else {
+ removeOSGiandUPnPDeviceHierarchy(((OSGiDeviceInfo) devices
+ .get(childrenUDN[i])).getOSGiDevice());
+ }
+ }
+ unregisterUPnPDevice(((OSGiDeviceInfo) devices.get(dev.getDescriptions(
+ null).get(UPnPDevice.UDN))).getRegistration());
+ devices.remove(dev.getDescriptions(null).get(UPnPDevice.UDN));
+ }
+
+ public synchronized void removeOSGiExpireDevice(Device dev) {
+ /*
+ * unregistering root device with all its children device from OSGi
+ * deleting root device and all its children from struct that conatin
+ * a list of local device
+ */
+ removeOSGiandUPnPDeviceHierarchy(((OSGiDeviceInfo) devices.get(dev
+ .getUDN())).getOSGiDevice());
+ }
+
+ public void registerUPnPDevice(Device dev, UPnPDeviceImpl upnpDev,
+ Dictionary prop) {
+ /*
+ * registering the new Device as OSGi UPnPDevice and then add
+ * ServiceRegistration and UPnPDevice reference to the hashtable
+ * that contains local devices
+ */
+ if (prop == null && upnpDev == null) {
+ UPnPDeviceImpl newDevice = new UPnPDeviceImpl(dev, context);
+ ServiceRegistration registration =
+ context.registerService(UPnPDevice.class.getName(),
+ newDevice,
+ newDevice.getDescriptions(null));
+ OSGiDeviceInfo deviceInfo =
+ new OSGiDeviceInfo(newDevice,registration);
+
+ String udn = (String) ((newDevice.getDescriptions(null)).get(UPnPDevice.UDN));
+ devices.put(udn, deviceInfo);
+ } else {
+ ServiceRegistration registration =
+ context.registerService(UPnPDevice.class.getName(), upnpDev, prop);
+ OSGiDeviceInfo deviceInfo =
+ new OSGiDeviceInfo(upnpDev, registration);
+ devices.put(upnpDev.getDescriptions(null).get(UPnPDevice.UDN),deviceInfo);
+ }
+ }
+
+
+ /*
+ * public void registerHierarchyUPnPDevice(Device dev) { registro il root
+ * con tutta la sua stirpe in osgi registerUPnPDevice(dev); DeviceList
+ * devList = dev.getDeviceList(); for (int i = 0; i < devList.size(); i++) {
+ * registerHierarchyUPnPDevice(devList.getDevice(i)); } }
+ */
+ public void unregisterUPnPDevice(ServiceRegistration registration) {
+ registration.unregister();
+
+ }
+
+ public Device findDeviceCtrl(ControlPoint ctrl, String udn) {
+ /*
+ * this return the device looking in all the struct
+ */
+
+ DeviceList devList = getDeviceList();
+ Device dev = null;
+ int i = 0;
+ while (i < devList.size() && (dev == null)) {
+ if (devList.getDevice(i).getUDN().equals(udn)) {
+ dev = devList.getDevice(i);
+ return dev;
+ }
+ dev = findDevice(udn, devList.getDevice(i));
+ i++;
+ }
+ return dev;
+ }
+
+ public Device findDevice(String udn, Device dev) {
+ /*
+ * look for the device if it exist, starting from the root on
+ * cyberlink struct
+ */
+ DeviceList devList = dev.getDeviceList();
+ Device aux = null;
+ for (int i = 0; i < devList.size(); i++) {
+ if (devList.getDevice(i).getUDN().equals(udn)) {
+ return devList.getDevice(i);
+ } else {
+ if((aux = findDevice(udn, devList.getDevice(i))) != null)
+ return aux;
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.cybergarage.upnp.device.SearchResponseListener#deviceSearchResponseReceived(org.cybergarage.upnp.ssdp.SSDPPacket)
+ */
+ public void deviceSearchResponseReceived(SSDPPacket ssdpPacket) {
+ Activator.logger.DEBUG("[Importer] deviceSearchResponseReceived");
+ Activator.logger.PACKET(ssdpPacket.toString());
+
+ String usn = ssdpPacket.getUSN();
+ ParseUSN parseUSN = new ParseUSN(usn);
+ String udn = parseUSN.getUDN();
+
+ ServiceReference[] refs = null;
+
+ String filter = "(&" + UPNP_DEVICE_FLTR + EXPORT_FLTR + ")";
+
+ try {
+ refs = context.getServiceReferences(UPnPDevice.class.getName(),
+ filter);
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+
+ if (refs != null) {
+ for (int i = 0; i < refs.length; i++) {
+ UPnPDevice dev = (UPnPDevice) context.getService(refs[i]);
+ Dictionary dic = dev.getDescriptions(null);
+ if (((String) dic.get(UPnPDevice.UDN)).equals(udn)) {
+ return;
+ }
+ }
+ }
+
+ if (devices.containsKey(udn)) {
+ Activator.logger.DEBUG("[Importer] Device already discovered");
+ /*
+ * Exist the registered device either in OSGi and
+ * hashtable of local device
+ */
+ if (parseUSN.isService()) {
+ doServiceUpdating(udn,parseUSN.getServiceType());
+ }
+ } else {
+ doDeviceRegistration(udn);
+ }
+
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent event) {
+ Activator.logger.DEBUG("[Importer] serviceChanged");
+ Activator.logger.DEBUG("Event::"+event.toString());
+
+ if (event.getType() == ServiceEvent.REGISTERED) {
+ /* check new listener registration */
+ ServiceReference serRef = event.getServiceReference();
+ Object obj = serRef.getProperty(UPnPEventListener.UPNP_FILTER);
+ /* obtain interested devices for the listener */
+ ServiceReference[] devicesRefs = null;
+ if (obj != null) {
+ Filter filter = (Filter) obj;
+ String filtra = filter.toString();
+ /*
+ * Avoid to implement the notification for device
+ * that are not been created by BaseDriver
+ */
+ String newfilter = "(&" + filtra + IMPORT_FLTR + ")";
+ //String newfilter = "(&" + filtra + "(!" + EXPORT_FLTR + ")" + ")";
+ //System.out.println(newfilter);
+ try {
+ devicesRefs = context.getServiceReferences(UPnPDevice.class
+ .getName(), newfilter);
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+
+ if (devicesRefs != null) {/*
+ * solo se ci sono dei device
+ * compatibili
+ *
+ * only if there is a compatibile device
+ */
+ Dictionary dic = new DictionaryProp();
+ /* cerco i servizi che matchano */
+ for (int i = 0; i < devicesRefs.length; i++) {
+ UPnPDevice device = (UPnPDevice) context.getService(devicesRefs[i]);
+ dic.put(UPnPDevice.ID, device.getDescriptions(null).get(UPnPDevice.UDN));
+ dic.put(UPnPDevice.TYPE, device.getDescriptions(null).get(UPnPDevice.TYPE));
+ UPnPService[] services = device.getServices();
+ //TODO fare l'unget del servizio UPnPDevice??
+ //TODO do I have to do the unget of UPnPDevice??
+ if (services != null) {
+ for (int j = 0; j < services.length; j++) {
+ dic.put(UPnPService.ID, services[j].getId());
+ dic.put(UPnPService.TYPE, services[j].getType());
+ //TODO add method boolean serviceEvented() so we can remove the below cycle
+ UPnPStateVariable[] stateVars = services[j].getStateVariables();
+ boolean hasEventedVars = false;
+ for (int k = 0; k < stateVars.length && ! hasEventedVars; k++) {
+ hasEventedVars = stateVars[k].sendsEvents();
+ if (hasEventedVars) {
+ if(filter.match(dic)){
+ UPnPEventListener listener =
+ (UPnPEventListener) context.getService(serRef);
+ FirstMessage msg = new FirstMessage(
+ ((UPnPServiceImpl) services[j]).getCyberService(),
+ listener);
+ subQueue.enqueue(msg);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else {/* obj==null (interested in all devices) */
+ try {
+ String newfilter = "(!(" + EXPORT_FLTR+ ")";
+ devicesRefs = context.getServiceReferences(UPnPDevice.class.getName(), newfilter);
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ if (devicesRefs != null) {/*
+ * solo se ci sono dei device
+ *
+ * only if there is a device
+ */
+
+ for (int i = 0; i < devicesRefs.length; i++) {
+ UPnPDevice device = (UPnPDevice) context
+ .getService(devicesRefs[i]);
+ UPnPService[] services = device.getServices();
+ //fare l'unget del servizio UPnPDevice??
+ //do I have to do the unget of UPnPDevice??
+ if (services != null) {
+ for (int j = 0; j < services.length; j++) {
+ UPnPStateVariable[] stateVars = services[j]
+ .getStateVariables();
+ boolean bool = false;
+ for (int k = 0; k < stateVars.length; k++) {
+ bool = stateVars[k].sendsEvents();
+ if (bool) {
+ break;
+ }
+ }
+ if (bool) {
+ UPnPEventListener listener =
+ (UPnPEventListener) context.getService(serRef);
+ FirstMessage msg = new FirstMessage(
+ ((UPnPServiceImpl) services[j]).getCyberService(),
+ listener);
+ subQueue.enqueue(msg);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ } else if (event.getType() == ServiceEvent.MODIFIED) {
+ Vector newServices = new Vector();
+ ServiceReference serRef = event.getServiceReference();
+ Filter filter = (Filter) serRef.getProperty(UPnPEventListener.UPNP_FILTER);
+ UPnPEventListener listener = (UPnPEventListener) context.getService(serRef);
+ ServiceReference[] devicesRefs = null;
+
+ if (filter != null) {
+ try {
+ String filtra = filter.toString();
+ String newfilter = "(&" + filtra + "(!" + EXPORT_FLTR + ")" + ")";
+ devicesRefs = context.getServiceReferences(UPnPDevice.class.getName(), newfilter);
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ if (devicesRefs != null) {/*
+ * solo se ci sono dei device
+ * compatibili
+ *
+ * only if there is a compatibile device
+ */
+ Dictionary dic = new DictionaryProp();
+ /*
+ * cerco i servizi che matchano
+ *
+ * look for the service that match
+ */
+ for (int i = 0; i < devicesRefs.length; i++) {
+ UPnPDevice device = (UPnPDevice) context
+ .getService(devicesRefs[i]);
+ dic.put(UPnPDevice.ID, device.getDescriptions(null)
+ .get(UPnPDevice.UDN));
+ dic.put(UPnPDevice.TYPE, device.getDescriptions(null)
+ .get(UPnPDevice.TYPE));
+ UPnPService[] services = device.getServices();
+
+ //fare l'unget del servizio UPnPDevice??
+ //do I have to do the unget of UPnPDevice??
+ if (services != null) {
+ for (int j = 0; j < services.length; j++) {
+ dic.put(UPnPService.ID, services[j].getId());
+ dic
+ .put(UPnPService.TYPE, services[j]
+ .getType());
+
+ UPnPStateVariable[] stateVars = services[j]
+ .getStateVariables();
+ boolean hasEventedVars = false;
+ for (int k = 0; k < stateVars.length; k++) {
+ hasEventedVars = stateVars[k].sendsEvents();
+ if (hasEventedVars) {
+ break;
+ }
+ }
+ if (!hasEventedVars) {
+ continue;
+ }
+
+ boolean bool = filter.match(dic);
+ if (bool) {
+ newServices
+ .add(((UPnPServiceImpl) services[j])
+ .getCyberService());
+ }
+ }//for services
+ }//services ==null
+ }//for devicesRefs
+ ListenerModified msg = new ListenerModified(newServices,
+ listener);
+ subQueue.enqueue(msg);
+ }//devicesrefs !=null
+ } else {//interrested in all devices
+ try {
+
+ String newfilter = "(!(" + UPnPDevice.UPNP_EXPORT + "=*"
+ + ")" + ")";
+ devicesRefs = context.getServiceReferences(UPnPDevice.class
+ .getName(), newfilter);
+ } catch (InvalidSyntaxException e) {
+ e.printStackTrace();
+ }
+ if (devicesRefs != null) {/*
+ * solo se ci sono dei device
+ *
+ * only if there is a device
+ */
+
+ for (int i = 0; i < devicesRefs.length; i++) {
+ UPnPDevice device = (UPnPDevice) context
+ .getService(devicesRefs[i]);
+ UPnPService[] services = device.getServices();
+ //fare l'unget del servizio UPnPDevice??
+ //do I have to do the unget of UPnPDevice??
+ if (services != null) {
+ for (int j = 0; j < services.length; j++) {
+ UPnPStateVariable[] stateVars = services[j]
+ .getStateVariables();
+ boolean hasEventedVars = false;
+ for (int k = 0; k < stateVars.length; k++) {
+ hasEventedVars = stateVars[k].sendsEvents();
+ if (hasEventedVars) {
+ break;
+ }
+ }
+ if (hasEventedVars) {
+ newServices
+ .add(((UPnPServiceImpl) services[j])
+ .getCyberService());
+ }//hasEventedvars
+ }//for services
+ }//services !=null
+ }//for devicesRefs
+ subQueue
+ .enqueue(new ListenerModified(newServices, listener));
+ }//devicesRefs !=null
+
+ }
+
+ } else if (event.getType() == ServiceEvent.UNREGISTERING) {
+ UPnPEventListener listener = (UPnPEventListener) context
+ .getService(event.getServiceReference());
+ if (listener != null) {
+ ListenerUnRegistration msg = new ListenerUnRegistration(
+ listener);
+ subQueue.enqueue(msg);
+ }
+ context.ungetService(event.getServiceReference());
+ }
+ } /*
+ * (non-Javadoc)
+ *
+ * @see org.cybergarage.upnp.event.EventListener#eventNotifyReceived(java.lang.String,
+ * long, java.lang.String, java.lang.String)
+ */
+ /*
+ * public void eventNotifyReceived(String uuid, long seq, String varName,
+ * String value) { // TODO Auto-generated method stub StateChanged msg = new
+ * StateChanged(uuid, varName, value,seq);,serviceFromSid(uuid)
+ * notifierQueue.enqueue(msg); }
+ */
+
+ public Service serviceFromSid(String sid) {
+ Enumeration e = devices.elements();
+ Service cyberService = null;
+ while (e.hasMoreElements()) {
+ OSGiDeviceInfo deviceinfo = (OSGiDeviceInfo) e.nextElement();
+ UPnPDevice device = deviceinfo.getOSGiDevice();
+ UPnPService[] services = (UPnPService[]) device.getServices();
+ UPnPServiceImpl[] servicesImpl = new UPnPServiceImpl[services.length];
+ for (int i = 0; i < servicesImpl.length; i++) {
+ servicesImpl[i] = (UPnPServiceImpl) services[i];
+ }
+ for (int i = 0; i < servicesImpl.length; i++) {
+ cyberService = servicesImpl[i].getCyberService();
+ boolean bool = cyberService.isSubscribed();
+ if (bool) {
+ if (cyberService.getSID().equals(sid)) {
+ return cyberService;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.felix.upnpbase.importer.MyEventListener#newEventArrived(java.lang.String,
+ * long, java.util.Dictionary)
+ */
+ public void newEventArrived(String uuid, long seq, PropertyList props) {
+ Activator.logger.DEBUG("[Importer] newEventArrived");
+ Service service = serviceFromSid(uuid);
+ if (service != null) {
+ int size = props.size();
+ Hashtable hash = new Hashtable();
+ for (int i = 0; i < size; i++) {
+ Property prop = props.getProperty(i);
+ String varName = prop.getName();
+ String varValue = prop.getValue();
+ String upnpType = service.getStateVariable(varName).getDataType();
+ Object valueObj;
+ try {
+ valueObj = Converter.parseString(varValue,upnpType);
+ } catch (Exception e) {
+ Activator.logger.ERROR("[Importer] Bad data value in Notify event: "
+ +"var name="+varName +" value="+varValue +" type="+upnpType + "\n"+e);
+ return;
+ }
+ hash.put(varName, valueObj);
+ }
+
+ Device device = service.getDevice();
+ StateChanged msg = new StateChanged(uuid, seq, hash, device, service);
+ notifierQueue.enqueue(msg);
+ }
+ }
+
+ public void doServiceUpdating(String udn,String serviceType){
+ Activator.logger.DEBUG("[Importer] check for service updating");
+ OSGiDeviceInfo deviceinfo = (OSGiDeviceInfo) devices.get(udn);
+ UPnPDeviceImpl device = deviceinfo.getOSGiDevice();
+ boolean isSerPresent = device.existServiceType(serviceType);
+ if (!isSerPresent) {
+ /*
+ * The serivice doesn't exist so it's new.
+ * Find the udn of owner device and re-register the owner
+ */
+ ServiceRegistration registar =
+ ((OSGiDeviceInfo) devices.remove(udn)).getRegistration();
+ String[] oldServicesID =
+ (String[]) device.getDescriptions(null).get(UPnPServiceImpl.ID);
+ String[] oldServicesType =
+ (String[]) device.getDescriptions(null).get(UPnPServiceImpl.TYPE);
+
+ //per via delle istanze multiple di un tipo di servizio
+ //to handle multiple instance of a serivice of the same type
+ Device cyberDevice = findDeviceCtrl(this, udn);
+ ServiceList serviceList = cyberDevice.getServiceList();
+ ArrayList newServicesID = new ArrayList();
+
+ for (int i = 0; i < serviceList.size(); i++) {
+ if (serviceList.getService(i).getServiceType()
+ .equals(serviceType))
+ {
+ newServicesID.add(serviceList.getService(i).getServiceID());
+ }
+ }
+
+ //adding the new servicesID
+ String[] currentServicesID =
+ new String[(oldServicesID.length + newServicesID.size())];
+ int endOld = 1;
+ for (int i = 0; i < oldServicesID.length; i++) {
+ currentServicesID[i] = oldServicesID[i];
+ endOld++;
+ }
+ int j = 0;
+ for (; endOld < currentServicesID.length; endOld++) {
+ currentServicesID[endOld] = (String) newServicesID.get(j);
+ j++;
+ }
+
+ //adding the new ServiceType
+ String[] currentServicesType = new String[oldServicesType.length + 1];
+ for (int i = 0; i < oldServicesType.length; i++) {
+ currentServicesType[i] = oldServicesType[i];
+ }
+ currentServicesType[currentServicesType.length - 1] = serviceType;
+
+
+ // unregistring the OSGi Device
+ // and setting new properties
+ unregisterUPnPDevice(registar);
+ device.setProperty(UPnPService.ID, currentServicesID);
+ device.setProperty(UPnPServiceImpl.TYPE,currentServicesType);
+
+ //registering the service with the updated properties
+ registerUPnPDevice(null, device, device.getDescriptions(null));
+ searchForListener(cyberDevice);
+ }
+ }
+
+ public void doDeviceRegistration(String udn,boolean checkDouble){
+ if(checkDouble){
+ try {
+ ServiceReference[] refs =
+ Activator.bc.getServiceReferences(
+ UPnPDevice.class.getName(),
+ "(" + UPnPDevice.UDN + "=" + udn + ")"
+ );
+ if(refs!=null)
+ return;
+ } catch (InvalidSyntaxException ignored) {
+ }
+ }
+ doDeviceRegistration(udn);
+ }
+
+ public void doDeviceRegistration(String udn){
+ /*
+ * registering the new device even if it is new root device or
+ * a new embedded device
+ */
+ Device dev = findDeviceCtrl(this, udn);
+ if (dev == null) {
+ Activator.logger.WARNING("Cyberlink notified packet from UDN:" +udn+ ", but Device instance doesn't exist in Cyberlink structs !");
+ }
+ if (dev != null) {
+ Activator.logger.INFO("[Importer] registering UPnPDevice UDN:"+dev.getFriendlyName());
+ registerUPnPDevice(dev, null, null);
+ searchForListener(dev);
+ /*
+ * now we can register all the device embedded device and service without
+ * recieving the NOTIFY
+ */
+ //XXX Think about this choice
+ for (Iterator i = dev.getDeviceList().iterator(); i.hasNext();) {
+ Device d = (Device) i.next();
+ doDeviceRegistration(d.getUDN(),true);
+ }
+ }
+ }
+
+ public void searchForListener(Device device) {
+ Activator.logger.DEBUG("[Importer] searching for UPnPEventListener");
+ ServiceReference[] listeners = null;
+ try {
+ listeners = context.getServiceReferences(UPnPEventListener.class.getName(), null);
+ } catch (InvalidSyntaxException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ if (listeners != null) {
+ String deviceID = device.getUDN();
+ String serviceID;
+ String deviceType = device.getDeviceType();
+ String serviceType;
+ Hashtable hash = new Hashtable();
+ hash.put(UPnPDevice.ID, deviceID);
+ hash.put(UPnPDevice.TYPE, deviceType);
+ ServiceList services = device.getServiceList();
+ Vector eventedSers = new Vector();
+
+ for (int i = 0; i < services.size(); i++) {
+ Service service = (Service) services.elementAt(i);
+ ServiceStateTable vars = service.getServiceStateTable();
+ for (int j = 0; j < vars.size(); j++) {
+ StateVariable var = (StateVariable) vars.elementAt(j);
+ if (var.isSendEvents()) {
+ eventedSers.add(service);
+ break;
+ }
+ }
+ }
+
+ for (int i = 0; i < listeners.length; i++) {
+ UPnPEventListener listener = (UPnPEventListener) context
+ .getService(listeners[i]);
+ Filter filter = (Filter) listeners[i]
+ .getProperty(UPnPEventListener.UPNP_FILTER);
+ if (filter == null) {
+ for (int j = 0; j < eventedSers.size(); j++) {
+ Service ser = (Service) eventedSers.elementAt(j);
+ subQueue.enqueue(new FirstMessage(ser, listener));
+ }
+ } else {
+ for (int j = 0; j < eventedSers.size(); j++) {
+ Service ser = (Service) eventedSers.elementAt(j);
+ serviceID = ser.getServiceID();
+ serviceType = ser.getServiceType();
+ hash.put(UPnPService.ID, serviceID);
+ hash.put(UPnPService.TYPE, serviceType);
+ boolean bool = filter.match(hash);
+ if (bool) {
+ subQueue.enqueue(new FirstMessage(ser, listener));
+ }
+
+ }
+ }
+
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/OSGiDeviceInfo.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/OSGiDeviceInfo.java
new file mode 100644
index 0000000..1fa69c6
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/OSGiDeviceInfo.java
@@ -0,0 +1,48 @@
+/*
+ * 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.basedriver.importer.core;
+
+
+import org.osgi.framework.ServiceRegistration;
+
+import org.apache.felix.upnp.basedriver.importer.core.upnp.UPnPDeviceImpl;
+
+/**
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class OSGiDeviceInfo {
+ private UPnPDeviceImpl osgidevice;
+ private ServiceRegistration registration;
+
+ /**
+ * @param osgidevice UPnPDeviceImpl a Service
+ * @param registration Serviceregistration of the UPnPDevice service
+ */
+ public OSGiDeviceInfo(UPnPDeviceImpl osgidevice,
+ ServiceRegistration registration) {
+ this.osgidevice = osgidevice;
+ this.registration = registration;
+ }
+ public UPnPDeviceImpl getOSGiDevice(){
+ return osgidevice;
+ }
+ public ServiceRegistration getRegistration(){
+ return registration;
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/FirstMessage.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/FirstMessage.java
new file mode 100644
index 0000000..c599165
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/FirstMessage.java
@@ -0,0 +1,67 @@
+/*
+ * 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.basedriver.importer.core.event.message;
+
+import org.cybergarage.upnp.Device;
+import org.cybergarage.upnp.Service;
+
+import org.osgi.service.upnp.UPnPEventListener;
+
+/**
+ * This class rappresent a message that is equeued for the Suscriber.<br>
+ * This is message is related to a registration of listener for a
+ * CyberLink Service during the registering of the UPnP Event Listener
+ *
+ * @author Matteo "matted" Demuru
+ *
+ */
+
+public class FirstMessage {
+ private Service service;
+ private UPnPEventListener listener;
+ private String sid;
+ private Device device;
+
+ public FirstMessage(Service service, UPnPEventListener listener) {
+ this.service = service;
+ this.listener = listener;
+ this.sid = "";
+ this.device = service.getDevice();
+ }
+ public Service getService() {
+ return service;
+ }
+ public UPnPEventListener getListener() {
+ return listener;
+ }
+ public void setSid(String sid) {
+ this.sid = sid;
+ }
+ public String getSid() {
+ return sid;
+ }
+ public Device getDevice() {
+ return device;
+ }
+ public String getDeviceID(){
+ return device.getUDN();
+ }
+ public String getServiceID(){
+ return service.getServiceID();
+ }
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/ListenerModified.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/ListenerModified.java
new file mode 100644
index 0000000..7b15d59
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/ListenerModified.java
@@ -0,0 +1,44 @@
+/*
+ * 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.basedriver.importer.core.event.message;
+
+import java.util.Vector;
+
+import org.osgi.service.upnp.UPnPEventListener;
+
+/**
+ * Message that is euqueued for Suscriber, only when a UPnPEventListener changes
+ * his properties
+ *
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class ListenerModified {
+ private Vector newServices;
+ private UPnPEventListener listener;
+ public ListenerModified(Vector newServices,UPnPEventListener listener){
+ this.newServices=newServices;
+ this.listener=listener;
+ }
+ public UPnPEventListener getListener(){
+ return listener;
+ }
+ public Vector getNewServices(){
+ return newServices;
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/ListenerUnRegistration.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/ListenerUnRegistration.java
new file mode 100644
index 0000000..434c9ce
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/ListenerUnRegistration.java
@@ -0,0 +1,38 @@
+/*
+ * 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.basedriver.importer.core.event.message;
+
+import org.osgi.service.upnp.UPnPEventListener;
+
+/**
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class ListenerUnRegistration {
+ private UPnPEventListener listener;
+ /**
+ * @param listener
+ */
+ public ListenerUnRegistration(UPnPEventListener listener) {
+ super();
+ this.listener = listener;
+ }
+ public UPnPEventListener getListener() {
+ return listener;
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/SidExipired.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/SidExipired.java
new file mode 100644
index 0000000..0324c7f
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/SidExipired.java
@@ -0,0 +1,44 @@
+/*
+ * 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.basedriver.importer.core.event.message;
+
+import org.cybergarage.upnp.Service;
+
+/**
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class SidExipired {
+private String sid;
+private Service service;
+/**
+ * @param sid
+ */
+ public SidExipired(String sid,Service service) {
+ super();
+ this.sid = sid;
+ this.service=service;
+ }
+ public String getSid(){
+ return sid;
+ }
+ public Service getService(){
+ return service;
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/StateChanged.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/StateChanged.java
new file mode 100644
index 0000000..7f26339
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/message/StateChanged.java
@@ -0,0 +1,79 @@
+/*
+ * 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.basedriver.importer.core.event.message;
+
+import java.util.Dictionary;
+
+import org.cybergarage.upnp.Device;
+import org.cybergarage.upnp.Service;
+
+/**
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class StateChanged {
+ private String sid;
+ private Dictionary dic;
+ private long seq;
+ private Service service;
+ private Device device;
+ /**
+ * @param sid
+ * @param dic
+ * @param varName
+ * @param varValue
+ */
+ public StateChanged(String sid, long seq, Dictionary dic, Device device,
+ Service service) {
+ super();
+ this.sid = sid;
+ /*
+ * this.varName = varName; this.varValue = varValue;
+ */
+ this.dic = dic;
+ /* dic.put(this.varName, this.varValue); */
+ //this.service=service;
+ this.seq = seq;
+ this.device = device;
+ this.service = service;
+ }
+
+ public Dictionary getDictionary() {
+ return dic;
+ }
+ public String getSid() {
+ return sid;
+ }
+ /*
+ * public String getVarName() { return varName; } public String
+ * getVarValue() { return varValue; }
+ */
+ public long getSeq() {
+ return seq;
+ }
+ /*
+ * public Service getService(){ return service; }
+ *
+ */
+ public String getDeviceID() {
+ return device.getUDN();
+ }
+ public String getServiceID() {
+ return service.getServiceID();
+ }
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/Listener2Sids.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/Listener2Sids.java
new file mode 100644
index 0000000..9d2e492
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/Listener2Sids.java
@@ -0,0 +1,58 @@
+/*
+ * 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.basedriver.importer.core.event.structs;
+
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.osgi.service.upnp.UPnPEventListener;
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Francesco Furfari
+ *
+ */
+public class Listener2Sids {
+ private Hashtable listenerSid;
+
+ public Listener2Sids() {
+ this.listenerSid = new Hashtable();
+ }
+
+ public void put(UPnPEventListener listener, String sid) {
+ if (!listenerSid.containsKey(listener)) {
+ Vector vec = new Vector();
+ vec.add(sid);
+ listenerSid.put(listener, vec);
+ } else {
+ Vector vec = (Vector) listenerSid.get(listener);
+ if (!vec.contains(sid)) {
+ vec.add(sid);
+ }
+ }
+ }
+
+ public final void remove(UPnPEventListener listener) {
+ listenerSid.remove(listener);
+ }
+
+ public final Vector get(UPnPEventListener listener) {
+ return ((Vector) listenerSid.get(listener));
+ }
+}
+
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/Monitor.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/Monitor.java
new file mode 100644
index 0000000..d178122
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/Monitor.java
@@ -0,0 +1,244 @@
+/*
+ * 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.basedriver.importer.core.event.structs;
+
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.cybergarage.upnp.Service;
+
+import org.osgi.service.upnp.UPnPEventListener;
+
+import org.apache.felix.upnp.basedriver.importer.core.MyCtrlPoint;
+import org.apache.felix.upnp.basedriver.importer.core.event.message.FirstMessage;
+import org.apache.felix.upnp.basedriver.importer.core.event.message.ListenerModified;
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Francesco Furfari
+ *
+ *
+ */
+public class Monitor {
+ private Hashtable sidStateVars;
+ private SidsListenersMaps sidListSid;
+
+ public Monitor() {
+ this.sidListSid = new SidsListenersMaps();
+ this.sidStateVars = new Hashtable();
+ }
+
+ public synchronized void putStateVars(String sid, StateVarsToNotify vars) {
+ sidStateVars.put(sid, vars);
+ Vector listeners = (Vector) sidListSid.getListenersFromSid(sid);
+ if (listeners != null) {
+ sidListSid.updateListeners(sid, vars.getDeviceID(), vars.getServiceID(), vars.getDictionary());
+ sidListSid.setAlreadyFirst(sid,true);
+ } else {
+ sidListSid.setAlreadyFirst(sid, false);
+ }
+ }
+ public synchronized void updateStateVars(String sid, Dictionary dic) {
+ StateVarsToNotify vars = (StateVarsToNotify) sidStateVars.get(sid);
+ if (vars != null) {
+ vars.updateDic(dic);
+ if (sidListSid.getAlreadyFirst(sid)) {
+ /*
+ * Sends only the changed StateVariable
+ */
+ sidListSid.updateListeners(sid,
+ vars.getDeviceID(), vars.getServiceID(),
+ dic);
+ } else {
+ /*
+ * Sends the sholw StateVariable for the service
+ */
+ boolean bool = sidListSid.updateListeners(sid,
+ vars.getDeviceID(), vars.getServiceID(),
+ vars.getDictionary());
+ if (bool) {
+ sidListSid.setAlreadyFirst(sid,true);
+ }
+ }
+ }
+ }
+
+/*
+ * controllare se bisogna fare un po' di cleaning
+ *
+ public synchronized StateVarsToNotify getStateVars(String sid) {
+ return (StateVarsToNotify) sidStateVars.get(sid);
+ }
+ public synchronized void removeStateVars(String sid) {
+ sidStateVars.remove(sid);
+ }
+*/
+ public synchronized void addListener(String sid, UPnPEventListener listener) {
+ StateVarsToNotify vars = (StateVarsToNotify) sidStateVars.get(sid);
+ if (vars != null) {
+ /*
+ * Notify the listener whit the whole StateVariables and then
+ * the next time you send only the changed StateVariables
+ */
+ listener.notifyUPnPEvent(vars.getDeviceID(),
+ vars.getServiceID(),vars.getDictionary());
+ }
+ sidListSid.putSid2Listeners(sid, listener);
+ sidListSid.putListener2Sids(listener, sid);
+ }
+
+ /**
+ * Delete the reference to the listener from the stuctures sid2Listeners and listener2Sids.
+ * Also if no more listner are listening for a UPnP Service that UPnP Service is unscribed.
+ *
+ * @param listener The listener to delete
+ * @param ctrl Needed for reference
+ */
+ public synchronized void delListener(UPnPEventListener listener,
+ MyCtrlPoint ctrl/*##renew, SidRenewer sidRenewer*/) {
+
+ //francesco-renew
+ // le strutture delle variabili di stato quando si ripulisono?
+
+ Vector sids = sidListSid.getSidsFromListener(listener);
+ if (sids != null) {
+ Iterator i = sids.iterator();
+ while(i.hasNext()){
+ String sid = (String) i.next();
+ Vector listeners =
+ sidListSid.getListenersFromSid(sid);
+ listeners.remove(listener);
+ if (listeners.size() == 0) {
+ Service service =
+ ctrl.serviceFromSid(sid);
+ //##renew Renewer renewer = sidRenewer.get((String) sids.elementAt(i));
+ //##renew renewer.stop();
+ if (service != null) {
+ boolean ok = ctrl.unsubscribe(service);
+ if (!ok) {
+ //TODO Log?s
+ service.clearSID();
+ }
+ }
+ sidListSid.setAlreadyFirst(sid,false);
+ sidStateVars.remove(sid);
+ i.remove();
+ }
+ }
+ sidListSid.removeListenerKey(listener);
+ }
+ }
+
+ public synchronized void updateListener(ListenerModified msg,
+ SubscriptionQueue subqueue, MyCtrlPoint ctrl/*##renew, SidRenewer sidRenewer*/) {
+ UPnPEventListener listener = msg.getListener();
+ Vector newServices = msg.getNewServices();
+ Vector subscribed = new Vector();
+ Vector notSubscribed = new Vector();
+
+ for (int i = 0; i < newServices.size(); i++) {
+ Service ser = (Service) newServices.elementAt(i);
+ if (ser.isSubscribed()) {
+ subscribed.add(ser);
+ } else {
+ notSubscribed.add(ser);
+ }
+ }
+
+
+ Vector oldSids = sidListSid.getSidsFromListener(listener);
+ // francesco-renew
+ // qua mi sembra che si esca troppo presto
+ // i servizi notSubribed si registrano soltanto dopo ""
+ if(oldSids==null) return;
+
+ for (int i = 0; i < notSubscribed.size(); i++) {
+ Service ser = (Service) notSubscribed.elementAt(i);
+ subqueue.enqueue(new FirstMessage(ser, listener));
+ }
+
+ for (int i = 0; i < oldSids.size(); i++) {
+ String oldSid = (String) oldSids.elementAt(i);
+ if (!subscribed.contains(oldSid)) {
+ // francesco-renew
+ // qua si rimuove il sid dalla lista Listner2Sids
+ // ma il Listner dalla lista sid2Listener?
+ // la delListner che si esegue dopo � pensata per rimuovere principalmente i
+ // listener e ci sono condizioni es. Lista Listener2Sid vuota
+ // che nn fanno rimuovere eventuali listener dalla sid2Listener
+ // controllare bene !!
+
+
+ unsubscribeListenerForSid(oldSid,listener,ctrl);
+ }
+ }
+
+ }
+
+ /**
+ * Unregister the listener as UPnPListener for the UPnPService with
+ * the spicfied SID
+ *
+ * @param sid
+ * @param listener
+ * @param ctrl
+ */
+ private void unsubscribeListenerForSid(String sid, UPnPEventListener listener, MyCtrlPoint ctrl) {
+ Vector listeners = sidListSid.getListenersFromSid(sid);
+ listeners.remove(listener);
+ if(listeners.size()==0){
+ Service service = ctrl.serviceFromSid(sid);
+ if (service != null) {
+ boolean ok = ctrl.unsubscribe(service);
+ if (!ok) {
+ //TODO Log?
+ service.clearSID();
+ }
+ }
+ sidListSid.setAlreadyFirst(sid,false);
+ sidStateVars.remove(sid);
+ }
+ Vector sids = sidListSid.getSidsFromListener(listener);
+ sids.remove(sid);
+ if(sids.size()==0){
+ sidListSid.removeListenerKey(listener);
+ }
+ }
+
+ public synchronized void delSid(String sid) {
+ Vector listeners = sidListSid.getListenersFromSid(sid);
+ if(listeners==null)return;
+ for (int i = 0; i < listeners.size(); i++) {
+ Vector sids = sidListSid.getSidsFromListener((UPnPEventListener) listeners
+ .elementAt(i));
+ sids.remove(sid);
+ }
+ sidListSid.removeSidKey(sid);
+ }
+
+ public synchronized void clearAll(String sid, Service service) {
+ service.clearSID();
+ delSid(sid);
+ sidStateVars.remove(sid);
+ }
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/NotifierQueue.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/NotifierQueue.java
new file mode 100644
index 0000000..409e04c
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/NotifierQueue.java
@@ -0,0 +1,54 @@
+/*
+ * 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.basedriver.importer.core.event.structs;
+
+import java.util.Vector;
+
+/**
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class NotifierQueue {
+ private Vector queue;
+
+ public NotifierQueue(){
+ queue=new Vector();
+ }
+
+ public synchronized void enqueue(Object obj){
+ queue.add(obj);
+ if(queue.size() == 1){
+ notify();
+ }
+
+ }
+
+ public synchronized Object dequeue(){
+ while(queue.size()==0){
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ return queue.remove(0);
+ }
+
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/Sid2Listeners.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/Sid2Listeners.java
new file mode 100644
index 0000000..85ddfd3
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/Sid2Listeners.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.basedriver.importer.core.event.structs;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.osgi.service.upnp.UPnPEventListener;
+
+/**
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class Sid2Listeners {
+ private Hashtable sidListener;
+ private Hashtable alreadyfirst;
+
+ public Sid2Listeners() {
+ this.sidListener = new Hashtable();
+ this.alreadyfirst = new Hashtable();
+ }
+
+ public void put(String sid, UPnPEventListener listener) {
+ if (!sidListener.containsKey(sid)) {
+ Vector vec = new Vector();
+ vec.add(listener);
+ sidListener.put(sid, vec);
+ } else {
+ Vector vec = (Vector) sidListener.get(sid);
+ if (!vec.contains(listener)) {
+ vec.add(listener);
+ }
+ }
+ }
+
+ public final void remove(String sid) {
+ sidListener.remove(sid);
+ }
+
+ public final Vector get(String sid) {
+ return ((Vector) sidListener.get(sid));
+ }
+
+ /**
+ * @param sid
+ * @param dictionary
+ */
+ public boolean updateListeners(String sid, String deviceID,String serviceID, Dictionary dictionary) {
+
+ Vector listeners = (Vector) sidListener.get(sid);
+ if (listeners != null) {
+ for (int i = 0; i < listeners.size(); i++) {
+ UPnPEventListener listener = (UPnPEventListener) listeners.elementAt(i);
+ listener.notifyUPnPEvent(deviceID, serviceID, dictionary);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public boolean getAlreadyFirst(String sid) {
+ return ((Boolean) alreadyfirst.get(sid)).booleanValue();
+ }
+
+ public void setAlreadyFirst(String sid, boolean bool) {
+ alreadyfirst.put(sid, new Boolean(bool));
+ }
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/SidRenewer.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/SidRenewer.java
new file mode 100644
index 0000000..4525048
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/SidRenewer.java
@@ -0,0 +1,49 @@
+/*
+ * 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.basedriver.importer.core.event.structs;
+
+
+import java.util.Hashtable;
+
+import org.apache.felix.upnp.basedriver.importer.core.event.thread.Renewer;
+
+/**
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class SidRenewer {
+private Hashtable hash;
+
+ /**
+ * @param hash
+ */
+ public SidRenewer() {
+ super();
+ this.hash = new Hashtable();
+ }
+
+ public synchronized void put(String sid, Renewer renewer){
+ hash.put(sid,renewer);
+ }
+ public synchronized Renewer get(String sid){
+ return (Renewer)hash.get(sid);
+ }
+ public synchronized void remove(String sid){
+ hash.remove(sid);
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/SidsListenersMaps.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/SidsListenersMaps.java
new file mode 100644
index 0000000..3e47be2
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/SidsListenersMaps.java
@@ -0,0 +1,78 @@
+/*
+ * 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.basedriver.importer.core.event.structs;
+
+import java.util.Dictionary;
+import java.util.Vector;
+
+import org.osgi.service.upnp.UPnPEventListener;
+
+/**
+ * This class contain two table:
+ * - sid2listener: have SID of Suscribed Service as key and a Vector of UPnPEventListener as value
+ * - listener2sids: have an UPnPEventListener as kay and a Vector of SID of Scriscrobed Service
+ *
+ * @author Matteo "matted" Demuru
+ * @author Francesco Furfari
+ * @author Stefano "Kismet" Lenzi
+ *
+ *
+ */
+public class SidsListenersMaps {
+ private Sid2Listeners sid2Listeners;
+ private Listener2Sids listeners2Sids;
+
+ public SidsListenersMaps(){
+ sid2Listeners=new Sid2Listeners();
+ listeners2Sids=new Listener2Sids();
+ }
+
+
+ /////////////////// Sid to Listeners //////////////////////////////////
+ public final void putSid2Listeners(String sid, UPnPEventListener listener) {
+ sid2Listeners.put(sid,listener);
+ }
+ public final Vector getListenersFromSid(String sid) {
+ return sid2Listeners.get(sid);
+ }
+ public final void removeSidKey(String sid) {
+ sid2Listeners.remove(sid);
+ }
+ public final boolean updateListeners(String sid, String deviceID, String serviceID,Dictionary dictionary){
+ return sid2Listeners.updateListeners(sid,deviceID,serviceID,dictionary);
+ }
+ public final boolean getAlreadyFirst(String sid) {
+ return sid2Listeners.getAlreadyFirst(sid);
+ }
+ public final void setAlreadyFirst(String sid, boolean bool) {
+ sid2Listeners.setAlreadyFirst(sid,bool);
+ }
+
+
+
+ /////////////////// Listener to Sids //////////////////////////////////
+ public final void putListener2Sids(UPnPEventListener listener,String sid) {
+ listeners2Sids.put(listener,sid);
+ }
+ public final Vector getSidsFromListener(UPnPEventListener listener){
+ return listeners2Sids.get(listener);
+ }
+ public final void removeListenerKey(UPnPEventListener listener){
+ listeners2Sids.remove(listener);
+ }
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/StateVarsToNotify.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/StateVarsToNotify.java
new file mode 100644
index 0000000..e9ec10f
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/StateVarsToNotify.java
@@ -0,0 +1,67 @@
+/*
+ * 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.basedriver.importer.core.event.structs;
+
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+
+import org.apache.felix.upnp.basedriver.importer.core.event.message.StateChanged;
+
+/**
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class StateVarsToNotify {
+ private Dictionary stateVars;
+ private String sid;
+ private String deviceID;
+ private String serviceID;
+
+ //public StateVarsToNotify(String sid, String deviceID, String serviceID,Dictionary dic) {
+ public StateVarsToNotify(StateChanged msg) {
+ this.stateVars= msg.getDictionary();
+ this.sid = msg.getSid();
+ this.deviceID = msg.getDeviceID();
+ this.serviceID = msg.getServiceID();
+ }
+
+
+ public synchronized Dictionary getDictionary() {
+ return stateVars;
+ }
+ public synchronized String getSid() {
+ return sid;
+ }
+ public synchronized String getDeviceID() {
+ return deviceID;
+ }
+ public synchronized String getServiceID() {
+ return serviceID;
+ }
+
+
+ public void updateDic(Dictionary dic){
+ Enumeration e=dic.keys();
+ while(e.hasMoreElements()){
+ String varName=(String)e.nextElement();
+ Object varValue=dic.get(varName);
+ stateVars.put(varName,varValue);
+ }
+ }
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/SubscriptionQueue.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/SubscriptionQueue.java
new file mode 100644
index 0000000..4275f9e
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/structs/SubscriptionQueue.java
@@ -0,0 +1,53 @@
+/*
+ * 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.basedriver.importer.core.event.structs;
+
+import java.util.Vector;
+
+
+
+/**
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class SubscriptionQueue {
+ private Vector queue;
+
+ public SubscriptionQueue(){
+ queue=new Vector();
+ }
+ public synchronized void enqueue(Object obj){
+ queue.add(obj);
+ if(queue.size()==1){
+ notify();
+ }
+ }
+ public synchronized Object dequeue(){
+ while(queue.size()==0){
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ return queue.remove(0);
+ }
+
+
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/thread/Notifier.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/thread/Notifier.java
new file mode 100644
index 0000000..30ca333
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/thread/Notifier.java
@@ -0,0 +1,55 @@
+/*
+ * 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.basedriver.importer.core.event.thread;
+
+import org.apache.felix.upnp.basedriver.importer.core.event.message.StateChanged;
+import org.apache.felix.upnp.basedriver.importer.core.event.structs.Monitor;
+import org.apache.felix.upnp.basedriver.importer.core.event.structs.NotifierQueue;
+import org.apache.felix.upnp.basedriver.importer.core.event.structs.StateVarsToNotify;
+
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Stefano "kismet-sl" Lenzi
+ *
+ */
+public class Notifier extends Thread {
+
+ private NotifierQueue notifierQueue;
+ private Monitor monitor;
+
+ public Notifier(NotifierQueue notifierQueue,Monitor monitor) {
+ super("Notifier");
+ this.notifierQueue = notifierQueue;
+ this.monitor = monitor;
+
+ }
+
+ public void run() {
+ while (true) {
+ StateChanged msg = (StateChanged) notifierQueue.dequeue();
+ StateVarsToNotify vars = null;
+ if (msg.getSeq() == 0) {
+ vars = new StateVarsToNotify(msg);
+ monitor.putStateVars(msg.getSid(),vars);
+ } else {
+ monitor.updateStateVars(msg.getSid(),msg.getDictionary());
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/thread/Renewer.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/thread/Renewer.java
new file mode 100644
index 0000000..cf87bcf
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/thread/Renewer.java
@@ -0,0 +1,86 @@
+/*
+ * 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.basedriver.importer.core.event.thread;
+
+
+import org.cybergarage.upnp.Service;
+
+import org.apache.felix.upnp.basedriver.importer.core.MyCtrlPoint;
+import org.apache.felix.upnp.basedriver.importer.core.event.message.SidExipired;
+import org.apache.felix.upnp.basedriver.importer.core.event.structs.SubscriptionQueue;
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Stefano "kismet-sl" Lenzi
+ * @author Francesco Furfari
+ *
+ *
+ */
+public class Renewer extends Thread {
+ private long timeout;
+ private String sid;
+ private Service service;
+ private MyCtrlPoint ctrl;
+ private boolean bool;
+ private SubscriptionQueue subqueue;
+ private final long time_before_renew=60000;
+ /**
+ * *
+ *
+ * @param timeout
+ * @param sid
+ * @param service
+ */
+ public Renewer(long timeout, String sid, Service service,
+ MyCtrlPoint ctrl,SubscriptionQueue subqueue) {
+ super("ReNewal" + sid);
+ if (timeout - time_before_renew > 0) {
+ this.timeout = timeout - time_before_renew;
+ } else {
+ this.timeout = timeout;
+ }
+ this.sid = sid;
+ this.service = service;
+ this.ctrl = ctrl;
+ bool = true;
+ this.subqueue=subqueue;
+ }
+ public void run() {
+ while (bool) {
+ try {
+ sleep(timeout);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ boolean ok = ctrl.subscribe(service, sid, 180000);
+ if (ok) {//renew ok
+ if (service.getTimeout() - time_before_renew > 0) {
+ timeout = service.getTimeout() - time_before_renew;
+ } else {
+ timeout = service.getTimeout();
+ }
+ } else {//renew not ok
+ bool=false;
+ //System.out.println("morto renewer");
+ subqueue.enqueue(new SidExipired(sid,service));
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/thread/SubScriber.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/thread/SubScriber.java
new file mode 100644
index 0000000..ab36182
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/event/thread/SubScriber.java
@@ -0,0 +1,107 @@
+/*
+ * 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.basedriver.importer.core.event.thread;
+
+
+import org.cybergarage.upnp.Service;
+
+import org.osgi.service.log.LogService;
+
+import org.apache.felix.upnp.basedriver.Activator;
+import org.apache.felix.upnp.basedriver.importer.core.MyCtrlPoint;
+import org.apache.felix.upnp.basedriver.importer.core.event.message.FirstMessage;
+import org.apache.felix.upnp.basedriver.importer.core.event.message.ListenerModified;
+import org.apache.felix.upnp.basedriver.importer.core.event.message.ListenerUnRegistration;
+import org.apache.felix.upnp.basedriver.importer.core.event.message.SidExipired;
+import org.apache.felix.upnp.basedriver.importer.core.event.structs.Monitor;
+import org.apache.felix.upnp.basedriver.importer.core.event.structs.SubscriptionQueue;
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Stefano "kismet-sl" Lenzi
+ * @author Francesco Furfari
+ *
+ *
+ */
+public class SubScriber extends Thread {
+
+ private MyCtrlPoint ctrl;
+ private SubscriptionQueue subQueue;
+ private boolean stopCond = true;
+ //##renew private SidRenewer sidRenew;
+ private Monitor monitor;
+
+
+ public SubScriber(MyCtrlPoint ctrl, SubscriptionQueue subQueue, Monitor monitor) {
+ super("Subscriber");
+ this.ctrl = ctrl;
+ this.subQueue = subQueue;
+ this.monitor=monitor;
+ //##renew this.sidRenew = new SidRenewer();
+
+ }
+
+ public void run() {
+ while (stopCond) {
+ Object msg = subQueue.dequeue();
+ if (msg instanceof FirstMessage) {
+ FirstMessage firstmsg = (FirstMessage) msg;
+ Service service = firstmsg.getService();
+ if (!service.isSubscribed()) {//is not subscribe
+ boolean ok = ctrl.subscribe(service,120000);
+ String sid = "";
+ if (ok) {//subcribe ok
+
+ sid = service.getSID();
+ firstmsg.setSid(sid);
+ // ########### Renew ########################
+// ##renew Renewer renewer = new Renewer((service.getTimeout()),
+// ##renew sid, service, ctrl, subQueue);
+// ##renew sidRenew.put(sid, renewer);
+// ##renew renewer.start();
+ // ########### Renew ########################
+ //StateVarsToNotify vars=monitor.getStateVars(sid);
+
+ monitor.addListener(sid,firstmsg.getListener());
+ } else {//subscribe not ok
+ Activator.logger.log(LogService.LOG_ERROR,"Sucribe failed");
+ }
+ } else {// already subscribe
+ monitor.addListener(service.getSID(),firstmsg.getListener());
+ }
+ } else if (msg instanceof ListenerModified) {
+ // ########### Renew ########################
+ monitor.updateListener((ListenerModified)msg,subQueue,ctrl/*##renew ,sidRenew*/);
+ // ########### Renew ########################
+ } else if (msg instanceof ListenerUnRegistration) {
+ ListenerUnRegistration unreg=(ListenerUnRegistration)msg;
+ // ########### Renew ########################
+ monitor.delListener(unreg.getListener(),ctrl/*##renew,sidRenew*/);
+ // ########### Renew ########################
+ } else if(msg instanceof SidExipired){
+ Activator.logger.WARNING("[Importer] Please report the bug.Used code - should be checked and removed");
+ /*
+ Activator.logger.INFO("Removing Expired Subscribe Service");
+ SidExipired sidExpired=(SidExipired)msg;
+ monitor.clearAll(sidExpired.getSid(),sidExpired.getService());
+ */
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPActionImpl.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPActionImpl.java
new file mode 100644
index 0000000..7f82fa4
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPActionImpl.java
@@ -0,0 +1,188 @@
+/*
+ * 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.basedriver.importer.core.upnp;
+
+
+import java.util.Dictionary;
+import java.util.Properties;
+
+import org.cybergarage.upnp.Action;
+import org.cybergarage.upnp.Argument;
+import org.cybergarage.upnp.ArgumentList;
+import org.cybergarage.upnp.UPnPStatus;
+
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+import org.apache.felix.upnp.extra.util.Converter;
+import org.apache.felix.upnp.extra.util.UPnPException;
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Stefanoi "kismet-sl" Lenzi
+ *
+ */
+public class UPnPActionImpl implements UPnPAction {
+
+ private Action act;
+ private UPnPServiceImpl actsFather;
+ /**
+ * @param act
+ */
+ public UPnPActionImpl(Action act,UPnPServiceImpl ser) {
+ // TODO to check
+ this.act=act;
+ actsFather=ser;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getName()
+ */
+ public String getName() {
+ // TODO to check
+ return act.getName();
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getReturnArgumentName()
+ */
+ public String getReturnArgumentName() {
+ /* TODO da discutere .. perche' mi dovrei riparsare l'xml
+ */
+
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getInputArgumentNames()
+ */
+ public String[] getInputArgumentNames() {
+ // TODO to check
+ ArgumentList argsList=act.getInputArgumentList();
+ if(argsList.size()==0){
+ return null;
+ }
+ String [] inputArgs=new String[argsList.size()];
+ for(int i=0;i<argsList.size();i++){
+ inputArgs[i]=argsList.getArgument(i).getName();
+ }
+ return inputArgs;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getOutputArgumentNames()
+ */
+ public String[] getOutputArgumentNames() {
+ // TODO to check
+ ArgumentList argsList=act.getOutputArgumentList();
+ if(argsList.size()==0){
+ return null;
+ }
+ String [] outArgs=new String[argsList.size()];
+ for(int i=0;i<argsList.size();i++){
+ outArgs[i]=argsList.getArgument(i).getName();
+ }
+ return outArgs;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#getStateVariable(java.lang.String)
+ */
+ public UPnPStateVariable getStateVariable(String argumentName) {
+ /*TODO controllare se non e'
+ troppo brutto il modo di ottenere
+ la UPnPStateVariable
+
+ check if the way to obtain the UPnPStateVariabile is not too bad
+
+ */
+ Argument arg=act.getArgument(argumentName);
+ if(arg==null){
+ return null;
+ }
+ String varName=arg.getRelatedStateVariableName();
+ return actsFather.getStateVariable(varName);
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPAction#invoke(java.util.Dictionary)
+ */
+ public Dictionary invoke(Dictionary args) throws Exception {
+ /*TODO da controllare se ho capito bene quello che
+ richiedeva il metodo
+
+ check if I have understood wath this method should do
+ */
+ /*
+ * mi ricavo gli argomenti e i valori
+ * e gli inserisco in un ArgumentList
+ *
+ * I look for argument and value and then I add them to ArgumentList
+ */
+ ArgumentList argsList=new ArgumentList();
+ argsList= act.getInputArgumentList();
+
+ for(int i=0;i<argsList.size();i++){
+ /*
+ TODO assumo che .getArgument(i) mi dia un Argument con solo il nome e non il valore
+ che sara' cio che ci mettero' io
+ e assumo anche che siano ordinati
+
+ * I assert that .getArgument(i) will return to me an Argument with only the name of the
+ * Argument and not it's value. I'll set the associated value by myself and
+ * Also I assert that the Argument are ordered
+ */
+ Argument argument=argsList.getArgument(i);
+ String argumentName=argument.getName();
+ //String relateVar=argument.getRelatedStateVariableName();
+ UPnPStateVariable stateVar=this.getStateVariable(argumentName);
+ String upnpType=stateVar.getUPnPDataType();
+ /*Class javaClass=stateVar.getJavaDataType();*/
+ //setto il valore dell'argomento di input
+ //setting the value related to the input argument
+ argument.setValue(Converter.toString(args.get(argumentName),upnpType));
+ }
+ act.setArgumentValues(argsList);
+ if(act.postControlAction()==true){
+ //TODO controllare cosa succede se non ho argomenti di out
+ //TODO check what happen if I don't have any output argument
+ Properties outDic=new Properties();
+ ArgumentList outArgs=act.getOutputArgumentList();
+ if(outArgs.size()==0){
+ return null;
+ }
+ for(int i=0;i<outArgs.size();i++){
+ Argument argument=outArgs.getArgument(i);
+ String argumentName=outArgs.getArgument(i).getName();
+ //String relateVar=argument.getRelatedStateVariableName();
+ UPnPStateVariable stateVar=getStateVariable(argumentName);
+ //String javaType=stateVar.getJavaDataType().getName();
+ //TODO ricordarsi di catchare nunber exception
+ //TODO rember to catch number exception
+ String upnpType=stateVar.getUPnPDataType();
+ outDic.put(argumentName,Converter.parseString(argument.getValue(),upnpType));
+ }
+ return outDic;
+ }else{
+ UPnPStatus controlStatus = act.getControlStatus();
+ throw new UPnPException(controlStatus.getCode(),controlStatus.getDescription());
+ }
+
+ }
+
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPDeviceImpl.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPDeviceImpl.java
new file mode 100644
index 0000000..f877dc3
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPDeviceImpl.java
@@ -0,0 +1,146 @@
+/*
+ * 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.basedriver.importer.core.upnp;
+
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.cybergarage.upnp.Device;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPIcon;
+import org.osgi.service.upnp.UPnPService;
+
+import org.apache.felix.upnp.basedriver.importer.util.DeviceSetup;
+import org.apache.felix.upnp.basedriver.importer.util.DictionaryProp;
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Stefanoi "kismet-sl" Lenzi
+ *
+ */
+public class UPnPDeviceImpl implements UPnPDevice {
+
+ /**
+ * <code>properties</code> Dictionary that contains Device properties
+ */
+ private DictionaryProp properties;
+ private Vector icons;
+ private Hashtable services;
+ /**
+ * @param dev
+ * Device the cyberLink Device used to rappresent the real UPnP
+ * Device
+ */
+ public UPnPDeviceImpl(Device dev, BundleContext context) {
+ properties = new DictionaryProp();
+ this.services=new Hashtable();
+ this.icons=new Vector();
+ DeviceSetup.deviceSetup(properties,dev,icons,services);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPDevice#getService(java.lang.String)
+ */
+ public UPnPService getService(String serviceId) {
+ return (UPnPServiceImpl) services.get(serviceId);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPDevice#getServices()
+ */
+ public UPnPService[] getServices() {
+ Enumeration e = services.elements();
+ if (e == null) {
+ //TODO restituisco null o un array vuoto null l'ho letto nella specifica
+ //TODO should I return null or an empty array? The specification seems to said to return null
+ return null;
+ }
+ UPnPService[] uPnPser = new UPnPService[services.size()];
+ int i = 0;
+ while (e.hasMoreElements()) {
+ uPnPser[i] = (UPnPServiceImpl) e.nextElement();
+ i++;
+ }
+ return uPnPser;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPDevice#getIcons(java.lang.String)
+ */
+ public UPnPIcon[] getIcons(String locale) {
+ if (locale != null) {
+ return null;
+ }
+ if(icons.size()==0){
+ return null;
+ }
+ return (UPnPIcon[]) icons.toArray(new UPnPIcon[]{});
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPDevice#getDescriptions(java.lang.String)
+ */
+
+ public Dictionary getDescriptions(String locale) {
+ //TODO Sent the right localized version of Description if are available
+ if (locale != null) {
+ return null;
+ }
+ return properties;
+ }
+
+ /**
+ * @param serviceType
+ * @return true if device contains the serviceType
+ */
+ public boolean existServiceType(String serviceType) {
+ String[] services = (String[]) properties.get(UPnPService.TYPE);
+ if (services != null) {
+ for (int i = 0; i < services.length; i++) {
+ if (services[i].equals(serviceType)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @param property
+ * @param obj
+ */
+ public void setProperty(String property, Object obj) {
+ properties.remove(property);
+ properties.put(property, obj);
+
+ }
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPIconImpl.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPIconImpl.java
new file mode 100644
index 0000000..24248ff
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPIconImpl.java
@@ -0,0 +1,111 @@
+/*
+ * 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.basedriver.importer.core.upnp;
+
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.cybergarage.upnp.Icon;
+
+import org.osgi.service.upnp.UPnPIcon;
+
+import org.apache.felix.upnp.basedriver.importer.util.HTTPRequestForIcon;
+import org.apache.felix.upnp.basedriver.importer.util.ParseLocation;
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Stefanoi "kismet-sl" Lenzi
+ *
+ */
+public class UPnPIconImpl implements UPnPIcon {
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getMimeType()
+ */
+ private Icon icon;
+ private org.cybergarage.upnp.Device cyberdev;
+ public UPnPIconImpl(Icon cybericon,org.cybergarage.upnp.Device cyberdev){
+ this.icon=cybericon;
+ this.cyberdev=cyberdev;
+ }
+ public String getMimeType() {
+ // TODO to check
+ return icon.getMimeType();
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getWidth()
+ */
+ public int getWidth() {
+ // TODO se parso una stringa vuota che succede ? da eccezione?penso di si
+ //TODO what happen if the String is empty? do I get an Exception? I think so
+ String width=icon.getWidth();
+ if(width.length()==0){
+ return -1;
+ }
+ return Integer.parseInt(width);
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getHeight()
+ */
+ public int getHeight() {
+ // TODO Auto-generated method stub
+ String higth=icon.getHeight();
+ if(higth.length()==0){
+ return -1;
+ }
+ return Integer.parseInt(higth);
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getSize()
+ */
+ public int getSize() {
+ // TODO Auto-generated method stub
+ return -1;
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getDepth()
+ */
+ public int getDepth() {
+ // TODO Auto-generated method stub
+ String depth=icon.getDepth();
+ if(depth.length()==0){
+ return -1;
+ }
+ return Integer.parseInt(depth);
+ }
+
+ /* (non-Javadoc)
+ * @see org.osgi.service.upnp.UPnPIcon#getInputStream()
+ */
+ public InputStream getInputStream() throws IOException {
+ // TODO Auto-generated method stub
+
+ String urlString=ParseLocation.getUrlBase(cyberdev.getLocation())+icon.getURL();
+ URL url=new URL(urlString);
+ HTTPRequestForIcon requestor=new HTTPRequestForIcon(url);
+
+ return requestor.getInputStream();
+ }
+
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPServiceImpl.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPServiceImpl.java
new file mode 100644
index 0000000..d7c46f7
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPServiceImpl.java
@@ -0,0 +1,164 @@
+/*
+ * 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.basedriver.importer.core.upnp;
+
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import org.cybergarage.upnp.Action;
+import org.cybergarage.upnp.ActionList;
+import org.cybergarage.upnp.Service;
+import org.cybergarage.upnp.ServiceStateTable;
+import org.cybergarage.upnp.StateVariable;
+
+import org.osgi.service.upnp.UPnPAction;
+import org.osgi.service.upnp.UPnPService;
+import org.osgi.service.upnp.UPnPStateVariable;
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Stefanoi "kismet-sl" Lenzi
+ *
+ */
+public class UPnPServiceImpl implements UPnPService {
+ private Service service;
+ private Hashtable actions;
+ private Hashtable stateVariables;
+
+ public UPnPServiceImpl(Service service) {
+ this.service = service;
+ actions = new Hashtable();
+ stateVariables=new Hashtable();
+ /*
+ * azioni
+ * action
+ */
+ ActionList actionlist = service.getActionList();
+ for (int i = 0; i < actionlist.size(); i++) {
+ Action act = actionlist.getAction(i);
+ actions.put(act.getName(), new UPnPActionImpl(act,this));
+ }
+ /*StateVariable*/
+ ServiceStateTable stateTable=service.getServiceStateTable();
+ for(int i=0;i<stateTable.size();i++){
+ StateVariable var= stateTable.getStateVariable(i);
+ stateVariables.put(var.getName(),new UPnPStateVariableImpl(var));
+ }
+
+
+ } /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPService#getId()
+ */
+ public String getId() {
+ // TODO Auto-generated method stub
+ return service.getServiceID();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPService#getType()
+ */
+ public String getType() {
+ // TODO Auto-generated method stub
+ return service.getServiceType();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPService#getVersion()
+ */
+ public String getVersion() {
+ // TODO da controllare si puo' migliorare lastindexof
+ //TODO to check can I speed up this? May be using lastIndexOf
+ String [] splited=service.getServiceType().split(":");
+ return splited[splited.length-1];
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPService#getAction(java.lang.String)
+ */
+ public UPnPAction getAction(String name) {
+ // TODO da controllare
+ //TODO to check
+ return (UPnPAction) actions.get(name);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPService#getActions()
+ */
+ public UPnPAction[] getActions() {
+ // TODO ricontrollare
+ //TODO check again
+ Enumeration e=actions.elements();
+ if(e==null){
+ return null;
+ }
+ UPnPAction [] uPnPacts=new UPnPAction[actions.size()];
+ int i=0;
+ while(e.hasMoreElements()){
+ uPnPacts[i]=(UPnPActionImpl)e.nextElement();
+ i++;
+ }
+ return uPnPacts;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPService#getStateVariables()
+ */
+ public UPnPStateVariable[] getStateVariables() {
+ // TODO ricontrollare
+ //TODO check again
+ UPnPStateVariableImpl [] vars =new UPnPStateVariableImpl[stateVariables.size()];
+ Enumeration e=stateVariables.elements();
+ if(e==null){
+ return null;
+ }
+ int i=0;
+ while(e.hasMoreElements()){
+ vars[i]=(UPnPStateVariableImpl)e.nextElement();
+ i++;
+ }
+ return vars;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPService#getStateVariable(java.lang.String)
+ */
+ public UPnPStateVariable getStateVariable(String name) {
+ // TODO ricontrollare
+ //TODO chack again
+ return (UPnPStateVariableImpl) stateVariables.get(name);
+ }
+
+ public Service getCyberService(){
+ return service;
+ }
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPStateVariableImpl.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPStateVariableImpl.java
new file mode 100644
index 0000000..55577b0
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPStateVariableImpl.java
@@ -0,0 +1,242 @@
+/*
+ * 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.basedriver.importer.core.upnp;
+
+
+import java.util.Date;
+import java.util.Hashtable;
+
+import org.cybergarage.upnp.AllowedValueList;
+import org.cybergarage.upnp.AllowedValueRange;
+import org.cybergarage.upnp.StateVariable;
+
+import org.osgi.service.upnp.UPnPStateVariable;
+
+import org.apache.felix.upnp.extra.util.Converter;
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Stefanoi "kismet-sl" Lenzi
+ *
+ */
+public class UPnPStateVariableImpl implements UPnPStateVariable {
+
+ private StateVariable variable;
+ private static Hashtable upnp2javaTable = null;
+
+ static{
+ upnp2javaTable = new Hashtable(30);
+ String[] upnpType = null;
+ upnpType = new String[]{"ui1","ui2","i1","i2","i4","int"};
+ for (int i = 0; i < upnpType.length; i++) {
+ upnp2javaTable.put(upnpType[i],Integer.class);
+ }
+
+ upnpType = new String[]{"ui4","time","time.tz"};
+ for (int i = 0; i < upnpType.length; i++) {
+ upnp2javaTable.put(upnpType[i],Long.class);
+ }
+
+ upnpType = new String[]{"r4","float"};
+ for (int i = 0; i < upnpType.length; i++) {
+ upnp2javaTable.put(upnpType[i],Float.class);
+ }
+
+ upnpType = new String[]{"r8","number","fixed.14.4"};
+ for (int i = 0; i < upnpType.length; i++) {
+ upnp2javaTable.put(upnpType[i],Double.class);
+ }
+
+ upnpType = new String[]{"char"};
+ for (int i = 0; i < upnpType.length; i++) {
+ upnp2javaTable.put(upnpType[i],Character.class);
+ }
+
+ upnpType = new String[]{"string","uri","uuid"};
+ for (int i = 0; i < upnpType.length; i++) {
+ upnp2javaTable.put(upnpType[i],String.class);
+ }
+
+ upnpType = new String[]{"date","dateTime","dateTime.tz"};
+ for (int i = 0; i < upnpType.length; i++) {
+ upnp2javaTable.put(upnpType[i],Date.class);
+ }
+
+ upnpType = new String[]{"boolean"};
+ for (int i = 0; i < upnpType.length; i++) {
+ upnp2javaTable.put(upnpType[i],Boolean.class);
+ }
+
+ upnpType = new String[]{"bin.base64","bin.hex"};
+ for (int i = 0; i < upnpType.length; i++) {
+ upnp2javaTable.put(upnpType[i],byte[].class);
+ }
+
+
+ }
+
+ /**
+ * @param variable
+ */
+ public UPnPStateVariableImpl(StateVariable variable) {
+
+ this.variable = variable;
+ } /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPStateVariable#getName()
+ */
+
+ public String getName() {
+ return variable.getName();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPStateVariable#getJavaDataType()
+ */
+ public Class getJavaDataType() {
+ return (Class) upnp2javaTable.get(variable.getDataType());
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPStateVariable#getUPnPDataType()
+ */
+ public String getUPnPDataType() {
+ return variable.getDataType();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPStateVariable#getDefaultValue()
+ */
+ public Object getDefaultValue() {
+ //TODO da implementare da zero.. e' raccommended ..
+ //TODO must be implemented from scretch, it's just raccommend
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPStateVariable#getAllowedValues()
+ */
+ public String[] getAllowedValues() {
+ if (variable.getDataType().equals("string")) {
+ AllowedValueList allowedvalue = variable.getAllowedValueList();
+ if (allowedvalue == null) return null;
+ if(allowedvalue.size()==0){
+ return null;
+ }
+ String[] values = new String[allowedvalue.size()];
+ for (int i = 0; i < allowedvalue.size(); i++) {
+ values[i] = allowedvalue.getAllowedValue(i).getValue();
+ }
+ return values;
+ }
+
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMinimum()
+ */
+ public Number getMinimum() {
+ // TODO stessa cosa get maximum
+ //TODO the same thing for getMaximum
+ AllowedValueRange allowedValueRange = variable.getAllowedValueRange();
+ if(allowedValueRange==null){
+ return null;
+ }
+ String min=allowedValueRange.getMinimum();
+ //francesco 22/10/2005
+ if (min.equals("")) return null;
+ try {
+ return (Number)Converter.parseString(min,getUPnPDataType());
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPStateVariable#getMaximum()
+ */
+ public Number getMaximum() {
+ // TODO suppongo che le invochino con cognizione di causa ??
+ //TODO I think that this method will be invoked from people that know what is doing
+ AllowedValueRange allowedValueRange = variable.getAllowedValueRange();
+ if(allowedValueRange==null){
+ return null;
+ }
+ String max = allowedValueRange.getMaximum();
+ //francesco 22/10/2005
+ if (max.equals("")) return null;
+ try {
+ return (Number)Converter.parseString(max,getUPnPDataType());
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPStateVariable#getStep()
+ */
+ public Number getStep() {
+ // TODO stssa cosa di getmaximum
+ //TODO same things of getMaxium
+ AllowedValueRange allowedValueRange = variable.getAllowedValueRange();
+ if(allowedValueRange==null){
+ return null;
+ }
+ String step = allowedValueRange.getStep();
+ //francesco 22/10/2005
+ if (step.equals("")) return null;
+ try {
+ return (Number)Converter.parseString(step,getUPnPDataType());
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.service.upnp.UPnPStateVariable#sendsEvents()
+ */
+ public boolean sendsEvents() {
+ return variable.isSendEvents();
+ }
+
+
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/DeviceSetup.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/DeviceSetup.java
new file mode 100644
index 0000000..0f6ad24
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/DeviceSetup.java
@@ -0,0 +1,146 @@
+/*
+ * 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.basedriver.importer.util;
+
+
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.cybergarage.upnp.Device;
+import org.cybergarage.upnp.DeviceList;
+import org.cybergarage.upnp.IconList;
+import org.cybergarage.upnp.Service;
+import org.cybergarage.upnp.ServiceList;
+
+import org.osgi.service.upnp.UPnPDevice;
+import org.osgi.service.upnp.UPnPIcon;
+import org.osgi.service.upnp.UPnPService;
+
+import org.apache.felix.upnp.basedriver.importer.core.upnp.UPnPIconImpl;
+import org.apache.felix.upnp.basedriver.importer.core.upnp.UPnPServiceImpl;
+import org.apache.felix.upnp.extra.util.Constants;
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Stefano "Kismet" Lenzi
+ *
+ */
+public class DeviceSetup {
+
+ public static void deviceSetup(DictionaryProp properties, Device dev,Vector icons,Hashtable services) {
+ //TODO se non ho device ho una devlist con zero elementi
+ //TODO if I don't have any device, the size of devlist is 0
+ DeviceList devList = dev.getDeviceList();
+ /* childrenUDN property */
+ if (devList.size() > 0) {
+ String[] childrenUDN = new String[devList.size()];
+ for (int i = 0; i < devList.size(); i++) {
+ childrenUDN[i] = devList.getDevice(i).getUDN();
+ }
+ properties.put(UPnPDevice.CHILDREN_UDN, childrenUDN);
+ }
+ /* DEVICE CATEGORY */
+ properties.put(
+ org.osgi.service
+ .device.Constants.DEVICE_CATEGORY,
+ new String[]{UPnPDevice.DEVICE_CATEGORY}
+ );
+
+ /*UPNP_IMPORT*/
+ properties.put(Constants.UPNP_IMPORT, "http://domoware.isti.cnr.it");
+
+ /* FRIENDLY_NAME */
+ //TODO controllato in metodo getFriendlyName se non esiste il frinedly mi restituisce una stringa vuota
+ //check the implementation fo getFriendlyName made by CyberLink
+ properties.put(UPnPDevice.FRIENDLY_NAME, dev.getFriendlyName());
+ /* MANUFACTURER */
+ properties.put(UPnPDevice.MANUFACTURER, dev.getManufacture());
+ /* MANUFACTURER_URL */
+ properties.put(UPnPDevice.MANUFACTURER_URL, dev.getManufactureURL());
+ /* MODEL_DESCRIPTION */
+ properties.put(UPnPDevice.MODEL_DESCRIPTION, dev.getModelDescription());
+ /* MODEL_NAME */
+ properties.put(UPnPDevice.MODEL_NAME, dev.getModelName());
+ /* MODEL_NUMBER */
+ properties.put(UPnPDevice.MODEL_NUMBER, dev.getModelNumber());
+ /* MODEL_URL */
+ properties.put(UPnPDevice.MODEL_URL, dev.getModelURL());
+ /* PARENT_UDN */
+ if (!dev.isRootDevice()) {
+ Device parent = dev.getParentDevice();
+ /*Device root = dev.getRootDevice();
+ if (root == null) {
+ System.out.println("il device " + dev.getFriendlyName()
+ + "non ha root !!!");
+ }*/
+ properties.put(UPnPDevice.PARENT_UDN, parent.getUDN());
+ }
+ /* PRESENTATION_URL */
+ properties.put(UPnPDevice.PRESENTATION_URL, dev.getPresentationURL());
+ /* SERIAL_NUMBER */
+ properties.put(UPnPDevice.SERIAL_NUMBER, dev.getSerialNumber());
+ /* TYPE */
+ properties.put(UPnPDevice.TYPE, dev.getDeviceType());
+ /* UDN */
+ properties.put(UPnPDevice.UDN, dev.getUDN());
+ /* UPC */
+ properties.put(UPnPDevice.UPC, dev.getUPC());
+
+ IconList iconsList = dev.getIconList();
+ if (iconsList.size() != 0) {
+ for (int i = 0; i < iconsList.size(); i++) {
+ UPnPIcon icon = new UPnPIconImpl(iconsList.getIcon(i),dev);
+ icons.add(icon);
+ }
+ }
+ /*
+ * servizi del device
+ * service of this device
+ */
+ ServiceList serviceList = dev.getServiceList();//ok mi restituisce una
+ // service list con zero
+ // elementi
+ /*
+ * if dev contain no service I'll get an empty SserviceList object
+ */
+ String[] servicesIDProperty = new String[serviceList.size()];
+ String[] servicesTypeProperty;
+ HashSet serTypeSet = new HashSet();
+ for (int i = 0; i < serviceList.size(); i++) {
+ Service service = serviceList.getService(i);
+ UPnPServiceImpl serviceImpl = new UPnPServiceImpl(service);
+ services.put(service.getServiceID(), serviceImpl);
+ servicesIDProperty[i] = serviceImpl.getId();
+ serTypeSet.add(serviceImpl.getType());
+ }
+ servicesTypeProperty = new String[serTypeSet.size()];
+ Iterator iter = serTypeSet.iterator();
+ int i = 0;
+ while (iter.hasNext()) {
+ servicesTypeProperty[i] = (String) iter.next();
+ i++;
+ }
+ properties.put(UPnPService.ID, servicesIDProperty);
+ properties.put(UPnPService.TYPE, servicesTypeProperty);
+
+
+ }
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/DictionaryProp.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/DictionaryProp.java
new file mode 100644
index 0000000..f3e8af0
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/DictionaryProp.java
@@ -0,0 +1,123 @@
+/*
+ * 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.basedriver.importer.util;
+
+import java.util.*;
+
+/**
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class DictionaryProp extends Dictionary {
+ private Hashtable hash=null;
+ /* (non-Javadoc)
+ * @see java.util.Dictionary#size()
+ */
+
+ public DictionaryProp(){
+ hash=new Hashtable();
+ }
+
+ public int size() {
+ // TODO Auto-generated method stub
+ return hash.size();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Dictionary#isEmpty()
+ */
+ public boolean isEmpty() {
+ // TODO Auto-generated method stub
+ return hash.isEmpty();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Dictionary#elements()
+ */
+ public Enumeration elements() {
+ // TODO Auto-generated method stub
+ return hash.elements();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Dictionary#keys()
+ */
+ public Enumeration keys() {
+ // TODO Auto-generated method stub
+ return hash.keys();
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Dictionary#get(java.lang.Object)
+ */
+ public Object get(Object key) {
+ // TODO Auto-generated method stub
+ String s=((String)key).toLowerCase();
+ return hash.get(s);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Dictionary#remove(java.lang.Object)
+ */
+ public Object remove(Object arg0) {
+ // TODO Auto-generated method stub
+ String s=((String)arg0).toLowerCase();
+ return hash.remove(s);
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Dictionary#put(java.lang.Object, java.lang.Object)
+ */
+ public Object put(Object arg0, Object arg1) {
+ // TODO Auto-generated method stub
+ String s=((String)arg0).toLowerCase();
+ return hash.put(s,arg1);
+ }
+
+ /**
+ * @param key
+ * @return
+ */
+ public boolean containsKey(Object key) {
+ //String s=((String)key).toLowerCase();
+ return hash.containsKey(key);
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer("");
+ Enumeration e = keys();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ sb.append(key).append(" = ");
+ if(get(key) instanceof String[]){
+ String[] aux = (String[]) get(key);
+ sb.append("[");
+ for (int i = 0; i < aux.length-1; i++) {
+ sb.append(aux[i]).append(",");
+ }
+ if(aux.length>0)
+ sb.append(aux[aux.length-1]);
+ sb.append("]");
+ }else{
+ sb.append(get(key).toString());
+ }
+ sb.append("\n");
+ }
+ return sb.toString();
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/HTTPRequestForIcon.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/HTTPRequestForIcon.java
new file mode 100644
index 0000000..dd19673
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/HTTPRequestForIcon.java
@@ -0,0 +1,98 @@
+/*
+ * 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.basedriver.importer.util;
+
+import java.io.*;
+import java.net.*;
+
+/**
+ * @author Matteo "matted" Demuru
+ * @author Stefanoi "kismet-sl" Lenzi
+ *
+ *
+ * TODO To change the template for this generated type comment go to Window -
+ * Preferences - Java - Code Style - Code Templates
+ */
+public class HTTPRequestForIcon {
+ private URL url;
+
+ public HTTPRequestForIcon(URL url) {
+ this.url = url;
+ }
+ public InputStream getInputStream() throws IOException {
+ //TODO da discutere
+ //TODO we should speak about that
+ InetAddress inet = InetAddress.getByName(url.getHost());
+ int port = url.getPort();
+ Socket socket = null;
+ socket = new Socket(inet, port);
+ OutputStream out = null;
+ out = socket.getOutputStream();
+ String CRLF = "\r\n";
+ url.getFile();
+ String request = "GET " + url.getPath() + " " + "HTTP/1.1" + CRLF
+ + "Host: " + url.getHost() + CRLF + "Connection: " + "close"
+ + CRLF + CRLF;
+ //System.out.println(request);
+ byte[] get = request.getBytes();
+ out.write(get, 0, get.length);
+ InputStream in = socket.getInputStream();
+ boolean exit = true;
+ while (exit) {
+ byte[] b = new byte[1];
+ in.read(b, 0, b.length);
+
+ if (b[0] == '\r') {
+ in.read(b, 0, b.length);
+ while (b[0] == '\r') {
+ in.read(b, 0, b.length);
+ }
+ if (b[0] != '\n') {
+ continue;
+ }
+ in.read(b, 0, b.length);
+ if (b[0] != '\r') {
+ continue;
+ }
+ in.read(b, 0, b.length);
+ if (b[0] != '\n') {
+ continue;
+ }
+ exit = false;
+ }
+ }
+
+ return in;
+
+ /*
+ * utilizzando la classe di satoshi HTTPResponse response=new
+ * HTTPResponse(in); InputStream
+ * iconInStream=response.getContentInputStream(); return iconInStream;
+ *
+ */
+ /*
+ *
+ * byte[] buff = new byte[maxLength]; int initial = 0; while (initial <
+ * maxLength - 1) { int read = 0; read = in.read(buff, initial, 1024);
+ * if (read == -1) break; initial += read; } System.out.println(new
+ * String(buff));
+ */
+
+ }
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/ParseLocation.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/ParseLocation.java
new file mode 100644
index 0000000..a401090
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/ParseLocation.java
@@ -0,0 +1,30 @@
+/*
+ * 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.basedriver.importer.util;
+
+/**
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class ParseLocation {
+ public static String getUrlBase(String location){
+ //http://148.12.14.144:65888/
+ String [] splited=location.split("/");
+ return splited[0]+"/"+"/"+splited[2];
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/ParseUSN.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/ParseUSN.java
new file mode 100644
index 0000000..511abff
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/util/ParseUSN.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.basedriver.importer.util;
+
+/**
+ * @author Matteo "matted" Demuru
+ *
+ */
+public class ParseUSN {
+ boolean service;
+ boolean device;
+ String udn;
+ String serviceType;
+
+ public ParseUSN(String usn) {
+ String [] splited=usn.split(":");
+ if(splited.length==5||splited.length==2){
+ udn="uuid:"+splited[1];
+ device=true;
+ service=false;
+ }else if(splited.length==8){
+ udn="uuid:"+splited[1];
+ if(splited[5].equals("device")){
+ device=true;
+ service=false;
+ }else{
+ serviceType=splited[3]+":"+splited[4]+":"+splited[5]+":"+splited[6]+":"+splited[7];
+ device=false;
+ service=true;
+ }
+ }
+ }
+
+ public boolean isService() {
+ return service;
+ }
+ public boolean isDevice() {
+ return device;
+ }
+ public String getUDN() {
+ return udn;
+ }
+ public String getServiceType() {
+ return serviceType;
+ }
+
+}
\ No newline at end of file
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/tool/Logger.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/tool/Logger.java
new file mode 100644
index 0000000..f253dfc
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/tool/Logger.java
@@ -0,0 +1,255 @@
+/*
+ * 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.basedriver.tool;
+
+import java.io.PrintStream;
+
+import org.cybergarage.util.Debug;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+import org.apache.felix.upnp.basedriver.Activator;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ * @author Francesco Furfari
+ *
+ */
+public class Logger implements ServiceListener {
+
+ private ServiceReference rls;
+ private LogService osgiLogService;
+ private int level;
+ private PrintStream out;
+ public final static String NEWLINE = System.getProperty("line.separator");
+ public static final String ROW ="\n================REQUEST=====================\n";
+ public static final String END_ROW ="--------------------------------------------";
+
+ private final static String LEVEL_TO_STRING[] = new String[]{
+ "",
+ "ERROR [ " + Activator.bc.getBundle().getBundleId() + " ] ",
+ "WARNING [ " + Activator.bc.getBundle().getBundleId() + " ] ",
+ "INFO [ " + Activator.bc.getBundle().getBundleId() + " ] ",
+ "DEBUG [ " + Activator.bc.getBundle().getBundleId() + " ] ",
+ };
+
+
+ /**
+ * Create a Logger with <code>System.out</code> as <tt>PrintStream</tt> and without
+ * reporting message on both <tt>PrintStream</tt> and <tt>LogService</tt>
+ *
+ * @param log <tt>ServiceReference</tt> to the <tt>LogService</tt> to use,
+ * or null to avoid the use of this service
+ *
+ * @see #Logger(LogService, PrintStream, boolean)
+ */
+ public Logger(String levelStr){
+ this.out = System.out;
+ try {
+ this.level = Integer.parseInt(levelStr);
+ } catch (Exception ex){
+ out.println("WARNING [UPnPBaseDriver Log]: " + levelStr+" is not a valid value!");
+ this.level=2;
+ }
+ findService();
+ }
+
+ public void setCyberDebug(String value){
+ try {
+ if (Boolean.valueOf(value).booleanValue()){
+ Debug.on();
+ out.println("INFO [UPnPBaseDriver] Started CyberLink Debug");
+ }
+ } catch (Exception ex){
+ out.println("WARNING [UPnPBaseDriver CyberLog]: " + value +" is not a valid value!");
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////// programmatic interface ////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////////
+
+ public void setLogLevel(int level){
+ if (level < 0 || level >4 ) throw new IllegalArgumentException("Log Level must be [0-4]");
+ this.level = level;
+ }
+
+ public int getLogLevel(){
+ return this.level;
+ }
+
+
+ public void setCyberDebug(boolean value){
+ if (value) Debug.on();
+ else Debug.off();
+ }
+
+ public boolean getCyberDebug(){
+ return Debug.isOn();
+ }
+ //////////////////////////// end programmatic interface ////////////////////////////
+
+
+ public final void ERROR(String message) {
+ log(1,message);
+ }
+
+ public final void WARNING(String message) {
+ log(2,message);
+ }
+
+ public final void INFO(String message) {
+ log(3,message);
+ }
+
+ public final void DEBUG(String message) {
+ log(4,message);
+ }
+
+ public final void PACKET(String message) {
+ log(4, new StringBuffer(ROW).append(message).append(END_ROW).toString());
+ }
+
+ /**
+ * Logs a message.
+ *
+ * <p>The <tt>ServiceReference</tt> field and the <tt>Throwable</tt>
+ * field of the <tt>LogEntry</tt> object will be set to <tt>null</tt>.
+ * @param msglevel The severity of the message.
+ * This should be one of the defined log levels
+ * but may be any integer that is interpreted in a user defined way.
+ * @param message Human readable string describing the condition or <tt>null</tt>.
+ * @see #LOG_ERROR
+ * @see #LOG_WARNING
+ * @see #LOG_INFO
+ * @see #LOG_DEBUG
+ */
+ public void log(int msglevel, String message) {
+ synchronized (this) {
+ if (msglevel <= this.level){
+ if (this.osgiLogService != null ){
+ osgiLogService.log(msglevel, message);
+ }
+ else {
+ StringBuffer sb = new StringBuffer(Logger.LEVEL_TO_STRING[msglevel]);
+ this.out.println(sb.append(message));
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Logs a message with an exception.
+ *
+ * <p>The <tt>ServiceReference</tt> field of the <tt>LogEntry</tt> object will be set to <tt>null</tt>.
+ * @param msglevel The severity of the message.
+ * This should be one of the defined log levels
+ * but may be any integer that is interpreted in a user defined way.
+ * @param message The human readable string describing the condition or <tt>null</tt>.
+ * @param exception The exception that reflects the condition or <tt>null</tt>.
+ * @see #LOG_ERROR
+ * @see #LOG_WARNING
+ * @see #LOG_INFO
+ * @see #LOG_DEBUG
+ */
+ public void log(int msglevel, String message, Throwable exception) {
+ synchronized (this) {
+ if (msglevel <= this.level){
+ if(this.osgiLogService != null){
+ osgiLogService.log(msglevel, message, exception);
+ }
+ else {
+ StringBuffer sb = new StringBuffer(Logger.LEVEL_TO_STRING[msglevel]);
+ this.out.println(sb.append(message).append(NEWLINE).append(exception));
+ exception.printStackTrace(this.out);
+ }
+ }
+ }
+ }
+
+ private synchronized void setLogService(ServiceReference reference){
+ this.rls = reference;
+ this.osgiLogService = (LogService) Activator.bc.getService(rls);
+ }
+ /**
+ * This look for a <tt>LogService</tt> if it founds no <tt>LogService</tt> will register a new
+ * Listener of LogService
+ *
+ */
+ private synchronized void findService() {
+ //PRE:Actually no LogService are setted and we are registered as ServiceListener
+ // for LogService (unregisterin event)
+ this.rls = Activator.bc.getServiceReference(LogService.class.getName());
+ if (this.rls != null){
+ this.osgiLogService = (LogService) Activator.bc.getService(rls);
+ }
+ try {
+ Activator.bc.addServiceListener(this,
+ "(" + Constants.OBJECTCLASS + "=" + LogService.class.getName() + ")"
+ );
+ } catch (InvalidSyntaxException ignore) {}
+ //POST: We are connected to a LogService or we are registered as ServiceListener
+ // for LogService(registering event)
+ }
+
+ private synchronized void releaseLogService() {
+ if( osgiLogService != null)
+ Activator.bc.ungetService(this.rls);
+ this.rls = null;
+ this.osgiLogService = null;
+ }
+
+ /**
+ * Used to keep track the existence of a <tt>LogService</tt>
+ *
+ * @see ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
+ */
+ public void serviceChanged(ServiceEvent e) {
+ switch (e.getType()) {
+ case ServiceEvent.REGISTERED: {
+ // put here code check for serviceid
+ setLogService(e.getServiceReference());
+ }break;
+
+ case ServiceEvent.MODIFIED:
+ break;
+
+ case ServiceEvent.UNREGISTERING: {
+ // put here code check for serviceid
+ releaseLogService();
+ }break;
+ }
+ }
+
+ /**
+ * Stop using the <tt>LogService</tt> and listening for those service event
+ *
+ * NOTE: All the message will be reported to <tt>PrintStream</tt>
+ *
+ */
+ public void close(){
+ Activator.bc.removeServiceListener(this);
+ releaseLogService();
+ }
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/tool/Util.java b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/tool/Util.java
new file mode 100644
index 0000000..bc8f046
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/java/org/apache/felix/upnp/basedriver/tool/Util.java
@@ -0,0 +1,94 @@
+/*
+ * 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.basedriver.tool;
+
+import java.io.File;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.upnp.UPnPDevice;
+
+/**
+ * @author Stefano "Kismet" Lenzi
+ *
+ */
+public class Util {
+
+ public static boolean isUPnPDevice(ServiceReference sr){
+ String[] aux = (String[]) sr.getProperty(Constants.OBJECTCLASS);
+ String val=UPnPDevice.class.getName();
+ int i;
+ for (i = 0; i < aux.length; i++) {
+ if(aux[i].equals(val)) break;
+ }
+ if(i==aux.length) return false;
+ aux = (String[]) sr.getProperty(org.osgi.service.device.Constants.DEVICE_CATEGORY);
+ val=UPnPDevice.DEVICE_CATEGORY;
+ for (i = 0; i < aux.length; i++) {
+ if(aux[i].equals(val))
+ return true;
+ }
+ return false;
+ }
+
+ public static final boolean isRootDevice(ServiceReference sr){
+ return (sr.getProperty(UPnPDevice.PARENT_UDN)==null)
+ && isUPnPDevice(sr);
+ }
+
+ public static final String getPropertyDefault(BundleContext bc, String propertyName, String defaultValue ){
+ String value = bc.getProperty(propertyName);
+ if(value == null)
+ return defaultValue;
+ return value;
+ }
+
+ public static String sanitizeFilename(String name){
+ return name.replaceAll("[:;\\,/*?<>\"|]","_");
+ }
+
+ public static boolean makeParentPath(String filePath){
+ int l=filePath.lastIndexOf(File.separator);
+ filePath=filePath.substring(0,l);
+ File p=new File(filePath);
+ if(p.exists())
+ return true;
+ return p.mkdirs();
+ }
+
+ /**
+ * @param d
+ */
+ public static boolean deleteRecursive(File d) {
+ if(!d.delete()){
+ if(d.isDirectory()){
+ File[] subs = d.listFiles();
+ for (int i = 0; i < subs.length; i++) {
+ if(!deleteRecursive(subs[i]))
+ return false;
+ }
+ return d.delete();
+ }else{
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/org.apache.felix.upnp.basedriver/src/main/resources/META-INF/Manifest.mf b/org.apache.felix.upnp.basedriver/src/main/resources/META-INF/Manifest.mf
new file mode 100644
index 0000000..b037441
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/resources/META-INF/Manifest.mf
@@ -0,0 +1,6 @@
+Manifest-Version: 1.0
+Bundle-ClassPath: .,lib/cyberlink-1.7-patched-release.jar
+Bundle-Author: Matteo Demuru <matte-d@users.sourceforge.net>,Stefano "
+ Kismet" Lenzi <kismet-sl@users.sourceforge.net>,Francesco Furfari <fr
+ ancesco.furfari@isti.cnr.it>,Satoshi Konno
+
diff --git a/org.apache.felix.upnp.basedriver/src/main/resources/lib/cyberlink-1.7-patched-debug.jar b/org.apache.felix.upnp.basedriver/src/main/resources/lib/cyberlink-1.7-patched-debug.jar
new file mode 100644
index 0000000..e8e7232
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/resources/lib/cyberlink-1.7-patched-debug.jar
Binary files differ
diff --git a/org.apache.felix.upnp.basedriver/src/main/resources/lib/cyberlink-1.7-patched-release.jar b/org.apache.felix.upnp.basedriver/src/main/resources/lib/cyberlink-1.7-patched-release.jar
new file mode 100644
index 0000000..851f577
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/resources/lib/cyberlink-1.7-patched-release.jar
Binary files differ
diff --git a/org.apache.felix.upnp.basedriver/src/main/resources/lib/install CyberLink.txt b/org.apache.felix.upnp.basedriver/src/main/resources/lib/install CyberLink.txt
new file mode 100644
index 0000000..c3b8448
--- /dev/null
+++ b/org.apache.felix.upnp.basedriver/src/main/resources/lib/install CyberLink.txt
@@ -0,0 +1,2 @@
+mvn install:install-file -DgroupId=org.cybergarage -DartifactId=cyberlink-patched-release
+-Dversion=1.7 -Dpackaging=jar -Dfile=<basedir>trunk\org.apache.felix.upnp.basedriver\src\main\resources\lib\cyberlink-1.7-patched-release.jar
\ No newline at end of file