1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/tools/internal/ws/processor/modeler/wsdl/PseudoSchemaBuilder.java Wed Apr 27 01:27:09 2016 +0800 1.3 @@ -0,0 +1,314 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.internal.ws.processor.modeler.wsdl; 1.30 + 1.31 +import com.sun.tools.internal.ws.processor.generator.Names; 1.32 +import static com.sun.tools.internal.ws.processor.modeler.wsdl.WSDLModelerBase.getExtensionOfType; 1.33 +import com.sun.tools.internal.ws.wscompile.ErrorReceiver; 1.34 +import com.sun.tools.internal.ws.wscompile.WsimportOptions; 1.35 +import com.sun.tools.internal.ws.wscompile.Options; 1.36 +import com.sun.tools.internal.ws.wsdl.document.*; 1.37 +import com.sun.tools.internal.ws.wsdl.document.jaxws.JAXWSBinding; 1.38 +import com.sun.tools.internal.ws.wsdl.document.schema.SchemaKinds; 1.39 +import com.sun.tools.internal.ws.wsdl.document.soap.SOAP12Binding; 1.40 +import com.sun.tools.internal.ws.wsdl.document.soap.SOAPBinding; 1.41 +import org.xml.sax.InputSource; 1.42 + 1.43 +import javax.xml.namespace.QName; 1.44 +import java.io.ByteArrayInputStream; 1.45 +import java.io.StringReader; 1.46 +import java.io.StringWriter; 1.47 +import java.nio.charset.StandardCharsets; 1.48 +import java.text.MessageFormat; 1.49 +import java.util.*; 1.50 + 1.51 + 1.52 +/** 1.53 + * Builds all possible pseudo schemas for async operation ResponseBean to feed to XJC. 1.54 + * 1.55 + * @author Vivek Pandey 1.56 + */ 1.57 +public class PseudoSchemaBuilder { 1.58 + 1.59 + private final StringWriter buf = new StringWriter(); 1.60 + private final WSDLDocument wsdlDocument; 1.61 + private WSDLModeler wsdlModeler; 1.62 + private final List<InputSource> schemas = new ArrayList<InputSource>(); 1.63 + private final HashMap<QName, Port> bindingNameToPortMap = new HashMap<QName, Port>(); 1.64 + private static final String w3ceprSchemaBinding = "<bindings\n" + 1.65 + " xmlns=\"http://java.sun.com/xml/ns/jaxb\"\n" + 1.66 + " xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"\n" + 1.67 + " xmlns:xjc=\"http://java.sun.com/xml/ns/jaxb/xjc\"\n" + 1.68 + " version=\"2.1\">\n" + 1.69 + " \n" + 1.70 + " <bindings scd=\"x-schema::wsa\" if-exists=\"true\">\n" + 1.71 + //comment the following, otw JAXB won't generate ObjectFactory, classes from wsa schema. See JAX-WS-804 1.72 + // " <schemaBindings map=\"false\" />\n" + 1.73 + " <bindings scd=\"wsa:EndpointReference\">\n" + 1.74 + " <class ref=\"javax.xml.ws.wsaddressing.W3CEndpointReference\" xjc:recursive=\"true\"/>\n" + 1.75 + " </bindings>\n" + 1.76 + " <bindings scd=\"~wsa:EndpointReferenceType\">\n" + 1.77 + " <class ref=\"javax.xml.ws.wsaddressing.W3CEndpointReference\" xjc:recursive=\"true\"/>\n" + 1.78 + " </bindings>\n" + 1.79 + " </bindings>\n" + 1.80 + "</bindings>"; 1.81 + 1.82 + private static final String memberSubmissionEPR = "<bindings\n" + 1.83 + " xmlns=\"http://java.sun.com/xml/ns/jaxb\"\n" + 1.84 + " xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\"\n" + 1.85 + " version=\"2.1\">\n" + 1.86 + " \n" + 1.87 + " <bindings scd=\"x-schema::wsa\" if-exists=\"true\">\n" + 1.88 +//comment the following, otw JAXB won't generate ObjectFactory, classes from wsa schema. See JAX-WS-804 1.89 +// " <schemaBindings map=\"false\" />\n" + 1.90 + " <bindings scd=\"wsa:EndpointReference\">\n" + 1.91 + " <class ref=\"com.sun.xml.internal.ws.developer.MemberSubmissionEndpointReference\"/>\n" + 1.92 + " </bindings>\n" + 1.93 + " <bindings scd=\"~wsa:EndpointReferenceType\">\n" + 1.94 + " <class ref=\"com.sun.xml.internal.ws.developer.MemberSubmissionEndpointReference\"/>\n" + 1.95 + " </bindings>\n" + 1.96 + " </bindings>\n" + 1.97 + "</bindings>"; 1.98 + 1.99 + private final static String sysId = "http://dummy.pseudo-schema#schema"; 1.100 + 1.101 + private WsimportOptions options; 1.102 + public static List<InputSource> build(WSDLModeler wsdlModeler, WsimportOptions options, ErrorReceiver errReceiver) { 1.103 + PseudoSchemaBuilder b = new PseudoSchemaBuilder(wsdlModeler.document); 1.104 + b.wsdlModeler = wsdlModeler; 1.105 + b.options = options; 1.106 + b.build(); 1.107 + int i; 1.108 + for(i = 0; i < b.schemas.size(); i++){ 1.109 + InputSource is = b.schemas.get(i); 1.110 + is.setSystemId(sysId+(i + 1)); 1.111 + } 1.112 + //add w3c EPR binding 1.113 + if(!(options.noAddressingBbinding) && options.target.isLaterThan(Options.Target.V2_1)){ 1.114 + InputSource is = new InputSource(new ByteArrayInputStream(w3ceprSchemaBinding.getBytes(StandardCharsets.UTF_8))); 1.115 + is.setSystemId(sysId+(++i +1)); 1.116 + b.schemas.add(is); 1.117 + } 1.118 + 1.119 + 1.120 + //TODO: uncomment after JAXB fixes the issue related to passing multiples of such bindings 1.121 + //add member submission EPR binding 1.122 +// InputSource is1 = new InputSource(new ByteArrayInputStream(memberSubmissionEPR.getBytes())); 1.123 +// is1.setSystemId(sysId+(++i + 1)); 1.124 +// b.schemas.add(is1); 1.125 + 1.126 + return b.schemas; 1.127 + } 1.128 + 1.129 + 1.130 + private PseudoSchemaBuilder(WSDLDocument _wsdl) { 1.131 + this.wsdlDocument = _wsdl; 1.132 + } 1.133 + 1.134 + private void build() { 1.135 + for(Iterator<Service> itr=wsdlDocument.getDefinitions().services(); itr.hasNext(); ) { 1.136 + build(itr.next()); 1.137 + } 1.138 + } 1.139 + 1.140 + private void build(Service service) { 1.141 + for( Iterator<Port> itr=service.ports(); itr.hasNext(); ) { 1.142 + build(itr.next() ); 1.143 + } 1.144 + } 1.145 + 1.146 + private void build(Port port) { 1.147 + if(wsdlModeler.isProvider(port)) 1.148 + return; 1.149 + Binding binding = port.resolveBinding(wsdlDocument); 1.150 + 1.151 + SOAPBinding soapBinding = 1.152 + (SOAPBinding)getExtensionOfType(binding, SOAPBinding.class); 1.153 + //lets try and see if its SOAP 1.2. dont worry about extension flag, its 1.154 + // handled much earlier 1.155 + if (soapBinding == null) { 1.156 + soapBinding = 1.157 + (SOAPBinding)getExtensionOfType(binding, SOAP12Binding.class); 1.158 + } 1.159 + if(soapBinding == null) 1.160 + return; 1.161 + PortType portType = binding.resolvePortType(wsdlDocument); 1.162 + 1.163 + QName bindingName = WSDLModelerBase.getQNameOf(binding); 1.164 + 1.165 + //we dont want to process the port bound to the binding processed earlier 1.166 + if(bindingNameToPortMap.containsKey(bindingName)) 1.167 + return; 1.168 + 1.169 + bindingNameToPortMap.put(bindingName, port); 1.170 + 1.171 + 1.172 + for(Iterator itr=binding.operations(); itr.hasNext();){ 1.173 + BindingOperation bindingOperation = (BindingOperation)itr.next(); 1.174 + 1.175 + // get only the bounded operations 1.176 + Set boundedOps = portType.getOperationsNamed(bindingOperation.getName()); 1.177 + if(boundedOps.size() != 1) 1.178 + continue; 1.179 + Operation operation = (Operation)boundedOps.iterator().next(); 1.180 + 1.181 + // No pseudo schema required for doc/lit 1.182 + if(wsdlModeler.isAsync(portType, operation)){ 1.183 + buildAsync(portType, operation, bindingOperation); 1.184 + } 1.185 + } 1.186 + } 1.187 + 1.188 + /** 1.189 + * @param portType 1.190 + * @param operation 1.191 + * @param bindingOperation 1.192 + */ 1.193 + private void buildAsync(PortType portType, Operation operation, BindingOperation bindingOperation) { 1.194 + String operationName = getCustomizedOperationName(operation);//operation.getName(); 1.195 + if(operationName == null) 1.196 + return; 1.197 + Message outputMessage = null; 1.198 + if(operation.getOutput() != null) 1.199 + outputMessage = operation.getOutput().resolveMessage(wsdlDocument); 1.200 + if(outputMessage != null){ 1.201 + List<MessagePart> allParts = new ArrayList<MessagePart>(outputMessage.getParts()); 1.202 + if(options != null && options.additionalHeaders) { 1.203 + List<MessagePart> addtionalHeaderParts = wsdlModeler.getAdditionHeaderParts(bindingOperation, outputMessage, false); 1.204 + allParts.addAll(addtionalHeaderParts); 1.205 + } 1.206 + if(allParts.size() > 1) 1.207 + build(getOperationName(operationName), allParts); 1.208 + } 1.209 + 1.210 + } 1.211 + 1.212 + private String getCustomizedOperationName(Operation operation) { 1.213 + JAXWSBinding jaxwsCustomization = (JAXWSBinding)getExtensionOfType(operation, JAXWSBinding.class); 1.214 + String operationName = (jaxwsCustomization != null)?((jaxwsCustomization.getMethodName() != null)?jaxwsCustomization.getMethodName().getName():null):null; 1.215 + if(operationName != null){ 1.216 + if(Names.isJavaReservedWord(operationName)){ 1.217 + return null; 1.218 + } 1.219 + 1.220 + return operationName; 1.221 + } 1.222 + return operation.getName(); 1.223 + } 1.224 + 1.225 + private void writeImports(QName elementName, List<MessagePart> parts){ 1.226 + Set<String> uris = new HashSet<String>(); 1.227 + for(MessagePart p:parts){ 1.228 + String ns = p.getDescriptor().getNamespaceURI(); 1.229 + if(!uris.contains(ns) && !ns.equals("http://www.w3.org/2001/XMLSchema") && !ns.equals(elementName.getNamespaceURI())){ 1.230 + print("<xs:import namespace=''{0}''/>", ns); 1.231 + uris.add(ns); 1.232 + } 1.233 + } 1.234 + } 1.235 + 1.236 + boolean asyncRespBeanBinding = false; 1.237 + private void build(QName elementName, List<MessagePart> allParts){ 1.238 + 1.239 + print( 1.240 + "<xs:schema xmlns:xs=''http://www.w3.org/2001/XMLSchema''" + 1.241 + " xmlns:jaxb=''http://java.sun.com/xml/ns/jaxb''" + 1.242 + " xmlns:xjc=''http://java.sun.com/xml/ns/jaxb/xjc''" + 1.243 + " jaxb:extensionBindingPrefixes=''xjc''" + 1.244 + " jaxb:version=''1.0''" + 1.245 + " targetNamespace=''{0}''>", 1.246 + elementName.getNamespaceURI()); 1.247 + 1.248 + writeImports(elementName, allParts); 1.249 + 1.250 + if(!asyncRespBeanBinding){ 1.251 + print( 1.252 + "<xs:annotation><xs:appinfo>" + 1.253 + " <jaxb:schemaBindings>" + 1.254 + " <jaxb:package name=''{0}'' />" + 1.255 + " </jaxb:schemaBindings>" + 1.256 + "</xs:appinfo></xs:annotation>", 1.257 + wsdlModeler.getJavaPackage() ); 1.258 + asyncRespBeanBinding = true; 1.259 + } 1.260 + 1.261 + print("<xs:element name=''{0}''>", elementName.getLocalPart()); 1.262 + print("<xs:complexType>"); 1.263 + print("<xs:sequence>"); 1.264 + 1.265 + 1.266 + for(MessagePart p:allParts) { 1.267 + //rpclit wsdl:part must reference schema type not element, also it must exclude headers and mime parts 1.268 + if(p.getDescriptorKind() == SchemaKinds.XSD_ELEMENT){ 1.269 + print("<xs:element ref=''types:{0}'' xmlns:types=''{1}''/>",p.getDescriptor().getLocalPart(), p.getDescriptor().getNamespaceURI()); 1.270 + }else{ 1.271 + print("<xs:element name=''{0}'' type=''{1}'' xmlns=''{2}'' />", 1.272 + p.getName(), 1.273 + p.getDescriptor().getLocalPart(), 1.274 + p.getDescriptor().getNamespaceURI() ); 1.275 + } 1.276 + } 1.277 + 1.278 + print("</xs:sequence>"); 1.279 + print("</xs:complexType>"); 1.280 + print("</xs:element>"); 1.281 + print("</xs:schema>"); 1.282 + 1.283 + // reset the StringWriter, so that next operation element could be written 1.284 + if(buf.toString().length() > 0){ 1.285 + //System.out.println("Response bean Schema for operation========> "+ elementName+"\n\n"+buf); 1.286 + InputSource is = new InputSource(new StringReader(buf.toString())); 1.287 + schemas.add(is); 1.288 + buf.getBuffer().setLength(0); 1.289 + } 1.290 + } 1.291 + 1.292 + private QName getOperationName(String operationName){ 1.293 + if(operationName == null) 1.294 + return null; 1.295 +// String namespaceURI = wsdlDocument.getDefinitions().getTargetNamespaceURI()+"?"+portType.getName()+"?" + operationName; 1.296 + String namespaceURI = ""; 1.297 + return new QName(namespaceURI, operationName+"Response"); 1.298 + } 1.299 + 1.300 + private void print( String msg ) { 1.301 + print( msg, new Object[0] ); 1.302 + } 1.303 + private void print( String msg, Object arg1 ) { 1.304 + print( msg, new Object[]{arg1} ); 1.305 + } 1.306 + private void print( String msg, Object arg1, Object arg2 ) { 1.307 + print( msg, new Object[]{arg1, arg2} ); 1.308 + } 1.309 + private void print( String msg, Object arg1, Object arg2, Object arg3 ) { 1.310 + print( msg, new Object[]{arg1,arg2,arg3} ); 1.311 + } 1.312 + private void print( String msg, Object[] args ) { 1.313 + buf.write(MessageFormat.format(msg,args)); 1.314 + buf.write('\n'); 1.315 + } 1.316 + 1.317 +}