2010-07-22 20:02:16 +02:00
/ *
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* The Apache Software License , Version 1 . 1
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*
* Copyright ( C ) 2002 The Apache Software Foundation . All rights reserved .
*
* Redistribution and use in source and binary forms , with or without modifica -
* tion , are permitted provided that the following conditions are met :
*
* 1 . Redistributions of source code must retain the above copyright notice ,
* this list of conditions and the following disclaimer .
*
* 2 . Redistributions in binary form must reproduce the above copyright notice ,
* this list of conditions and the following disclaimer in the documentation
* and / or other materials provided with the distribution .
*
* 3 . The end - user documentation included with the redistribution , if any , must
* include the following acknowledgment : " This product includes software
* developed by SuperBonBon Industries ( http : //www.sbbi.net/)."
* Alternately , this acknowledgment may appear in the software itself , if
* and wherever such third - party acknowledgments normally appear .
*
* 4 . The names " UPNPLib " and " SuperBonBon Industries " must not be
* used to endorse or promote products derived from this software without
* prior written permission . For written permission , please contact
* info @sbbi.net.
*
* 5 . Products derived from this software may not be called
* " SuperBonBon Industries " , nor may " SBBI " appear in their name ,
* without prior written permission of SuperBonBon Industries .
*
* THIS SOFTWARE IS PROVIDED ` ` AS IS ' ' AND ANY EXPRESSED OR IMPLIED WARRANTIES ,
* INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT ,
* INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLU -
* DING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS
* OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT
* ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*
* This software consists of voluntary contributions made by many individuals
* on behalf of SuperBonBon Industries . For more information on
* SuperBonBon Industries , please see < http : //www.sbbi.net/>.
* /
package net.yacy.upnp.services ;
import org.apache.commons.jxpath.* ;
import org.apache.commons.jxpath.xml.* ;
import java.util.* ;
import java.io.IOException ;
import java.net.* ;
import net.yacy.upnp.JXPathParser ;
import net.yacy.upnp.devices.* ;
/ * *
* Representation of an UPNP service
* @author < a href = " mailto:superbonbon@sbbi.net " > SuperBonBon < / a >
* @version 1 . 0
* /
public class UPNPService {
protected String serviceType ;
protected String serviceId ;
private int specVersionMajor ;
private int specVersionMinor ;
protected URL SCPDURL ;
protected String SCPDURLData ;
protected URL controlURL ;
protected URL eventSubURL ;
protected UPNPDevice serviceOwnerDevice ;
2010-07-24 15:48:45 +02:00
protected Map < String , ServiceAction > UPNPServiceActions ;
protected Map < String , ServiceStateVariable > UPNPServiceStateVariables ;
2010-07-22 20:02:16 +02:00
private String USN ;
private boolean parsedSCPD = false ;
private DocumentContainer UPNPService ;
public UPNPService ( JXPathContext serviceCtx , URL baseDeviceURL , UPNPDevice serviceOwnerDevice ) throws MalformedURLException {
this . serviceOwnerDevice = serviceOwnerDevice ;
2010-07-22 21:13:37 +02:00
serviceType = ( String ) serviceCtx . getValue ( " upnp:serviceType " ) ;
serviceId = ( String ) serviceCtx . getValue ( " upnp:serviceId " ) ;
SCPDURL = UPNPRootDevice . getURL ( ( String ) serviceCtx . getValue ( " upnp:SCPDURL " ) , baseDeviceURL ) ;
controlURL = UPNPRootDevice . getURL ( ( String ) serviceCtx . getValue ( " upnp:controlURL " ) , baseDeviceURL ) ;
eventSubURL = UPNPRootDevice . getURL ( ( String ) serviceCtx . getValue ( " upnp:eventSubURL " ) , baseDeviceURL ) ;
2010-07-22 20:02:16 +02:00
USN = serviceOwnerDevice . getUDN ( ) . concat ( " :: " ) . concat ( serviceType ) ;
}
public String getServiceType ( ) {
return serviceType ;
}
public String getServiceId ( ) {
return serviceId ;
}
public String getUSN ( ) {
return USN ;
}
public URL getSCPDURL ( ) {
return SCPDURL ;
}
public URL getControlURL ( ) {
return controlURL ;
}
public URL getEventSubURL ( ) {
return eventSubURL ;
}
public int getSpecVersionMajor ( ) {
lazyInitiate ( ) ;
return specVersionMajor ;
}
public int getSpecVersionMinor ( ) {
lazyInitiate ( ) ;
return specVersionMinor ;
}
public UPNPDevice getServiceOwnerDevice ( ) {
return serviceOwnerDevice ;
}
/ * *
* Retreives a service action for its given name
* @param actionName the service action name
* @return a ServiceAction object or null if no matching action for this service has been found
* /
public ServiceAction getUPNPServiceAction ( String actionName ) {
lazyInitiate ( ) ;
2010-07-24 15:48:45 +02:00
return UPNPServiceActions . get ( actionName ) ;
2010-07-22 20:02:16 +02:00
}
/ * *
* Retreives a service state variable for its given name
* @param stateVariableName the state variable name
* @return a ServiceStateVariable object or null if no matching state variable has been found
* /
public ServiceStateVariable getUPNPServiceStateVariable ( String stateVariableName ) {
lazyInitiate ( ) ;
2010-07-24 15:48:45 +02:00
return UPNPServiceStateVariables . get ( stateVariableName ) ;
2010-07-22 20:02:16 +02:00
}
2010-07-27 08:48:01 +02:00
public Iterator < String > getAvailableActionsName ( ) {
2010-07-22 20:02:16 +02:00
lazyInitiate ( ) ;
return UPNPServiceActions . keySet ( ) . iterator ( ) ;
}
public int getAvailableActionsSize ( ) {
lazyInitiate ( ) ;
return UPNPServiceActions . keySet ( ) . size ( ) ;
}
2010-07-27 08:48:01 +02:00
public Iterator < String > getAvailableStateVariableName ( ) {
2010-07-22 20:02:16 +02:00
lazyInitiate ( ) ;
return UPNPServiceStateVariables . keySet ( ) . iterator ( ) ;
}
public int getAvailableStateVariableSize ( ) {
lazyInitiate ( ) ;
return UPNPServiceStateVariables . keySet ( ) . size ( ) ;
}
private void parseSCPD ( ) {
try {
DocumentContainer . registerXMLParser ( DocumentContainer . MODEL_DOM , new JXPathParser ( ) ) ;
UPNPService = new DocumentContainer ( SCPDURL , DocumentContainer . MODEL_DOM ) ;
JXPathContext context = JXPathContext . newContext ( this ) ;
2010-07-22 21:13:37 +02:00
context . registerNamespace ( " scpdns " , " urn:schemas-upnp-org:service-1-0 " ) ;
Pointer rootPtr = context . getPointer ( " UPNPService/scpdns:scpd " ) ;
2010-07-22 20:02:16 +02:00
JXPathContext rootCtx = context . getRelativeContext ( rootPtr ) ;
2010-07-22 21:13:37 +02:00
rootCtx . registerNamespace ( " scpdns " , " urn:schemas-upnp-org:service-1-0 " ) ;
2010-07-22 20:02:16 +02:00
2010-07-22 21:13:37 +02:00
specVersionMajor = Integer . parseInt ( ( String ) rootCtx . getValue ( " scpdns:specVersion/scpdns:major " ) ) ;
specVersionMinor = Integer . parseInt ( ( String ) rootCtx . getValue ( " scpdns:specVersion/scpdns:minor " ) ) ;
2010-07-22 20:02:16 +02:00
parseServiceStateVariables ( rootCtx ) ;
2010-07-22 21:13:37 +02:00
Pointer actionsListPtr = rootCtx . getPointer ( " scpdns:actionList " ) ;
2010-07-22 20:02:16 +02:00
JXPathContext actionsListCtx = context . getRelativeContext ( actionsListPtr ) ;
2010-07-22 21:13:37 +02:00
actionsListCtx . registerNamespace ( " scpdns " , " urn:schemas-upnp-org:service-1-0 " ) ;
Double arraySize = ( Double ) actionsListCtx . getValue ( " count( scpdns:action ) " ) ;
2010-07-24 15:48:45 +02:00
UPNPServiceActions = new HashMap < String , ServiceAction > ( ) ;
2010-07-22 20:02:16 +02:00
for ( int i = 1 ; i < = arraySize . intValue ( ) ; i + + ) {
ServiceAction action = new ServiceAction ( ) ;
2010-07-22 21:13:37 +02:00
action . name = ( String ) actionsListCtx . getValue ( " scpdns:action[ " + i + " ]/scpdns:name " ) ;
2010-07-22 20:02:16 +02:00
action . parent = this ;
Pointer argumentListPtr = null ;
try {
2010-07-22 21:13:37 +02:00
argumentListPtr = actionsListCtx . getPointer ( " scpdns:action[ " + i + " ]/scpdns:argumentList " ) ;
2013-07-17 18:31:30 +02:00
} catch ( final JXPathException ex ) {
2010-07-22 20:02:16 +02:00
// there is no arguments list.
}
if ( argumentListPtr ! = null ) {
JXPathContext argumentListCtx = actionsListCtx . getRelativeContext ( argumentListPtr ) ;
2010-07-22 21:13:37 +02:00
argumentListCtx . registerNamespace ( " scpdns " , " urn:schemas-upnp-org:service-1-0 " ) ;
Double arraySizeArgs = ( Double ) argumentListCtx . getValue ( " count( scpdns:argument ) " ) ;
2010-07-22 20:02:16 +02:00
2010-07-24 15:48:45 +02:00
List < ServiceActionArgument > orderedActionArguments = new ArrayList < ServiceActionArgument > ( ) ;
2010-07-22 20:02:16 +02:00
for ( int z = 1 ; z < = arraySizeArgs . intValue ( ) ; z + + ) {
ServiceActionArgument arg = new ServiceActionArgument ( ) ;
2010-07-22 21:13:37 +02:00
arg . name = ( String ) argumentListCtx . getValue ( " scpdns:argument[ " + z + " ]/scpdns:name " ) ;
String direction = ( String ) argumentListCtx . getValue ( " scpdns:argument[ " + z + " ]/scpdns:direction " ) ;
2010-07-22 20:02:16 +02:00
arg . direction = direction . equals ( ServiceActionArgument . DIRECTION_IN ) ? ServiceActionArgument . DIRECTION_IN : ServiceActionArgument . DIRECTION_OUT ;
2010-07-22 21:13:37 +02:00
String stateVarName = ( String ) argumentListCtx . getValue ( " scpdns:argument[ " + z + " ]/scpdns:relatedStateVariable " ) ;
2010-07-24 15:48:45 +02:00
ServiceStateVariable stateVar = UPNPServiceStateVariables . get ( stateVarName ) ;
2010-07-22 20:02:16 +02:00
if ( stateVar = = null ) {
throw new IllegalArgumentException ( " Unable to find any state variable named " + stateVarName + " for service " + getServiceId ( ) + " action " + action . name + " argument " + arg . name ) ;
}
arg . relatedStateVariable = stateVar ;
orderedActionArguments . add ( arg ) ;
}
if ( arraySizeArgs . intValue ( ) > 0 ) {
action . setActionArguments ( orderedActionArguments ) ;
}
}
UPNPServiceActions . put ( action . getName ( ) , action ) ;
}
parsedSCPD = true ;
2013-07-17 18:31:30 +02:00
} catch ( final Throwable t ) {
2010-07-22 20:02:16 +02:00
throw new RuntimeException ( " Error during lazy SCDP file parsing at " + SCPDURL , t ) ;
}
}
private void parseServiceStateVariables ( JXPathContext rootContext ) {
2010-07-22 21:13:37 +02:00
Pointer serviceStateTablePtr = rootContext . getPointer ( " scpdns:serviceStateTable " ) ;
2010-07-22 20:02:16 +02:00
JXPathContext serviceStateTableCtx = rootContext . getRelativeContext ( serviceStateTablePtr ) ;
2010-07-22 21:13:37 +02:00
serviceStateTableCtx . registerNamespace ( " scpdns " , " urn:schemas-upnp-org:service-1-0 " ) ;
Double arraySize = ( Double ) serviceStateTableCtx . getValue ( " count( scpdns:stateVariable ) " ) ;
2010-07-24 15:48:45 +02:00
UPNPServiceStateVariables = new HashMap < String , ServiceStateVariable > ( ) ;
2010-07-22 20:02:16 +02:00
for ( int i = 1 ; i < = arraySize . intValue ( ) ; i + + ) {
ServiceStateVariable srvStateVar = new ServiceStateVariable ( ) ;
String sendEventsLcl = null ;
try {
2010-07-22 21:13:37 +02:00
sendEventsLcl = ( String ) serviceStateTableCtx . getValue ( " scpdns:stateVariable[ " + i + " ]/scpdns:@sendEvents " ) ;
2013-07-17 18:31:30 +02:00
} catch ( final JXPathException defEx ) {
2010-07-22 20:02:16 +02:00
// sendEvents not provided defaulting according to specs to "yes"
sendEventsLcl = " yes " ;
}
srvStateVar . parent = this ;
srvStateVar . sendEvents = sendEventsLcl . equalsIgnoreCase ( " no " ) ? false : true ;
2010-07-22 21:13:37 +02:00
srvStateVar . name = ( String ) serviceStateTableCtx . getValue ( " scpdns:stateVariable[ " + i + " ]/scpdns:name " ) ;
srvStateVar . dataType = ( String ) serviceStateTableCtx . getValue ( " scpdns:stateVariable[ " + i + " ]/scpdns:dataType " ) ;
2010-07-22 20:02:16 +02:00
try {
2010-07-22 21:13:37 +02:00
srvStateVar . defaultValue = ( String ) serviceStateTableCtx . getValue ( " scpdns:stateVariable[ " + i + " ]/scpdns:defaultValue " ) ;
2013-07-17 18:31:30 +02:00
} catch ( final JXPathException defEx ) {
2010-07-22 20:02:16 +02:00
// can happend since default value is not
}
Pointer allowedValuesPtr = null ;
try {
2010-07-22 21:13:37 +02:00
allowedValuesPtr = serviceStateTableCtx . getPointer ( " scpdns:stateVariable[ " + i + " ]/scpdns:allowedValueList " ) ;
2013-07-17 18:31:30 +02:00
} catch ( final JXPathException ex ) {
2010-07-22 20:02:16 +02:00
// there is no allowed values list.
}
if ( allowedValuesPtr ! = null ) {
JXPathContext allowedValuesCtx = serviceStateTableCtx . getRelativeContext ( allowedValuesPtr ) ;
2010-07-22 21:13:37 +02:00
allowedValuesCtx . registerNamespace ( " scpdns " , " urn:schemas-upnp-org:service-1-0 " ) ;
Double arraySizeAllowed = ( Double ) allowedValuesCtx . getValue ( " count( scpdns:allowedValue ) " ) ;
2010-07-24 15:48:45 +02:00
srvStateVar . allowedvalues = new HashSet < String > ( ) ;
2010-07-22 20:02:16 +02:00
for ( int z = 1 ; z < = arraySizeAllowed . intValue ( ) ; z + + ) {
2010-07-22 21:13:37 +02:00
String allowedValue = ( String ) allowedValuesCtx . getValue ( " scpdns:allowedValue[ " + z + " ] " ) ;
2010-07-22 20:02:16 +02:00
srvStateVar . allowedvalues . add ( allowedValue ) ;
}
}
Pointer allowedValueRangePtr = null ;
try {
2010-07-22 21:13:37 +02:00
allowedValueRangePtr = serviceStateTableCtx . getPointer ( " scpdns:stateVariable[ " + i + " ]/scpdns:allowedValueRange " ) ;
2013-07-17 18:31:30 +02:00
} catch ( final JXPathException ex ) {
2010-07-22 20:02:16 +02:00
// there is no allowed values list, can happen
}
if ( allowedValueRangePtr ! = null ) {
2010-07-22 21:13:37 +02:00
srvStateVar . minimumRangeValue = ( String ) serviceStateTableCtx . getValue ( " scpdns:stateVariable[ " + i + " ]/scpdns:allowedValueRange/scpdns:minimum " ) ;
srvStateVar . maximumRangeValue = ( String ) serviceStateTableCtx . getValue ( " scpdns:stateVariable[ " + i + " ]/scpdns:allowedValueRange/scpdns:maximum " ) ;
2010-07-22 20:02:16 +02:00
try {
2010-07-22 21:13:37 +02:00
srvStateVar . stepRangeValue = ( String ) serviceStateTableCtx . getValue ( " scpdns:stateVariable[ " + i + " ]/scpdns:allowedValueRange/scpdns:step " ) ;
2013-07-17 18:31:30 +02:00
} catch ( final JXPathException stepEx ) {
2010-07-22 20:02:16 +02:00
// can happend since step is not mandatory
}
}
UPNPServiceStateVariables . put ( srvStateVar . getName ( ) , srvStateVar ) ;
}
}
private void lazyInitiate ( ) {
if ( ! parsedSCPD )
synchronized ( this ) {
if ( ! parsedSCPD )
parseSCPD ( ) ;
}
}
/ * *
* Used for JXPath parsing , do not use this method
* @return a Container object for Xpath parsing capabilities
* /
public Container getUPNPService ( ) {
return UPNPService ;
}
public String getSCDPData ( ) {
if ( SCPDURLData = = null ) {
try {
java . io . InputStream in = SCPDURL . openConnection ( ) . getInputStream ( ) ;
int readen = 0 ;
byte [ ] buff = new byte [ 512 ] ;
2011-03-08 02:51:51 +01:00
StringBuilder strBuff = new StringBuilder ( ) ;
2010-07-22 20:02:16 +02:00
while ( ( readen = in . read ( buff ) ) ! = - 1 ) {
strBuff . append ( new String ( buff , 0 , readen ) ) ;
}
in . close ( ) ;
SCPDURLData = strBuff . toString ( ) ;
2013-07-17 18:31:30 +02:00
} catch ( final IOException ioEx ) {
2010-07-22 20:02:16 +02:00
return null ;
}
}
return SCPDURLData ;
}
}