1 19 package org.netbeans.modules.apisupport.project.metainf; 20 21 import java.io.IOException ; 22 import java.io.InputStream ; 23 import java.util.ArrayList ; 24 import java.util.Collections ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.TreeMap ; 28 import javax.swing.Action ; 29 import org.netbeans.api.project.ProjectManager; 30 import org.netbeans.modules.apisupport.project.NbModuleProject; 31 import org.netbeans.modules.apisupport.project.Util; 32 import org.openide.DialogDisplayer; 33 import org.openide.ErrorManager; 34 import org.openide.NotifyDescriptor; 35 import org.openide.actions.DeleteAction; 36 import org.openide.filesystems.FileChangeListener; 37 import org.openide.filesystems.FileObject; 38 import org.openide.nodes.AbstractNode; 39 import org.openide.nodes.Children; 40 import org.openide.nodes.Node; 41 import org.openide.util.NbBundle; 42 import org.openide.util.RequestProcessor; 43 44 48 public final class ServiceNodeHandler { 49 private static final String KEY_WAIT = "wait"; 51 private static final String THIS_SERVICES = NbBundle.getMessage(ServiceNodeHandler.class,"LBL_this_services"); 52 private static final String THIS_SERVICES_IN_CONTEXT = NbBundle.getMessage(ServiceNodeHandler.class,"LBL_this_services_in_context"); 53 static final String ROOT_NODE_NAME = NbBundle.getMessage(ServiceNodeHandler.class,"LBL_META_INF_services"); 54 TreeMap allServicesMap ; 56 TreeMap moduleServiceMap; 58 59 int prevAllServicesCount = -1; 60 int prevModuleServicesCount = -1; 61 62 final NbModuleProject project; 63 List moduleServices; 64 65 67 ServiceRootChildren moduleChild ; 68 70 ServiceRootChildren allInContextChild; 71 boolean registeredListener; 72 74 private FileObject metaInfServicesFo; 75 77 private String codeNameBase; 78 80 class ServiceRootChildren extends Children.Keys { 81 boolean fullyComputed = false; 82 84 private final boolean bProjectServices ; 85 86 ServiceRootChildren(boolean bProjectServices) { 87 this.bProjectServices = bProjectServices; 88 } 89 protected Node[] createNodes(Object key) { 90 if (key == KEY_WAIT) { 92 return new Node[] {new AbstractNode(Children.LEAF) { 93 public String getName() { 94 return KEY_WAIT; 95 } 96 public String getDisplayName() { 97 return NbBundle.getMessage(ServiceNodeHandler.class,"LBL_ServiceNode_please_wait"); 98 } 99 public Action [] getActions(boolean context) { 100 return new Action [0]; 101 } 102 }}; 103 } else if (key instanceof String ) { 104 Node parent = getNode(); 105 String parentName = parent.getName(); 106 boolean isThisModule = parentName == THIS_SERVICES; 107 ServiceNode node = new ServiceNode((String )key,isThisModule); 108 return new Node[] {node}; 109 } else { 110 throw new AssertionError (key); 111 } 112 113 114 } 115 116 protected void addNotify() { 117 SUtil.log(SUtil.LOG_SERVICE_NODE_HANDLER_ADD_NOTIFY); 118 super.addNotify(); 119 if (fullyComputed) { 120 Object keys[] = null; 121 if (bProjectServices) { 122 keys = moduleServiceMap.keySet().toArray(); 124 prevModuleServicesCount = moduleServiceMap.keySet().size(); 125 SUtil.log(SUtil.LOG_SET_KEYS); 126 setKeys(keys); 127 } else { 128 keys = allServicesMap.keySet().toArray(); 129 prevAllServicesCount = allServicesMap.keySet().size(); 130 setKeys(keys); 131 } 132 } else { 133 SUtil.log(SUtil.LOG_COMPUTE_KEYS); 134 setKeys(new Object [] {KEY_WAIT}); 135 RequestProcessor.getDefault().post(new Runnable () { 136 public void run() { 137 try { 138 Object keys[] = null; 139 synchronized(ServiceNodeHandler.this) { 142 if (moduleServiceMap == null) { 143 moduleServiceMap = new TreeMap (); 144 moduleServices = Service.getOnlyProjectServices(project); 145 sortServices(moduleServiceMap, moduleServices); 146 } 147 if (bProjectServices) { 148 keys = moduleServiceMap.keySet().toArray(); 150 prevModuleServicesCount = moduleServiceMap.keySet().size(); 151 } else { 152 if (allServicesMap == null) { 153 allServicesMap = new TreeMap (); 154 List services = ServiceViewUpdater.getAllServices(ServiceNodeHandler.this); 155 if (services != null) { 156 assert moduleServiceMap!=null; 157 sortServices(allServicesMap, services); 158 } 159 } 160 prevAllServicesCount = allServicesMap.keySet().size(); 161 keys = allServicesMap.keySet().toArray(); 162 if (keys.length > 0) { 163 SUtil.log(keys[0].toString()); 164 } 165 } 166 167 } 168 setKeys(keys); 169 synchronized (ServiceNodeHandler.this) { 170 fullyComputed = true; 172 SUtil.log(SUtil.LOG_END_COMPUTE_KEYS); 173 } 174 } catch (IOException e) { 175 Util.err.notify(ErrorManager.INFORMATIONAL, e); 176 } 177 } 179 180 181 private void sortServices(final TreeMap map, final List services) { 182 for (Iterator it = services.iterator() ; it.hasNext();) { 184 Service service = (Service) it.next(); 185 assert map != null; 186 List theSameServices = (List ) map.get(service.getFileName()); 187 if (theSameServices == null) { 188 theSameServices = new ArrayList (); 189 map.put(service.getFileName(),theSameServices); 190 } 191 theSameServices.add(service); 192 } 193 } 194 }); } } 197 198 void refreshKeys() { 199 if (bProjectServices) { 200 setKeys(moduleServiceMap.keySet()); 201 prevModuleServicesCount = moduleServiceMap.size(); 202 } else { 203 setKeys(allServicesMap.keySet()); 204 prevAllServicesCount = allServicesMap.size(); 205 } 206 207 } 208 209 public void updateNode(String keyName) { 210 Node nodes[] = this.getNodes() ; 211 for (int nIt = 0 ; nIt < nodes.length; nIt++) { 212 ServiceNode n = (ServiceNode)nodes[nIt]; 213 if (n.getName().equals(keyName)) { 214 n.refreshName(); 215 ((ServiceNodeChildren)n.getChildren()).nodesChanged(); 216 } 217 } 218 } 219 220 protected void removeNotify() { 221 setKeys(Collections.EMPTY_SET); 222 super.removeNotify(); 223 } 224 225 } 226 class ServiceClassKey { 227 String name; 228 boolean bRemoved; 229 ServiceClassKey(String name,boolean bRemoved) { 230 this.name = name; 231 this.bRemoved = bRemoved; 232 } 233 234 public int hashCode() { 235 return name.hashCode(); 236 } 237 238 public boolean equals(Object obj) { 239 return (obj instanceof ServiceClassKey) && ((ServiceClassKey)obj).name.equals(name); 240 } 241 242 } 243 244 class ServiceNodeChildren extends Children.Keys { 245 private boolean isThisModule; 246 248 private TreeMap keys; 249 boolean initialized = true; 250 251 ServiceNodeChildren(boolean isThisModule) { 252 this.isThisModule = isThisModule; 253 } 255 private TreeMap getKeysMap () { 256 if (keys == null) { 257 keys = new TreeMap (); 258 } 259 return keys; 260 } 261 262 private ServiceClassKey addKey(ServiceClassKey key,TreeMap newKeyMap) { 263 TreeMap keys = getKeysMap(); 264 ServiceClassKey oldKey = (ServiceClassKey)keys.get(key.name); 265 if (oldKey == null) { 266 oldKey = key; 267 } else if (oldKey.bRemoved != key.bRemoved) { 268 oldKey.bRemoved = key.bRemoved; 269 refreshKey(oldKey); 270 } 271 newKeyMap.put(key.name,oldKey); 272 return oldKey; 273 } 274 275 protected void addNotify() { 276 ServiceNode serviceNode = (ServiceNode) getNode(); 277 isThisModule = serviceNode.isThisModule(); 278 List servicesGroup = (List ) ((isThisModule) ? moduleServiceMap.get(serviceNode.getName()) : 279 allServicesMap.get(serviceNode.getName())); 280 281 List classes = new ArrayList (); 282 List maskedClasses = new ArrayList (); 283 284 Service service = null; 285 TreeMap newKeyMap = new TreeMap (); 286 for (Iterator sIt = servicesGroup.iterator(); sIt.hasNext() ; ) { 289 service = (Service) sIt.next(); 290 for (Iterator ssIt = service.getClasses().iterator() ; ssIt.hasNext() ; ) { 291 String name = (String )ssIt.next(); 292 if (name.charAt(0) == '-') { 293 maskedClasses.add(name); 294 } else { 295 classes.add(name); 296 } 297 } 298 } 299 300 int i; 303 for (i = 0 ; i < classes.size() ; i++) { 304 String name = (String )classes.get(i); 305 ServiceClassKey key = new ServiceClassKey(name,false); 306 if (!isThisModule) { 307 String filteredName = '-' + name; 308 for (int fIt = 0 ; fIt < maskedClasses.size() ; fIt++) { 310 if (maskedClasses.get(fIt).equals(filteredName)) { 311 key.bRemoved = true; 312 } 313 } 314 } 315 key = addKey(key,newKeyMap); 316 317 } 318 if (isThisModule) { 321 for ( int j = 0; j < maskedClasses.size() ; j++ ) { 322 addKey(new ServiceClassKey((String )maskedClasses.get(j),false),newKeyMap); 323 } 324 } 325 this.keys = newKeyMap; 326 setKeys(getKeysMap().values()); 327 initialized = true; 328 } 329 protected Node[] createNodes(Object key) { 330 ServiceClassKey classKey = (ServiceClassKey)key; 331 ServiceClassNode node = new ServiceClassNode(classKey.name,classKey.bRemoved); 332 return new Node[] {node}; 333 } 334 335 synchronized void nodesChanged() { 336 if (initialized) { 337 addNotify(); 338 } 339 340 } 341 } 342 344 public final class ServiceNode extends AbstractNode { 345 ServiceNode(String name,boolean isThisModule) { 346 super(new ServiceNodeChildren(isThisModule)); 347 setName(name); 348 setIconBaseWithExtension("org/netbeans/modules/apisupport/project/metainf/interface.png"); 349 } 350 public void updateChildren() { 351 ((ServiceNodeChildren) getChildren()).nodesChanged(); 352 fireDisplayNameChange(null,null); 353 } 354 boolean isThisModule() { 355 return (getParentNode() == null) ? false : ( getParentNode().getName() == THIS_SERVICES); 356 } 357 public String getHtmlDisplayName() { 358 List services = (List ) moduleServiceMap.get(getName()); 359 360 return (services != null && !isThisModule()) ? "<b>" + getName() + "</b>" : getName(); } 362 363 public Action [] getActions(boolean context) { 364 return new Action [] {AddService.getInstance()}; 365 } 366 367 369 void addService(String serviceName, String classServiceName) { 370 List services = (List )allServicesMap.get(serviceName); 371 boolean exists = false; 372 for (int sIt = 0 ; sIt < services.size() ; sIt++ ) { 373 Service service = (Service) services.get(sIt); 374 List classes = service.getClasses(); 375 for (int cIt = 0 ; cIt < classes.size() ; cIt++) { 376 String className = (String ) classes.get(cIt); 377 if (classServiceName.equals(className)) { 378 exists = true; 380 NotifyDescriptor.Message msgDesc = 381 new NotifyDescriptor.Message(NbBundle.getMessage(ServiceNodeHandler.class,"MSG_ServiceExist",className)); 382 DialogDisplayer.getDefault().notify(msgDesc); 383 } 384 } 385 } 386 if (!exists) { 387 services = (List )moduleServiceMap.get(serviceName); 388 Service service = null; 389 if (services != null && services.size() > 0) { 390 service = (Service) services.get(0); 391 } else { 392 service = new Service(project.getCodeNameBase(),serviceName,new ArrayList ()); 393 } 394 service.getClasses().add(classServiceName); 395 service.write(project); 396 } 397 } 398 399 void refreshName() { 400 fireDisplayNameChange(null,null); 401 } 402 NbModuleProject getProject() { 403 return project; 404 } 405 406 } 407 408 410 public final class ServiceClassNode extends AbstractNode { 411 413 boolean bRemoved ; 414 ServiceClassNode(String className, boolean bRemoved) { 415 super(Children.LEAF); 416 setName(className); 417 this.bRemoved = bRemoved; 418 if (className.startsWith("-")) { setIconBaseWithExtension("org/netbeans/modules/apisupport/project/metainf/noinstance.png"); 420 } else { 421 setIconBaseWithExtension("org/netbeans/modules/apisupport/project/metainf/instance.png"); 422 } 423 } 424 Service getService() { 425 if (getParentNode() != null) { 427 List services = (List ) allServicesMap.get(getParentNode().getName() ); 428 String name = getName(); 429 if (services != null) { 430 for (Iterator it = services.iterator() ; it.hasNext() ; ) { 431 Service service = (Service) it.next(); 432 for (Iterator cIt = service.getClasses().iterator() ; cIt.hasNext() ; ) { 433 if (name.equals(cIt.next())) { 434 return service; 435 } 436 } 437 } 438 } 439 } 440 return null; 441 } 442 public Action [] getActions(boolean context) { 443 return new Action [] {DeleteAction.get(DeleteAction.class)}; 444 } 445 446 public String getHtmlDisplayName() { 447 List services = (List ) moduleServiceMap.get(getParentNode().getName() ); 448 String name = getName(); 449 boolean bFound = false; 450 if (services != null) { 451 for (Iterator it = services.iterator() ; it.hasNext() ; ) { 452 Service service = (Service) it.next(); 453 for (Iterator cIt = service.getClasses().iterator() ; cIt.hasNext() ; ) { 454 if (name.equals(cIt.next())) { 455 bFound = true; 456 break; 457 } 458 } 459 } 460 } 461 String dispName = (bFound && getParentNode().getParentNode().getName() != THIS_SERVICES) ? "<b>" + name + "</b>" : name; if (bRemoved) { 463 dispName = "<s>" + dispName + "</s>"; } 465 return dispName; 466 } 467 public boolean canDestroy() { 468 return true; 469 } 470 public boolean canCopy() { 471 return false; 472 } 473 public void destroy() throws IOException { 474 Service service = getService(); 475 if (service != null) { 477 Service moduleService = null; 478 List moduleServices = (List ) moduleServiceMap.get(service.getFileName()); 479 if (moduleServices == null || moduleServices.size() == 0) { 480 ArrayList classes = new ArrayList (); 482 moduleService = new Service(service.getCodebase(), 483 service.getFileName(), 484 classes); 485 } else { 486 moduleService = (Service) moduleServices.get(0); 487 } 488 moduleService.removeClass(getName(),project); 489 } 490 } 491 } 492 493 public ServiceNodeHandler(NbModuleProject project) { 494 this.project = project; 495 if (!registeredListener) { 496 ProjectManager.mutex().postWriteRequest(new Runnable () { 499 public void run() { 500 registerFileObjectListener(); 501 } 502 }); 503 } 504 505 } 506 507 509 public Node createServiceRootNode() { 510 return new ServiceRootNode(); 511 } 512 513 class ServiceRootNode extends AbstractNode { 514 ServiceRootNode () { 515 super (new Children.Array()); 516 setDisplayName(ROOT_NODE_NAME); 517 setName(ROOT_NODE_NAME); 518 Children.Array childs = (Children.Array)getChildren(); 519 childs.add(new Node[]{createServiceFolderNode(true), 520 createServiceFolderNode(false)}); 521 setIconBaseWithExtension("org/netbeans/modules/apisupport/project/metainf/services.png"); 522 } 523 ServiceNodeHandler getNodeHandler() { 524 return ServiceNodeHandler.this; 525 } 526 527 public Action [] getActions(boolean context) { 528 return new Action [0]; 529 } 530 } 531 532 static class ServiceFolderNode extends AbstractNode { 533 ServiceFolderNode(Children children) { 534 super(children); 535 } 536 public Action [] getActions(boolean context) { 537 return new Action [0]; 538 } 539 } 540 private Node createServiceFolderNode(boolean bProjectServices) { 541 ServiceRootChildren children = new ServiceRootChildren(bProjectServices); 542 AbstractNode node = new ServiceFolderNode(children); 543 if (bProjectServices) { 544 node.setDisplayName(THIS_SERVICES); 545 node.setName(THIS_SERVICES); 546 node.setIconBaseWithExtension("org/netbeans/modules/apisupport/project/metainf/export.png"); 547 moduleChild = children; 548 } else { 549 node.setDisplayName(THIS_SERVICES_IN_CONTEXT); 550 node.setName(THIS_SERVICES_IN_CONTEXT); 551 node.setIconBaseWithExtension("org/netbeans/modules/apisupport/project/metainf/services.png"); 552 allInContextChild = children; 553 } 554 return node; 555 } 556 557 561 564 public void registerFileObjectListener() { 565 FileObject srcDir = project.getSourceDirectory(); 566 567 if (srcDir != null) { 569 if (!registeredListener) { 570 registeredListener = true; 571 FileObject fo = srcDir.getFileObject("META-INF"); FileChangeListener listener = ServicesFileListener.getInstance(); 573 if (fo != null) { 574 fo.removeFileChangeListener(listener); 575 fo.addFileChangeListener(listener); 576 metaInfServicesFo = fo; 577 fo = fo.getFileObject("services"); if (fo != null) { 579 fo.removeFileChangeListener(listener); 580 fo.addFileChangeListener(listener); 581 metaInfServicesFo = fo; 582 } 583 } else { 584 srcDir.removeFileChangeListener(listener); 585 srcDir.addFileChangeListener(listener); 586 metaInfServicesFo = srcDir; 587 } 588 } 589 } else { 590 ErrorManager em = ErrorManager.getDefault(); 592 em.log(" project.getSourceDirectory() = null"); 593 em.log("codenamebase = " + project.getCodeNameBase() ); 594 em.log("projectroot = " + project.getProjectDirectory().getPath()); 595 } 596 } 597 598 void updateFile(FileObject fo) { 599 try { 600 if (fo.getParent() == SUtil.getServicesFolder(project,false) ) { 601 InputStream is = fo.getInputStream(); 602 Service service = Service.createService(project.getCodeNameBase(),fo.getNameExt(), is ); 603 is.close(); 604 ServiceViewUpdater.serviceUpdated(service,this); 605 } 607 } catch (IOException ioe) { 608 ErrorManager.getDefault().notify(ioe); 609 } 610 611 } 612 613 614 616 void removeFile(FileObject fileObject) throws IOException { 617 if (fileObject.getParent() == SUtil.getServicesFolder(project,false) ) { 618 String name = fileObject.getNameExt(); 619 if (moduleServiceMap != null) { 620 Service service = null; 621 synchronized (this) { 622 List services = (List )moduleServiceMap.get(name); 623 if (services != null && services.size() > 0 ) { 624 service = (Service)services.get(0); 625 } 626 moduleServiceMap.remove(name); 627 628 if (allServicesMap != null ) { 629 services = (List )allServicesMap.get(name); 630 if (services != null) { 631 services.remove(service); 632 633 if (services.isEmpty()) { 634 allServicesMap.remove(name); 635 } 636 } 637 } 638 } 639 updateNode(service); 640 } 641 } 642 } 643 644 649 private void updateNode(Service service) { 650 String name = (service == null) ? null : service.getFileName(); 651 if (moduleChild != null && moduleChild.fullyComputed &&moduleServiceMap != null ) { 652 if (prevModuleServicesCount == moduleServiceMap.size() && name != null ) { 653 moduleChild.updateNode(name); 655 } else { 656 moduleChild.refreshKeys(); 657 prevModuleServicesCount = moduleServiceMap.size(); 658 } 659 } 660 if (allInContextChild != null && allInContextChild.fullyComputed && allServicesMap != null) { 661 if (prevAllServicesCount == allServicesMap.size() && name != null) { 662 allInContextChild.updateNode(name); 663 } else { 664 allInContextChild.refreshKeys(); 665 prevAllServicesCount = allServicesMap.size(); 666 } 667 } 668 } 669 670 public int hashCode() { 671 return getCodeNameBase().hashCode(); 672 } 673 674 public boolean equals(Object obj) { 675 return obj instanceof ServiceNodeHandler && 676 getCodeNameBase().equals(((ServiceNodeHandler)obj).getCodeNameBase()); 677 } 678 679 void updateService(Service service) { 680 synchronized (this) { 682 if (moduleServiceMap != null) { 683 List services = (List ) moduleServiceMap.get(service.getFileName()) ; 684 if (service.getCodebase().equals(project.getCodeNameBase())) { 685 if (services != null && services.size() > 0 ) { 686 services.remove(0); 687 } else { 688 services = new ArrayList (); 689 moduleServiceMap.put(service.getFileName(),services); 690 } 691 services.add(service); 692 } 693 694 if (allServicesMap != null) { 695 services = (List ) allServicesMap.get(service.getFileName()) ; 696 if (services != null && services.size() > 0 ) { 697 for (int sIt = 0 ; sIt < services.size() ; sIt++ ) { 699 if (((Service)services.get(sIt)).getCodebase().equals(service.getCodebase())) { 700 services.remove(sIt); 701 break; 702 } 703 } 704 } else { 705 services = new ArrayList (); 706 allServicesMap.put(service.getFileName(),services); 707 } 708 services.add(service); 709 } 710 updateNode(service); 711 } 712 } 713 } 714 715 NbModuleProject getProject() { 716 return project; 717 } 718 719 private String getCodeNameBase() { 720 String cnb = project.getCodeNameBase(); 721 if (cnb == null) { 723 cnb = codeNameBase; 724 } else { 725 codeNameBase = cnb; 726 } 727 if (cnb == null) { 728 cnb = "unknown"; } 730 return cnb; 731 } 732 } 733 | Popular Tags |