| /* |
| * 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.RootDescription; |
| 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.apache.felix.upnp.basedriver.Activator; |
| import org.apache.felix.upnp.basedriver.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 String extractDeviceType(ServiceReference sr) { |
| Object aux = sr.getProperty(UPnPDevice.TYPE); |
| if(aux instanceof String){ |
| return (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; |
| } |
| } |
| return v[maxindex]; |
| }else{ |
| return ""; |
| } |
| } |
| |
| 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); |
| |
| devUPnP.setDeviceType(extractDeviceType(sr)); |
| 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.setDeviceType(extractDeviceType(sr)); |
| 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 that 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++) { |
| boolean valid=true; |
| 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++) { |
| UPnPStateVariable variable = actions[j].getStateVariable(names[k]); |
| if(variable==null){ |
| /* |
| * //TODO Create a stict and relaxed behavior of the base driver which |
| * export as much it can or export only 100% complaint UPnPDevice service |
| */ |
| Activator.logger.WARNING( |
| "UPnP Device that cotains serviceId="+id+" contains the action " |
| +actions[j].getName()+" with the Input argument "+names[k] |
| +" not related to any UPnPStateVariable. Thus this action won't be exported"); |
| valid=false; |
| break; |
| } |
| Argument a = new Argument(); |
| a.setDirection(Argument.IN); |
| a.setName(names[k]); |
| a.setRelatedStateVariableName(variable.getName()); |
| al.add(a); |
| } |
| } |
| names=actions[j].getOutputArgumentNames(); |
| if(names!=null && valid){ |
| for (int k = 0; k < names.length; k++) { |
| UPnPStateVariable variable = actions[j].getStateVariable(names[k]); |
| if(variable==null){ |
| /* |
| * //TODO Create a stict and relaxed behavior of the base driver which |
| * export as much it can or export only 100% complaint UPnPDevice service |
| */ |
| Activator.logger.WARNING( |
| "UPnP Device that cotains serviceId="+id+" contains the action " |
| +actions[j].getName()+" with the Output argument "+names[k] |
| +" not related to any UPnPStateVariable. Thus this action won't be exported"); |
| } |
| Argument a = new Argument(); |
| a.setDirection(Argument.OUT); |
| a.setName(names[k]); |
| a.setRelatedStateVariableName(variable.getName()); |
| al.add(a); |
| } |
| } |
| if(valid) { |
| 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; |
| } |
| } |