protected void writeActionOutputArguments( Document d, Element actionResponseElement, ActionInvocation actionInvocation) { for (ActionArgument argument : actionInvocation.getAction().getOutputArguments()) { log.fine("Writing action output argument: " + argument.getName()); String value = actionInvocation.getOutput(argument) != null ? actionInvocation.getOutput(argument).toString() : ""; XMLUtil.appendNewElement(d, actionResponseElement, argument.getName(), value); } }
private void generateActionArgument( ActionArgument actionArgument, Document descriptor, Element actionElement) { Element actionArgumentElement = appendNewElement(descriptor, actionElement, ELEMENT.argument); appendNewElementIfNotNull( descriptor, actionArgumentElement, ELEMENT.name, actionArgument.getName()); appendNewElementIfNotNull( descriptor, actionArgumentElement, ELEMENT.direction, actionArgument.getDirection().toString().toLowerCase(Locale.ENGLISH)); if (actionArgument.isReturnValue()) { // TODO: UPNP VIOLATION: WMP12 will discard RenderingControl service if it contains <retval> // tags log.warning( "UPnP specification violation: Not producing <retval> element to be compatible with WMP12: " + actionArgument); // appendNewElement(descriptor, actionArgumentElement, ELEMENT.retval); } appendNewElementIfNotNull( descriptor, actionArgumentElement, ELEMENT.relatedStateVariable, actionArgument.getRelatedStateVariableName()); }
/** * Finds all element nodes in the list that match any argument name or argument alias, throws * {@link ActionException} if not all arguments were found. */ protected List<Node> getMatchingNodes(NodeList nodeList, ActionArgument[] args) throws ActionException { List<String> names = new ArrayList<>(); for (ActionArgument argument : args) { names.add(argument.getName()); names.addAll(Arrays.asList(argument.getAliases())); } List<Node> matches = new ArrayList<>(); for (int i = 0; i < nodeList.getLength(); i++) { Node child = nodeList.item(i); if (child.getNodeType() != Node.ELEMENT_NODE) continue; if (names.contains(getUnprefixedNodeName(child))) matches.add(child); } if (matches.size() < args.length) { throw new ActionException( ErrorCode.ARGUMENT_VALUE_INVALID, "Invalid number of input or output arguments in XML message, expected " + args.length + " but found " + matches.size()); } return matches; }
/** * Creates an instance of {@link ActionArgumentValue} and wraps an {@link InvalidValueException} * as an {@link ActionException} with the appropriate {@link ErrorCode}. */ protected ActionArgumentValue createValue(ActionArgument arg, String value) throws ActionException { try { return new ActionArgumentValue(arg, value); } catch (InvalidValueException ex) { throw new ActionException( ErrorCode.ARGUMENT_VALUE_INVALID, "Wrong type or invalid value for '" + arg.getName() + "': " + ex.getMessage(), ex); } }
/** * The UPnP spec says that action arguments must be in the order as declared by the service. This * method however is lenient, the action argument nodes in the XML can be in any order, as long as * they are all there everything is OK. */ protected ActionArgumentValue[] readArgumentValues(NodeList nodeList, ActionArgument[] args) throws ActionException { List<Node> nodes = getMatchingNodes(nodeList, args); ActionArgumentValue[] values = new ActionArgumentValue[args.length]; for (int i = 0; i < args.length; i++) { ActionArgument arg = args[i]; Node node = findActionArgumentNode(nodes, arg); if (node == null) { throw new ActionException( ErrorCode.ARGUMENT_VALUE_INVALID, "Could not find argument '" + arg.getName() + "' node"); } log.fine("Reading action argument: " + arg.getName()); String value = XMLUtil.getTextContent(node); values[i] = createValue(arg, value); } return values; }
@SuppressWarnings({"rawtypes", "unchecked"}) private ActionArgumentValue[] getArguments(final Action<RemoteService> action) { final ActionArgument[] actionArguments = action.getArguments(); final Map<String, Object> argumentValues = getArgumentValues(); final List<ActionArgumentValue<RemoteService>> actionArgumentValues = new ArrayList<>(actionArguments.length); for (final ActionArgument<RemoteService> actionArgument : actionArguments) { if (actionArgument.getDirection() == Direction.IN) { final Object value = argumentValues.get(actionArgument.getName()); logger.trace( "Action {}: add arg value for {}: {} (expected datatype: {})", action.getName(), actionArgument, value, actionArgument.getDatatype().getDisplayString()); actionArgumentValues.add(new ActionArgumentValue<>(actionArgument, value)); } } return actionArgumentValues.toArray(new ActionArgumentValue[actionArgumentValues.size()]); }