W3CAddressingWSDLParserExtension.java revision 524:dcaa586ab756
1227614Sluigi/* 2227614Sluigi * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 3227614Sluigi * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4227614Sluigi * 5227614Sluigi * This code is free software; you can redistribute it and/or modify it 6227614Sluigi * under the terms of the GNU General Public License version 2 only, as 7227614Sluigi * published by the Free Software Foundation. Oracle designates this 8227614Sluigi * particular file as subject to the "Classpath" exception as provided 9227614Sluigi * by Oracle in the LICENSE file that accompanied this code. 10227614Sluigi * 11227614Sluigi * This code is distributed in the hope that it will be useful, but WITHOUT 12227614Sluigi * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13227614Sluigi * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14227614Sluigi * version 2 for more details (a copy is included in the LICENSE file that 15227614Sluigi * accompanied this code). 16227614Sluigi * 17227614Sluigi * You should have received a copy of the GNU General Public License version 18227614Sluigi * 2 along with this work; if not, write to the Free Software Foundation, 19227614Sluigi * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20227614Sluigi * 21227614Sluigi * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22227614Sluigi * or visit www.oracle.com if you need additional information or have any 23227614Sluigi * questions. 24227614Sluigi */ 25227614Sluigi 26232238Sluigipackage com.sun.xml.internal.ws.wsdl.parser; 27227614Sluigi 28227614Sluigiimport com.sun.xml.internal.ws.api.addressing.AddressingVersion; 29232238Sluigiimport com.sun.xml.internal.ws.api.model.wsdl.WSDLFeaturedObject; 30227614Sluigiimport static com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation.ANONYMOUS; 31232238Sluigiimport com.sun.xml.internal.ws.api.model.wsdl.editable.*; 32228276Sluigiimport com.sun.xml.internal.ws.api.wsdl.parser.WSDLParserExtension; 33232238Sluigiimport com.sun.xml.internal.ws.api.wsdl.parser.WSDLParserExtensionContext; 34227614Sluigiimport com.sun.xml.internal.ws.streaming.XMLStreamReaderUtil; 35227614Sluigi 36227614Sluigiimport javax.xml.namespace.QName; 37227614Sluigiimport javax.xml.stream.XMLStreamException; 38227614Sluigiimport javax.xml.stream.XMLStreamReader; 39227614Sluigiimport javax.xml.ws.WebServiceException; 40227614Sluigiimport javax.xml.ws.soap.AddressingFeature; 41227614Sluigi 42227614Sluigi/** 43227614Sluigi * W3C WS-Addressing Runtime WSDL parser extension 44231594Sluigi * 45227614Sluigi * @author Arun Gupta 46231594Sluigi */ 47227614Sluigipublic class W3CAddressingWSDLParserExtension extends WSDLParserExtension { 48227614Sluigi @Override 49227614Sluigi public boolean bindingElements(EditableWSDLBoundPortType binding, XMLStreamReader reader) { 50227614Sluigi return addressibleElement(reader, binding); 51227614Sluigi } 52227614Sluigi 53227614Sluigi @Override 54227614Sluigi public boolean portElements(EditableWSDLPort port, XMLStreamReader reader) { 55227614Sluigi return addressibleElement(reader, port); 56227614Sluigi } 57227614Sluigi 58227614Sluigi private boolean addressibleElement(XMLStreamReader reader, WSDLFeaturedObject binding) { 59227614Sluigi QName ua = reader.getName(); 60227614Sluigi if (ua.equals(AddressingVersion.W3C.wsdlExtensionTag)) { 61227614Sluigi String required = reader.getAttributeValue(WSDLConstants.NS_WSDL, "required"); 62227614Sluigi binding.addFeature(new AddressingFeature(true, Boolean.parseBoolean(required))); 63227614Sluigi XMLStreamReaderUtil.skipElement(reader); 64227614Sluigi return true; // UsingAddressing is consumed 65227614Sluigi } 66227614Sluigi 67227614Sluigi return false; 68227614Sluigi } 69227614Sluigi 70227614Sluigi @Override 71227614Sluigi public boolean bindingOperationElements(EditableWSDLBoundOperation operation, XMLStreamReader reader) { 72227614Sluigi EditableWSDLBoundOperation edit = (EditableWSDLBoundOperation) operation; 73232238Sluigi 74227614Sluigi QName anon = reader.getName(); 75227614Sluigi if (anon.equals(AddressingVersion.W3C.wsdlAnonymousTag)) { 76228276Sluigi try { 77228276Sluigi String value = reader.getElementText(); 78228276Sluigi if (value == null || value.trim().equals("")) { 79228276Sluigi throw new WebServiceException("Null values not permitted in wsaw:Anonymous."); 80228276Sluigi // TODO: throw exception only if wsdl:required=true 81228276Sluigi // TODO: is this the right exception ? 82228276Sluigi } else if (value.equals("optional")) { 83232238Sluigi edit.setAnonymous(ANONYMOUS.optional); 84228276Sluigi } else if (value.equals("required")) { 85228276Sluigi edit.setAnonymous(ANONYMOUS.required); 86228276Sluigi } else if (value.equals("prohibited")) { 87228276Sluigi edit.setAnonymous(ANONYMOUS.prohibited); 88228276Sluigi } else { 89228276Sluigi throw new WebServiceException("wsaw:Anonymous value \"" + value + "\" not understood."); 90228276Sluigi // TODO: throw exception only if wsdl:required=true 91228276Sluigi // TODO: is this the right exception ? 92228276Sluigi } 93228276Sluigi } catch (XMLStreamException e) { 94228276Sluigi throw new WebServiceException(e); // TODO: is this the correct behavior ? 95228276Sluigi } 96228276Sluigi 97228276Sluigi return true; // consumed the element 98228276Sluigi } 99228276Sluigi 100228276Sluigi return false; 101228276Sluigi } 102228276Sluigi 103228276Sluigi public void portTypeOperationInputAttributes(EditableWSDLInput input, XMLStreamReader reader) { 104228276Sluigi String action = ParserUtil.getAttribute(reader, getWsdlActionTag()); 105228276Sluigi if (action != null) { 106228276Sluigi input.setAction(action); 107228276Sluigi input.setDefaultAction(false); 108231778Sluigi } 109228276Sluigi } 110228276Sluigi 111231778Sluigi 112228276Sluigi public void portTypeOperationOutputAttributes(EditableWSDLOutput output, XMLStreamReader reader) { 113228276Sluigi String action = ParserUtil.getAttribute(reader, getWsdlActionTag()); 114228276Sluigi if (action != null) { 115228276Sluigi output.setAction(action); 116228276Sluigi output.setDefaultAction(false); 117228276Sluigi } 118228276Sluigi } 119228276Sluigi 120228276Sluigi 121228276Sluigi public void portTypeOperationFaultAttributes(EditableWSDLFault fault, XMLStreamReader reader) { 122228276Sluigi String action = ParserUtil.getAttribute(reader, getWsdlActionTag()); 123232238Sluigi if (action != null) { 124228276Sluigi fault.setAction(action); 125228276Sluigi fault.setDefaultAction(false); 126231594Sluigi } 127227614Sluigi } 128231594Sluigi 129232238Sluigi /** 130231796Sluigi * Process wsdl:portType operation after the entire WSDL model has been populated. 131227614Sluigi * The task list includes: <p> 132232238Sluigi * <ul> 133227614Sluigi * <li>Patch the value of UsingAddressing in wsdl:port and wsdl:binding</li> 134227614Sluigi * <li>Populate actions for the messages that do not have an explicit wsaw:Action</li> 135227614Sluigi * <li>Patch the default value of wsaw:Anonymous=optional if none is specified</li> 136227614Sluigi * </ul> 137232238Sluigi * @param context 138227614Sluigi */ 139228276Sluigi @Override 140227614Sluigi public void finished(WSDLParserExtensionContext context) { 141227614Sluigi EditableWSDLModel model = context.getWSDLModel(); 142227614Sluigi for (EditableWSDLService service : model.getServices().values()) { 143227614Sluigi for (EditableWSDLPort port : service.getPorts()) { 144227614Sluigi EditableWSDLBoundPortType binding = port.getBinding(); 145227614Sluigi 146232238Sluigi // populate actions for the messages that do not have an explicit wsaw:Action 147232238Sluigi populateActions(binding); 148232238Sluigi 149231778Sluigi // patch the default value of wsaw:Anonymous=optional if none is specified 150231778Sluigi patchAnonymousDefault(binding); 151232238Sluigi } 152232238Sluigi } 153231881Sluigi } 154232238Sluigi 155227614Sluigi protected String getNamespaceURI() { 156232238Sluigi return AddressingVersion.W3C.wsdlNsUri; 157228276Sluigi } 158228276Sluigi 159227614Sluigi protected QName getWsdlActionTag() { 160227614Sluigi return AddressingVersion.W3C.wsdlActionTag; 161227614Sluigi } 162231778Sluigi /** 163231778Sluigi * Populate all the Actions 164232238Sluigi * 165227614Sluigi * @param binding soapbinding:operation 166227614Sluigi */ 167227614Sluigi private void populateActions(EditableWSDLBoundPortType binding) { 168227614Sluigi EditableWSDLPortType porttype = binding.getPortType(); 169227614Sluigi for (EditableWSDLOperation o : porttype.getOperations()) { 170227614Sluigi // TODO: this may be performance intensive. Alternatively default action 171227614Sluigi // TODO: can be calculated when the operation is actually invoked. 172228276Sluigi EditableWSDLBoundOperation wboi = binding.get(o.getName()); 173227614Sluigi 174228276Sluigi if (wboi == null) { 175229939Sluigi //If this operation is unbound set the action to default 176232238Sluigi o.getInput().setAction(defaultInputAction(o)); 177227614Sluigi continue; 178227614Sluigi } 179232238Sluigi String soapAction = wboi.getSOAPAction(); 180232238Sluigi if (o.getInput().getAction() == null || o.getInput().getAction().equals("")) { 181232238Sluigi // explicit wsaw:Action is not specified 182232238Sluigi 183227614Sluigi if (soapAction != null && !soapAction.equals("")) { 184227614Sluigi // if soapAction is non-empty, use that 185228276Sluigi o.getInput().setAction(soapAction); 186227614Sluigi } else { 187228276Sluigi // otherwise generate default Action 188227614Sluigi o.getInput().setAction(defaultInputAction(o)); 189232238Sluigi } 190228276Sluigi } 191227614Sluigi 192227614Sluigi // skip output and fault processing for one-way methods 193228276Sluigi if (o.getOutput() == null) 194227614Sluigi continue; 195228276Sluigi 196227614Sluigi if (o.getOutput().getAction() == null || o.getOutput().getAction().equals("")) { 197228276Sluigi o.getOutput().setAction(defaultOutputAction(o)); 198228276Sluigi } 199228276Sluigi 200228276Sluigi if (o.getFaults() == null || !o.getFaults().iterator().hasNext()) 201228276Sluigi continue; 202228276Sluigi 203231778Sluigi for (EditableWSDLFault f : o.getFaults()) { 204228276Sluigi if (f.getAction() == null || f.getAction().equals("")) { 205228276Sluigi f.setAction(defaultFaultAction(f.getName(), o)); 206228276Sluigi } 207228276Sluigi 208228276Sluigi } 209232238Sluigi } 210228276Sluigi } 211228276Sluigi 212228276Sluigi /** 213228276Sluigi * Patch the default value of wsaw:Anonymous=optional if none is specified 214228276Sluigi * 215228276Sluigi * @param binding WSDLBoundPortTypeImpl 216232238Sluigi */ 217231778Sluigi protected void patchAnonymousDefault(EditableWSDLBoundPortType binding) { 218231198Sluigi for (EditableWSDLBoundOperation wbo : binding.getBindingOperations()) { 219227614Sluigi if (wbo.getAnonymous() == null) 220227614Sluigi wbo.setAnonymous(ANONYMOUS.optional); 221227614Sluigi } 222227614Sluigi } 223227614Sluigi 224227614Sluigi private String defaultInputAction(EditableWSDLOperation o) { 225227614Sluigi return buildAction(o.getInput().getName(), o, false); 226228276Sluigi } 227227614Sluigi 228227614Sluigi private String defaultOutputAction(EditableWSDLOperation o) { 229231594Sluigi return buildAction(o.getOutput().getName(), o, false); 230227614Sluigi } 231231594Sluigi 232232238Sluigi private String defaultFaultAction(String name, EditableWSDLOperation o) { 233231796Sluigi return buildAction(name, o, true); 234227614Sluigi } 235232238Sluigi 236232238Sluigi protected static final String buildAction(String name, EditableWSDLOperation o, boolean isFault) { 237232238Sluigi String tns = o.getName().getNamespaceURI(); 238227614Sluigi 239228276Sluigi String delim = SLASH_DELIMITER; 240227614Sluigi 241227614Sluigi // TODO: is this the correct way to find the separator ? 242227614Sluigi if (!tns.startsWith("http")) 243227614Sluigi delim = COLON_DELIMITER; 244231778Sluigi 245227614Sluigi if (tns.endsWith(delim)) 246227614Sluigi tns = tns.substring(0, tns.length()-1); 247227614Sluigi 248227614Sluigi if (o.getPortTypeName() == null) 249232238Sluigi throw new WebServiceException("\"" + o.getName() + "\" operation's owning portType name is null."); 250232238Sluigi 251232238Sluigi return tns + 252231778Sluigi delim + 253231778Sluigi o.getPortTypeName().getLocalPart() + 254232238Sluigi delim + 255232238Sluigi (isFault ? o.getName().getLocalPart() + delim + "Fault" + delim : "") + 256232238Sluigi name; 257232238Sluigi } 258232238Sluigi 259232238Sluigi protected static final String COLON_DELIMITER = ":"; 260227614Sluigi protected static final String SLASH_DELIMITER = "/"; 261232238Sluigi} 262232238Sluigi