Fixed bug #FELIX-460 in BuildDevice
Removed unused code and avoiding overriding of UPnP configuration in ThreadExporter
Added caching and better control on constraint defined for imported Device in UPnPStateVariableImpl
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@610454 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/upnp/basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/BuildDevice.java b/upnp/basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/BuildDevice.java
index 9fd4ca7..65e431a 100644
--- a/upnp/basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/BuildDevice.java
+++ b/upnp/basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/BuildDevice.java
@@ -171,7 +171,7 @@
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="
+ Activator.logger.WARNING("UPnP Device that cotains serviceId="
+id+" is deregistered from the framework while is exported");
return;
}
@@ -194,6 +194,7 @@
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();
@@ -201,29 +202,51 @@
String[] names=actions[j].getInputArgumentNames();
if(names!=null){
for (int k = 0; k < names.length; k++) {
- Argument a = new Argument();
+ 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(
- actions[j].getStateVariable(names[k]).getName()
- );
+ a.setRelatedStateVariableName(variable.getName());
al.add(a);
}
}
names=actions[j].getOutputArgumentNames();
- if(names!=null){
+ 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(
- actions[j].getStateVariable(names[k]).getName()
- );
+ a.setRelatedStateVariableName(variable.getName());
al.add(a);
}
}
- act.setArgumentList(al);
- ser.addAction(act);
+ if(valid) {
+ act.setArgumentList(al);
+ ser.addAction(act);
+ }
}
UPnPStateVariable[] vars = services[i].getStateVariables();
diff --git a/upnp/basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ThreadExporter.java b/upnp/basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ThreadExporter.java
index 281abba..1c0c971 100644
--- a/upnp/basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ThreadExporter.java
+++ b/upnp/basedriver/src/main/java/org/apache/felix/upnp/basedriver/export/ThreadExporter.java
@@ -101,13 +101,10 @@
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("");
@@ -138,75 +135,33 @@
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)
- );
+ 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)
+ );
+ }
}
}
}
@@ -274,7 +229,6 @@
*/
private boolean bindInvokes(Device d, ServiceReference rootDevice) {
bindInvoke(d,rootDevice);
- //Activator.bc.ungetService(rootDevice);
ServiceReference[] childs = null;
try {
childs = Activator.bc.getServiceReferences(
@@ -290,20 +244,12 @@
}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{
@@ -311,48 +257,7 @@
}
}
- /*
- /**
- * @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
diff --git a/upnp/basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPStateVariableImpl.java b/upnp/basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPStateVariableImpl.java
index e5b5f8d..f64b995 100644
--- a/upnp/basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPStateVariableImpl.java
+++ b/upnp/basedriver/src/main/java/org/apache/felix/upnp/basedriver/importer/core/upnp/UPnPStateVariableImpl.java
@@ -29,6 +29,7 @@
import org.osgi.service.upnp.UPnPStateVariable;
+import org.apache.felix.upnp.basedriver.Activator;
import org.apache.felix.upnp.basedriver.util.Converter;
/*
@@ -37,6 +38,16 @@
public class UPnPStateVariableImpl implements UPnPStateVariable {
private StateVariable variable;
+
+ private Number max = null;
+ private Number min = null;
+ private Number step = null;
+
+ private String[] values = null;
+
+ private Boolean hasMaxMinStep = null;
+ private Boolean hasRangeValues = null;
+
private static Hashtable upnp2javaTable = null;
static{
@@ -96,37 +107,30 @@
public UPnPStateVariableImpl(StateVariable variable) {
this.variable = variable;
- } /*
- * (non-Javadoc)
- *
- * @see org.osgi.service.upnp.UPnPStateVariable#getName()
- */
+ }
+ /**
+ * @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() {
@@ -134,100 +138,132 @@
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;
+ if(hasRangeValues == null)
+ initValueConstraint();
+
+ return values;
}
- /*
- * (non-Javadoc)
- *
+ /**
* @see org.osgi.service.upnp.UPnPStateVariable#getMinimum()
*/
public Number getMinimum() {
- //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;
- }
+ if(hasMaxMinStep == null)
+ initValueConstraint();
+
+ return min;
}
- /*
- * (non-Javadoc)
- *
+ /**
* @see org.osgi.service.upnp.UPnPStateVariable#getMaximum()
*/
public Number getMaximum() {
- //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;
- }
+ if(hasMaxMinStep == null)
+ initValueConstraint();
+
+ return max;
}
- /*
- * (non-Javadoc)
- *
+ /**
+ * <b>NOTE:</b> This type of control caches the value recieved by the Device so if XML changes it doesn't affect the OSGi service
+ *
+ * @since 0.3
+ */
+ private void initValueConstraint(){
+ if(hasRangeValues != null || hasMaxMinStep != null)
+ return;
+
+ hasRangeValues = Boolean.FALSE;
+ hasMaxMinStep = Boolean.FALSE;
+
+ final AllowedValueRange allowedValueRange = variable.getAllowedValueRange();
+ final AllowedValueList allowedValueList = variable.getAllowedValueList();
+
+ if(allowedValueRange != null && allowedValueList != null){
+ Activator.logger.WARNING("Imported device with StateVariable "
+ +variable.getName()+" contains either AllowedValueRange and AllowedValueList UPnP doesn't allow it because it. Neither of the restriction will be applied");
+
+ }else if( allowedValueRange != null ){
+
+ initMaxMinStep(allowedValueRange);
+
+ }else if( allowedValueList != null ){
+
+ initAllowedValues(allowedValueList);
+
+ }
+ }
+
+ /**
+ * @param allowedValueList
+ * @since 0.3
+ */
+ private void initAllowedValues(AllowedValueList allowedValueList){
+ //PRE:invoked only by initValueConstraint() thus allowedValueList must not null
+ if (String.class != getJavaDataType()) {
+ Activator.logger.WARNING("Imported device with StateVariable "
+ +variable.getName()+" contains AllowedValueList but its UPnP type doesn't allow it because it is +"+getUPnPDataType());
+ return;
+ }
+
+ if(allowedValueList.size() == 0){
+ return ;
+ }
+
+ values = new String[allowedValueList.size()];
+ for (int i = 0; i < allowedValueList.size(); i++) {
+ values[i] = allowedValueList.getAllowedValue(i).getValue();
+ }
+ }
+
+ /**
+ * @param allowedValueRange
+ * @since 0.3
+ */
+ private void initMaxMinStep(AllowedValueRange allowedValueRange){
+ //PRE:invoked only by initValueConstraint() thus allowedValueRange must not be null
+ if(allowedValueRange==null){
+ return;
+ }
+
+ if(!Number.class.isAssignableFrom(getJavaDataType())){
+ Activator.logger.WARNING("Imported device with StateVariable "
+ +variable.getName()+" contains AllowedValueRange but its UPnP type doesn't allow it because it is +"+getUPnPDataType());
+ return;
+ }
+
+ final String maxStr = allowedValueRange.getMaximum();
+ final String minStr = allowedValueRange.getMinimum();
+ final String stepStr = allowedValueRange.getStep();
+
+ try{
+ final String type = getUPnPDataType();
+ max = (Number)Converter.parseString(maxStr,type);
+ min = (Number)Converter.parseString(minStr,type);
+ step = (Number)Converter.parseString(stepStr,type);
+ }catch(Exception ex){
+ Activator.logger.WARNING("Imported device with StateVariable "
+ +variable.getName()+" contains an invalid definition for AllowedValueRange");
+ }
+ hasMaxMinStep = Boolean.TRUE;
+ }
+
+ /**
* @see org.osgi.service.upnp.UPnPStateVariable#getStep()
*/
public Number getStep() {
- //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;
- }
+ if(hasMaxMinStep == null)
+ initValueConstraint();
+
+ return step;
+
}
- /*
- * (non-Javadoc)
- *
+ /**
* @see org.osgi.service.upnp.UPnPStateVariable#sendsEvents()
*/
public boolean sendsEvents() {