/* | |
* Licensed to the Apache Software Foundation (ASF) under one | |
* or more contributor license agreements. See the NOTICE file | |
* distributed with this work for additional information | |
* regarding copyright ownership. The ASF licenses this file | |
* to you 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.ParseUSN; | |
import org.apache.felix.upnp.extra.util.Converter; | |
/* | |
* @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a> | |
*/ | |
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()); | |
/* | |
* 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) { | |
//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 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) {/* | |
* | |
* only if there is a compatibile device | |
*/ | |
Dictionary dic = new Hashtable(); | |
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 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) {/* | |
* | |
* 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(); | |
//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) {/* | |
* | |
* only if there is a compatibile device | |
*/ | |
Dictionary dic = new Hashtable(); | |
/* | |
* 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(); | |
//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) {/* | |
* 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(); | |
//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); | |
//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)); | |
} | |
} | |
} | |
} | |
} | |
} | |
} |