KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > j2ee > ejbcore > api > methodcontroller > AbstractMethodController


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.modules.j2ee.ejbcore.api.methodcontroller;
20
21 import org.netbeans.modules.j2ee.common.method.MethodModelSupport;
22 import org.netbeans.modules.j2ee.common.method.MethodModel;
23 import com.sun.source.tree.ClassTree;
24 import com.sun.source.tree.MethodTree;
25 import com.sun.source.util.Trees;
26 import java.io.IOException JavaDoc;
27 import java.rmi.RemoteException JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Arrays JavaDoc;
30 import java.util.Collections JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Set JavaDoc;
33 import javax.lang.model.element.Element;
34 import javax.lang.model.element.ExecutableElement;
35 import javax.lang.model.element.Modifier;
36 import javax.lang.model.element.TypeElement;
37 import javax.lang.model.type.TypeMirror;
38 import javax.lang.model.util.ElementFilter;
39 import javax.lang.model.util.Types;
40 import org.netbeans.api.java.source.CompilationController;
41 import org.netbeans.api.java.source.JavaSource;
42 import org.netbeans.api.java.source.JavaSource.Phase;
43 import org.netbeans.api.java.source.SourceUtils;
44 import org.netbeans.api.java.source.WorkingCopy;
45 import org.netbeans.modules.j2ee.common.source.AbstractTask;
46 import org.netbeans.modules.j2ee.dd.api.ejb.EntityAndSession;
47 import org.openide.ErrorManager;
48 import org.openide.filesystems.FileObject;
49
50 /**
51  *
52  * @author Chris Webster
53  * @author Martin Adamek
54  */

55 public abstract class AbstractMethodController extends EjbMethodController {
56     
57     private final FileObject ejbClassFO;
58     private final EntityAndSession model;
59     protected Set JavaDoc classesForSave;
60     private final boolean simplified;
61     
62     public AbstractMethodController(FileObject ejbClassFO, EntityAndSession model) {
63         this.ejbClassFO = ejbClassFO;
64         this.model = model;
65         this.simplified = model.getRoot().getVersion().doubleValue() > 2.1;
66     }
67     
68     public interface GenerateFromImpl {
69         void getInterfaceMethodFromImpl(MethodType methodType, String JavaDoc homeClass, String JavaDoc componentClass);
70         String JavaDoc getDestinationInterface();
71         MethodModel getInterfaceMethod();
72     }
73     
74     public interface GenerateFromIntf {
75         void getInterfaceMethodFromImpl(MethodType methodType);
76         MethodModel getImplMethod();
77         MethodModel getSecondaryMethod();
78     }
79     
80     public abstract GenerateFromImpl createGenerateFromImpl();
81     public abstract GenerateFromIntf createGenerateFromIntf();
82     
83     @Override JavaDoc
84     public final MethodModel createAndAdd(MethodModel clientView, boolean local, boolean isComponent) {
85         String JavaDoc home = null;
86         String JavaDoc component = null;
87         if (local) {
88             home = model.getLocalHome();
89             component = findBusinessInterface(model.getLocal());
90         } else {
91             home = model.getHome();
92             component = findBusinessInterface(model.getRemote());
93         }
94         if (isComponent) {
95             try {
96                 addMethodToClass(component, clientView);
97             } catch (IOException JavaDoc e) {
98                 ErrorManager.getDefault().notify(e);
99             }
100
101         } else {
102             try {
103                 addMethodToClass(home, clientView);
104             } catch (IOException JavaDoc e) {
105                 ErrorManager.getDefault().notify(e);
106             }
107         }
108         String JavaDoc ejbClass = model.getEjbClass();
109         if (hasJavaImplementation(clientView)) {
110             for (MethodModel me : getImplementationMethods(clientView)) {
111                 try {
112                     if (!findInClass(ejbClass, me)) {
113                         addMethodToClass(ejbClass, me);
114                     }
115                 } catch (IOException JavaDoc e) {
116                     ErrorManager.getDefault().notify(e);
117                 }
118             }
119         }
120         MethodModel result = clientView;
121         if (!local && !simplified) {
122             result = addExceptionIfNecessary(clientView, RemoteException JavaDoc.class.getName());
123         }
124         return result;
125             //TODO: RETOUCHE opening generated method in editor
126
// if (methodToOpen != null) {
127
// StatementBlock stBlock = null;
128
// if (methodToOpen.isValid())
129
// stBlock = methodToOpen.getBody();
130
// if (stBlock != null)
131
// JMIUtils.openInEditor(stBlock);
132
// }
133
}
134     
135     @Override JavaDoc
136     public final void createAndAddInterface(MethodModel beanImpl, boolean local) {
137         MethodType methodType = getMethodTypeFromImpl(beanImpl);
138         GenerateFromImpl generateFromImpl = createGenerateFromImpl();
139         String JavaDoc home = null;
140         String JavaDoc component = null;
141         if (local) {
142             home = model.getLocalHome();
143             component = findBusinessInterface(model.getLocal());
144         } else {
145             home = model.getHome();
146             component = findBusinessInterface(model.getRemote());
147         }
148         generateFromImpl.getInterfaceMethodFromImpl(methodType, home, component);
149         MethodModel method = generateFromImpl.getInterfaceMethod();
150         if (!local && !simplified) {
151             method = addExceptionIfNecessary(method, RemoteException JavaDoc.class.getName());
152         }
153         method = MethodModel.create(
154                 method.getName(),
155                 method.getReturnType(),
156                 method.getBody(),
157                 method.getParameters(),
158                 method.getExceptions(),
159                 Collections.<Modifier>emptySet()
160                 );
161
162         String JavaDoc destinationInterface = generateFromImpl.getDestinationInterface();
163         try {
164             addMethodToClass(destinationInterface, method);
165         } catch (IOException JavaDoc e) {
166             ErrorManager.getDefault().notify(e);
167         }
168
169     }
170     
171     @Override JavaDoc
172     public final void createAndAddImpl(MethodModel intfView) {
173         MethodType methodType = getMethodTypeFromInterface(intfView);
174         GenerateFromIntf generateFromIntf = createGenerateFromIntf();
175         generateFromIntf.getInterfaceMethodFromImpl(methodType);
176         MethodModel method = generateFromIntf.getImplMethod();
177         String JavaDoc ejbClass = model.getEjbClass();
178         try {
179             addMethodToClass(ejbClass, method);
180         } catch (IOException JavaDoc e) {
181             ErrorManager.getDefault().notify(e);
182         }
183
184     }
185     
186     private List JavaDoc<MethodModel> getImplementationMethods(MethodModel intfView) {
187         MethodType methodType = getMethodTypeFromInterface(intfView);
188         GenerateFromIntf generateFromIntf = createGenerateFromIntf();
189         generateFromIntf.getInterfaceMethodFromImpl(methodType);
190         MethodModel primary = generateFromIntf.getImplMethod();
191         MethodModel secondary = generateFromIntf.getSecondaryMethod();
192         List JavaDoc<MethodModel> methods = null;
193         if (secondary != null) {
194             methods = Arrays.asList(new MethodModel[] {primary, secondary});
195         } else {
196             methods = Collections.singletonList(primary);
197         }
198         return methods;
199     }
200     
201     @Override JavaDoc
202     public final List JavaDoc<MethodModel> getImplementation(MethodModel intfView) {
203         List JavaDoc<MethodModel> methods = getImplementationMethods(intfView);
204         List JavaDoc<MethodModel> result = new ArrayList JavaDoc<MethodModel>(methods.size());
205         for (MethodModel method : methods) {
206             boolean exists = findInClass(getBeanClass(), method);
207             if (exists) {
208                 result.add(method);
209             }
210         }
211         return result;
212     }
213     
214     @Override JavaDoc
215     public final ClassMethodPair getInterface(MethodModel beanImpl, boolean local) {
216         MethodType methodType = getMethodTypeFromImpl(beanImpl);
217         assert methodType != null: "method cannot be used in interface";
218         GenerateFromImpl generateFromImpl = createGenerateFromImpl();
219         String JavaDoc home = null;
220         String JavaDoc component = null;
221         if (local) {
222             home = model.getLocalHome();
223             component = findBusinessInterface(model.getLocal());
224         } else {
225             home = model.getHome();
226             component = findBusinessInterface(model.getRemote());
227         }
228         generateFromImpl.getInterfaceMethodFromImpl(methodType,home,component);
229         MethodModel interfaceMethodModel = generateFromImpl.getInterfaceMethod();
230         String JavaDoc destinationInterface = generateFromImpl.getDestinationInterface();
231         boolean exists = findInClass(destinationInterface, interfaceMethodModel);
232         return exists ? new ClassMethodPair(destinationInterface, interfaceMethodModel) : null;
233     }
234     
235     
236     /** Performs the check if the method is defined in apporpriate interface
237      * @return false if the interface is found but does not contain matching method.
238      */

239     @Override JavaDoc
240     public boolean hasMethodInInterface(MethodModel method, MethodType methodType, boolean local) {
241         String JavaDoc intf = null;
242         MethodModel methodCopy = method;
243         if (methodType.getKind() == MethodType.Kind.BUSINESS) {
244             intf = findBusinessInterface(local ? model.getLocal() : model.getRemote());
245         } else if (methodType.getKind() == MethodType.Kind.CREATE) {
246             String JavaDoc name = chopAndUpper(methodCopy.getName(), "ejb"); //NOI18N
247
String JavaDoc type = local ? model.getLocal() : model.getRemote();
248             methodCopy = MethodModel.create(
249                     name,
250                     type,
251                     methodCopy.getBody(),
252                     methodCopy.getParameters(),
253                     methodCopy.getExceptions(),
254                     methodCopy.getModifiers()
255                     );
256             intf = local ? model.getLocalHome() : model.getHome();
257         }
258         if (methodCopy.getName() == null || intf == null || methodCopy.getReturnType() == null) {
259             return true;
260         }
261         if (findInClass(intf, methodCopy)) {
262             return true;
263         }
264         return false;
265     }
266     
267     private String JavaDoc chopAndUpper(String JavaDoc fullName, String JavaDoc chop) {
268         StringBuffer JavaDoc stringBuffer = new StringBuffer JavaDoc(fullName);
269         stringBuffer.delete(0, chop.length());
270         stringBuffer.setCharAt(0, Character.toLowerCase(stringBuffer.charAt(0)));
271         return stringBuffer.toString();
272     }
273     
274     private MethodModel addExceptionIfNecessary(MethodModel method, String JavaDoc exceptionName) {
275         if (!method.getExceptions().contains(exceptionName)) {
276             List JavaDoc<String JavaDoc> exceptions = new ArrayList JavaDoc<String JavaDoc>(method.getExceptions());
277             exceptions.add(exceptionName);
278             return MethodModel.create(
279                     method.getName(),
280                     method.getReturnType(),
281                     method.getBody(),
282                     method.getParameters(),
283                     exceptions,
284                     method.getModifiers()
285                     );
286         }
287         return method;
288     }
289     
290     private String JavaDoc findBusinessInterface(String JavaDoc compInterfaceName) {
291         String JavaDoc beanClass = model.getEjbClass();
292         if (compInterfaceName == null || beanClass == null) {
293             return null;
294         }
295         // get bean interfaces
296
List JavaDoc<String JavaDoc> beanInterfaces = getInterfaces(beanClass);
297         // get method interfaces
298
List JavaDoc<String JavaDoc> compInterfaces = getInterfaces(compInterfaceName);
299         // look for common candidates
300
compInterfaces.retainAll(beanInterfaces);
301         if (compInterfaces.isEmpty()) {
302             return compInterfaceName;
303         }
304         String JavaDoc business = compInterfaces.get(0);
305         return business == null ? compInterfaceName : business;
306     }
307     
308     private List JavaDoc<String JavaDoc> getInterfaces(final String JavaDoc className) {
309         JavaSource javaSource = JavaSource.forFileObject(ejbClassFO);
310         final List JavaDoc<String JavaDoc> result = new ArrayList JavaDoc<String JavaDoc>();
311         try {
312             javaSource.runUserActionTask(new AbstractTask<CompilationController>() {
313                 public void run(CompilationController controller) throws IOException JavaDoc {
314                     controller.toPhase(Phase.ELEMENTS_RESOLVED);
315                     TypeElement typeElement = controller.getElements().getTypeElement(className);
316                     Types types = controller.getTypes();
317                     for (TypeMirror interfaceType : typeElement.getInterfaces()) {
318                         Element element = types.asElement(interfaceType);
319                         String JavaDoc interfaceFqn = ((TypeElement) element).getQualifiedName().toString();
320                         result.add(interfaceFqn);
321                     }
322                 }
323             }, true);
324         } catch (IOException JavaDoc e) {
325             ErrorManager.getDefault().notify(e);
326         }
327         return result;
328     }
329     
330     @Override JavaDoc
331     public final String JavaDoc getBeanClass() {
332         return model.getEjbClass() == null ? null : model.getEjbClass();
333     }
334     
335     @Override JavaDoc
336     public final List JavaDoc<String JavaDoc> getLocalInterfaces() {
337         if (!hasLocal()) {
338             return Collections.<String JavaDoc>emptyList();
339         }
340         List JavaDoc<String JavaDoc> resultList = new ArrayList JavaDoc<String JavaDoc>(2);
341         if (model.getLocalHome() != null) {
342             resultList.add(model.getLocalHome());
343         }
344         if (model.getLocal() != null) {
345             resultList.add(findBusinessInterface(model.getLocal()));
346         }
347         
348         return resultList;
349     }
350     
351     @Override JavaDoc
352     public final List JavaDoc<String JavaDoc> getRemoteInterfaces() {
353         if (!hasRemote()) {
354             return Collections.<String JavaDoc>emptyList();
355         }
356         List JavaDoc<String JavaDoc> resultList = new ArrayList JavaDoc<String JavaDoc>(2);
357         if (model.getHome() != null) {
358             resultList.add(model.getHome());
359         }
360         if (model.getRemote() != null) {
361             resultList.add(findBusinessInterface(model.getRemote()));
362         }
363         return resultList;
364     }
365     
366     @Override JavaDoc
367     public final void delete(MethodModel interfaceMethod, boolean local) {
368         List JavaDoc<MethodModel> impls = getImplementation(interfaceMethod);
369         boolean checkOther = local ? hasRemote() : hasLocal();
370         if (!impls.isEmpty()) {
371             for (MethodModel impl : impls) {
372                 if (impl != null) { // could be null here if the method is missing
373
ClassMethodPair classMethodPair = getInterface(impl, !local);
374                     if (((checkOther && classMethodPair == null)) || !checkOther) {
375                         try {
376                             removeMethodFromClass(classMethodPair.getClassName(), classMethodPair.getMethodModel());
377                         } catch (IOException JavaDoc e) {
378                             ErrorManager.getDefault().notify(e);
379                         }
380
381                     }
382                 }
383             }
384             try {
385                 removeMethodFromClass(getBeanClass(), interfaceMethod);
386             } catch (IOException JavaDoc e) {
387                 ErrorManager.getDefault().notify(e);
388             }
389
390         }
391     }
392     
393     @Override JavaDoc
394     public boolean hasRemote() {
395         String JavaDoc intf = model.getHome();
396         if (!simplified) {
397             if (intf == null) {
398                 return false;
399             }
400         }
401         intf = model.getRemote();
402         if (intf == null || findBusinessInterface(intf) == null) {
403             return false;
404         }
405         return true;
406     }
407     
408     @Override JavaDoc
409     public boolean hasLocal() {
410         String JavaDoc intf = model.getLocalHome();
411         if (!simplified) {
412             if (intf == null) {
413                 return false;
414             }
415         }
416         intf = model.getLocal();
417         if (intf == null || findBusinessInterface(intf) == null) {
418             return false;
419         }
420         return true;
421     }
422     
423     @Override JavaDoc
424     public MethodModel getPrimaryImplementation(MethodModel intfView) {
425         List JavaDoc<MethodModel> impls = getImplementation(intfView);
426         return impls.isEmpty() ? null : impls.get(0);
427     }
428     
429     @Override JavaDoc
430     public String JavaDoc getRemote() {
431         return model.getRemote();
432     }
433     
434     @Override JavaDoc
435     public String JavaDoc getLocal() {
436         return model.getLocal();
437     }
438     
439 // public final MethodModel addMethod(MethodModel method, boolean local, boolean isComponent) {
440
// TypeElement javaClass = getBeanInterface(local, isComponent);
441
// assert javaClass != null;
442
// addMethodToClass(javaClass, method);
443
// if (!local) {
444
// method = addExceptionIfNecessary(method, RemoteException.class.getName());
445
// }
446
// createBeanMethod(method);
447
// return method;
448
// }
449

450     public String JavaDoc getBeanInterface(boolean local, boolean isComponent) {
451         if (isComponent) {
452             return findBusinessInterface(local ? model.getLocal() : model.getRemote());
453         } else {
454             String JavaDoc className = local ? model.getLocalHome() : model.getHome();
455             return className;
456         }
457     }
458     
459     private void createBeanMethod(MethodModel method) throws IOException JavaDoc {
460         String JavaDoc beanClass = model.getEjbClass();
461         if (hasJavaImplementation(method)) {
462             List JavaDoc<MethodModel> implMethods = getImplementationMethods(method);
463             for (MethodModel me : implMethods) {
464                 if (!findInClass(beanClass, me)) {
465                     addMethodToClass(beanClass, method);
466                 }
467             }
468         }
469     }
470     
471     public final void removeMethod(MethodModel method, boolean local, boolean isComponent) {
472         String JavaDoc clazz = getBeanInterface(local, isComponent);
473         MethodModel methodCopy = method;
474         assert clazz != null;
475         if (!local) {
476             methodCopy = addExceptionIfNecessary(methodCopy, RemoteException JavaDoc.class.getName());
477         }
478         try {
479             removeMethodFromClass(clazz, methodCopy);
480             createBeanMethod(methodCopy);
481         } catch (IOException JavaDoc e) {
482             ErrorManager.getDefault().notify(e);
483         }
484
485     }
486
487     // util candidates
488
// -------------------------------------------------------------------------
489

490     protected boolean findInClass(final String JavaDoc clazz, final MethodModel methodModel) {
491         try {
492             return methodFindInClass(clazz, methodModel);
493         } catch (IOException JavaDoc e) {
494             ErrorManager.getDefault().notify(e);
495             return false;
496         }
497
498     }
499
500     private boolean methodFindInClass(final String JavaDoc clazz, final MethodModel methodModel) throws IOException JavaDoc {
501         JavaSource javaSource = JavaSource.forFileObject(ejbClassFO);
502         final boolean [] result = new boolean[] {false};
503         javaSource.runUserActionTask(new AbstractTask<CompilationController>() {
504             public void run(CompilationController controller) throws IOException JavaDoc {
505                 controller.toPhase(Phase.ELEMENTS_RESOLVED);
506                 TypeElement typeElement = controller.getElements().getTypeElement(clazz);
507                 for (ExecutableElement method : ElementFilter.methodsIn(typeElement.getEnclosedElements())) {
508                     if (MethodModelSupport.isSameMethod(controller, method, methodModel)) {
509                         result[0] = true;
510                         return;
511                     }
512                 }
513             }
514         }, true);
515         return result[0];
516     }
517     
518     protected void addMethodToClass(final String JavaDoc className, final MethodModel method) throws IOException JavaDoc {
519         FileObject fileObject = resolveFileObjectForClass(ejbClassFO, className);
520         JavaSource javaSource = JavaSource.forFileObject(fileObject);
521         javaSource.runModificationTask(new AbstractTask<WorkingCopy>() {
522             public void run(WorkingCopy workingCopy) throws IOException JavaDoc {
523                 workingCopy.toPhase(Phase.ELEMENTS_RESOLVED);
524                 Trees trees = workingCopy.getTrees();
525                 TypeElement clazz = workingCopy.getElements().getTypeElement(className);
526                 ClassTree classTree = trees.getTree(clazz);
527                 MethodTree methodTree = MethodModelSupport.createMethodTree(workingCopy, method);
528                 ClassTree modifiedClassTree = workingCopy.getTreeMaker().addClassMember(classTree, methodTree);
529                 workingCopy.rewrite(classTree, modifiedClassTree);
530             }
531         }).commit();
532     }
533
534     protected void removeMethodFromClass(final String JavaDoc className, final MethodModel methodModel) throws IOException JavaDoc {
535         FileObject fileObject = resolveFileObjectForClass(ejbClassFO, className);
536         JavaSource javaSource = JavaSource.forFileObject(fileObject);
537         javaSource.runModificationTask(new AbstractTask<WorkingCopy>() {
538             public void run(WorkingCopy workingCopy) throws IOException JavaDoc {
539                 workingCopy.toPhase(Phase.ELEMENTS_RESOLVED);
540                 if (methodFindInClass(className, methodModel)) {
541                     TypeElement foundClass = workingCopy.getElements().getTypeElement(className);
542                     Trees trees = workingCopy.getTrees();
543                     ClassTree classTree = trees.getTree(foundClass);
544                     MethodTree methodTree = MethodModelSupport.createMethodTree(workingCopy, methodModel);
545                     ClassTree modifiedClassTree = workingCopy.getTreeMaker().removeClassMember(classTree, methodTree);
546                     workingCopy.rewrite(classTree, modifiedClassTree);
547                 }
548             }
549         }).commit();
550     }
551
552     /**
553      * Tries to find {@link FileObject} which contains class with given className.<br>
554      * This method will enter javac context for referenceFileObject to find class by its className,
555      * therefore don't call this method within other javac context.
556      *
557      * @param referenceFileObject helper file for entering javac context
558      * @param className fully-qualified class name to resolve file for
559      * @return resolved file or null if not found
560      */

561     private FileObject resolveFileObjectForClass(FileObject referenceFileObject, final String JavaDoc className) throws IOException JavaDoc {
562         final FileObject[] result = new FileObject[1];
563         JavaSource javaSource = JavaSource.forFileObject(referenceFileObject);
564         javaSource.runUserActionTask(new AbstractTask<CompilationController>() {
565             public void run(CompilationController controller) {
566                 TypeElement typeElement = controller.getElements().getTypeElement(className);
567                 result[0] = SourceUtils.getFile(typeElement, controller.getClasspathInfo());
568             }
569         }, true);
570         return result[0];
571     }
572     
573 }
Popular Tags