001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.tools.ws.processor.generator;
038:
039: import com.sun.codemodel.*;
040: import com.sun.tools.ws.api.TJavaGeneratorExtension;
041: import com.sun.tools.ws.processor.model.*;
042: import com.sun.tools.ws.processor.model.java.JavaInterface;
043: import com.sun.tools.ws.processor.model.java.JavaMethod;
044: import com.sun.tools.ws.processor.model.java.JavaParameter;
045: import com.sun.tools.ws.processor.model.jaxb.JAXBType;
046: import com.sun.tools.ws.processor.model.jaxb.JAXBTypeAndAnnotation;
047: import com.sun.tools.ws.wscompile.ErrorReceiver;
048: import com.sun.tools.ws.wscompile.Options;
049: import com.sun.tools.ws.wscompile.WsimportOptions;
050: import com.sun.tools.ws.wscompile.AbortException;
051: import com.sun.tools.ws.wsdl.document.soap.SOAPStyle;
052: import com.sun.tools.ws.wsdl.document.PortType;
053: import com.sun.tools.ws.wsdl.document.Kinds;
054: import com.sun.tools.ws.resources.GeneratorMessages;
055:
056: import javax.jws.WebMethod;
057: import javax.jws.WebParam;
058: import javax.jws.WebService;
059: import javax.jws.soap.SOAPBinding;
060: import javax.xml.bind.annotation.XmlSeeAlso;
061: import javax.xml.namespace.QName;
062: import javax.xml.ws.Holder;
063: import java.util.ArrayList;
064: import java.util.List;
065:
066: import org.xml.sax.Locator;
067:
068: public class SeiGenerator extends GeneratorBase {
069: private String serviceNS;
070: private TJavaGeneratorExtension extension;
071: private List<TJavaGeneratorExtension> extensionHandlers;
072:
073: public static void generate(Model model, WsimportOptions options,
074: ErrorReceiver receiver,
075: TJavaGeneratorExtension... extensions) {
076: SeiGenerator seiGenerator = new SeiGenerator(model, options,
077: receiver, extensions);
078: seiGenerator.doGeneration();
079: }
080:
081: private SeiGenerator(Model model, WsimportOptions options,
082: ErrorReceiver receiver,
083: TJavaGeneratorExtension... extensions) {
084: super (model, options, receiver);
085: extensionHandlers = new ArrayList<TJavaGeneratorExtension>();
086:
087: // register handlers for default extensions
088: //spec does not require generation of these annotations
089: // and we can infer from wsdl anyway, so lets disable it
090: //register(new W3CAddressingJavaGeneratorExtension());
091:
092: for (TJavaGeneratorExtension j : extensions)
093: register(j);
094:
095: this .extension = new JavaGeneratorExtensionFacade(
096: extensionHandlers
097: .toArray(new TJavaGeneratorExtension[0]));
098: }
099:
100: private void write(Port port) {
101: JavaInterface intf = port.getJavaInterface();
102: String className = Names.customJavaTypeClassName(intf);
103:
104: if (donotOverride
105: && GeneratorUtil.classExists(options, className)) {
106: log("Class " + className + " exists. Not overriding.");
107: return;
108: }
109:
110: JDefinedClass cls = null;
111: try {
112: cls = getClass(className, ClassType.INTERFACE);
113: } catch (JClassAlreadyExistsException e) {
114: QName portTypeName = (QName) port
115: .getProperty(ModelProperties.PROPERTY_WSDL_PORT_TYPE_NAME);
116: Locator loc = null;
117: if (portTypeName != null) {
118: PortType pt = port.portTypes.get(portTypeName);
119: if (pt != null)
120: loc = pt.getLocator();
121: }
122: receiver.error(loc, GeneratorMessages
123: .GENERATOR_SEI_CLASS_ALREADY_EXIST(intf.getName(),
124: portTypeName));
125: return;
126: }
127: // If the class has methods it has already been defined
128: // so skip it.
129: if (!cls.methods().isEmpty())
130: return;
131:
132: //write class comment - JAXWS warning
133: JDocComment comment = cls.javadoc();
134:
135: String ptDoc = intf.getJavaDoc();
136: if (ptDoc != null) {
137: comment.add(ptDoc);
138: comment.add("\n\n");
139: }
140:
141: for (String doc : getJAXWSClassComment()) {
142: comment.add(doc);
143: }
144:
145: //@WebService
146: JAnnotationUse webServiceAnn = cls.annotate(cm
147: .ref(WebService.class));
148: writeWebServiceAnnotation(port, webServiceAnn);
149:
150: //@HandlerChain
151: writeHandlerConfig(Names.customJavaTypeClassName(port
152: .getJavaInterface()), cls, options);
153:
154: //@SOAPBinding
155: writeSOAPBinding(port, cls);
156:
157: //@XmlSeeAlso
158: if (options.target.isLaterThan(Options.Target.V2_1))
159: writeXmlSeeAlso(cls);
160:
161: for (Operation operation : port.getOperations()) {
162: JavaMethod method = operation.getJavaMethod();
163:
164: //@WebMethod
165: JMethod m;
166: JDocComment methodDoc;
167: String methodJavaDoc = operation.getJavaDoc();
168: if (method.getReturnType().getName().equals("void")) {
169: m = cls.method(JMod.PUBLIC, void.class, method
170: .getName());
171: methodDoc = m.javadoc();
172: } else {
173: JAXBTypeAndAnnotation retType = method.getReturnType()
174: .getType();
175: m = cls.method(JMod.PUBLIC, retType.getType(), method
176: .getName());
177: retType.annotate(m);
178: methodDoc = m.javadoc();
179: JCommentPart ret = methodDoc.addReturn();
180: ret.add("returns " + retType.getName());
181: }
182: if (methodJavaDoc != null)
183: methodDoc.add(methodJavaDoc);
184:
185: writeWebMethod(operation, m);
186: JClass holder = cm.ref(Holder.class);
187: for (JavaParameter parameter : method.getParametersList()) {
188: JVar var;
189: JAXBTypeAndAnnotation paramType = parameter.getType()
190: .getType();
191: if (parameter.isHolder()) {
192: var = m.param(holder.narrow(paramType.getType()
193: .boxify()), parameter.getName());
194: } else {
195: var = m.param(paramType.getType(), parameter
196: .getName());
197: }
198:
199: //annotate parameter with JAXB annotations
200: paramType.annotate(var);
201: methodDoc.addParam(var);
202: JAnnotationUse paramAnn = var.annotate(cm
203: .ref(WebParam.class));
204: writeWebParam(operation, parameter, paramAnn);
205: }
206: com.sun.tools.ws.wsdl.document.Operation wsdlOp = operation
207: .getWSDLPortTypeOperation();
208: for (Fault fault : operation.getFaultsSet()) {
209: m._throws(fault.getExceptionClass());
210: methodDoc.addThrows(fault.getExceptionClass());
211: wsdlOp.putFault(fault.getWsdlFaultName(), fault
212: .getExceptionClass());
213: }
214:
215: //It should be the last thing to invoke after JMethod is built completely
216: extension.writeMethodAnnotations(wsdlOp, m);
217: }
218: }
219:
220: private void writeXmlSeeAlso(JDefinedClass cls) {
221: if (model.getJAXBModel().getS2JJAXBModel() != null) {
222: List<JClass> objectFactories = model.getJAXBModel()
223: .getS2JJAXBModel().getAllObjectFactories();
224:
225: //if there are no object facotires, dont generate @XmlSeeAlso
226: if (objectFactories.size() == 0)
227: return;
228:
229: JAnnotationUse xmlSeeAlso = cls.annotate(cm
230: .ref(XmlSeeAlso.class));
231: JAnnotationArrayMember paramArray = xmlSeeAlso
232: .paramArray("value");
233: for (JClass of : objectFactories) {
234: paramArray = paramArray.param(of);
235: }
236: }
237:
238: }
239:
240: private void writeWebMethod(Operation operation, JMethod m) {
241: Response response = operation.getResponse();
242: JAnnotationUse webMethodAnn = m.annotate(cm
243: .ref(WebMethod.class));
244: String operationName = (operation instanceof AsyncOperation) ? ((AsyncOperation) operation)
245: .getNormalOperation().getName().getLocalPart()
246: : operation.getName().getLocalPart();
247:
248: if (!m.name().equals(operationName)) {
249: webMethodAnn.param("operationName", operationName);
250: }
251:
252: if (operation.getSOAPAction() != null
253: && operation.getSOAPAction().length() > 0) {
254: webMethodAnn.param("action", operation.getSOAPAction());
255: }
256:
257: if (operation.getResponse() == null) {
258: m.annotate(javax.jws.Oneway.class);
259: } else if (!operation.getJavaMethod().getReturnType().getName()
260: .equals("void")
261: && operation.getResponse().getParametersList().size() > 0) {
262: Block block;
263: String resultName = null;
264: String nsURI = null;
265: if (operation.getResponse().getBodyBlocks().hasNext()) {
266: block = operation.getResponse().getBodyBlocks().next();
267: resultName = block.getName().getLocalPart();
268: if (isDocStyle || block.getLocation() == Block.HEADER) {
269: nsURI = block.getName().getNamespaceURI();
270: }
271: }
272:
273: for (Parameter parameter : operation.getResponse()
274: .getParametersList()) {
275: if (parameter.getParameterIndex() == -1) {
276: if (operation.isWrapped() || !isDocStyle) {
277: if (parameter.getBlock().getLocation() == Block.HEADER) {
278: resultName = parameter.getBlock().getName()
279: .getLocalPart();
280: } else {
281: resultName = parameter.getName();
282: }
283: if (isDocStyle
284: || (parameter.getBlock().getLocation() == Block.HEADER)) {
285: nsURI = parameter.getType().getName()
286: .getNamespaceURI();
287: }
288: } else if (isDocStyle) {
289: JAXBType t = (JAXBType) parameter.getType();
290: resultName = t.getName().getLocalPart();
291: nsURI = t.getName().getNamespaceURI();
292: }
293: if (!(operation instanceof AsyncOperation)) {
294: JAnnotationUse wr = null;
295:
296: if (!resultName.equals("return")) {
297: wr = m.annotate(javax.jws.WebResult.class);
298: wr.param("name", resultName);
299: }
300: if ((nsURI != null)
301: && (!nsURI.equals(serviceNS) || (isDocStyle && operation
302: .isWrapped()))) {
303: if (wr == null)
304: wr = m
305: .annotate(javax.jws.WebResult.class);
306: wr.param("targetNamespace", nsURI);
307: }
308: //doclit wrapped could have additional headers
309: if (!(isDocStyle && operation.isWrapped())
310: || (parameter.getBlock().getLocation() == Block.HEADER)) {
311: if (wr == null)
312: wr = m
313: .annotate(javax.jws.WebResult.class);
314: wr.param("partName", parameter.getName());
315: }
316: if (parameter.getBlock().getLocation() == Block.HEADER) {
317: if (wr == null)
318: wr = m
319: .annotate(javax.jws.WebResult.class);
320: wr.param("header", true);
321: }
322: }
323: }
324:
325: }
326: }
327:
328: //DOC/BARE
329: if (!sameParamStyle) {
330: if (!operation.isWrapped()) {
331: JAnnotationUse sb = m.annotate(SOAPBinding.class);
332: sb.param("parameterStyle",
333: SOAPBinding.ParameterStyle.BARE);
334: }
335: }
336:
337: if (operation.isWrapped()
338: && operation.getStyle().equals(SOAPStyle.DOCUMENT)) {
339: Block reqBlock = operation.getRequest().getBodyBlocks()
340: .next();
341: JAnnotationUse reqW = m
342: .annotate(javax.xml.ws.RequestWrapper.class);
343: reqW.param("localName", reqBlock.getName().getLocalPart());
344: reqW.param("targetNamespace", reqBlock.getName()
345: .getNamespaceURI());
346: reqW.param("className", reqBlock.getType().getJavaType()
347: .getName());
348:
349: if (response != null) {
350: JAnnotationUse resW = m
351: .annotate(javax.xml.ws.ResponseWrapper.class);
352: Block resBlock = response.getBodyBlocks().next();
353: resW.param("localName", resBlock.getName()
354: .getLocalPart());
355: resW.param("targetNamespace", resBlock.getName()
356: .getNamespaceURI());
357: resW.param("className", resBlock.getType()
358: .getJavaType().getName());
359: }
360: }
361: }
362:
363: private boolean isMessageParam(Parameter param, Message message) {
364: Block block = param.getBlock();
365:
366: return (message.getBodyBlockCount() > 0 && block.equals(message
367: .getBodyBlocks().next()))
368: || (message.getHeaderBlockCount() > 0 && block
369: .equals(message.getHeaderBlocks().next()));
370: }
371:
372: private boolean isHeaderParam(Parameter param, Message message) {
373: if (message.getHeaderBlockCount() == 0)
374: return false;
375:
376: for (Block headerBlock : message.getHeaderBlocksMap().values())
377: if (param.getBlock().equals(headerBlock))
378: return true;
379:
380: return false;
381: }
382:
383: private boolean isAttachmentParam(Parameter param, Message message) {
384: if (message.getAttachmentBlockCount() == 0)
385: return false;
386:
387: for (Block attBlock : message.getAttachmentBlocksMap().values())
388: if (param.getBlock().equals(attBlock))
389: return true;
390:
391: return false;
392: }
393:
394: private boolean isUnboundParam(Parameter param, Message message) {
395: if (message.getUnboundBlocksCount() == 0)
396: return false;
397:
398: for (Block unboundBlock : message.getUnboundBlocksMap()
399: .values())
400: if (param.getBlock().equals(unboundBlock))
401: return true;
402:
403: return false;
404: }
405:
406: private void writeWebParam(Operation operation,
407: JavaParameter javaParameter, JAnnotationUse paramAnno) {
408: Parameter param = javaParameter.getParameter();
409: Request req = operation.getRequest();
410: Response res = operation.getResponse();
411:
412: boolean header = isHeaderParam(param, req)
413: || (res != null && isHeaderParam(param, res));
414:
415: String name;
416: boolean isWrapped = operation.isWrapped();
417:
418: if ((param.getBlock().getLocation() == Block.HEADER)
419: || (isDocStyle && !isWrapped))
420: name = param.getBlock().getName().getLocalPart();
421: else
422: name = param.getName();
423:
424: paramAnno.param("name", name);
425:
426: String ns = null;
427:
428: if (isDocStyle) {
429: ns = param.getBlock().getName().getNamespaceURI(); // its bare nsuri
430: if (isWrapped) {
431: ns = param.getType().getName().getNamespaceURI();
432: }
433: } else if (header) {
434: ns = param.getBlock().getName().getNamespaceURI();
435: }
436:
437: if ((ns != null)
438: && (!ns.equals(serviceNS) || (isDocStyle && isWrapped)))
439: paramAnno.param("targetNamespace", ns);
440:
441: if (header) {
442: paramAnno.param("header", true);
443: }
444:
445: if (param.isINOUT()) {
446: paramAnno.param("mode", javax.jws.WebParam.Mode.INOUT);
447: } else if ((res != null)
448: && (isMessageParam(param, res)
449: || isHeaderParam(param, res)
450: || isAttachmentParam(param, res)
451: || isUnboundParam(param, res) || param.isOUT())) {
452: paramAnno.param("mode", javax.jws.WebParam.Mode.OUT);
453: }
454:
455: //doclit wrapped could have additional headers
456: if (!(isDocStyle && isWrapped) || header)
457: paramAnno.param("partName", javaParameter.getParameter()
458: .getName());
459: }
460:
461: private boolean isDocStyle = true;
462: private boolean sameParamStyle = true;
463:
464: private void writeSOAPBinding(Port port, JDefinedClass cls) {
465: JAnnotationUse soapBindingAnn = null;
466: isDocStyle = port.getStyle() == null
467: || port.getStyle().equals(SOAPStyle.DOCUMENT);
468: if (!isDocStyle) {
469: soapBindingAnn = cls.annotate(SOAPBinding.class);
470: soapBindingAnn.param("style", SOAPBinding.Style.RPC);
471: port.setWrapped(true);
472: }
473: if (isDocStyle) {
474: boolean first = true;
475: boolean isWrapper = true;
476: for (Operation operation : port.getOperations()) {
477: if (first) {
478: isWrapper = operation.isWrapped();
479: first = false;
480: continue;
481: }
482: sameParamStyle = (isWrapper == operation.isWrapped());
483: if (!sameParamStyle)
484: break;
485: }
486: if (sameParamStyle)
487: port.setWrapped(isWrapper);
488: }
489: if (sameParamStyle && !port.isWrapped()) {
490: if (soapBindingAnn == null)
491: soapBindingAnn = cls.annotate(SOAPBinding.class);
492: soapBindingAnn.param("parameterStyle",
493: SOAPBinding.ParameterStyle.BARE);
494: }
495: }
496:
497: private void writeWebServiceAnnotation(Port port, JAnnotationUse wsa) {
498: QName name = (QName) port
499: .getProperty(ModelProperties.PROPERTY_WSDL_PORT_TYPE_NAME);
500: wsa.param("name", name.getLocalPart());
501: wsa.param("targetNamespace", name.getNamespaceURI());
502: }
503:
504: public void visit(Model model) throws Exception {
505: for (Service s : model.getServices()) {
506: s.accept(this );
507: }
508: }
509:
510: public void visit(Service service) throws Exception {
511: String jd = model.getJavaDoc();
512: if (jd != null) {
513: JPackage pkg = cm._package(options.defaultPackage);
514: pkg.javadoc().add(jd);
515: }
516:
517: for (Port p : service.getPorts()) {
518: visitPort(service, p);
519: }
520: }
521:
522: private void visitPort(Service service, Port port) {
523: if (port.isProvider()) {
524: return; // Not generating for Provider based endpoint
525: }
526: write(port);
527: }
528:
529: private void register(TJavaGeneratorExtension h) {
530: extensionHandlers.add(h);
531: }
532: }
|