1 12 package org.eclipse.debug.core.sourcelookup; 13 14 import com.ibm.icu.text.MessageFormat; 15 import java.util.ArrayList ; 16 import java.util.Arrays ; 17 import java.util.HashMap ; 18 import java.util.Iterator ; 19 import java.util.List ; 20 import java.util.Map ; 21 22 import org.eclipse.core.runtime.CoreException; 23 import org.eclipse.core.runtime.ISafeRunnable; 24 import org.eclipse.core.runtime.IStatus; 25 import org.eclipse.core.runtime.MultiStatus; 26 import org.eclipse.core.runtime.SafeRunner; 27 import org.eclipse.core.runtime.Status; 28 import org.eclipse.debug.core.DebugPlugin; 29 import org.eclipse.debug.core.ILaunch; 30 import org.eclipse.debug.core.ILaunchConfiguration; 31 import org.eclipse.debug.core.ILaunchConfigurationListener; 32 import org.eclipse.debug.core.ILaunchListener; 33 import org.eclipse.debug.core.ILaunchManager; 34 import org.eclipse.debug.core.IStatusHandler; 35 import org.eclipse.debug.core.model.IStackFrame; 36 import org.eclipse.debug.core.sourcelookup.containers.DefaultSourceContainer; 37 import org.eclipse.debug.internal.core.sourcelookup.SourceLookupMessages; 38 import org.w3c.dom.Document ; 39 import org.w3c.dom.Element ; 40 import org.w3c.dom.Node ; 41 import org.w3c.dom.NodeList ; 42 43 69 public abstract class AbstractSourceLookupDirector implements ISourceLookupDirector, ILaunchConfigurationListener, ILaunchListener { 70 71 protected String fId; 73 protected ArrayList fParticipants = new ArrayList (); 75 protected ISourceContainer[] fSourceContainers = null; 77 protected ILaunchConfiguration fConfig; 79 protected boolean fDuplicates = false; 81 protected ISourcePathComputer fComputer = null; 83 87 protected Map fResolvedElements = null; 88 89 protected static final IStatus fPromptStatus = new Status(IStatus.INFO, "org.eclipse.debug.ui", 200, "", null); protected static final IStatus fResolveDuplicatesStatus = new Status(IStatus.INFO, "org.eclipse.debug.ui", 205, "", null); 92 protected static final String DIRECTOR_ROOT_NODE = "sourceLookupDirector"; protected static final String CONTAINERS_NODE = "sourceContainers"; protected static final String DUPLICATES_ATTR = "duplicates"; protected static final String CONTAINER_NODE = "container"; protected static final String CONTAINER_TYPE_ATTR = "typeId"; protected static final String CONTAINER_MEMENTO_ATTR = "memento"; 100 class SourceLookupQuery implements ISafeRunnable { 101 102 private List fSourceElements = new ArrayList (); 103 private Object fElement = null; 104 private Throwable fException = null; 105 106 SourceLookupQuery(Object element) { 107 fElement = element; 108 } 109 110 113 public void handleException(Throwable exception) { 114 fException = exception; 115 } 116 117 122 public Throwable getException() { 123 return fException; 124 } 125 126 129 public void run() throws Exception { 130 MultiStatus multiStatus = null; 131 CoreException single = null; 132 ISourceLookupParticipant[] participants = getParticipants(); 133 for(int i=0; i < participants.length; i++) { 134 Object [] sourceArray; 135 try { 136 sourceArray = participants[i].findSourceElements(fElement); 137 if (sourceArray !=null && sourceArray.length > 0) { 138 if (isFindDuplicates()) { 139 for(int j=0; j<sourceArray.length; j++) 140 if(!checkDuplicate(sourceArray[j], fSourceElements)) 141 fSourceElements.add(sourceArray[j]); 142 } else { 143 fSourceElements.add(sourceArray[0]); 144 return; 145 } 146 } 147 } catch (CoreException e) { 148 if (single == null) { 149 single = e; 150 } else if (multiStatus == null) { 151 multiStatus = new MultiStatus(DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, new IStatus[]{single.getStatus()}, SourceLookupMessages.AbstractSourceLookupDirector_19, null); 152 multiStatus.add(e.getStatus()); 153 } else { 154 multiStatus.add(e.getStatus()); 155 } 156 } 157 } 158 if (fSourceElements.isEmpty()) { 159 if (multiStatus != null) { 161 fException = new CoreException(multiStatus); 162 } else if (single != null) { 163 fException = single; 164 } 165 } 166 } 167 168 public List getSourceElements() { 169 return fSourceElements; 170 } 171 172 public void dispose() { 173 fElement = null; 174 fSourceElements = null; 175 fException = null; 176 } 177 178 } 179 180 183 public AbstractSourceLookupDirector() { 184 } 185 186 192 public void setId(String id) { 193 fId = id; 194 } 195 196 199 public synchronized void dispose() { 200 ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); 201 launchManager.removeLaunchConfigurationListener(this); 202 launchManager.removeLaunchListener(this); 203 Iterator iterator = fParticipants.iterator(); 204 while (iterator.hasNext()) { 205 ISourceLookupParticipant participant = (ISourceLookupParticipant) iterator.next(); 206 if(participant != this) 208 participant.dispose(); 209 } 210 fParticipants.clear(); 211 if (fSourceContainers != null) { 212 for (int i = 0; i < fSourceContainers.length; i++) { 213 fSourceContainers[i].dispose(); 214 } 215 } 216 fSourceContainers = null; 217 fResolvedElements = null; 218 } 219 220 227 protected void abort(String message, Throwable exception) throws CoreException { 228 IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, message, exception); 229 throw new CoreException(status); 230 } 231 232 239 private List parseSourceContainers(NodeList list) throws CoreException { 240 List containers = new ArrayList (); 241 for (int i=0; i < list.getLength(); i++) { 242 if(!(list.item(i).getNodeType() == Node.ELEMENT_NODE)) 243 continue; 244 Element element = (Element )list.item(i); 245 String typeId = element.getAttribute(CONTAINER_TYPE_ATTR); 246 if (typeId == null || typeId.equals("")) { abort(SourceLookupMessages.AbstractSourceLookupDirector_11, null); 248 } 249 ISourceContainerType type = DebugPlugin.getDefault().getLaunchManager().getSourceContainerType(typeId); 250 if(type == null) { 251 abort(MessageFormat.format(SourceLookupMessages.AbstractSourceLookupDirector_12, new String []{typeId}), null); 252 } 253 String memento = element.getAttribute(CONTAINER_MEMENTO_ATTR); 254 if (memento == null || memento.equals("")) { abort(SourceLookupMessages.AbstractSourceLookupDirector_13, null); 256 } 257 ISourceContainer container = type.createSourceContainer(memento); 258 containers.add(container); 259 } 260 return containers; 261 } 262 263 270 private synchronized void addSourceLookupParticipant(ISourceLookupParticipant participant) { 271 if (!fParticipants.contains(participant)) { 272 fParticipants.add(participant); 273 participant.init(this); 274 } 275 } 276 277 280 public synchronized ISourceContainer[] getSourceContainers() { 281 if (fSourceContainers == null) { 282 return new ISourceContainer[0]; 283 } 284 ISourceContainer[] copy = new ISourceContainer[fSourceContainers.length]; 285 System.arraycopy(fSourceContainers, 0, copy, 0, fSourceContainers.length); 286 return copy; 287 } 288 289 292 public boolean isFindDuplicates() { 293 return fDuplicates; 294 } 295 296 299 public void setFindDuplicates(boolean duplicates) { 300 fDuplicates = duplicates; 301 } 302 303 309 private synchronized void removeSourceLookupParticipant(ISourceLookupParticipant participant) { 310 if (fParticipants.remove(participant)) { 311 participant.dispose(); 312 } 313 } 314 315 318 public void launchConfigurationAdded(ILaunchConfiguration configuration) { 319 ILaunchConfiguration from = DebugPlugin.getDefault().getLaunchManager().getMovedFrom(configuration); 320 if (from != null && from.equals(getLaunchConfiguration())) { 321 fConfig = configuration; 322 } 323 } 324 325 332 public void launchConfigurationChanged(ILaunchConfiguration configuration) { 333 if (fConfig == null || configuration.isWorkingCopy()) { 334 return; 335 } 336 if(fConfig.equals(configuration)) { 337 try{ 338 String locatorMemento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO,(String )null); 339 if (locatorMemento == null) { 340 initializeDefaults(configuration); 341 } else { 342 initializeFromMemento(locatorMemento, configuration); 343 } 344 } catch (CoreException e){ 345 } 346 } 347 } 348 349 350 353 public void launchConfigurationRemoved(ILaunchConfiguration configuration) { 354 if (configuration.equals(getLaunchConfiguration())) { 355 if (DebugPlugin.getDefault().getLaunchManager().getMovedTo(configuration) == null) { 356 fConfig = null; 357 } 358 } 359 } 360 361 364 public synchronized String getMemento() throws CoreException { 365 Document doc = DebugPlugin.newDocument(); 366 Element rootNode = doc.createElement(DIRECTOR_ROOT_NODE); 367 doc.appendChild(rootNode); 368 369 Element pathNode = doc.createElement(CONTAINERS_NODE); 370 if(fDuplicates) { 371 pathNode.setAttribute(DUPLICATES_ATTR, "true"); } else { 373 pathNode.setAttribute(DUPLICATES_ATTR, "false"); } 375 rootNode.appendChild(pathNode); 376 if(fSourceContainers !=null){ 377 for(int i=0; i<fSourceContainers.length; i++){ 378 Element node = doc.createElement(CONTAINER_NODE); 379 ISourceContainer container = fSourceContainers[i]; 380 ISourceContainerType type = container.getType(); 381 node.setAttribute(CONTAINER_TYPE_ATTR, type.getId()); 382 node.setAttribute(CONTAINER_MEMENTO_ATTR, type.getMemento(container)); 383 pathNode.appendChild(node); 384 } 385 } 386 return DebugPlugin.serializeDocument(doc); 387 } 388 389 392 public void initializeFromMemento(String memento) throws CoreException { 393 doInitializeFromMemento(memento, true); 394 } 395 396 406 protected void doInitializeFromMemento(String memento, boolean dispose) throws CoreException { 407 if (dispose) { 408 dispose(); 409 } 410 Element rootElement = DebugPlugin.parseDocument(memento); 411 if (!rootElement.getNodeName().equalsIgnoreCase(DIRECTOR_ROOT_NODE)) { 412 abort(SourceLookupMessages.AbstractSourceLookupDirector_14, null); 413 } 414 NodeList list = rootElement.getChildNodes(); 415 int length = list.getLength(); 416 for (int i = 0; i < length; ++i) { 417 Node node = list.item(i); 418 short type = node.getNodeType(); 419 if (type == Node.ELEMENT_NODE) { 420 Element entry = (Element ) node; 421 if(entry.getNodeName().equalsIgnoreCase(CONTAINERS_NODE)){ 422 setFindDuplicates("true".equals(entry.getAttribute(DUPLICATES_ATTR))); NodeList children = entry.getChildNodes(); 424 List containers = parseSourceContainers(children); 425 setSourceContainers((ISourceContainer[]) containers.toArray(new ISourceContainer[containers.size()])); 426 } 427 } 428 } 429 initializeParticipants(); 430 } 431 432 438 public void setSourceContainers(ISourceContainer[] containers) { 439 synchronized (this) { 440 List list = Arrays.asList( containers ); 441 ISourceContainer[] old = getSourceContainers(); 442 for (int i = 0; i < old.length; i++) { 443 if (!list.contains(old[i])) 445 old[i].dispose(); 446 } 447 fSourceContainers = containers; 448 for (int i = 0; i < containers.length; i++) { 449 ISourceContainer container = containers[i]; 450 container.init(this); 451 } 452 } 453 fResolvedElements = null; 455 ISourceLookupParticipant[] participants = getParticipants(); 457 for (int i = 0; i < participants.length; i++) { 458 ISourceLookupParticipant participant = participants[i]; 459 participant.sourceContainersChanged(this); 460 } 461 } 462 463 467 public Object getSourceElement(IStackFrame stackFrame) { 468 return getSourceElement((Object )stackFrame); 469 } 470 471 478 protected List doSourceLookup(Object element) { 479 SourceLookupQuery query = new SourceLookupQuery(element); 480 SafeRunner.run(query); 481 List sources = query.getSourceElements(); 482 query.dispose(); 483 return sources; 484 } 485 486 499 public Object resolveSourceElement(Object element, List sources) { 500 Iterator duplicates = sources.iterator(); 502 while (duplicates.hasNext()) { 503 Object dup = duplicates.next(); 504 Object resolved = getCachedElement(dup); 505 if (resolved != null) { 506 return resolved; 507 } 508 } 509 IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(fPromptStatus); 511 if (prompter != null) { 512 try { 513 Object result = prompter.handleStatus(fResolveDuplicatesStatus, new Object []{element, sources}); 514 if (result != null) { 515 cacheResolvedElement(sources, result); 516 return result; 517 } 518 } catch (CoreException e) { 519 } 520 } 521 return sources.get(0); 522 } 523 524 530 private boolean checkDuplicate(Object sourceToAdd, List sources){ 531 if(sources.size() == 0) 532 return false; 533 Iterator iterator = sources.iterator(); 534 while(iterator.hasNext()) 535 if(iterator.next().equals(sourceToAdd)) 536 return true; 537 return false; 538 } 539 540 543 public void initializeFromMemento(String memento, ILaunchConfiguration configuration) throws CoreException { 544 dispose(); 545 setLaunchConfiguration(configuration); 546 doInitializeFromMemento(memento, false); 547 } 548 549 552 public void initializeDefaults(ILaunchConfiguration configuration) throws CoreException { 553 dispose(); 554 setLaunchConfiguration(configuration); 555 setSourceContainers(new ISourceContainer[]{new DefaultSourceContainer()}); 556 initializeParticipants(); 557 } 558 559 562 public ILaunchConfiguration getLaunchConfiguration() { 563 return fConfig; 564 } 565 566 576 protected void setLaunchConfiguration(ILaunchConfiguration configuration) { 577 fConfig = configuration; 578 ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); 579 launchManager.addLaunchConfigurationListener(this); 580 launchManager.addLaunchListener(this); 581 } 582 583 586 public void launchAdded(ILaunch launch) { 587 } 588 591 public void launchChanged(ILaunch launch) { 592 } 593 596 public void launchRemoved(ILaunch launch) { 597 if (this.equals(launch.getSourceLocator())) { 598 dispose(); 599 } 600 } 601 604 public synchronized ISourceLookupParticipant[] getParticipants() { 605 return (ISourceLookupParticipant[]) fParticipants.toArray(new ISourceLookupParticipant[fParticipants.size()]); 606 } 607 610 public boolean supportsSourceContainerType(ISourceContainerType type) { 611 return true; 612 } 613 614 622 protected void cacheResolvedElement(List duplicates, Object sourceElement) { 623 if (fResolvedElements == null) { 624 fResolvedElements = new HashMap (10); 625 } 626 Iterator iterator = duplicates.iterator(); 627 while (iterator.hasNext()) { 628 Object dup = iterator.next(); 629 fResolvedElements.put(dup, sourceElement); 630 } 631 632 } 633 634 641 protected Object getCachedElement(Object duplicate) { 642 if (fResolvedElements != null) { 643 return fResolvedElements.get(duplicate); 644 } 645 return null; 646 } 647 648 655 protected void clearCachedElement(Object duplicate) { 656 if (fResolvedElements != null) { 657 fResolvedElements.remove(duplicate); 658 } 659 } 660 661 664 public void clearSourceElements(Object element) { 665 List list = doSourceLookup(element); 666 if (list.size() > 0) { 667 Iterator iterator = list.iterator(); 668 while (iterator.hasNext()) { 669 clearCachedElement(iterator.next()); 670 } 671 } 672 } 673 676 public void addParticipants(ISourceLookupParticipant[] participants) { 677 for (int i = 0; i < participants.length; i++) { 678 ISourceLookupParticipant participant = participants[i]; 679 addSourceLookupParticipant(participant); 680 participant.sourceContainersChanged(this); 681 } 682 } 683 686 public void removeParticipants(ISourceLookupParticipant[] participants) { 687 for (int i = 0; i < participants.length; i++) { 688 removeSourceLookupParticipant(participants[i]); 689 } 690 } 691 692 695 public String getId() { 696 return fId; 697 } 698 701 public ISourcePathComputer getSourcePathComputer() { 702 if (fComputer == null && getLaunchConfiguration() != null) { 703 try { 704 return DebugPlugin.getDefault().getLaunchManager().getSourcePathComputer(getLaunchConfiguration()); 705 } catch (CoreException e) { 706 } 707 } 708 return fComputer; 709 } 710 713 public void setSourcePathComputer(ISourcePathComputer computer) { 714 fComputer = computer; 715 } 716 719 public Object [] findSourceElements(Object object) throws CoreException { 720 SourceLookupQuery query = new SourceLookupQuery(object); 721 SafeRunner.run(query); 722 List sources = query.getSourceElements(); 723 Throwable exception = query.getException(); 724 query.dispose(); 725 if (exception != null && sources.isEmpty()) { 726 if (exception instanceof CoreException) { 727 throw (CoreException)exception; 728 } 729 abort(SourceLookupMessages.AbstractSourceLookupDirector_10, exception); 730 } 731 return sources.toArray(); 732 } 733 736 public Object getSourceElement(Object element) { 737 List sources = doSourceLookup(element); 738 if(sources.size() == 1) { 739 return sources.get(0); 740 } else if(sources.size() > 1) { 741 return resolveSourceElement(element, sources); 742 } else { 743 return null; 744 } 745 } 746 } 747 | Popular Tags |