|
1 /* |
|
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. Oracle designates this |
|
8 * particular file as subject to the "Classpath" exception as provided |
|
9 * by Oracle in the LICENSE file that accompanied this code. |
|
10 * |
|
11 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 * version 2 for more details (a copy is included in the LICENSE file that |
|
15 * accompanied this code). |
|
16 * |
|
17 * You should have received a copy of the GNU General Public License version |
|
18 * 2 along with this work; if not, write to the Free Software Foundation, |
|
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 * |
|
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 * or visit www.oracle.com if you need additional information or have any |
|
23 * questions. |
|
24 */ |
|
25 |
|
26 package com.sun.tools.internal.ws.processor.modeler.wsdl; |
|
27 |
|
28 import com.sun.tools.internal.ws.processor.generator.Names; |
|
29 import static com.sun.tools.internal.ws.processor.modeler.wsdl.WSDLModelerBase.getExtensionOfType; |
|
30 import com.sun.tools.internal.ws.wscompile.ErrorReceiver; |
|
31 import com.sun.tools.internal.ws.wscompile.WsimportOptions; |
|
32 import com.sun.tools.internal.ws.wscompile.Options; |
|
33 import com.sun.tools.internal.ws.wsdl.document.*; |
|
34 import com.sun.tools.internal.ws.wsdl.document.jaxws.JAXWSBinding; |
|
35 import com.sun.tools.internal.ws.wsdl.document.schema.SchemaKinds; |
|
36 import com.sun.tools.internal.ws.wsdl.document.soap.SOAP12Binding; |
|
37 import com.sun.tools.internal.ws.wsdl.document.soap.SOAPBinding; |
|
38 import org.xml.sax.InputSource; |
|
39 |
|
40 import javax.xml.namespace.QName; |
|
41 import java.io.ByteArrayInputStream; |
|
42 import java.io.StringReader; |
|
43 import java.io.StringWriter; |
|
44 import java.nio.charset.StandardCharsets; |
|
45 import java.text.MessageFormat; |
|
46 import java.util.*; |
|
47 |
|
48 |
|
49 /** |
|
50 * Builds all possible pseudo schemas for async operation ResponseBean to feed to XJC. |
|
51 * |
|
52 * @author Vivek Pandey |
|
53 */ |
|
54 public class PseudoSchemaBuilder { |
|
55 |
|
56 private final StringWriter buf = new StringWriter(); |
|
57 private final WSDLDocument wsdlDocument; |
|
58 private WSDLModeler wsdlModeler; |
|
59 private final List<InputSource> schemas = new ArrayList<InputSource>(); |
|
60 private final HashMap<QName, Port> bindingNameToPortMap = new HashMap<QName, Port>(); |
|
61 private static final String w3ceprSchemaBinding = "<bindings\n" + |
|
62 " xmlns=\"http://java.sun.com/xml/ns/jaxb\"\n" + |
|
63 " xmlns:wsa=\"http://www.w3.org/2005/08/addressing\"\n" + |
|
64 " xmlns:xjc=\"http://java.sun.com/xml/ns/jaxb/xjc\"\n" + |
|
65 " version=\"2.1\">\n" + |
|
66 " \n" + |
|
67 " <bindings scd=\"x-schema::wsa\" if-exists=\"true\">\n" + |
|
68 //comment the following, otw JAXB won't generate ObjectFactory, classes from wsa schema. See JAX-WS-804 |
|
69 // " <schemaBindings map=\"false\" />\n" + |
|
70 " <bindings scd=\"wsa:EndpointReference\">\n" + |
|
71 " <class ref=\"javax.xml.ws.wsaddressing.W3CEndpointReference\" xjc:recursive=\"true\"/>\n" + |
|
72 " </bindings>\n" + |
|
73 " <bindings scd=\"~wsa:EndpointReferenceType\">\n" + |
|
74 " <class ref=\"javax.xml.ws.wsaddressing.W3CEndpointReference\" xjc:recursive=\"true\"/>\n" + |
|
75 " </bindings>\n" + |
|
76 " </bindings>\n" + |
|
77 "</bindings>"; |
|
78 |
|
79 private static final String memberSubmissionEPR = "<bindings\n" + |
|
80 " xmlns=\"http://java.sun.com/xml/ns/jaxb\"\n" + |
|
81 " xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/08/addressing\"\n" + |
|
82 " version=\"2.1\">\n" + |
|
83 " \n" + |
|
84 " <bindings scd=\"x-schema::wsa\" if-exists=\"true\">\n" + |
|
85 //comment the following, otw JAXB won't generate ObjectFactory, classes from wsa schema. See JAX-WS-804 |
|
86 // " <schemaBindings map=\"false\" />\n" + |
|
87 " <bindings scd=\"wsa:EndpointReference\">\n" + |
|
88 " <class ref=\"com.sun.xml.internal.ws.developer.MemberSubmissionEndpointReference\"/>\n" + |
|
89 " </bindings>\n" + |
|
90 " <bindings scd=\"~wsa:EndpointReferenceType\">\n" + |
|
91 " <class ref=\"com.sun.xml.internal.ws.developer.MemberSubmissionEndpointReference\"/>\n" + |
|
92 " </bindings>\n" + |
|
93 " </bindings>\n" + |
|
94 "</bindings>"; |
|
95 |
|
96 private final static String sysId = "http://dummy.pseudo-schema#schema"; |
|
97 |
|
98 private WsimportOptions options; |
|
99 public static List<InputSource> build(WSDLModeler wsdlModeler, WsimportOptions options, ErrorReceiver errReceiver) { |
|
100 PseudoSchemaBuilder b = new PseudoSchemaBuilder(wsdlModeler.document); |
|
101 b.wsdlModeler = wsdlModeler; |
|
102 b.options = options; |
|
103 b.build(); |
|
104 int i; |
|
105 for(i = 0; i < b.schemas.size(); i++){ |
|
106 InputSource is = b.schemas.get(i); |
|
107 is.setSystemId(sysId+(i + 1)); |
|
108 } |
|
109 //add w3c EPR binding |
|
110 if(!(options.noAddressingBbinding) && options.target.isLaterThan(Options.Target.V2_1)){ |
|
111 InputSource is = new InputSource(new ByteArrayInputStream(w3ceprSchemaBinding.getBytes(StandardCharsets.UTF_8))); |
|
112 is.setSystemId(sysId+(++i +1)); |
|
113 b.schemas.add(is); |
|
114 } |
|
115 |
|
116 |
|
117 //TODO: uncomment after JAXB fixes the issue related to passing multiples of such bindings |
|
118 //add member submission EPR binding |
|
119 // InputSource is1 = new InputSource(new ByteArrayInputStream(memberSubmissionEPR.getBytes())); |
|
120 // is1.setSystemId(sysId+(++i + 1)); |
|
121 // b.schemas.add(is1); |
|
122 |
|
123 return b.schemas; |
|
124 } |
|
125 |
|
126 |
|
127 private PseudoSchemaBuilder(WSDLDocument _wsdl) { |
|
128 this.wsdlDocument = _wsdl; |
|
129 } |
|
130 |
|
131 private void build() { |
|
132 for(Iterator<Service> itr=wsdlDocument.getDefinitions().services(); itr.hasNext(); ) { |
|
133 build(itr.next()); |
|
134 } |
|
135 } |
|
136 |
|
137 private void build(Service service) { |
|
138 for( Iterator<Port> itr=service.ports(); itr.hasNext(); ) { |
|
139 build(itr.next() ); |
|
140 } |
|
141 } |
|
142 |
|
143 private void build(Port port) { |
|
144 if(wsdlModeler.isProvider(port)) |
|
145 return; |
|
146 Binding binding = port.resolveBinding(wsdlDocument); |
|
147 |
|
148 SOAPBinding soapBinding = |
|
149 (SOAPBinding)getExtensionOfType(binding, SOAPBinding.class); |
|
150 //lets try and see if its SOAP 1.2. dont worry about extension flag, its |
|
151 // handled much earlier |
|
152 if (soapBinding == null) { |
|
153 soapBinding = |
|
154 (SOAPBinding)getExtensionOfType(binding, SOAP12Binding.class); |
|
155 } |
|
156 if(soapBinding == null) |
|
157 return; |
|
158 PortType portType = binding.resolvePortType(wsdlDocument); |
|
159 |
|
160 QName bindingName = WSDLModelerBase.getQNameOf(binding); |
|
161 |
|
162 //we dont want to process the port bound to the binding processed earlier |
|
163 if(bindingNameToPortMap.containsKey(bindingName)) |
|
164 return; |
|
165 |
|
166 bindingNameToPortMap.put(bindingName, port); |
|
167 |
|
168 |
|
169 for(Iterator itr=binding.operations(); itr.hasNext();){ |
|
170 BindingOperation bindingOperation = (BindingOperation)itr.next(); |
|
171 |
|
172 // get only the bounded operations |
|
173 Set boundedOps = portType.getOperationsNamed(bindingOperation.getName()); |
|
174 if(boundedOps.size() != 1) |
|
175 continue; |
|
176 Operation operation = (Operation)boundedOps.iterator().next(); |
|
177 |
|
178 // No pseudo schema required for doc/lit |
|
179 if(wsdlModeler.isAsync(portType, operation)){ |
|
180 buildAsync(portType, operation, bindingOperation); |
|
181 } |
|
182 } |
|
183 } |
|
184 |
|
185 /** |
|
186 * @param portType |
|
187 * @param operation |
|
188 * @param bindingOperation |
|
189 */ |
|
190 private void buildAsync(PortType portType, Operation operation, BindingOperation bindingOperation) { |
|
191 String operationName = getCustomizedOperationName(operation);//operation.getName(); |
|
192 if(operationName == null) |
|
193 return; |
|
194 Message outputMessage = null; |
|
195 if(operation.getOutput() != null) |
|
196 outputMessage = operation.getOutput().resolveMessage(wsdlDocument); |
|
197 if(outputMessage != null){ |
|
198 List<MessagePart> allParts = new ArrayList<MessagePart>(outputMessage.getParts()); |
|
199 if(options != null && options.additionalHeaders) { |
|
200 List<MessagePart> addtionalHeaderParts = wsdlModeler.getAdditionHeaderParts(bindingOperation, outputMessage, false); |
|
201 allParts.addAll(addtionalHeaderParts); |
|
202 } |
|
203 if(allParts.size() > 1) |
|
204 build(getOperationName(operationName), allParts); |
|
205 } |
|
206 |
|
207 } |
|
208 |
|
209 private String getCustomizedOperationName(Operation operation) { |
|
210 JAXWSBinding jaxwsCustomization = (JAXWSBinding)getExtensionOfType(operation, JAXWSBinding.class); |
|
211 String operationName = (jaxwsCustomization != null)?((jaxwsCustomization.getMethodName() != null)?jaxwsCustomization.getMethodName().getName():null):null; |
|
212 if(operationName != null){ |
|
213 if(Names.isJavaReservedWord(operationName)){ |
|
214 return null; |
|
215 } |
|
216 |
|
217 return operationName; |
|
218 } |
|
219 return operation.getName(); |
|
220 } |
|
221 |
|
222 private void writeImports(QName elementName, List<MessagePart> parts){ |
|
223 Set<String> uris = new HashSet<String>(); |
|
224 for(MessagePart p:parts){ |
|
225 String ns = p.getDescriptor().getNamespaceURI(); |
|
226 if(!uris.contains(ns) && !ns.equals("http://www.w3.org/2001/XMLSchema") && !ns.equals(elementName.getNamespaceURI())){ |
|
227 print("<xs:import namespace=''{0}''/>", ns); |
|
228 uris.add(ns); |
|
229 } |
|
230 } |
|
231 } |
|
232 |
|
233 boolean asyncRespBeanBinding = false; |
|
234 private void build(QName elementName, List<MessagePart> allParts){ |
|
235 |
|
236 print( |
|
237 "<xs:schema xmlns:xs=''http://www.w3.org/2001/XMLSchema''" + |
|
238 " xmlns:jaxb=''http://java.sun.com/xml/ns/jaxb''" + |
|
239 " xmlns:xjc=''http://java.sun.com/xml/ns/jaxb/xjc''" + |
|
240 " jaxb:extensionBindingPrefixes=''xjc''" + |
|
241 " jaxb:version=''1.0''" + |
|
242 " targetNamespace=''{0}''>", |
|
243 elementName.getNamespaceURI()); |
|
244 |
|
245 writeImports(elementName, allParts); |
|
246 |
|
247 if(!asyncRespBeanBinding){ |
|
248 print( |
|
249 "<xs:annotation><xs:appinfo>" + |
|
250 " <jaxb:schemaBindings>" + |
|
251 " <jaxb:package name=''{0}'' />" + |
|
252 " </jaxb:schemaBindings>" + |
|
253 "</xs:appinfo></xs:annotation>", |
|
254 wsdlModeler.getJavaPackage() ); |
|
255 asyncRespBeanBinding = true; |
|
256 } |
|
257 |
|
258 print("<xs:element name=''{0}''>", elementName.getLocalPart()); |
|
259 print("<xs:complexType>"); |
|
260 print("<xs:sequence>"); |
|
261 |
|
262 |
|
263 for(MessagePart p:allParts) { |
|
264 //rpclit wsdl:part must reference schema type not element, also it must exclude headers and mime parts |
|
265 if(p.getDescriptorKind() == SchemaKinds.XSD_ELEMENT){ |
|
266 print("<xs:element ref=''types:{0}'' xmlns:types=''{1}''/>",p.getDescriptor().getLocalPart(), p.getDescriptor().getNamespaceURI()); |
|
267 }else{ |
|
268 print("<xs:element name=''{0}'' type=''{1}'' xmlns=''{2}'' />", |
|
269 p.getName(), |
|
270 p.getDescriptor().getLocalPart(), |
|
271 p.getDescriptor().getNamespaceURI() ); |
|
272 } |
|
273 } |
|
274 |
|
275 print("</xs:sequence>"); |
|
276 print("</xs:complexType>"); |
|
277 print("</xs:element>"); |
|
278 print("</xs:schema>"); |
|
279 |
|
280 // reset the StringWriter, so that next operation element could be written |
|
281 if(buf.toString().length() > 0){ |
|
282 //System.out.println("Response bean Schema for operation========> "+ elementName+"\n\n"+buf); |
|
283 InputSource is = new InputSource(new StringReader(buf.toString())); |
|
284 schemas.add(is); |
|
285 buf.getBuffer().setLength(0); |
|
286 } |
|
287 } |
|
288 |
|
289 private QName getOperationName(String operationName){ |
|
290 if(operationName == null) |
|
291 return null; |
|
292 // String namespaceURI = wsdlDocument.getDefinitions().getTargetNamespaceURI()+"?"+portType.getName()+"?" + operationName; |
|
293 String namespaceURI = ""; |
|
294 return new QName(namespaceURI, operationName+"Response"); |
|
295 } |
|
296 |
|
297 private void print( String msg ) { |
|
298 print( msg, new Object[0] ); |
|
299 } |
|
300 private void print( String msg, Object arg1 ) { |
|
301 print( msg, new Object[]{arg1} ); |
|
302 } |
|
303 private void print( String msg, Object arg1, Object arg2 ) { |
|
304 print( msg, new Object[]{arg1, arg2} ); |
|
305 } |
|
306 private void print( String msg, Object arg1, Object arg2, Object arg3 ) { |
|
307 print( msg, new Object[]{arg1,arg2,arg3} ); |
|
308 } |
|
309 private void print( String msg, Object[] args ) { |
|
310 buf.write(MessageFormat.format(msg,args)); |
|
311 buf.write('\n'); |
|
312 } |
|
313 |
|
314 } |