|
1 /* |
|
2 * Copyright (c) 1997, 2013, 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.generator; |
|
27 |
|
28 import com.sun.codemodel.internal.ClassType; |
|
29 import com.sun.codemodel.internal.JAnnotationUse; |
|
30 import com.sun.codemodel.internal.JBlock; |
|
31 import com.sun.codemodel.internal.JCatchBlock; |
|
32 import com.sun.codemodel.internal.JClass; |
|
33 import com.sun.codemodel.internal.JClassAlreadyExistsException; |
|
34 import com.sun.codemodel.internal.JCommentPart; |
|
35 import com.sun.codemodel.internal.JConditional; |
|
36 import com.sun.codemodel.internal.JDefinedClass; |
|
37 import com.sun.codemodel.internal.JDocComment; |
|
38 import com.sun.codemodel.internal.JExpr; |
|
39 import com.sun.codemodel.internal.JFieldVar; |
|
40 import com.sun.codemodel.internal.JInvocation; |
|
41 import com.sun.codemodel.internal.JMethod; |
|
42 import com.sun.codemodel.internal.JMod; |
|
43 import com.sun.codemodel.internal.JTryBlock; |
|
44 import com.sun.codemodel.internal.JType; |
|
45 import com.sun.codemodel.internal.JVar; |
|
46 import com.sun.tools.internal.ws.processor.model.Model; |
|
47 import com.sun.tools.internal.ws.processor.model.ModelProperties; |
|
48 import com.sun.tools.internal.ws.processor.model.Port; |
|
49 import com.sun.tools.internal.ws.processor.model.Service; |
|
50 import com.sun.tools.internal.ws.processor.model.java.JavaInterface; |
|
51 import com.sun.tools.internal.ws.resources.GeneratorMessages; |
|
52 import com.sun.tools.internal.ws.wscompile.ErrorReceiver; |
|
53 import com.sun.tools.internal.ws.wscompile.Options; |
|
54 import com.sun.tools.internal.ws.wscompile.WsimportOptions; |
|
55 import com.sun.tools.internal.ws.wsdl.document.PortType; |
|
56 import com.sun.xml.internal.ws.spi.db.BindingHelper; |
|
57 |
|
58 import org.xml.sax.Locator; |
|
59 |
|
60 import javax.xml.namespace.QName; |
|
61 import javax.xml.ws.WebEndpoint; |
|
62 import javax.xml.ws.WebServiceClient; |
|
63 import javax.xml.ws.WebServiceFeature; |
|
64 import javax.xml.ws.WebServiceException; |
|
65 import java.net.MalformedURLException; |
|
66 import java.net.URL; |
|
67 |
|
68 import com.sun.xml.internal.ws.util.ServiceFinder; |
|
69 import java.util.Locale; |
|
70 |
|
71 /** |
|
72 * @author WS Development Team |
|
73 * @author Jitendra Kotamraju |
|
74 */ |
|
75 public class ServiceGenerator extends GeneratorBase { |
|
76 |
|
77 public static void generate(Model model, WsimportOptions options, ErrorReceiver receiver) { |
|
78 ServiceGenerator serviceGenerator = new ServiceGenerator(model, options, receiver); |
|
79 serviceGenerator.doGeneration(); |
|
80 } |
|
81 |
|
82 private ServiceGenerator(Model model, WsimportOptions options, ErrorReceiver receiver) { |
|
83 init(model, options, receiver); |
|
84 } |
|
85 |
|
86 @Override |
|
87 public void visit(Service service) { |
|
88 JavaInterface intf = service.getJavaInterface(); |
|
89 String className = Names.customJavaTypeClassName(intf); |
|
90 if (donotOverride && GeneratorUtil.classExists(options, className)) { |
|
91 log("Class " + className + " exists. Not overriding."); |
|
92 return; |
|
93 } |
|
94 |
|
95 JDefinedClass cls; |
|
96 try { |
|
97 cls = getClass(className, ClassType.CLASS); |
|
98 } catch (JClassAlreadyExistsException e) { |
|
99 receiver.error(service.getLocator(), GeneratorMessages.GENERATOR_SERVICE_CLASS_ALREADY_EXIST(className, service.getName())); |
|
100 return; |
|
101 } |
|
102 |
|
103 cls._extends(javax.xml.ws.Service.class); |
|
104 String serviceFieldName = BindingHelper.mangleNameToClassName(service.getName().getLocalPart()).toUpperCase(Locale.ENGLISH); |
|
105 String wsdlLocationName = serviceFieldName + "_WSDL_LOCATION"; |
|
106 JFieldVar urlField = cls.field(JMod.PRIVATE | JMod.STATIC | JMod.FINAL, URL.class, wsdlLocationName); |
|
107 |
|
108 JFieldVar exField = cls.field(JMod.PRIVATE | JMod.STATIC | JMod.FINAL, WebServiceException.class, serviceFieldName+"_EXCEPTION"); |
|
109 |
|
110 |
|
111 String serviceName = serviceFieldName + "_QNAME"; |
|
112 cls.field(JMod.PRIVATE | JMod.STATIC | JMod.FINAL, QName.class, serviceName, |
|
113 JExpr._new(cm.ref(QName.class)).arg(service.getName().getNamespaceURI()).arg(service.getName().getLocalPart())); |
|
114 |
|
115 JClass qNameCls = cm.ref(QName.class); |
|
116 JInvocation inv; |
|
117 inv = JExpr._new(qNameCls); |
|
118 inv.arg("namespace"); |
|
119 inv.arg("localpart"); |
|
120 |
|
121 if (options.useBaseResourceAndURLToLoadWSDL) { |
|
122 writeClassLoaderBaseResourceWSDLLocation(className, cls, urlField, exField); |
|
123 } else if (wsdlLocation.startsWith("http://") || wsdlLocation.startsWith("https://") || wsdlLocation.startsWith("file:/")) { |
|
124 writeAbsWSDLLocation(cls, urlField, exField); |
|
125 } else if (wsdlLocation.startsWith("META-INF/")) { |
|
126 writeClassLoaderResourceWSDLLocation(className, cls, urlField, exField); |
|
127 } else { |
|
128 writeResourceWSDLLocation(className, cls, urlField, exField); |
|
129 } |
|
130 |
|
131 //write class comment - JAXWS warning |
|
132 JDocComment comment = cls.javadoc(); |
|
133 |
|
134 if (service.getJavaDoc() != null) { |
|
135 comment.add(service.getJavaDoc()); |
|
136 comment.add("\n\n"); |
|
137 } |
|
138 |
|
139 for (String doc : getJAXWSClassComment()) { |
|
140 comment.add(doc); |
|
141 } |
|
142 |
|
143 // Generating constructor |
|
144 // for e.g: public ExampleService() |
|
145 JMethod constructor1 = cls.constructor(JMod.PUBLIC); |
|
146 String constructor1Str = String.format("super(__getWsdlLocation(), %s);", serviceName); |
|
147 constructor1.body().directStatement(constructor1Str); |
|
148 |
|
149 // Generating constructor |
|
150 // for e.g: public ExampleService(WebServiceFeature ... features) |
|
151 if (options.target.isLaterThan(Options.Target.V2_2)) { |
|
152 JMethod constructor2 = cls.constructor(JMod.PUBLIC); |
|
153 constructor2.varParam(WebServiceFeature.class, "features"); |
|
154 String constructor2Str = String.format("super(__getWsdlLocation(), %s, features);", serviceName); |
|
155 constructor2.body().directStatement(constructor2Str); |
|
156 } |
|
157 |
|
158 // Generating constructor |
|
159 // for e.g: public ExampleService(URL wsdlLocation) |
|
160 if (options.target.isLaterThan(Options.Target.V2_2)) { |
|
161 JMethod constructor3 = cls.constructor(JMod.PUBLIC); |
|
162 constructor3.param(URL.class, "wsdlLocation"); |
|
163 String constructor3Str = String.format("super(wsdlLocation, %s);", serviceName); |
|
164 constructor3.body().directStatement(constructor3Str); |
|
165 } |
|
166 |
|
167 // Generating constructor |
|
168 // for e.g: public ExampleService(URL wsdlLocation, WebServiceFeature ... features) |
|
169 if (options.target.isLaterThan(Options.Target.V2_2)) { |
|
170 JMethod constructor4 = cls.constructor(JMod.PUBLIC); |
|
171 constructor4.param(URL.class, "wsdlLocation"); |
|
172 constructor4.varParam(WebServiceFeature.class, "features"); |
|
173 String constructor4Str = String.format("super(wsdlLocation, %s, features);", serviceName); |
|
174 constructor4.body().directStatement(constructor4Str); |
|
175 } |
|
176 |
|
177 // Generating constructor |
|
178 // for e.g: public ExampleService(URL wsdlLocation, QName serviceName) |
|
179 JMethod constructor5 = cls.constructor(JMod.PUBLIC); |
|
180 constructor5.param(URL.class, "wsdlLocation"); |
|
181 constructor5.param(QName.class, "serviceName"); |
|
182 constructor5.body().directStatement("super(wsdlLocation, serviceName);"); |
|
183 |
|
184 // Generating constructor |
|
185 // for e.g: public ExampleService(URL, QName, WebServiceFeature ...) |
|
186 if (options.target.isLaterThan(Options.Target.V2_2)) { |
|
187 JMethod constructor6 = cls.constructor(JMod.PUBLIC); |
|
188 constructor6.param(URL.class, "wsdlLocation"); |
|
189 constructor6.param(QName.class, "serviceName"); |
|
190 constructor6.varParam(WebServiceFeature.class, "features"); |
|
191 constructor6.body().directStatement("super(wsdlLocation, serviceName, features);"); |
|
192 } |
|
193 |
|
194 //@WebService |
|
195 JAnnotationUse webServiceClientAnn = cls.annotate(cm.ref(WebServiceClient.class)); |
|
196 writeWebServiceClientAnnotation(service, webServiceClientAnn); |
|
197 |
|
198 // additional annotations |
|
199 for (GeneratorExtension f:ServiceFinder.find(GeneratorExtension.class)) { |
|
200 f.writeWebServiceClientAnnotation(options, cm, cls); |
|
201 } |
|
202 |
|
203 |
|
204 //@HandlerChain |
|
205 writeHandlerConfig(Names.customJavaTypeClassName(service.getJavaInterface()), cls, options); |
|
206 |
|
207 for (Port port : service.getPorts()) { |
|
208 if (port.isProvider()) { |
|
209 continue; // No getXYZPort() for porvider based endpoint |
|
210 } |
|
211 |
|
212 //Get the SEI class |
|
213 JType retType; |
|
214 try { |
|
215 retType = getClass(port.getJavaInterface().getName(), ClassType.INTERFACE); |
|
216 } catch (JClassAlreadyExistsException e) { |
|
217 QName portTypeName = |
|
218 (QName) port.getProperty( |
|
219 ModelProperties.PROPERTY_WSDL_PORT_TYPE_NAME); |
|
220 Locator loc = null; |
|
221 if (portTypeName != null) { |
|
222 PortType pt = port.portTypes.get(portTypeName); |
|
223 if (pt != null) { |
|
224 loc = pt.getLocator(); |
|
225 } |
|
226 } |
|
227 receiver.error(loc, GeneratorMessages.GENERATOR_SEI_CLASS_ALREADY_EXIST(port.getJavaInterface().getName(), portTypeName)); |
|
228 return; |
|
229 } |
|
230 |
|
231 //write getXyzPort() |
|
232 writeDefaultGetPort(port, retType, cls); |
|
233 |
|
234 //write getXyzPort(WebServicesFeature...) |
|
235 if (options.target.isLaterThan(Options.Target.V2_1)) { |
|
236 writeGetPort(port, retType, cls); |
|
237 } |
|
238 } |
|
239 |
|
240 writeGetWsdlLocation(cm.ref(URL.class), cls, urlField, exField); |
|
241 } |
|
242 |
|
243 private void writeGetPort(Port port, JType retType, JDefinedClass cls) { |
|
244 JMethod m = cls.method(JMod.PUBLIC, retType, port.getPortGetter()); |
|
245 JDocComment methodDoc = m.javadoc(); |
|
246 if (port.getJavaDoc() != null) { |
|
247 methodDoc.add(port.getJavaDoc()); |
|
248 } |
|
249 JCommentPart ret = methodDoc.addReturn(); |
|
250 JCommentPart paramDoc = methodDoc.addParam("features"); |
|
251 paramDoc.append("A list of "); |
|
252 paramDoc.append("{@link " + WebServiceFeature.class.getName() + "}"); |
|
253 paramDoc.append("to configure on the proxy. Supported features not in the <code>features</code> parameter will have their default values."); |
|
254 ret.add("returns " + retType.name()); |
|
255 m.varParam(WebServiceFeature.class, "features"); |
|
256 JBlock body = m.body(); |
|
257 StringBuilder statement = new StringBuilder("return "); |
|
258 statement.append("super.getPort(new QName(\"").append(port.getName().getNamespaceURI()).append("\", \"").append(port.getName().getLocalPart()).append("\"), "); |
|
259 statement.append(retType.name()); |
|
260 statement.append(".class, features);"); |
|
261 body.directStatement(statement.toString()); |
|
262 writeWebEndpoint(port, m); |
|
263 } |
|
264 |
|
265 |
|
266 /* |
|
267 Generates the code to create URL for absolute WSDL location |
|
268 |
|
269 for e.g.: |
|
270 static { |
|
271 URL url = null; |
|
272 WebServiceException e = null; |
|
273 try { |
|
274 url = new URL("http://ExampleService.wsdl"); |
|
275 } catch (MalformedURLException ex) { |
|
276 e = new WebServiceException(ex); |
|
277 } |
|
278 EXAMPLESERVICE_WSDL_LOCATION = url; |
|
279 EXAMPLESERVICE_EXCEPTION = e; |
|
280 } |
|
281 */ |
|
282 private void writeAbsWSDLLocation(JDefinedClass cls, JFieldVar urlField, JFieldVar exField) { |
|
283 JBlock staticBlock = cls.init(); |
|
284 JVar urlVar = staticBlock.decl(cm.ref(URL.class), "url", JExpr._null()); |
|
285 JVar exVar = staticBlock.decl(cm.ref(WebServiceException.class), "e", JExpr._null()); |
|
286 |
|
287 JTryBlock tryBlock = staticBlock._try(); |
|
288 tryBlock.body().assign(urlVar, JExpr._new(cm.ref(URL.class)).arg(wsdlLocation)); |
|
289 JCatchBlock catchBlock = tryBlock._catch(cm.ref(MalformedURLException.class)); |
|
290 catchBlock.param("ex"); |
|
291 catchBlock.body().assign(exVar, JExpr._new(cm.ref(WebServiceException.class)).arg(JExpr.ref("ex"))); |
|
292 |
|
293 staticBlock.assign(urlField, urlVar); |
|
294 staticBlock.assign(exField, exVar); |
|
295 } |
|
296 |
|
297 /* |
|
298 Generates the code to create URL for WSDL location as resource |
|
299 |
|
300 for e.g.: |
|
301 static { |
|
302 EXAMPLESERVICE_WSDL_LOCATION = ExampleService.class.getResource(...); |
|
303 Exception e = null; |
|
304 if (EXAMPLESERVICE_WSDL_LOCATION == null) { |
|
305 e = new WebServiceException("..."); |
|
306 } |
|
307 EXAMPLESERVICE_EXCEPTION = e; |
|
308 } |
|
309 */ |
|
310 private void writeResourceWSDLLocation(String className, JDefinedClass cls, JFieldVar urlField, JFieldVar exField) { |
|
311 JBlock staticBlock = cls.init(); |
|
312 staticBlock.assign(urlField, JExpr.dotclass(cm.ref(className)).invoke("getResource").arg(wsdlLocation)); |
|
313 JVar exVar = staticBlock.decl(cm.ref(WebServiceException.class), "e", JExpr._null()); |
|
314 JConditional ifBlock = staticBlock._if(urlField.eq(JExpr._null())); |
|
315 ifBlock._then().assign(exVar, JExpr._new(cm.ref(WebServiceException.class)).arg( |
|
316 "Cannot find "+JExpr.quotify('\'', wsdlLocation)+" wsdl. Place the resource correctly in the classpath.")); |
|
317 staticBlock.assign(exField, exVar); |
|
318 } |
|
319 |
|
320 /* |
|
321 Generates the code to create URL for WSDL location as classloader resource |
|
322 |
|
323 for e.g.: |
|
324 static { |
|
325 EXAMPLESERVICE_WSDL_LOCATION = ExampleService.class.getClassLoader().getResource(...); |
|
326 Exception e = null; |
|
327 if (EXAMPLESERVICE_WSDL_LOCATION == null) { |
|
328 e = new WebServiceException("..."); |
|
329 } |
|
330 EXAMPLESERVICE_EXCEPTION = e; |
|
331 } |
|
332 */ |
|
333 private void writeClassLoaderResourceWSDLLocation(String className, JDefinedClass cls, JFieldVar urlField, JFieldVar exField) { |
|
334 JBlock staticBlock = cls.init(); |
|
335 staticBlock.assign(urlField, JExpr.dotclass(cm.ref(className)).invoke("getClassLoader").invoke("getResource").arg(wsdlLocation)); |
|
336 JVar exVar = staticBlock.decl(cm.ref(WebServiceException.class), "e", JExpr._null()); |
|
337 JConditional ifBlock = staticBlock._if(urlField.eq(JExpr._null())); |
|
338 ifBlock._then().assign(exVar, JExpr._new(cm.ref(WebServiceException.class)).arg( |
|
339 "Cannot find "+JExpr.quotify('\'', wsdlLocation)+" wsdl. Place the resource correctly in the classpath.")); |
|
340 staticBlock.assign(exField, exVar); |
|
341 } |
|
342 |
|
343 /* |
|
344 Generates the code to create URL for WSDL location from classloader base resource |
|
345 |
|
346 for e.g.: |
|
347 static { |
|
348 Exception e = null; |
|
349 URL url = null; |
|
350 try { |
|
351 url = new URL(ExampleService.class.getClassLoader().getResource("."), ...); |
|
352 } catch (MalformedURLException murl) { |
|
353 e = new WebServiceException(murl); |
|
354 } |
|
355 EXAMPLESERVICE_WSDL_LOCATION = url; |
|
356 EXAMPLESERVICE_EXCEPTION = e; |
|
357 } |
|
358 */ |
|
359 private void writeClassLoaderBaseResourceWSDLLocation(String className, JDefinedClass cls, JFieldVar urlField, JFieldVar exField) { |
|
360 JBlock staticBlock = cls.init(); |
|
361 JVar exVar = staticBlock.decl(cm.ref(WebServiceException.class), "e", JExpr._null()); |
|
362 JVar urlVar = staticBlock.decl(cm.ref(URL.class), "url", JExpr._null()); |
|
363 JTryBlock tryBlock = staticBlock._try(); |
|
364 tryBlock.body().assign(urlVar, JExpr._new(cm.ref(URL.class)).arg(JExpr.dotclass(cm.ref(className)).invoke("getResource").arg(".")).arg(wsdlLocation)); |
|
365 JCatchBlock catchBlock = tryBlock._catch(cm.ref(MalformedURLException.class)); |
|
366 JVar murlVar = catchBlock.param("murl"); |
|
367 catchBlock.body().assign(exVar, JExpr._new(cm.ref(WebServiceException.class)).arg(murlVar)); |
|
368 staticBlock.assign(urlField, urlVar); |
|
369 staticBlock.assign(exField, exVar); |
|
370 } |
|
371 |
|
372 /* |
|
373 Generates code that gives wsdl URL. If there is an exception in |
|
374 creating the URL, it throws an exception. |
|
375 |
|
376 for example: |
|
377 |
|
378 private URL __getWsdlLocation() { |
|
379 if (EXAMPLESERVICE_EXCEPTION != null) { |
|
380 throw EXAMPLESERVICE_EXCEPTION; |
|
381 } |
|
382 return EXAMPLESERVICE_WSDL_LOCATION; |
|
383 } |
|
384 */ |
|
385 private void writeGetWsdlLocation(JType retType, JDefinedClass cls, JFieldVar urlField, JFieldVar exField) { |
|
386 JMethod m = cls.method(JMod.PRIVATE|JMod.STATIC , retType, "__getWsdlLocation"); |
|
387 JConditional ifBlock = m.body()._if(exField.ne(JExpr._null())); |
|
388 ifBlock._then()._throw(exField); |
|
389 m.body()._return(urlField); |
|
390 } |
|
391 |
|
392 private void writeDefaultGetPort(Port port, JType retType, JDefinedClass cls) { |
|
393 String portGetter = port.getPortGetter(); |
|
394 JMethod m = cls.method(JMod.PUBLIC, retType, portGetter); |
|
395 JDocComment methodDoc = m.javadoc(); |
|
396 if (port.getJavaDoc() != null) { |
|
397 methodDoc.add(port.getJavaDoc()); |
|
398 } |
|
399 JCommentPart ret = methodDoc.addReturn(); |
|
400 ret.add("returns " + retType.name()); |
|
401 JBlock body = m.body(); |
|
402 StringBuilder statement = new StringBuilder("return "); |
|
403 statement.append("super.getPort(new QName(\"").append(port.getName().getNamespaceURI()).append("\", \"").append(port.getName().getLocalPart()).append("\"), "); |
|
404 statement.append(retType.name()); |
|
405 statement.append(".class);"); |
|
406 body.directStatement(statement.toString()); |
|
407 writeWebEndpoint(port, m); |
|
408 } |
|
409 |
|
410 private void writeWebServiceClientAnnotation(Service service, JAnnotationUse wsa) { |
|
411 String serviceName = service.getName().getLocalPart(); |
|
412 String serviceNS = service.getName().getNamespaceURI(); |
|
413 wsa.param("name", serviceName); |
|
414 wsa.param("targetNamespace", serviceNS); |
|
415 wsa.param("wsdlLocation", wsdlLocation); |
|
416 } |
|
417 |
|
418 private void writeWebEndpoint(Port port, JMethod m) { |
|
419 JAnnotationUse webEndpointAnn = m.annotate(cm.ref(WebEndpoint.class)); |
|
420 webEndpointAnn.param("name", port.getName().getLocalPart()); |
|
421 } |
|
422 } |