/* | |
* 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.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 <a href="mailto:dev@felix.apache.org">Felix Project Team</a> | |
*/ | |
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.setModelNumber((String) sr.getProperty(UPnPDevice.MODEL_NUMBER)); | |
devUPnP.setModelURL((String) sr.getProperty(UPnPDevice.MODEL_URL)); | |
devUPnP.setSerialNumber((String) sr.getProperty(UPnPDevice.SERIAL_NUMBER)); | |
devUPnP.setUDN((String) sr.getProperty(UPnPDevice.UDN)); | |
devUPnP.setUPC((String) sr.getProperty(UPnPDevice.UPC)); | |
devUPnP.setLocation("/gen-desc.xml"); | |
addServices("",devUPnP,sr); | |
addDevices("",devUPnP,sr); | |
devUPnP.setPresentationURL((String) sr.getProperty(UPnPDevice.PRESENTATION_URL)); | |
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.setModelNumber((String) sr.getProperty(UPnPDevice.MODEL_NUMBER)); | |
devUPnP.setModelURL((String) sr.getProperty(UPnPDevice.MODEL_URL)); | |
devUPnP.setSerialNumber((String) sr.getProperty(UPnPDevice.SERIAL_NUMBER)); | |
devUPnP.setUDN((String) sr.getProperty(UPnPDevice.UDN)); | |
devUPnP.setUPC((String) sr.getProperty(UPnPDevice.UPC)); | |
devUPnP.setLocation(id+"/gen-desc.xml"); | |
addServices(id,devUPnP,sr); | |
addDevices(id,devUPnP,sr); | |
parent.addDevice(devUPnP); // twa: essential!!!!!!! | |
devUPnP.setPresentationURL((String) sr.getProperty(UPnPDevice.PRESENTATION_URL)); | |
} | |
/** | |
* 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"); | |
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); | |
} | |
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); | |
} | |
Activator.bc.ungetService(sr); | |
} | |
} | |
public static Device createCyberLinkDevice(ServiceReference sr){ | |
Node root = buildRootNode(); | |
Device devUPnP = buildRootDeviceNode(root,sr); | |
return devUPnP; | |
} | |
} |