1 11 package org.eclipse.jdt.launching.sourcelookup; 12 13 14 import java.io.File ; 15 import java.io.IOException ; 16 import java.io.StringReader ; 17 import com.ibm.icu.text.MessageFormat; 18 import java.util.ArrayList ; 19 import java.util.HashMap ; 20 import java.util.Iterator ; 21 import java.util.List ; 22 23 import javax.xml.parsers.DocumentBuilder ; 24 import javax.xml.parsers.DocumentBuilderFactory ; 25 import javax.xml.parsers.ParserConfigurationException ; 26 import javax.xml.transform.TransformerException ; 27 28 import org.eclipse.core.resources.IProject; 29 import org.eclipse.core.resources.IResource; 30 import org.eclipse.core.resources.ResourcesPlugin; 31 import org.eclipse.core.runtime.CoreException; 32 import org.eclipse.core.runtime.IPath; 33 import org.eclipse.core.runtime.IStatus; 34 import org.eclipse.core.runtime.Path; 35 import org.eclipse.core.runtime.Status; 36 import org.eclipse.debug.core.DebugPlugin; 37 import org.eclipse.debug.core.ILaunchConfiguration; 38 import org.eclipse.debug.core.ILaunchConfigurationType; 39 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; 40 import org.eclipse.debug.core.model.IPersistableSourceLocator; 41 import org.eclipse.debug.core.model.IStackFrame; 42 import org.eclipse.jdt.core.IClasspathEntry; 43 import org.eclipse.jdt.core.IJavaModel; 44 import org.eclipse.jdt.core.IJavaProject; 45 import org.eclipse.jdt.core.IPackageFragmentRoot; 46 import org.eclipse.jdt.core.JavaCore; 47 import org.eclipse.jdt.core.JavaModelException; 48 import org.eclipse.jdt.debug.core.IJavaStackFrame; 49 import org.eclipse.jdt.debug.core.IJavaThread; 50 import org.eclipse.jdt.internal.launching.LaunchingMessages; 51 import org.eclipse.jdt.internal.launching.LaunchingPlugin; 52 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; 53 import org.eclipse.jdt.launching.IRuntimeClasspathEntry; 54 import org.eclipse.jdt.launching.JavaRuntime; 55 import org.w3c.dom.Document ; 56 import org.w3c.dom.Element ; 57 import org.w3c.dom.Node ; 58 import org.w3c.dom.NodeList ; 59 import org.xml.sax.InputSource ; 60 import org.xml.sax.SAXException ; 61 import org.xml.sax.helpers.DefaultHandler ; 62 63 64 95 public class JavaSourceLocator implements IPersistableSourceLocator { 96 97 101 public static final String ID_JAVA_SOURCE_LOCATOR = LaunchingPlugin.getUniqueIdentifier() + ".javaSourceLocator"; 103 106 private IJavaSourceLocation[] fLocations; 107 108 111 public JavaSourceLocator() { 112 setSourceLocations(new IJavaSourceLocation[0]); 113 } 114 115 124 public JavaSourceLocator(IJavaProject[] projects, boolean includeRequired) throws JavaModelException { 125 ArrayList requiredProjects = new ArrayList (); 126 for (int i= 0; i < projects.length; i++) { 127 if (includeRequired) { 128 collectRequiredProjects(projects[i], requiredProjects); 129 } else { 130 if (!requiredProjects.contains(projects[i])) { 131 requiredProjects.add(projects[i]); 132 } 133 } 134 } 135 136 HashMap external = new HashMap (); 138 ArrayList list = new ArrayList (); 139 Iterator iter = requiredProjects.iterator(); 141 while (iter.hasNext()) { 142 IJavaProject p = (IJavaProject)iter.next(); 143 try { 144 IPackageFragmentRoot[] roots = p.getPackageFragmentRoots(); 145 for (int i = 0; i < roots.length; i++) { 146 if (roots[i].isExternal()) { 147 IPath location = roots[i].getPath(); 148 if (external.get(location) == null) { 149 external.put(location, location); 150 list.add(new PackageFragmentRootSourceLocation(roots[i])); 151 } 152 } else { 153 list.add(new PackageFragmentRootSourceLocation(roots[i])); 154 } 155 } 156 } catch (CoreException e) { 157 if (e instanceof JavaModelException) { 158 throw (JavaModelException)e; 159 } 160 throw new JavaModelException(e); 161 } 162 } 163 IJavaSourceLocation[] locations = (IJavaSourceLocation[])list.toArray(new IJavaSourceLocation[list.size()]); 164 setSourceLocations(locations); 165 } 166 167 174 public JavaSourceLocator(IJavaSourceLocation[] locations) { 175 setSourceLocations(locations); 176 } 177 178 186 public JavaSourceLocator(IJavaProject project) throws CoreException { 187 setSourceLocations(getDefaultSourceLocations(project)); 188 } 189 190 197 public void setSourceLocations(IJavaSourceLocation[] locations) { 198 fLocations = locations; 199 } 200 201 208 public IJavaSourceLocation[] getSourceLocations() { 209 return fLocations; 210 } 211 212 221 public Object [] getSourceElements(IStackFrame stackFrame) { 222 if (stackFrame instanceof IJavaStackFrame) { 223 IJavaStackFrame frame = (IJavaStackFrame)stackFrame; 224 String name = null; 225 try { 226 name = getFullyQualfiedName(frame); 227 if (name == null) { 228 return null; 229 } 230 } catch (CoreException e) { 231 if (e.getStatus().getCode() != IJavaThread.ERR_THREAD_NOT_SUSPENDED) { 233 LaunchingPlugin.log(e); 234 } 235 return null; 236 } 237 List list = new ArrayList (); 238 IJavaSourceLocation[] locations = getSourceLocations(); 239 for (int i = 0; i < locations.length; i++) { 240 try { 241 Object sourceElement = locations[i].findSourceElement(name); 242 if (sourceElement != null) { 243 list.add(sourceElement); 244 } 245 } catch (CoreException e) { 246 LaunchingPlugin.log(e); 248 } 249 } 250 return list.toArray(); 251 } 252 return null; 253 } 254 255 258 public Object getSourceElement(IStackFrame stackFrame) { 259 if (stackFrame instanceof IJavaStackFrame) { 260 IJavaStackFrame frame = (IJavaStackFrame)stackFrame; 261 String name = null; 262 try { 263 name = getFullyQualfiedName(frame); 264 if (name == null) { 265 return null; 266 } 267 } catch (CoreException e) { 268 if (e.getStatus().getCode() != IJavaThread.ERR_THREAD_NOT_SUSPENDED) { 270 LaunchingPlugin.log(e); 271 } 272 return null; 273 } 274 IJavaSourceLocation[] locations = getSourceLocations(); 275 for (int i = 0; i < locations.length; i++) { 276 try { 277 Object sourceElement = locations[i].findSourceElement(name); 278 if (sourceElement != null) { 279 return sourceElement; 280 } 281 } catch (CoreException e) { 282 LaunchingPlugin.log(e); 284 } 285 } 286 } 287 return null; 288 } 289 290 private String getFullyQualfiedName(IJavaStackFrame frame) throws CoreException { 291 String name = null; 292 if (frame.isObsolete()) { 293 return null; 294 } 295 String sourceName = frame.getSourceName(); 296 if (sourceName == null) { 297 name = frame.getDeclaringTypeName(); 299 } else { 300 304 int index = sourceName.lastIndexOf('\\'); 306 if (index == -1) { 307 index = sourceName.lastIndexOf('/'); 308 } 309 if (index >= 0) { 310 sourceName = sourceName.substring(index + 1); 311 } 312 313 String declName= frame.getDeclaringTypeName(); 314 index = declName.lastIndexOf('.'); 315 if (index >= 0) { 316 name = declName.substring(0, index + 1); 317 } else { 318 name = ""; } 320 index = sourceName.lastIndexOf('.'); 321 if (index >= 0) { 322 name += sourceName.substring(0, index) ; 323 } 324 } 325 return name; 326 } 327 328 336 protected static void collectRequiredProjects(IJavaProject proj, ArrayList res) throws JavaModelException { 337 if (!res.contains(proj)) { 338 res.add(proj); 339 340 IJavaModel model= proj.getJavaModel(); 341 342 IClasspathEntry[] entries= proj.getRawClasspath(); 343 for (int i= 0; i < entries.length; i++) { 344 IClasspathEntry curr= entries[i]; 345 if (curr.getEntryKind() == IClasspathEntry.CPE_PROJECT) { 346 IJavaProject ref= model.getJavaProject(curr.getPath().segment(0)); 347 if (ref.exists()) { 348 collectRequiredProjects(ref, res); 349 } 350 } 351 } 352 } 353 } 354 355 366 public static IJavaSourceLocation[] getDefaultSourceLocations(IJavaProject project) throws CoreException { 367 ILaunchConfigurationType type = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION); 369 ILaunchConfigurationWorkingCopy config = type.newInstance(null, project.getElementName()); 370 config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getElementName()); 371 JavaSourceLocator locator = new JavaSourceLocator(); 372 locator.initializeDefaults(config); 373 return locator.getSourceLocations(); 374 } 375 376 379 public String getMemento() throws CoreException { 380 try { 381 Document doc = LaunchingPlugin.getDocument(); 382 Element node = doc.createElement("javaSourceLocator"); doc.appendChild(node); 384 385 IJavaSourceLocation[] locations = getSourceLocations(); 386 for (int i = 0; i < locations.length; i++) { 387 Element child = doc.createElement("javaSourceLocation"); child.setAttribute("class", locations[i].getClass().getName()); child.setAttribute("memento", locations[i].getMemento()); node.appendChild(child); 391 } 392 393 return LaunchingPlugin.serializeDocument(doc); 394 } catch (IOException e) { 395 abort(LaunchingMessages.JavaSourceLocator_Unable_to_create_memento_for_Java_source_locator__4, e); 396 } catch (ParserConfigurationException e) { 397 abort(LaunchingMessages.JavaSourceLocator_Unable_to_create_memento_for_Java_source_locator__4, e); 398 } catch (TransformerException e) { 399 abort(LaunchingMessages.JavaSourceLocator_Unable_to_create_memento_for_Java_source_locator__4, e); 400 } 401 return null; 403 } 404 405 408 public void initializeDefaults(ILaunchConfiguration configuration) throws CoreException { 409 IRuntimeClasspathEntry[] entries = JavaRuntime.computeUnresolvedSourceLookupPath(configuration); 410 IRuntimeClasspathEntry[] resolved = JavaRuntime.resolveSourceLookupPath(entries, configuration); 411 setSourceLocations(getSourceLocations(resolved)); 412 } 413 414 417 public void initializeFromMemento(String memento) throws CoreException { 418 Exception ex = null; 419 try { 420 Element root = null; 421 DocumentBuilder parser = 422 DocumentBuilderFactory.newInstance().newDocumentBuilder(); 423 parser.setErrorHandler(new DefaultHandler ()); 424 StringReader reader = new StringReader (memento); 425 InputSource source = new InputSource (reader); 426 root = parser.parse(source).getDocumentElement(); 427 428 if (!root.getNodeName().equalsIgnoreCase("javaSourceLocator")) { abort(LaunchingMessages.JavaSourceLocator_Unable_to_restore_Java_source_locator___invalid_format__6, null); 430 } 431 432 List sourceLocations = new ArrayList (); 433 ClassLoader classLoader = LaunchingPlugin.getDefault().getDescriptor().getPluginClassLoader(); 434 435 NodeList list = root.getChildNodes(); 436 int length = list.getLength(); 437 for (int i = 0; i < length; ++i) { 438 Node node = list.item(i); 439 short type = node.getNodeType(); 440 if (type == Node.ELEMENT_NODE) { 441 Element entry = (Element ) node; 442 if (entry.getNodeName().equalsIgnoreCase("javaSourceLocation")) { String className = entry.getAttribute("class"); String data = entry.getAttribute("memento"); if (isEmpty(className)) { 446 abort(LaunchingMessages.JavaSourceLocator_Unable_to_restore_Java_source_locator___invalid_format__10, null); 447 } 448 Class clazz = null; 449 try { 450 clazz = classLoader.loadClass(className); 451 } catch (ClassNotFoundException e) { 452 abort(MessageFormat.format(LaunchingMessages.JavaSourceLocator_Unable_to_restore_source_location___class_not_found___0__11, new String [] {className}), e); 453 } 454 455 IJavaSourceLocation location = null; 456 try { 457 location = (IJavaSourceLocation)clazz.newInstance(); 458 } catch (IllegalAccessException e) { 459 abort(LaunchingMessages.JavaSourceLocator_Unable_to_restore_source_location__12, e); 460 } catch (InstantiationException e) { 461 abort(LaunchingMessages.JavaSourceLocator_Unable_to_restore_source_location__12, e); 462 } 463 location.initializeFrom(data); 464 sourceLocations.add(location); 465 } else { 466 abort(LaunchingMessages.JavaSourceLocator_Unable_to_restore_Java_source_locator___invalid_format__14, null); 467 } 468 } 469 } 470 setSourceLocations((IJavaSourceLocation[])sourceLocations.toArray(new IJavaSourceLocation[sourceLocations.size()])); 471 return; 472 } catch (ParserConfigurationException e) { 473 ex = e; 474 } catch (SAXException e) { 475 ex = e; 476 } catch (IOException e) { 477 ex = e; 478 } 479 abort(LaunchingMessages.JavaSourceLocator_Exception_occurred_initializing_source_locator__15, ex); 480 } 481 482 486 private static IJavaSourceLocation[] getSourceLocations(IRuntimeClasspathEntry[] entries) { 487 List locations = new ArrayList (entries.length); 488 for (int i = 0; i < entries.length; i++) { 489 IRuntimeClasspathEntry entry = entries[i]; 490 IJavaSourceLocation location = null; 491 switch (entry.getType()) { 492 case IRuntimeClasspathEntry.PROJECT: 493 IProject project = (IProject)entry.getResource(); 494 if (project != null && project.exists() && project.isOpen()) { 495 location = new JavaProjectSourceLocation(JavaCore.create(project)); 496 } 497 break; 498 case IRuntimeClasspathEntry.ARCHIVE: 499 location = getArchiveSourceLocation(entry); 501 if (location == null) { 502 String path = entry.getSourceAttachmentLocation(); 503 if (path == null) { 504 path = entry.getLocation(); 506 } 507 if (path != null) { 508 File file = new File (path); 509 if (file.exists()) { 510 if (file.isDirectory()) { 511 location = new DirectorySourceLocation(file); 512 } else { 513 location = new ArchiveSourceLocation(path, entry.getSourceAttachmentRootLocation()); 514 } 515 } 516 } 517 } 518 break; 519 case IRuntimeClasspathEntry.VARIABLE: 520 String source = entry.getSourceAttachmentLocation(); 521 if (source != null) { 522 location = new ArchiveSourceLocation(source, entry.getSourceAttachmentRootLocation()); 523 } 524 break; 525 case IRuntimeClasspathEntry.CONTAINER: 526 throw new IllegalArgumentException (LaunchingMessages.JavaSourceLocator_Illegal_to_have_a_container_resolved_to_a_container_1); 527 } 528 if (location != null) { 529 locations.add(location); 530 } 531 } 532 return (IJavaSourceLocation[])locations.toArray(new IJavaSourceLocation[locations.size()]); 533 } 534 535 private boolean isEmpty(String string) { 536 return string == null || string.length() == 0; 537 } 538 539 542 private void abort(String message, Throwable e) throws CoreException { 543 IStatus s = new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), IJavaLaunchConfigurationConstants.ERR_INTERNAL_ERROR, message, e); 544 throw new CoreException(s); 545 } 546 547 556 private static boolean equalOrNull(Object a, Object b) { 557 if (a == null) { 558 return b == null; 559 } 560 if (b == null) { 561 return false; 562 } 563 return a.equals(b); 564 } 565 566 576 private static boolean isSourceAttachmentEqual(IPackageFragmentRoot root, IRuntimeClasspathEntry entry) throws JavaModelException { 577 return equalOrNull(root.getSourceAttachmentPath(), entry.getSourceAttachmentPath()); 578 } 579 580 589 private static IJavaSourceLocation getArchiveSourceLocation(IRuntimeClasspathEntry entry) { 590 IResource resource = entry.getResource(); 591 if (resource == null) { 592 IJavaModel model = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()); 596 try { 597 IJavaProject[] jps = model.getJavaProjects(); 598 for (int i = 0; i < jps.length; i++) { 599 IPackageFragmentRoot[] allRoots = jps[i].getPackageFragmentRoots(); 600 for (int j = 0; j < allRoots.length; j++) { 601 IPackageFragmentRoot root = allRoots[j]; 602 if (root.isExternal() && root.getPath().equals(new Path(entry.getLocation()))) { 603 if (isSourceAttachmentEqual(root, entry)) { 604 return new PackageFragmentRootSourceLocation(root); 606 } 607 } 608 } 609 } 610 } catch (JavaModelException e) { 611 LaunchingPlugin.log(e); 612 } 613 } else { 614 IProject project = resource.getProject(); 616 IJavaProject jp = JavaCore.create(project); 617 try { 618 if (jp != null && jp.exists()) { 619 IPackageFragmentRoot root = jp.getPackageFragmentRoot(resource); 620 IPackageFragmentRoot[] allRoots = jp.getPackageFragmentRoots(); 621 for (int j = 0; j < allRoots.length; j++) { 622 if (allRoots[j].equals(root)) { 623 if (isSourceAttachmentEqual(root, entry)) { 625 return new PackageFragmentRootSourceLocation(root); 627 } 628 } 629 } 630 631 } 632 IJavaModel model = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()); 635 IJavaProject[] jps = model.getJavaProjects(); 636 for (int i = 0; i < jps.length; i++) { 637 IPackageFragmentRoot[] allRoots = jps[i].getPackageFragmentRoots(); 638 for (int j = 0; j < allRoots.length; j++) { 639 IPackageFragmentRoot root = allRoots[j]; 640 if (!root.isExternal() && root.getPath().equals(entry.getPath())) { 641 if (isSourceAttachmentEqual(root, entry)) { 642 return new PackageFragmentRootSourceLocation(root); 644 } 645 } 646 } 647 } 648 } catch (JavaModelException e) { 649 LaunchingPlugin.log(e); 650 } 651 } 652 return null; 653 } 654 655 } 656 | Popular Tags |