1 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 ; 27 import java.rmi.RemoteException ; 28 import java.util.ArrayList ; 29 import java.util.Arrays ; 30 import java.util.Collections ; 31 import java.util.List ; 32 import java.util.Set ; 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 55 public abstract class AbstractMethodController extends EjbMethodController { 56 57 private final FileObject ejbClassFO; 58 private final EntityAndSession model; 59 protected Set 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 homeClass, String componentClass); 70 String 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 84 public final MethodModel createAndAdd(MethodModel clientView, boolean local, boolean isComponent) { 85 String home = null; 86 String 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 e) { 98 ErrorManager.getDefault().notify(e); 99 } 100 101 } else { 102 try { 103 addMethodToClass(home, clientView); 104 } catch (IOException e) { 105 ErrorManager.getDefault().notify(e); 106 } 107 } 108 String 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 e) { 116 ErrorManager.getDefault().notify(e); 117 } 118 } 119 } 120 MethodModel result = clientView; 121 if (!local && !simplified) { 122 result = addExceptionIfNecessary(clientView, RemoteException .class.getName()); 123 } 124 return result; 125 } 134 135 @Override 136 public final void createAndAddInterface(MethodModel beanImpl, boolean local) { 137 MethodType methodType = getMethodTypeFromImpl(beanImpl); 138 GenerateFromImpl generateFromImpl = createGenerateFromImpl(); 139 String home = null; 140 String 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 .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 destinationInterface = generateFromImpl.getDestinationInterface(); 163 try { 164 addMethodToClass(destinationInterface, method); 165 } catch (IOException e) { 166 ErrorManager.getDefault().notify(e); 167 } 168 169 } 170 171 @Override 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 ejbClass = model.getEjbClass(); 178 try { 179 addMethodToClass(ejbClass, method); 180 } catch (IOException e) { 181 ErrorManager.getDefault().notify(e); 182 } 183 184 } 185 186 private List <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 <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 202 public final List <MethodModel> getImplementation(MethodModel intfView) { 203 List <MethodModel> methods = getImplementationMethods(intfView); 204 List <MethodModel> result = new ArrayList <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 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 home = null; 220 String 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 destinationInterface = generateFromImpl.getDestinationInterface(); 231 boolean exists = findInClass(destinationInterface, interfaceMethodModel); 232 return exists ? new ClassMethodPair(destinationInterface, interfaceMethodModel) : null; 233 } 234 235 236 239 @Override 240 public boolean hasMethodInInterface(MethodModel method, MethodType methodType, boolean local) { 241 String 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 name = chopAndUpper(methodCopy.getName(), "ejb"); String 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 chopAndUpper(String fullName, String chop) { 268 StringBuffer stringBuffer = new StringBuffer (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 exceptionName) { 275 if (!method.getExceptions().contains(exceptionName)) { 276 List <String > exceptions = new ArrayList <String >(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 findBusinessInterface(String compInterfaceName) { 291 String beanClass = model.getEjbClass(); 292 if (compInterfaceName == null || beanClass == null) { 293 return null; 294 } 295 List <String > beanInterfaces = getInterfaces(beanClass); 297 List <String > compInterfaces = getInterfaces(compInterfaceName); 299 compInterfaces.retainAll(beanInterfaces); 301 if (compInterfaces.isEmpty()) { 302 return compInterfaceName; 303 } 304 String business = compInterfaces.get(0); 305 return business == null ? compInterfaceName : business; 306 } 307 308 private List <String > getInterfaces(final String className) { 309 JavaSource javaSource = JavaSource.forFileObject(ejbClassFO); 310 final List <String > result = new ArrayList <String >(); 311 try { 312 javaSource.runUserActionTask(new AbstractTask<CompilationController>() { 313 public void run(CompilationController controller) throws IOException { 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 interfaceFqn = ((TypeElement) element).getQualifiedName().toString(); 320 result.add(interfaceFqn); 321 } 322 } 323 }, true); 324 } catch (IOException e) { 325 ErrorManager.getDefault().notify(e); 326 } 327 return result; 328 } 329 330 @Override 331 public final String getBeanClass() { 332 return model.getEjbClass() == null ? null : model.getEjbClass(); 333 } 334 335 @Override 336 public final List <String > getLocalInterfaces() { 337 if (!hasLocal()) { 338 return Collections.<String >emptyList(); 339 } 340 List <String > resultList = new ArrayList <String >(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 352 public final List <String > getRemoteInterfaces() { 353 if (!hasRemote()) { 354 return Collections.<String >emptyList(); 355 } 356 List <String > resultList = new ArrayList <String >(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 367 public final void delete(MethodModel interfaceMethod, boolean local) { 368 List <MethodModel> impls = getImplementation(interfaceMethod); 369 boolean checkOther = local ? hasRemote() : hasLocal(); 370 if (!impls.isEmpty()) { 371 for (MethodModel impl : impls) { 372 if (impl != null) { ClassMethodPair classMethodPair = getInterface(impl, !local); 374 if (((checkOther && classMethodPair == null)) || !checkOther) { 375 try { 376 removeMethodFromClass(classMethodPair.getClassName(), classMethodPair.getMethodModel()); 377 } catch (IOException e) { 378 ErrorManager.getDefault().notify(e); 379 } 380 381 } 382 } 383 } 384 try { 385 removeMethodFromClass(getBeanClass(), interfaceMethod); 386 } catch (IOException e) { 387 ErrorManager.getDefault().notify(e); 388 } 389 390 } 391 } 392 393 @Override 394 public boolean hasRemote() { 395 String 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 409 public boolean hasLocal() { 410 String 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 424 public MethodModel getPrimaryImplementation(MethodModel intfView) { 425 List <MethodModel> impls = getImplementation(intfView); 426 return impls.isEmpty() ? null : impls.get(0); 427 } 428 429 @Override 430 public String getRemote() { 431 return model.getRemote(); 432 } 433 434 @Override 435 public String getLocal() { 436 return model.getLocal(); 437 } 438 439 450 public String getBeanInterface(boolean local, boolean isComponent) { 451 if (isComponent) { 452 return findBusinessInterface(local ? model.getLocal() : model.getRemote()); 453 } else { 454 String className = local ? model.getLocalHome() : model.getHome(); 455 return className; 456 } 457 } 458 459 private void createBeanMethod(MethodModel method) throws IOException { 460 String beanClass = model.getEjbClass(); 461 if (hasJavaImplementation(method)) { 462 List <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 clazz = getBeanInterface(local, isComponent); 473 MethodModel methodCopy = method; 474 assert clazz != null; 475 if (!local) { 476 methodCopy = addExceptionIfNecessary(methodCopy, RemoteException .class.getName()); 477 } 478 try { 479 removeMethodFromClass(clazz, methodCopy); 480 createBeanMethod(methodCopy); 481 } catch (IOException e) { 482 ErrorManager.getDefault().notify(e); 483 } 484 485 } 486 487 490 protected boolean findInClass(final String clazz, final MethodModel methodModel) { 491 try { 492 return methodFindInClass(clazz, methodModel); 493 } catch (IOException e) { 494 ErrorManager.getDefault().notify(e); 495 return false; 496 } 497 498 } 499 500 private boolean methodFindInClass(final String clazz, final MethodModel methodModel) throws IOException { 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 { 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 className, final MethodModel method) throws IOException { 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 { 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 className, final MethodModel methodModel) throws IOException { 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 { 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 561 private FileObject resolveFileObjectForClass(FileObject referenceFileObject, final String className) throws IOException { 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 |