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-2007 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:
042: package org.netbeans.modules.websvc.core;
043:
044: import com.sun.source.tree.AnnotationTree;
045: import com.sun.source.tree.ClassTree;
046: import com.sun.source.tree.ExpressionTree;
047: import com.sun.source.tree.MethodTree;
048: import com.sun.source.tree.ModifiersTree;
049: import com.sun.source.tree.Tree;
050: import com.sun.source.tree.TypeParameterTree;
051: import com.sun.source.tree.VariableTree;
052: import java.io.IOException;
053: import java.util.ArrayList;
054: import java.util.Collections;
055: import java.util.Iterator;
056: import java.util.List;
057: import javax.lang.model.element.AnnotationMirror;
058: import javax.lang.model.element.ExecutableElement;
059: import javax.lang.model.element.Modifier;
060: import javax.lang.model.element.TypeElement;
061: import org.netbeans.api.java.source.CancellableTask;
062: import org.netbeans.api.java.source.JavaSource;
063: import org.netbeans.api.java.source.JavaSource.Phase;
064: import org.netbeans.api.java.source.TreeMaker;
065: import org.netbeans.api.java.source.WorkingCopy;
066: import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlModel;
067: import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlOperation;
068: import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlParameter;
069: import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlPort;
070: import org.netbeans.modules.websvc.api.jaxws.wsdlmodel.WsdlService;
071: import org.netbeans.modules.websvc.api.support.java.SourceUtils;
072: import org.openide.cookies.SaveCookie;
073: import org.openide.filesystems.FileObject;
074: import org.openide.loaders.DataObject;
075:
076: /**
077: *
078: * @author mkuchtiak
079: */
080: public class MethodGenerator {
081: FileObject implClassFo;
082: WsdlModel wsdlModel;
083:
084: /** Creates a new instance of MethodGenerator */
085: public MethodGenerator(WsdlModel wsdlModel, FileObject implClassFo) {
086: this .implClassFo = implClassFo;
087: this .wsdlModel = wsdlModel;
088: }
089:
090: public void generateMethod(final String operationName)
091: throws IOException {
092:
093: // Use Progress API to display generator messages.
094: //ProgressHandle handle = ProgressHandleFactory.createHandle(NbBundle.getMessage(MethodGenerator.class, "TXT_AddingMethod")); //NOI18N
095: //handle.start(100);
096:
097: JavaSource targetSource = JavaSource.forFileObject(implClassFo);
098: CancellableTask<WorkingCopy> task = new CancellableTask<WorkingCopy>() {
099:
100: public void run(WorkingCopy workingCopy)
101: throws java.io.IOException {
102: workingCopy.toPhase(Phase.RESOLVED);
103: ClassTree javaClass = SourceUtils
104: .getPublicTopLevelTree(workingCopy);
105: if (javaClass != null) {
106:
107: // get proper wsdlOperation;
108: WsdlOperation wsdlOperation = getWsdlOperation(operationName);
109:
110: TreeMaker make = workingCopy.getTreeMaker();
111:
112: // return type
113: String returnType = wsdlOperation
114: .getReturnTypeName();
115:
116: // create parameters
117: List<WsdlParameter> parameters = wsdlOperation
118: .getParameters();
119: List<VariableTree> params = new ArrayList<VariableTree>();
120: for (WsdlParameter parameter : parameters) {
121: // create parameter:
122: params.add(make.Variable(make.Modifiers(
123: Collections.<Modifier> emptySet(),
124: Collections
125: .<AnnotationTree> emptyList()),
126: parameter.getName(), // name
127: make
128: .Identifier(parameter
129: .getTypeName()), // parameter type
130: null // initializer - does not make sense in parameters.
131: ));
132: }
133:
134: // create exceptions
135: Iterator<String> exceptions = wsdlOperation
136: .getExceptions();
137: List<ExpressionTree> exc = new ArrayList<ExpressionTree>();
138: while (exceptions.hasNext()) {
139: String exception = exceptions.next();
140: exc.add(make.Identifier(exception));
141: }
142:
143: // create method
144: ModifiersTree methodModifiers = make
145: .Modifiers(
146: Collections
147: .<Modifier> singleton(Modifier.PUBLIC),
148: Collections
149: .<AnnotationTree> emptyList());
150: MethodTree method = make
151: .Method(
152: methodModifiers, // public
153: wsdlOperation.getJavaName(), // operation name
154: make.Identifier(returnType), // return type
155: Collections
156: .<TypeParameterTree> emptyList(), // type parameters - none
157: params,
158: exc, // throws
159: "{ //TODO implement this method\nthrow new UnsupportedOperationException(\"Not implemented yet.\") }", // body text
160: null // default value - not applicable here, used by annotations
161: );
162:
163: ClassTree modifiedClass = make.addClassMember(
164: javaClass, method);
165:
166: workingCopy.rewrite(javaClass, modifiedClass);
167: }
168: }
169:
170: public void cancel() {
171: }
172: };
173: targetSource.runModificationTask(task).commit();
174: DataObject dobj = DataObject.find(implClassFo);
175: if (dobj != null) {
176: SaveCookie cookie = dobj.getCookie(SaveCookie.class);
177: if (cookie != null)
178: cookie.save();
179: }
180: }
181:
182: public static void deleteMethod(final FileObject implClass,
183: final String operationName) throws IOException {
184: JavaSource targetSource = JavaSource.forFileObject(implClass);
185: CancellableTask<WorkingCopy> task = new CancellableTask<WorkingCopy>() {
186: public void run(WorkingCopy workingCopy)
187: throws java.io.IOException {
188: workingCopy.toPhase(Phase.ELEMENTS_RESOLVED);
189: //workingCopy.toPhase(Phase.ELEMENTS_RESOLVED);
190: ClassTree javaClass = SourceUtils
191: .getPublicTopLevelTree(workingCopy);
192: if (javaClass != null) {
193: ExecutableElement method = new MethodVisitor(
194: workingCopy).getMethod(operationName);
195: TreeMaker make = workingCopy.getTreeMaker();
196: if (method != null) {
197: MethodTree methodTree = workingCopy.getTrees()
198: .getTree(method);
199: ClassTree modifiedJavaClass = make
200: .removeClassMember(javaClass,
201: methodTree);
202: workingCopy.rewrite(javaClass,
203: modifiedJavaClass);
204: boolean removeImplementsClause = false;
205: //find out if there are no more exposed operations, if so remove the implements clause
206: if (!new MethodVisitor(workingCopy)
207: .hasPublicMethod()) {
208: removeImplementsClause = true;
209: }
210:
211: if (removeImplementsClause) {
212: //TODO: need to remove implements clause on the SEI
213: //for now all implements are being remove
214: List<? extends Tree> implementeds = javaClass
215: .getImplementsClause();
216: for (Tree implemented : implementeds) {
217: modifiedJavaClass = make
218: .removeClassImplementsClause(
219: modifiedJavaClass,
220: implemented);
221: }
222: workingCopy.rewrite(javaClass,
223: modifiedJavaClass);
224: }
225: }
226: }
227: }
228:
229: //}
230: public void cancel() {
231: }
232: };
233: targetSource.runModificationTask(task).commit();
234: DataObject dobj = DataObject.find(implClass);
235: if (dobj != null) {
236: SaveCookie cookie = dobj.getCookie(SaveCookie.class);
237: if (cookie != null)
238: cookie.save();
239: }
240: }
241:
242: public static void removeMethod(final FileObject implClass,
243: final String operationName) throws IOException {
244: JavaSource targetSource = JavaSource.forFileObject(implClass);
245: CancellableTask<WorkingCopy> task = new CancellableTask<WorkingCopy>() {
246: public void run(WorkingCopy workingCopy)
247: throws java.io.IOException {
248: workingCopy.toPhase(Phase.ELEMENTS_RESOLVED);
249: TypeElement classEl = SourceUtils
250: .getPublicTopLevelElement(workingCopy);
251: if (classEl != null) {
252: ExecutableElement method = new MethodVisitor(
253: workingCopy).getMethod(operationName);
254: if (method != null) {
255: ClassTree javaClass = workingCopy.getTrees()
256: .getTree(classEl);
257: //first find out if @WebService annotation is present in the class
258: boolean foundWebServiceAnnotation = false;
259: TypeElement wsElement = workingCopy
260: .getElements().getTypeElement(
261: "javax.jws.WebService"); //NOI18N
262: if (wsElement != null) {
263: List<? extends AnnotationMirror> annotations = classEl
264: .getAnnotationMirrors();
265: for (AnnotationMirror anMirror : annotations) {
266: if (workingCopy.getTypes().isSameType(
267: wsElement.asType(),
268: anMirror.getAnnotationType())) {
269: foundWebServiceAnnotation = true;
270: break;
271: }
272: }
273: }
274: //do the class methods have at least one WebMethod annotation
275: boolean classHasWebMethods = new MethodVisitor(
276: workingCopy).hasWebMethod();
277: TreeMaker make = workingCopy.getTreeMaker();
278: MethodTree methodTree = workingCopy.getTrees()
279: .getTree(method);
280: if (methodTree != null) {
281: if (foundWebServiceAnnotation) {
282: if (!classHasWebMethods) {
283: //if class has no WebMethod annotations, add WebMethod annotation to all
284: //methods except the removed operation
285: List<ExecutableElement> publicMethods = new MethodVisitor(
286: workingCopy)
287: .getPublicMethods();
288: for (ExecutableElement m : publicMethods) {
289: if (m != method) {
290: TypeElement webMethodAnn = workingCopy
291: .getElements()
292: .getTypeElement(
293: "javax.jws.WebMethod"); //NOI18N
294: List<ExpressionTree> emptyList = Collections
295: .emptyList();
296:
297: AnnotationTree webMethodAnnotation = make
298: .Annotation(
299: make
300: .QualIdent(webMethodAnn),
301: emptyList);
302: MethodTree mTree = workingCopy
303: .getTrees()
304: .getTree(m);
305: ModifiersTree modTree = mTree
306: .getModifiers();
307: ModifiersTree newModifiersTree = make
308: .addModifiersAnnotation(
309: modTree,
310: webMethodAnnotation);
311: workingCopy.rewrite(
312: modTree,
313: newModifiersTree);
314: }
315: }
316: } else { //there are WebMethod annotations in the class, remove WebMethod annotation from the method
317: ModifiersTree modifiersTree = methodTree
318: .getModifiers();
319: ModifiersTree newModTree = make
320: .Modifiers(modifiersTree
321: .getFlags());
322: workingCopy.rewrite(modifiersTree,
323: newModTree);
324: }
325: } else { //no @WebService annotation, there must have been a @WebMethod annotation, remove it
326: AnnotationMirror webMethodAnMirr = getWebMethodAnnotation(
327: workingCopy, method);
328: if (webMethodAnMirr != null) {
329: ModifiersTree modifiersTree = methodTree
330: .getModifiers();
331: AnnotationTree annotTree = (AnnotationTree) workingCopy
332: .getTrees().getTree(
333: classEl,
334: webMethodAnMirr);
335: ModifiersTree newModTree = make
336: .removeModifiersAnnotation(
337: modifiersTree,
338: annotTree);
339: workingCopy.rewrite(modifiersTree,
340: newModTree);
341: }
342: }
343:
344: boolean removeImplementsClause = false;
345: //find out if there are no more exposed operations, if so remove the implements clause
346: if (foundWebServiceAnnotation) {
347: //if there is a WebService annotation find out if there are no more public methods
348: if (!new MethodVisitor(workingCopy)
349: .hasPublicMethod()) {
350: removeImplementsClause = true;
351: }
352: } else {
353: if (!new MethodVisitor(workingCopy)
354: .hasWebMethod()) {
355: removeImplementsClause = true;
356: }
357: }
358: if (removeImplementsClause) {
359: //TODO: need to remove implements clause on the SEI
360: //for now all implements are being removed
361: List<? extends Tree> implementeds = javaClass
362: .getImplementsClause();
363: ClassTree modifiedJavaClass = javaClass;
364: for (Tree implemented : implementeds) {
365: modifiedJavaClass = make
366: .removeClassImplementsClause(
367: modifiedJavaClass,
368: implemented);
369: }
370: workingCopy.rewrite(javaClass,
371: modifiedJavaClass);
372: }
373: }
374: }
375: }
376: }
377:
378: public void cancel() {
379: }
380: };
381: targetSource.runModificationTask(task).commit();
382: DataObject dobj = DataObject.find(implClass);
383: if (dobj != null) {
384: SaveCookie cookie = dobj.getCookie(SaveCookie.class);
385: if (cookie != null)
386: cookie.save();
387: }
388: }
389:
390: private static AnnotationMirror getWebMethodAnnotation(
391: WorkingCopy workingCopy, ExecutableElement method) {
392: TypeElement methodAnnotationEl = workingCopy.getElements()
393: .getTypeElement("javax.jws.WebMethod"); //NOI18N
394: List<? extends AnnotationMirror> methodAnnotations = method
395: .getAnnotationMirrors();
396: for (AnnotationMirror anMirror : methodAnnotations) {
397: if (workingCopy.getTypes().isSameType(
398: methodAnnotationEl.asType(),
399: anMirror.getAnnotationType())) {
400: return anMirror;
401: }
402: }
403: return null;
404: }
405:
406: private WsdlOperation getWsdlOperation(String operationName) {
407: // TODO: exclude non DOCUMENT/LITERAL ports
408: List<WsdlService> services = wsdlModel.getServices();
409: for (WsdlService service : services) {
410: List<WsdlPort> ports = service.getPorts();
411: for (WsdlPort port : ports) {
412: List<WsdlOperation> operations = port.getOperations();
413: for (WsdlOperation operation : operations) {
414: if (operationName.equals(operation.getName()))
415: return operation;
416: }
417: }
418: }
419: return null;
420: }
421:
422: }
|