/** * Set the value of an input parameter before a message service call. If the param name already * exists, the param value will be overwritten with the new value provided * * @param parameterName the parameter name * @param parameterValue the string parameter value * @return the current ActionMessage object instance * @throws IllegalArgumentException if the provided parameterName is not valid for this message or * if no input parameters are required for this message */ public ActionMessage setInputParameter(String parameterName, String parameterValue) throws IllegalArgumentException { if (serviceAction.getInputActionArguments() == null) { throw new IllegalArgumentException("No input parameters required for this message"); } Argument arg = serviceAction.getInputActionArgument(parameterName); if (arg == null) { throw new IllegalArgumentException( "Wrong input argument name for this action:" + parameterName + " available parameters are : " + serviceAction.getInputActionArguments()); } for (Iterator<InputParamContainer> i = inputParameters.iterator(); i.hasNext(); ) { InputParamContainer container = i.next(); if (container.name.equals(parameterName)) { container.value = parameterValue; return this; } } // nothing found add the new value InputParamContainer container = new InputParamContainer(); container.name = parameterName; container.value = parameterValue; inputParameters.add(container); return this; }
/** * Set the value of an input parameter before a message service call * * @param parameterName the parameter name * @param parameterValue the date parameter value, will be automatically translated to the correct * ISO 8601 date format for the given action input param related state variable * @return the current ActionMessage object instance * @throws IllegalArgumentException if the provided parameterName is not valid for this message or * if no input parameters are required for this message */ public ActionMessage setInputParameter(String parameterName, Date parameterValue) throws IllegalArgumentException { if (serviceAction.getInputActionArguments() == null) { throw new IllegalArgumentException("No input parameters required for this message"); } Argument arg = serviceAction.getInputActionArgument(parameterName); if (arg == null) { throw new IllegalArgumentException( "Wrong input argument name for this action:" + parameterName + " available parameters are : " + serviceAction.getInputActionArguments()); } StateVariable linkedVar = arg.getRelatedStateVariable(); if (linkedVar.dataType.equals(StateVariableTypes.TIME)) { return setInputParameter(parameterName, ISO8601Date.getIsoTime(parameterValue)); } else if (linkedVar.dataType.equals(StateVariableTypes.TIME_TZ)) { return setInputParameter(parameterName, ISO8601Date.getIsoTimeZone(parameterValue)); } else if (linkedVar.dataType.equals(StateVariableTypes.DATE)) { return setInputParameter(parameterName, ISO8601Date.getIsoDate(parameterValue)); } else if (linkedVar.dataType.equals(StateVariableTypes.DATETIME)) { return setInputParameter(parameterName, ISO8601Date.getIsoDateTime(parameterValue)); } else if (linkedVar.dataType.equals(StateVariableTypes.DATETIME_TZ)) { return setInputParameter(parameterName, ISO8601Date.getIsoDateTimeZone(parameterValue)); } else { throw new IllegalArgumentException( "Related input state variable " + linkedVar.name + " is not of an date type"); } }
/** * Protected constuctor so that only messages factories can build it * * @param service the service for which the * @param serviceAction */ protected ActionMessage(Service service, Action serviceAction) { this.service = service; this.serviceAction = serviceAction; if (serviceAction.getInputActionArguments() != null) { inputParameters = new ArrayList<InputParamContainer>(); } }
/** * Executes the message and retuns the UPNP device response, according to the UPNP specs, this * method could take up to 30 secs to process ( time allowed for a device to respond to a request * ) * * @return a response object containing the UPNP parsed response * @throws IOException if some IOException occurs during message send and reception process * @throws UPNPResponseException if an UPNP error message is returned from the server or if some * parsing exception occurs ( detailErrorCode = 899, detailErrorDescription = SAXException * message ) */ public ActionResponse service() throws IOException, UPNPResponseException { ActionResponse rtrVal = null; UPNPResponseException upnpEx = null; IOException ioEx = null; StringBuilder body = new StringBuilder(256); body.append("<?xml version=\"1.0\"?>\r\n"); body.append("<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\""); body.append(" s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"); body.append("<s:Body>"); body.append("<u:") .append(serviceAction.getName()) .append(" xmlns:u=\"") .append(service.serviceType) .append("\">"); if (serviceAction.getInputActionArguments() != null) { // this action requires params so we just set them... for (Iterator<InputParamContainer> itr = inputParameters.iterator(); itr.hasNext(); ) { InputParamContainer container = itr.next(); body.append("<").append(container.name).append(">").append(container.value); body.append("</").append(container.name).append(">"); } } body.append("</u:").append(serviceAction.getName()).append(">"); body.append("</s:Body>"); body.append("</s:Envelope>"); URL url = new URL(service.controlURL.toString()); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false); conn.setRequestMethod("POST"); conn.setInstanceFollowRedirects(false); // conn.setConnectTimeout( 30000 ); conn.setRequestProperty("HOST", url.getHost() + ":" + url.getPort()); conn.setRequestProperty("CONTENT-TYPE", "text/xml; charset=\"utf-8\""); conn.setRequestProperty("CONTENT-LENGTH", Integer.toString(body.length())); conn.setRequestProperty( "SOAPACTION", "\"" + service.serviceType + "#" + serviceAction.getName() + "\""); OutputStream out = conn.getOutputStream(); out.write(body.toString().getBytes()); out.flush(); out.close(); conn.connect(); InputStream input = null; try { input = conn.getInputStream(); } catch (IOException ex) { // java can throw an exception if he error code is 500 or 404 // or something else than 200 // but the device sends 500 error message with content that // is required // this content is accessible with the getErrorStream input = conn.getErrorStream(); } if (input != null) { int response = conn.getResponseCode(); String responseBody = getResponseBody(input); SAXParserFactory saxParFact = SAXParserFactory.newInstance(); saxParFact.setValidating(false); saxParFact.setNamespaceAware(true); ActionMessageResponseParser msgParser = new ActionMessageResponseParser(serviceAction); StringReader stringReader = new StringReader(responseBody); InputSource src = new InputSource(stringReader); try { SAXParser parser = saxParFact.newSAXParser(); parser.parse(src, msgParser); } catch (ParserConfigurationException confEx) { // should never happen // we throw a runtimeException to notify the env problem throw new RuntimeException( "ParserConfigurationException during SAX parser creation, please check your env settings:" + confEx.getMessage()); } catch (SAXException saxEx) { // kind of tricky but better than nothing.. upnpEx = new UPNPResponseException(899, saxEx.getMessage()); } finally { try { input.close(); } catch (IOException ex) { // ignore } } if (upnpEx == null) { if (response == HttpURLConnection.HTTP_OK) { rtrVal = msgParser.getActionResponse(); } else if (response == HttpURLConnection.HTTP_INTERNAL_ERROR) { upnpEx = msgParser.getUPNPResponseException(); } else { ioEx = new IOException("Unexpected server HTTP response:" + response); } } } try { out.close(); } catch (IOException ex) { // ignore } conn.disconnect(); if (upnpEx != null) { throw upnpEx; } if (rtrVal == null && ioEx == null) { ioEx = new IOException("Unable to receive a response from the UPNP device"); } if (ioEx != null) { throw ioEx; } return rtrVal; }