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
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.websvc.core.dev.wizard;
042:
043: import org.netbeans.modules.websvc.api.support.java.GenerationUtils;
044: import org.netbeans.modules.websvc.api.support.java.SourceUtils;
045: import org.netbeans.modules.websvc.core.ProjectInfo;
046: import com.sun.source.tree.AnnotationTree;
047: import com.sun.source.tree.AssignmentTree;
048: import com.sun.source.tree.BlockTree;
049: import com.sun.source.tree.ClassTree;
050: import com.sun.source.tree.ExpressionTree;
051: import com.sun.source.tree.MethodInvocationTree;
052: import com.sun.source.tree.MethodTree;
053: import com.sun.source.tree.ModifiersTree;
054: import com.sun.source.tree.StatementTree;
055: import com.sun.source.tree.VariableTree;
056: import java.beans.PropertyVetoException;
057: import java.io.File;
058: import java.io.IOException;
059: import java.net.URL;
060: import java.util.ArrayList;
061: import java.util.Collections;
062: import java.util.HashSet;
063: import java.util.List;
064: import java.util.Set;
065: import javax.lang.model.element.Element;
066: import javax.lang.model.element.ElementKind;
067: import javax.lang.model.element.ExecutableElement;
068: import javax.lang.model.element.Modifier;
069: import javax.lang.model.element.Name;
070: import javax.lang.model.element.TypeElement;
071: import javax.lang.model.element.VariableElement;
072: import javax.lang.model.type.TypeKind;
073: import org.netbeans.api.java.classpath.ClassPath;
074: import org.netbeans.api.java.project.JavaProjectConstants;
075: import org.netbeans.api.java.source.CancellableTask;
076: import org.netbeans.api.java.source.Comment;
077: import org.netbeans.api.java.source.GeneratorUtilities;
078: import org.netbeans.api.java.source.JavaSource;
079: import org.netbeans.api.java.source.JavaSource.Phase;
080: import org.netbeans.api.java.source.TreeMaker;
081: import org.netbeans.api.java.source.WorkingCopy;
082: import org.netbeans.api.progress.ProgressHandle;
083: import org.netbeans.api.progress.ProgressHandleFactory;
084: import org.netbeans.api.project.Project;
085: import org.netbeans.api.project.ProjectManager;
086: import org.netbeans.api.project.ProjectUtils;
087: import org.netbeans.api.project.SourceGroup;
088: import org.netbeans.api.project.libraries.Library;
089: import org.netbeans.api.project.libraries.LibraryManager;
090: import org.netbeans.modules.j2ee.api.ejbjar.EjbReference;
091: import org.netbeans.modules.j2ee.common.Util;
092: import org.netbeans.modules.websvc.api.jaxws.project.config.JaxWsModel;
093: import org.netbeans.modules.websvc.api.jaxws.project.config.Service;
094: import org.netbeans.modules.websvc.api.jaxws.project.config.ServiceAlreadyExistsExeption;
095: import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlModel;
096: import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlModelListener;
097: import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlModeler;
098: import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlPort;
099: import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlService;
100: import org.netbeans.modules.websvc.core.ServiceCreator;
101: import org.netbeans.modules.websvc.core.JaxWsUtils;
102: import org.netbeans.modules.websvc.jaxws.api.JAXWSSupport;
103: import org.netbeans.spi.java.project.classpath.ProjectClassPathExtender;
104: import org.netbeans.spi.project.ui.templates.support.Templates;
105: import org.openide.DialogDisplayer;
106: import org.openide.ErrorManager;
107: import org.openide.NotifyDescriptor;
108: import org.openide.WizardDescriptor;
109: import org.openide.filesystems.FileObject;
110: import org.openide.filesystems.FileUtil;
111: import org.openide.loaders.DataFolder;
112: import org.openide.loaders.DataObject;
113: import org.openide.nodes.Node;
114: import org.openide.util.NbBundle;
115: import org.openide.util.RequestProcessor;
116:
117: /**
118: *
119: * @author Radko, Milan Kuchtiak
120: */
121: public class JaxWsServiceCreator implements ServiceCreator {
122:
123: private ProjectInfo projectInfo;
124: private WizardDescriptor wiz;
125: private boolean addJaxWsLib;
126: private int serviceType;
127: private int projectType;
128:
129: /**
130: * Creates a new instance of WebServiceClientCreator
131: */
132: public JaxWsServiceCreator(ProjectInfo projectInfo,
133: WizardDescriptor wiz, boolean addJaxWsLib) {
134: this .projectInfo = projectInfo;
135: this .wiz = wiz;
136: this .addJaxWsLib = addJaxWsLib;
137: }
138:
139: public void createService() throws IOException {
140: serviceType = ((Integer) wiz
141: .getProperty(WizardProperties.WEB_SERVICE_TYPE))
142: .intValue();
143: projectType = projectInfo.getProjectType();
144:
145: // Use Progress API to display generator messages.
146: final ProgressHandle handle = ProgressHandleFactory
147: .createHandle(NbBundle.getMessage(
148: JaxWsServiceCreator.class,
149: "TXT_WebServiceGeneration")); //NOI18N
150: handle.start(100);
151:
152: Runnable r = new Runnable() {
153:
154: public void run() {
155: try {
156: generateWebService(handle);
157: } catch (Exception e) {
158: //finish progress bar
159: handle.finish();
160: String message = e.getLocalizedMessage();
161: if (message != null) {
162: ErrorManager.getDefault().notify(
163: ErrorManager.INFORMATIONAL, e);
164: NotifyDescriptor nd = new NotifyDescriptor.Message(
165: message, NotifyDescriptor.ERROR_MESSAGE);
166: DialogDisplayer.getDefault().notify(nd);
167: } else {
168: ErrorManager.getDefault().notify(
169: ErrorManager.EXCEPTION, e);
170: }
171: }
172: }
173: };
174: RequestProcessor.getDefault().post(r);
175: }
176:
177: public void createServiceFromWsdl() throws IOException {
178:
179: //initProjectInfo(project);
180:
181: final ProgressHandle handle = ProgressHandleFactory
182: .createHandle(NbBundle.getMessage(
183: JaxWsServiceCreator.class,
184: "TXT_WebServiceGeneration")); //NOI18N
185:
186: Runnable r = new Runnable() {
187:
188: public void run() {
189: try {
190: handle.start();
191: generateWsFromWsdl15(handle);
192: } catch (Exception e) {
193: //finish progress bar
194: handle.finish();
195: String message = e.getLocalizedMessage();
196: if (message != null) {
197: ErrorManager.getDefault().notify(
198: ErrorManager.INFORMATIONAL, e);
199: NotifyDescriptor nd = new NotifyDescriptor.Message(
200: message, NotifyDescriptor.ERROR_MESSAGE);
201: DialogDisplayer.getDefault().notify(nd);
202: } else {
203: ErrorManager.getDefault().notify(
204: ErrorManager.EXCEPTION, e);
205: }
206: }
207: }
208: };
209: RequestProcessor.getDefault().post(r);
210: }
211:
212: //TODO it should be refactored to prevent duplicate code but it is more readable now during development
213: private void generateWebService(ProgressHandle handle)
214: throws Exception {
215:
216: FileObject pkg = Templates.getTargetFolder(wiz);
217: String wsName = Templates.getTargetName(wiz);
218:
219: if (serviceType == WizardProperties.FROM_SCRATCH) {
220: // if ((projectType == ProjectInfo.JSE_PROJECT_TYPE && Util.isSourceLevel16orHigher(project)) ||
221: // ((Util.isJavaEE5orHigher(project) &&
222: // (projectType == WEB_PROJECT_TYPE || projectType == EJB_PROJECT_TYPE))) ||
223: // (jwsdpSupported)
224: // ) {
225: JAXWSSupport jaxWsSupport = JAXWSSupport
226: .getJAXWSSupport(projectInfo.getProject()
227: .getProjectDirectory());
228: wsName = getUniqueJaxwsName(jaxWsSupport, wsName);
229: handle.progress(NbBundle.getMessage(
230: JaxWsServiceCreator.class, "MSG_GEN_WS"), 50); //NOI18N
231: //add the JAXWS 2.0 library, if not already added
232: if (addJaxWsLib) {
233: addJaxws21Library(projectInfo.getProject());
234: }
235: generateJaxWSImplFromTemplate(pkg, wsName, projectType);
236: handle.finish();
237: return;
238: }
239: if (serviceType == WizardProperties.ENCAPSULATE_SESSION_BEAN) {
240: if (/*(projectType == JSE_PROJECT_TYPE && Util.isSourceLevel16orHigher(project)) ||*/(Util
241: .isJavaEE5orHigher(projectInfo.getProject()) && (projectType == ProjectInfo.WEB_PROJECT_TYPE || projectType == ProjectInfo.EJB_PROJECT_TYPE)) //NOI18N
242: ) {
243:
244: JAXWSSupport jaxWsSupport = JAXWSSupport
245: .getJAXWSSupport(projectInfo.getProject()
246: .getProjectDirectory());
247: wsName = getUniqueJaxwsName(jaxWsSupport, wsName);
248: handle.progress(NbBundle.getMessage(
249: JaxWsServiceCreator.class,
250: "MSG_GEN_SEI_AND_IMPL"), 50); //NOI18N
251: Node[] nodes = (Node[]) wiz
252: .getProperty(WizardProperties.DELEGATE_TO_SESSION_BEAN);
253: generateWebServiceFromEJB(wsName, pkg, projectInfo,
254: nodes);
255:
256: handle.progress(70);
257: handle.finish();
258: }
259: }
260: }
261:
262: private FileObject generateJaxWSImplFromTemplate(FileObject pkg,
263: String wsName, int projectType) throws Exception {
264: DataFolder df = DataFolder.findFolder(pkg);
265: FileObject template = Templates.getTemplate(wiz);
266:
267: if (projectType == ProjectInfo.EJB_PROJECT_TYPE) { //EJB Web Service
268: FileObject templateParent = template.getParent();
269: template = templateParent.getFileObject("EjbWebService",
270: "java"); //NOI18N
271: }
272: DataObject dTemplate = DataObject.find(template);
273: DataObject dobj = dTemplate.createFromTemplate(df, wsName);
274: FileObject createdFile = dobj.getPrimaryFile();
275: createdFile.setAttribute("jax-ws-service",
276: java.lang.Boolean.TRUE);
277: dobj.setValid(false);
278: dobj = DataObject.find(createdFile);
279: final JaxWsModel jaxWsModel = projectInfo.getProject()
280: .getLookup().lookup(JaxWsModel.class);
281: if (jaxWsModel != null) {
282: ClassPath classPath = ClassPath.getClassPath(createdFile,
283: ClassPath.SOURCE);
284: String serviceImplPath = classPath.getResourceName(
285: createdFile, '.', false);
286: Service service = jaxWsModel.addService(wsName,
287: serviceImplPath);
288: ProjectManager.mutex().writeAccess(new Runnable() {
289:
290: public void run() {
291: try {
292: jaxWsModel.write();
293: } catch (IOException ex) {
294: ErrorManager.getDefault().notify(ex);
295: }
296: }
297: });
298: JaxWsUtils.openFileInEditor(dobj, service);
299: }
300:
301: return createdFile;
302: }
303:
304: private String getUniqueJaxwsName(JAXWSSupport jaxWsSupport,
305: String origName) {
306: List<Service> webServices = jaxWsSupport.getServices();
307: List<String> serviceNames = new ArrayList<String>(webServices
308: .size());
309: for (Service service : webServices) {
310: serviceNames.add(service.getName());
311: }
312: return uniqueWSName(origName, serviceNames);
313: }
314:
315: private String uniqueWSName(final String origName,
316: List<String> names) {
317: int uniquifier = 0;
318: String truename = origName;
319: while (names.contains(truename)) {
320: truename = origName + String.valueOf(++uniquifier);
321: }
322: return truename;
323: }
324:
325: private void addJaxws21Library(Project project) throws Exception {
326:
327: // check if the wsimport class is already present - this means we don't need to add the library
328: SourceGroup[] sgs = ProjectUtils
329: .getSources(project)
330: .getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA);
331: ClassPath classPath = ClassPath.getClassPath(sgs[0]
332: .getRootFolder(), ClassPath.COMPILE);
333: FileObject wsimportFO = classPath
334: .findResource("com/sun/tools/ws/ant/WsImport.class"); // NOI18N
335: if (wsimportFO != null) {
336: return;
337: }
338:
339: ProjectClassPathExtender pce = (ProjectClassPathExtender) project
340: .getLookup().lookup(ProjectClassPathExtender.class);
341: Library jaxws21_ext = LibraryManager.getDefault().getLibrary(
342: "jaxws21"); //NOI18N
343: if (pce != null && jaxws21_ext != null) {
344: try {
345: pce.addLibrary(jaxws21_ext);
346: } catch (IOException e) {
347: throw new Exception("Unable to add JAXWS 21 Library. "
348: + e.getMessage());
349: }
350: } else {
351: throw new Exception("Unable to add JAXWS 2.1 Library. "
352: + "ProjectClassPathExtender or library not found");
353: }
354: }
355:
356: private void generateWsFromWsdl15(final ProgressHandle handle)
357: throws Exception {
358: String wsdlFilePath = (String) wiz
359: .getProperty(WizardProperties.WSDL_FILE_PATH);
360: URL wsdlUrl = null;
361: if (wsdlFilePath == null) {
362: wsdlUrl = new URL((String) wiz
363: .getProperty(WizardProperties.WSDL_URL));
364: } else {
365: File normalizedWsdlFilePath = FileUtil
366: .normalizeFile(new File(wsdlFilePath));
367: //convert to URI first to take care of spaces
368: wsdlUrl = normalizedWsdlFilePath.toURI().toURL();
369: }
370: final URL wsdlURL = wsdlUrl;
371: final WsdlService service = (WsdlService) wiz
372: .getProperty(WizardProperties.WSDL_SERVICE);
373: final Boolean useProvider = (Boolean) wiz
374: .getProperty(WizardProperties.USE_PROVIDER);
375: if (service == null) {
376: FileObject targetFolder = Templates.getTargetFolder(wiz);
377: String targetName = Templates.getTargetName(wiz);
378:
379: // create a fake implementation class to enable WS functionality (to enable WS node creation)
380: if (targetFolder != null) {
381: GenerationUtils.createClass(targetFolder, targetName,
382: null);
383: }
384:
385: WsdlServiceHandler handler = (WsdlServiceHandler) wiz
386: .getProperty(WizardProperties.WSDL_SERVICE_HANDLER);
387: JaxWsUtils.generateJaxWsArtifacts(projectInfo.getProject(),
388: targetFolder, targetName, wsdlURL, handler
389: .getServiceName(), handler.getPortName());
390: WsdlModeler wsdlModeler = (WsdlModeler) wiz
391: .getProperty(WizardProperties.WSDL_MODELER);
392: if (wsdlModeler != null
393: && wsdlModeler.getCreationException() != null) {
394: handle.finish();
395: DialogDisplayer
396: .getDefault()
397: .notify(
398: new NotifyDescriptor.Message(
399: NbBundle
400: .getMessage(
401: JaxWsServiceCreator.class,
402: "TXT_CannotGenerateArtifacts",
403: wsdlModeler
404: .getCreationException()
405: .getLocalizedMessage()),
406: NotifyDescriptor.ERROR_MESSAGE));
407: } else {
408: handle.finish();
409: }
410: } else {
411: final WsdlPort port = (WsdlPort) wiz
412: .getProperty(WizardProperties.WSDL_PORT);
413: //String portJavaName = port.getJavaName();
414: WsdlModeler wsdlModeler = (WsdlModeler) wiz
415: .getProperty(WizardProperties.WSDL_MODELER);
416: // don't set the packageName for modeler (use the default one generated from target Namespace)
417: wsdlModeler.generateWsdlModel(new WsdlModelListener() {
418:
419: public void modelCreated(WsdlModel model) {
420: if (model == null) {
421: handle.finish();
422: return;
423: }
424: WsdlService service1 = model
425: .getServiceByName(service.getName());
426: WsdlPort port1 = service1.getPortByName(port
427: .getName());
428:
429: port1.setSOAPVersion(port.getSOAPVersion());
430: FileObject targetFolder = Templates
431: .getTargetFolder(wiz);
432: String targetName = Templates.getTargetName(wiz);
433:
434: try {
435: JaxWsUtils.generateJaxWsImplementationClass(
436: projectInfo.getProject(), targetFolder,
437: targetName, wsdlURL, service1, port1,
438: useProvider);
439: handle.finish();
440: } catch (Exception ex) {
441: handle.finish();
442: ErrorManager.getDefault().notify(
443: ErrorManager.EXCEPTION, ex);
444: }
445: }
446: });
447: }
448: }
449:
450: private void generateWebServiceFromEJB(String wsName,
451: FileObject pkg, ProjectInfo projectInfo, Node[] nodes)
452: throws IOException, ServiceAlreadyExistsExeption,
453: PropertyVetoException {
454:
455: if (nodes != null && nodes.length == 1) {
456:
457: EjbReference ejbRef = nodes[0].getLookup().lookup(
458: EjbReference.class);
459: if (ejbRef != null) {
460:
461: DataFolder df = DataFolder.findFolder(pkg);
462: FileObject template = Templates.getTemplate(wiz);
463:
464: if (projectType == ProjectInfo.EJB_PROJECT_TYPE) { //EJB Web Service
465: FileObject templateParent = template.getParent();
466: template = templateParent.getFileObject(
467: "EjbWebService", "java"); //NOI18N
468: }
469: DataObject dTemplate = DataObject.find(template);
470: DataObject dobj = dTemplate.createFromTemplate(df,
471: wsName);
472: FileObject createdFile = dobj.getPrimaryFile();
473: createdFile.setAttribute("jax-ws-service",
474: java.lang.Boolean.TRUE);
475: dobj.setValid(false);
476: dobj = DataObject.find(createdFile);
477:
478: ClassPath classPath = ClassPath.getClassPath(
479: createdFile, ClassPath.SOURCE);
480: String serviceImplPath = classPath.getResourceName(
481: createdFile, '.', false);
482: generateDelegateMethods(createdFile, ejbRef);
483:
484: final JaxWsModel jaxWsModel = projectInfo.getProject()
485: .getLookup().lookup(JaxWsModel.class);
486: if (jaxWsModel != null) {
487: Service service = jaxWsModel.addService(wsName,
488: serviceImplPath);
489: ProjectManager.mutex().writeAccess(new Runnable() {
490:
491: public void run() {
492: try {
493: jaxWsModel.write();
494: } catch (IOException ex) {
495: ErrorManager.getDefault().notify(ex);
496: }
497: }
498: });
499: JaxWsUtils.openFileInEditor(dobj, service);
500: }
501: }
502: }
503: }
504:
505: private void generateDelegateMethods(final FileObject targetFo,
506: final EjbReference ref) throws IOException {
507: final boolean[] onClassPath = new boolean[1];
508: final String[] interfaceClass = new String[1];
509:
510: JavaSource targetSource = JavaSource.forFileObject(targetFo);
511: CancellableTask<WorkingCopy> modificationTask = new CancellableTask<WorkingCopy>() {
512:
513: public void run(WorkingCopy workingCopy) throws IOException {
514: workingCopy.toPhase(Phase.RESOLVED);
515:
516: TreeMaker make = workingCopy.getTreeMaker();
517:
518: TypeElement typeElement = SourceUtils
519: .getPublicTopLevelElement(workingCopy);
520: if (typeElement != null) {
521: VariableTree ejbRefInjection = null;
522: interfaceClass[0] = ref.getLocal();
523: if (interfaceClass[0] == null) {
524: interfaceClass[0] = ref.getRemote();
525: }
526:
527: ejbRefInjection = generateEjbInjection(workingCopy,
528: make, interfaceClass[0], onClassPath);
529:
530: if (ejbRefInjection != null) {
531: String comment1 = "Add business logic below. (Right-click in editor and choose"; //NOI18N
532: String comment2 = "\"Web Service > Add Operation\""; //NOI18N
533: make.addComment(ejbRefInjection, Comment
534: .create(Comment.Style.LINE, 0, 0, 4,
535: comment1), false);
536: make.addComment(ejbRefInjection, Comment
537: .create(Comment.Style.LINE, 0, 0, 4,
538: comment2), false);
539:
540: ClassTree javaClass = workingCopy.getTrees()
541: .getTree(typeElement);
542: ClassTree modifiedClass = make
543: .insertClassMember(javaClass, 0,
544: ejbRefInjection);
545:
546: if (onClassPath[0]) {
547: TypeElement beanInterface = workingCopy
548: .getElements().getTypeElement(
549: interfaceClass[0]);
550: modifiedClass = generateMethods(
551: workingCopy, make, typeElement,
552: modifiedClass, beanInterface);
553: }
554:
555: workingCopy.rewrite(javaClass, modifiedClass);
556: }
557: }
558: }
559:
560: public void cancel() {
561: }
562: };
563: targetSource.runModificationTask(modificationTask).commit();
564:
565: if (!onClassPath[0]) {
566: RequestProcessor.getDefault().post(new Runnable() {
567:
568: public void run() {
569: DialogDisplayer.getDefault().notify(
570: new NotifyDescriptor.Message(NbBundle
571: .getMessage(
572: JaxWsServiceCreator.class,
573: "MSG_EJB_NOT_ON_CLASSPATH",
574: interfaceClass[0], targetFo
575: .getName()),
576: NotifyDescriptor.WARNING_MESSAGE));
577: }
578: });
579: }
580: }
581:
582: private VariableTree generateEjbInjection(WorkingCopy workingCopy,
583: TreeMaker make, String beanInterface, boolean[] onClassPath) {
584:
585: TypeElement ejbAnElement = workingCopy.getElements()
586: .getTypeElement("javax.ejb.EJB"); //NOI18N
587: TypeElement interfaceElement = workingCopy.getElements()
588: .getTypeElement(beanInterface); //NOI18N
589:
590: AnnotationTree ejbAnnotation = make.Annotation(make
591: .QualIdent(ejbAnElement), Collections
592: .<ExpressionTree> emptyList());
593: // create method modifier: public and no annotation
594: ModifiersTree methodModifiers = make.Modifiers(Collections
595: .<Modifier> singleton(Modifier.PRIVATE), Collections
596: .<AnnotationTree> singletonList(ejbAnnotation));
597:
598: onClassPath[0] = interfaceElement != null;
599:
600: return make.Variable(methodModifiers, "ejbRef", //NOI18N
601: onClassPath[0] ? make.Type(interfaceElement.asType())
602: : make.Identifier(beanInterface), null);
603: }
604:
605: private ClassTree generateMethods(WorkingCopy workingCopy,
606: TreeMaker make, TypeElement classElement,
607: ClassTree modifiedClass, TypeElement beanInterface)
608: throws IOException {
609:
610: GeneratorUtilities utils = GeneratorUtilities.get(workingCopy);
611:
612: List<? extends Element> interfaceElements = beanInterface
613: .getEnclosedElements();
614: TypeElement webMethodEl = workingCopy.getElements()
615: .getTypeElement("javax.jws.WebMethod"); //NOI18N
616: assert (webMethodEl != null);
617: if (webMethodEl == null) {
618: return modifiedClass;
619: }
620:
621: Set<String> operationNames = new HashSet<String>();
622: for (Element el : interfaceElements) {
623: if (el.getKind() == ElementKind.METHOD) {
624: ExecutableElement methodEl = (ExecutableElement) el;
625: MethodTree method = utils
626: .createAbstractMethodImplementation(
627: classElement, methodEl);
628:
629: Name methodName = methodEl.getSimpleName();
630: boolean isVoid = workingCopy.getTypes().getNoType(
631: TypeKind.VOID) == methodEl.getReturnType();
632:
633: String operationName = findUniqueOperationName(
634: operationNames, methodName.toString());
635: operationNames.add(operationName);
636:
637: // generate @WebMethod annotation
638: AssignmentTree opName = make.Assignment(make
639: .Identifier("operationName"), make
640: .Literal(operationName)); //NOI18N
641:
642: AnnotationTree webMethodAn = make.Annotation(make
643: .QualIdent(webMethodEl), Collections
644: .<ExpressionTree> singletonList(opName));
645: ModifiersTree modifiersTree = make
646: .Modifiers(
647: Collections
648: .<Modifier> singleton(Modifier.PUBLIC),
649: Collections
650: .<AnnotationTree> singletonList(webMethodAn));
651:
652: // generate @RequestWrapper and @RequestResponse annotations
653: if (!methodName.contentEquals(operationName)) {
654: TypeElement requestWrapperEl = workingCopy
655: .getElements().getTypeElement(
656: "javax.xml.ws.RequestWrapper"); //NOI18N
657: TypeElement responseWrapperEl = workingCopy
658: .getElements().getTypeElement(
659: "javax.xml.ws.ResponseWrapper"); //NOI18N
660: AssignmentTree className = make.Assignment(make
661: .Identifier("className"), make
662: .Literal(operationName)); //NOI18N
663: AnnotationTree requestWrapperAn = make
664: .Annotation(
665: make.QualIdent(requestWrapperEl),
666: Collections
667: .<ExpressionTree> singletonList(className));
668: modifiersTree = make.addModifiersAnnotation(
669: modifiersTree, requestWrapperAn);
670:
671: if (!isVoid) { // only if not void
672: className = make.Assignment(make
673: .Identifier("className"), make
674: .Literal(operationName + "Response")); //NOI18N
675: AnnotationTree responseWrapperAn = make
676: .Annotation(
677: make
678: .QualIdent(responseWrapperEl),
679: Collections
680: .<ExpressionTree> singletonList(className));
681: modifiersTree = make.addModifiersAnnotation(
682: modifiersTree, responseWrapperAn);
683: }
684: }
685:
686: // generate @Oneway annotation
687: if (isVoid) {
688: TypeElement onewayEl = workingCopy.getElements()
689: .getTypeElement("javax.jws.Oneway"); //NOI18N
690: AnnotationTree onewayAn = make.Annotation(make
691: .QualIdent(onewayEl), Collections
692: .<ExpressionTree> emptyList());
693: modifiersTree = make.addModifiersAnnotation(
694: modifiersTree, onewayAn);
695: }
696: // parameters
697: List<? extends VariableTree> params = method
698: .getParameters();
699: List<VariableTree> newParams = new ArrayList<VariableTree>();
700: if (params.size() > 0) {
701: TypeElement paramEl = workingCopy.getElements()
702: .getTypeElement("javax.jws.WebParam"); //NOI18N
703: for (VariableTree param : params) {
704: String paramName = param.getName().toString();
705: AssignmentTree nameAttr = make.Assignment(make
706: .Identifier("name"), make
707: .Literal(paramName)); //NOI18N
708: AnnotationTree paramAn = make
709: .Annotation(
710: make.QualIdent(paramEl),
711: Collections
712: .<ExpressionTree> singletonList(nameAttr));
713: ModifiersTree paramModifierTree = make
714: .addModifiersAnnotation(param
715: .getModifiers(), paramAn);
716: newParams
717: .add(make.Variable(paramModifierTree,
718: param.getName(), param
719: .getType(), null));
720: }
721: }
722:
723: // method body
724: List<ExpressionTree> arguments = new ArrayList<ExpressionTree>();
725: for (VariableElement ve : methodEl.getParameters()) {
726: arguments.add(make.Identifier(ve.getSimpleName()));
727: }
728: MethodInvocationTree inv = make.MethodInvocation(
729: Collections.<ExpressionTree> emptyList(), make
730: .MemberSelect(
731: make.Identifier("ejbRef"),
732: methodName), //NOI18N
733: arguments);
734:
735: StatementTree statement = isVoid ? make
736: .ExpressionStatement(inv) : make.Return(inv);
737:
738: BlockTree body = make.Block(Collections
739: .singletonList(statement), false);
740:
741: MethodTree delegatingMethod = make.Method(
742: modifiersTree, method.getName(), method
743: .getReturnType(), method
744: .getTypeParameters(), newParams, method
745: .getThrows(), body, null);
746: modifiedClass = make.addClassMember(modifiedClass,
747: delegatingMethod);
748: }
749: }
750: return modifiedClass;
751: }
752:
753: private String findUniqueOperationName(Set<String> existingNames,
754: String operationName) {
755: if (!existingNames.contains(operationName)) {
756: return operationName;
757: } else {
758: int i = 1;
759: String newName = operationName + "_1"; //NOI18N
760: while (existingNames.contains(newName)) {
761: newName = operationName + "_" + String.valueOf(++i); //NOI18N
762: }
763: return newName;
764: }
765: }
766: }
|