// Copyright (C) 2012 jOVAL.org. All rights reserved. // This software is licensed under the AGPL 3.0 license available at http://www.joval.org/agpl_v3.txt package jwsmv.wsman.operation; import java.io.IOException; import java.util.List; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; import javax.security.auth.login.FailedLoginException; import javax.xml.bind.Unmarshaller; import javax.xml.ws.http.HTTPException; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xmlsoap.ws.transfer.AnyXmlType; import org.xmlsoap.ws.transfer.CreateResponseType; import org.xmlsoap.ws.transfer.ResourceCreated; import jwsmv.wsman.Port; import jwsmv.wsman.FaultException; /** * Create operation implementation class. * * @author David A. Solin * @version %I% %G% */ public class CreateOperation extends BaseOperation<AnyXmlType, Object> { public CreateOperation(AnyXmlType input) { super("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create", input); } static final String WSA04 = "http://schemas.xmlsoap.org/ws/2004/08/addressing"; static final String WSA10 = "http://www.w3.org/2005/08/addressing"; /** * The CreateResponseType is merely a container for a ResourceCreated, which is itself defined to be one of the two * EndpointReferenceType classes. Since XSD does not allow unions of complex types, the schema is loosely defined using * xs:any, and consequently, JAXB unmarshals the XML into DOM Elements. * * This IOperation implementation has no such restrictions, so we construct the appropriate EndpointReferenceType from * the DOM, and return it. * * @returns either an org.w3c.ws.addressing.EndpointReferenceType, or an org.xmlsoap.ws.addressing.EndpointReferenceType. */ @Override public Object dispatch(Port port) throws IOException, HTTPException, JAXBException, FaultException, FailedLoginException { Object obj = dispatch0(port); if (obj instanceof List) { for (Object elt : (List)obj) { if (elt instanceof ResourceCreated) { obj = elt; break; } } } if (obj instanceof ResourceCreated) { // // ResourceCreated is ambiguous, so its children will be Nodes. We must determine the appropriate // type and unmarshall the correct JAXB objects. // Unmarshaller unmarshaller = Port.getUnmarshaller(); List<Element> list = ((ResourceCreated)obj).getAny(); String ns = list.get(0).getNamespaceURI(); if (WSA10.equals(ns)) { org.w3c.ws.addressing.EndpointReferenceType ref = Factories.WSADDRESS.createEndpointReferenceType(); for (Element node : list) { if ("Address".equals(node.getLocalName())) { org.w3c.ws.addressing.AttributedURIType address = Factories.WSADDRESS.createAttributedURIType(); int numAttrs = node.getAttributes().getLength(); for (int i=0; i < numAttrs; i++) { Node attr = node.getAttributes().item(i); QName key = new QName(attr.getNamespaceURI(), attr.getLocalName()); address.getOtherAttributes().put(key, attr.getTextContent()); } address.setValue(node.getTextContent()); ref.setAddress(address); } else if ("Metadata".equals(node.getLocalName())) { org.w3c.ws.addressing.MetadataType md = Factories.WSADDRESS.createMetadataType(); int numAttrs = node.getAttributes().getLength(); for (int i=0; i < numAttrs; i++) { Node attr = node.getAttributes().item(i); QName key = new QName(attr.getNamespaceURI(), attr.getLocalName()); md.getOtherAttributes().put(key, attr.getTextContent()); } int numChildren = node.getChildNodes().getLength(); for (int i=0; i < numChildren; i++) { Node child = node.getChildNodes().item(i); md.getAny().add(convert(child, unmarshaller)); } ref.setMetadata(md); } else if ("ReferenceParameters".equals(node.getLocalName())) { org.w3c.ws.addressing.ReferenceParametersType params = Factories.WSADDRESS.createReferenceParametersType(); int numAttrs = node.getAttributes().getLength(); for (int i=0; i < numAttrs; i++) { Node attr = node.getAttributes().item(i); QName key = new QName(attr.getNamespaceURI(), attr.getLocalName()); params.getOtherAttributes().put(key, attr.getTextContent()); } int numChildren = node.getChildNodes().getLength(); for (int i=0; i < numChildren; i++) { Node param = node.getChildNodes().item(i); params.getAny().add(convert(param, unmarshaller)); } ref.setReferenceParameters(params); } else { ref.getAny().add(node); } } return ref; } else if (WSA04.equals(ns)) { org.xmlsoap.ws.addressing.EndpointReferenceType ref = Factories.ADDRESS.createEndpointReferenceType(); for (Object element : list) { Node node = (Node)element; if ("Address".equals(node.getLocalName())) { org.xmlsoap.ws.addressing.AttributedURI address = Factories.ADDRESS.createAttributedURI(); int numAttrs = node.getAttributes().getLength(); for (int i=0; i < numAttrs; i++) { Node attr = node.getAttributes().item(i); QName key = new QName(attr.getNamespaceURI(), attr.getLocalName()); address.getOtherAttributes().put(key, attr.getTextContent()); } address.setValue(node.getTextContent()); ref.setAddress(address); } else if ("ReferenceProperties".equals(node.getLocalName())) { org.xmlsoap.ws.addressing.ReferencePropertiesType props = Factories.ADDRESS.createReferencePropertiesType(); int numChildren = node.getChildNodes().getLength(); for (int i=0; i < numChildren; i++) { Node prop = node.getChildNodes().item(i); props.getAny().add(convert(prop, unmarshaller)); } ref.setReferenceProperties(props); } else if ("ReferenceParameters".equals(node.getLocalName())) { org.xmlsoap.ws.addressing.ReferenceParametersType params = Factories.ADDRESS.createReferenceParametersType(); int numChildren = node.getChildNodes().getLength(); for (int i=0; i < numChildren; i++) { Node param = node.getChildNodes().item(i); params.getAny().add(convert(param, unmarshaller)); } ref.setReferenceParameters(params); } else if ("PortType".equals(node.getLocalName())) { org.xmlsoap.ws.addressing.AttributedQName portType = Factories.ADDRESS.createAttributedQName(); int numAttrs = node.getAttributes().getLength(); for (int i=0; i < numAttrs; i++) { Node attr = node.getAttributes().item(i); QName key = new QName(attr.getNamespaceURI(), attr.getLocalName()); portType.getOtherAttributes().put(key, attr.getTextContent()); } portType.setValue(new QName(node.getNamespaceURI(), node.getLocalName())); ref.setPortType(portType); } else if ("ServiceName".equals(node.getLocalName())) { org.xmlsoap.ws.addressing.ServiceNameType svc = Factories.ADDRESS.createServiceNameType(); int numAttrs = node.getAttributes().getLength(); for (int i=0; i < numAttrs; i++) { Node attr = node.getAttributes().item(i); if (attr.getNamespaceURI().equals(XMLNS) && attr.getLocalName().equals("PortName")) { svc.setPortName(attr.getTextContent()); } else { QName key = new QName(attr.getNamespaceURI(), attr.getLocalName()); svc.getOtherAttributes().put(key, attr.getTextContent()); } } svc.setValue(new QName(node.getNamespaceURI(), node.getLocalName())); ref.setServiceName(svc); } else { ref.getAny().add(node); } } return ref; } else { throw new IllegalArgumentException("Namespace: " + ns); } } else { throw new IllegalArgumentException(obj == null ? "null" : obj.getClass().getName()); } } // Private /** * Attempt to unmarshal DOM node(s). */ private Object convert(Node node, Unmarshaller unmarshaller) { try { return unmarshaller.unmarshal(node); } catch (JAXBException e) { return node; } } }