001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.launching.sourcelookup;
011:
012: import java.io.File;
013: import java.io.IOException;
014: import java.io.StringReader;
015: import java.util.ArrayList;
016: import java.util.HashMap;
017: import java.util.Iterator;
018: import java.util.List;
019:
020: import javax.xml.parsers.DocumentBuilder;
021: import javax.xml.parsers.DocumentBuilderFactory;
022: import javax.xml.parsers.ParserConfigurationException;
023:
024: import org.eclipse.core.resources.IProject;
025: import org.eclipse.core.resources.IResource;
026: import org.eclipse.core.resources.ResourcesPlugin;
027: import org.eclipse.core.runtime.CoreException;
028: import org.eclipse.core.runtime.IPath;
029: import org.eclipse.core.runtime.IStatus;
030: import org.eclipse.core.runtime.Path;
031: import org.eclipse.core.runtime.Status;
032: import org.eclipse.debug.core.DebugPlugin;
033: import org.eclipse.debug.core.ILaunchConfiguration;
034: import org.eclipse.debug.core.ILaunchConfigurationType;
035: import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
036: import org.eclipse.debug.core.model.IPersistableSourceLocator;
037: import org.eclipse.debug.core.model.IStackFrame;
038: import org.eclipse.jdt.core.IClasspathEntry;
039: import org.eclipse.jdt.core.IJavaModel;
040: import org.eclipse.jdt.core.IJavaProject;
041: import org.eclipse.jdt.core.IPackageFragmentRoot;
042: import org.eclipse.jdt.core.JavaCore;
043: import org.eclipse.jdt.core.JavaModelException;
044: import org.eclipse.jdt.debug.core.IJavaStackFrame;
045: import org.eclipse.jdt.debug.core.IJavaThread;
046: import org.eclipse.jdt.internal.launching.LaunchingMessages;
047: import org.eclipse.jdt.internal.launching.LaunchingPlugin;
048: import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
049: import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
050: import org.eclipse.jdt.launching.JavaRuntime;
051: import org.w3c.dom.Document;
052: import org.w3c.dom.Element;
053: import org.w3c.dom.Node;
054: import org.w3c.dom.NodeList;
055: import org.xml.sax.InputSource;
056: import org.xml.sax.SAXException;
057: import org.xml.sax.helpers.DefaultHandler;
058:
059: import com.ibm.icu.text.MessageFormat;
060:
061: /**
062: * Locates source for a Java debug session by searching
063: * a configurable set of source locations.
064: * <p>
065: * This class may be instantiated; it is not intended to be subclassed.
066: * </p>
067: * @see org.eclipse.debug.core.model.ISourceLocator
068: * @since 2.0
069: * @deprecated In 3.0, the debug platform provides source lookup facilities that
070: * should be used in place of the Java source lookup support provided in 2.0.
071: * The new facilities provide a source lookup director that coordinates source
072: * lookup among a set of participants, searching a set of source containers.
073: * See the following packages: <code>org.eclipse.debug.core.sourcelookup</code>
074: * and <code>org.eclipse.debug.core.sourcelookup.containers</code>. This class
075: * has been replaced by a Java source lookup director and Java source lookup
076: * participant. To migrate to the new source lookup support clients should
077: * add two new attributes to their launch configuration type extensions:<ul>
078: * <li>sourceLocatorId="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"</li>
079: * <li>sourcePathComputerId="org.eclipse.jdt.launching.sourceLookup.javaSourcePathComputer"</li>
080: * </ul>
081: * The source locator id attribute specifies to use the Java source lookup director
082: * for launch configurations of the associated type, and the source path computer id
083: * attribute specifies the class to use when computing a default source lookup
084: * path for a launch configuration. The path computer referenced/provided (by the
085: * above id), computes a default source lookup path based on the support provided in
086: * the 2.0 release - i.e. a configuration's <code>ATTR_SOURCE_PATH_PROVIDER</code>
087: * attribute (if present), or a default source lookup path based on a configuration's
088: * runtime classpath. This class has been replaced by the Java source lookup
089: * director which is an internal class, but can be used via the
090: * <code>sourceLocatorId</code> attribute on a launch configuration type extension.
091: */
092: public class JavaSourceLocator implements IPersistableSourceLocator {
093:
094: /**
095: * Identifier for the 'Java Source Locator' extension
096: * (value <code>"org.eclipse.jdt.launching.javaSourceLocator"</code>).
097: */
098: public static final String ID_JAVA_SOURCE_LOCATOR = LaunchingPlugin
099: .getUniqueIdentifier()
100: + ".javaSourceLocator"; //$NON-NLS-1$
101:
102: /**
103: * A collection of the source locations to search
104: */
105: private IJavaSourceLocation[] fLocations;
106:
107: /**
108: * Constructs a new empty JavaSourceLocator.
109: */
110: public JavaSourceLocator() {
111: setSourceLocations(new IJavaSourceLocation[0]);
112: }
113:
114: /**
115: * Constructs a new Java source locator that looks in the
116: * specified project for source, and required projects, if
117: * <code>includeRequired</code> is <code>true</code>.
118: *
119: * @param projects the projects in which to look for source
120: * @param includeRequired whether to look in required projects
121: * as well
122: */
123: public JavaSourceLocator(IJavaProject[] projects,
124: 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: // only add external entries with the same location once
137: HashMap external = new HashMap();
138: ArrayList list = new ArrayList();
139: // compute the default locations for each project, and add unique ones
140: Iterator iter = requiredProjects.iterator();
141: while (iter.hasNext()) {
142: IJavaProject p = (IJavaProject) iter.next();
143: try {
144: IPackageFragmentRoot[] roots = p
145: .getPackageFragmentRoots();
146: for (int i = 0; i < roots.length; i++) {
147: if (roots[i].isExternal()) {
148: IPath location = roots[i].getPath();
149: if (external.get(location) == null) {
150: external.put(location, location);
151: list
152: .add(new PackageFragmentRootSourceLocation(
153: roots[i]));
154: }
155: } else {
156: list.add(new PackageFragmentRootSourceLocation(
157: roots[i]));
158: }
159: }
160: } catch (CoreException e) {
161: if (e instanceof JavaModelException) {
162: throw (JavaModelException) e;
163: }
164: throw new JavaModelException(e);
165: }
166: }
167: IJavaSourceLocation[] locations = (IJavaSourceLocation[]) list
168: .toArray(new IJavaSourceLocation[list.size()]);
169: setSourceLocations(locations);
170: }
171:
172: /**
173: * Constructs a new JavaSourceLocator that searches the
174: * specified set of source locations for source elements.
175: *
176: * @param locations the source locations to search for
177: * source, in the order they should be searched
178: */
179: public JavaSourceLocator(IJavaSourceLocation[] locations) {
180: setSourceLocations(locations);
181: }
182:
183: /**
184: * Constructs a new JavaSourceLocator that searches the
185: * default set of source locations for the given Java project.
186: *
187: * @param project Java project
188: * @exception CoreException if an exception occurs reading
189: * the classpath of the given or any required project
190: */
191: public JavaSourceLocator(IJavaProject project) throws CoreException {
192: setSourceLocations(getDefaultSourceLocations(project));
193: }
194:
195: /**
196: * Sets the locations that will be searched, in the order
197: * to be searched.
198: *
199: * @param locations the locations that will be searched, in the order
200: * to be searched
201: */
202: public void setSourceLocations(IJavaSourceLocation[] locations) {
203: fLocations = locations;
204: }
205:
206: /**
207: * Returns the locations that this source locator is currently
208: * searching, in the order that they are searched.
209: *
210: * @return the locations that this source locator is currently
211: * searching, in the order that they are searched
212: */
213: public IJavaSourceLocation[] getSourceLocations() {
214: return fLocations;
215: }
216:
217: /**
218: * Returns all source elements that correspond to the type associated with
219: * the given stack frame, or <code>null</code> if none.
220: *
221: * @param stackFrame stack frame
222: * @return all source elements that correspond to the type associated with
223: * the given stack frame, or <code>null</code> if none
224: * @since 2.1
225: */
226: public Object[] getSourceElements(IStackFrame stackFrame) {
227: if (stackFrame instanceof IJavaStackFrame) {
228: IJavaStackFrame frame = (IJavaStackFrame) stackFrame;
229: String name = null;
230: try {
231: name = getFullyQualfiedName(frame);
232: if (name == null) {
233: return null;
234: }
235: } catch (CoreException e) {
236: // if the thread has since resumed, return null
237: if (e.getStatus().getCode() != IJavaThread.ERR_THREAD_NOT_SUSPENDED) {
238: LaunchingPlugin.log(e);
239: }
240: return null;
241: }
242: List list = new ArrayList();
243: IJavaSourceLocation[] locations = getSourceLocations();
244: for (int i = 0; i < locations.length; i++) {
245: try {
246: Object sourceElement = locations[i]
247: .findSourceElement(name);
248: if (sourceElement != null) {
249: list.add(sourceElement);
250: }
251: } catch (CoreException e) {
252: // log the error and try the next source location
253: LaunchingPlugin.log(e);
254: }
255: }
256: return list.toArray();
257: }
258: return null;
259: }
260:
261: /* (non-Javadoc)
262: * @see org.eclipse.debug.core.model.ISourceLocator#getSourceElement(org.eclipse.debug.core.model.IStackFrame)
263: */
264: public Object getSourceElement(IStackFrame stackFrame) {
265: if (stackFrame instanceof IJavaStackFrame) {
266: IJavaStackFrame frame = (IJavaStackFrame) stackFrame;
267: String name = null;
268: try {
269: name = getFullyQualfiedName(frame);
270: if (name == null) {
271: return null;
272: }
273: } catch (CoreException e) {
274: // if the thread has since resumed, return null
275: if (e.getStatus().getCode() != IJavaThread.ERR_THREAD_NOT_SUSPENDED) {
276: LaunchingPlugin.log(e);
277: }
278: return null;
279: }
280: IJavaSourceLocation[] locations = getSourceLocations();
281: for (int i = 0; i < locations.length; i++) {
282: try {
283: Object sourceElement = locations[i]
284: .findSourceElement(name);
285: if (sourceElement != null) {
286: return sourceElement;
287: }
288: } catch (CoreException e) {
289: // log the error and try the next source location
290: LaunchingPlugin.log(e);
291: }
292: }
293: }
294: return null;
295: }
296:
297: private String getFullyQualfiedName(IJavaStackFrame frame)
298: throws CoreException {
299: String name = null;
300: if (frame.isObsolete()) {
301: return null;
302: }
303: String sourceName = frame.getSourceName();
304: if (sourceName == null) {
305: // no debug attributes, guess at source name
306: name = frame.getDeclaringTypeName();
307: } else {
308: // build source name from debug attributes using
309: // the source file name and the package of the declaring
310: // type
311:
312: // @see bug# 21518 - remove absolute path prefix
313: int index = sourceName.lastIndexOf('\\');
314: if (index == -1) {
315: index = sourceName.lastIndexOf('/');
316: }
317: if (index >= 0) {
318: sourceName = sourceName.substring(index + 1);
319: }
320:
321: String declName = frame.getDeclaringTypeName();
322: index = declName.lastIndexOf('.');
323: if (index >= 0) {
324: name = declName.substring(0, index + 1);
325: } else {
326: name = ""; //$NON-NLS-1$
327: }
328: index = sourceName.lastIndexOf('.');
329: if (index >= 0) {
330: name += sourceName.substring(0, index);
331: }
332: }
333: return name;
334: }
335:
336: /**
337: * Adds all projects required by <code>proj</code> to the list
338: * <code>res</code>
339: *
340: * @param proj the project for which to compute required
341: * projects
342: * @param res the list to add all required projects too
343: */
344: protected static void collectRequiredProjects(IJavaProject proj,
345: ArrayList res) throws JavaModelException {
346: if (!res.contains(proj)) {
347: res.add(proj);
348:
349: IJavaModel model = proj.getJavaModel();
350:
351: IClasspathEntry[] entries = proj.getRawClasspath();
352: for (int i = 0; i < entries.length; i++) {
353: IClasspathEntry curr = entries[i];
354: if (curr.getEntryKind() == IClasspathEntry.CPE_PROJECT) {
355: IJavaProject ref = model.getJavaProject(curr
356: .getPath().segment(0));
357: if (ref.exists()) {
358: collectRequiredProjects(ref, res);
359: }
360: }
361: }
362: }
363: }
364:
365: /**
366: * Returns a default collection of source locations for
367: * the given Java project. Default source locations consist
368: * of the given project and all of its required projects .
369: *
370: * @param project Java project
371: * @return a collection of source locations for all required
372: * projects
373: * @exception CoreException if an exception occurs reading
374: * computing the default locations
375: */
376: public static IJavaSourceLocation[] getDefaultSourceLocations(
377: IJavaProject project) throws CoreException {
378: // create a temporary launch config
379: ILaunchConfigurationType type = DebugPlugin
380: .getDefault()
381: .getLaunchManager()
382: .getLaunchConfigurationType(
383: IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);
384: ILaunchConfigurationWorkingCopy config = type.newInstance(null,
385: project.getElementName());
386: config.setAttribute(
387: IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME,
388: project.getElementName());
389: JavaSourceLocator locator = new JavaSourceLocator();
390: locator.initializeDefaults(config);
391: return locator.getSourceLocations();
392: }
393:
394: /* (non-Javadoc)
395: * @see org.eclipse.debug.core.model.IPersistableSourceLocator#getMemento()
396: */
397: public String getMemento() throws CoreException {
398: Document doc = DebugPlugin.newDocument();
399: Element node = doc.createElement("javaSourceLocator"); //$NON-NLS-1$
400: doc.appendChild(node);
401:
402: IJavaSourceLocation[] locations = getSourceLocations();
403: for (int i = 0; i < locations.length; i++) {
404: Element child = doc.createElement("javaSourceLocation"); //$NON-NLS-1$
405: child.setAttribute(
406: "class", locations[i].getClass().getName()); //$NON-NLS-1$
407: child.setAttribute("memento", locations[i].getMemento()); //$NON-NLS-1$
408: node.appendChild(child);
409: }
410: return DebugPlugin.serializeDocument(doc);
411: }
412:
413: /* (non-Javadoc)
414: * @see org.eclipse.debug.core.model.IPersistableSourceLocator#initializeDefaults(org.eclipse.debug.core.ILaunchConfiguration)
415: */
416: public void initializeDefaults(ILaunchConfiguration configuration)
417: throws CoreException {
418: IRuntimeClasspathEntry[] entries = JavaRuntime
419: .computeUnresolvedSourceLookupPath(configuration);
420: IRuntimeClasspathEntry[] resolved = JavaRuntime
421: .resolveSourceLookupPath(entries, configuration);
422: setSourceLocations(getSourceLocations(resolved));
423: }
424:
425: /* (non-Javadoc)
426: * @see org.eclipse.debug.core.model.IPersistableSourceLocator#initializeFromMemento(java.lang.String)
427: */
428: public void initializeFromMemento(String memento)
429: throws CoreException {
430: Exception ex = null;
431: try {
432: Element root = null;
433: DocumentBuilder parser = DocumentBuilderFactory
434: .newInstance().newDocumentBuilder();
435: parser.setErrorHandler(new DefaultHandler());
436: StringReader reader = new StringReader(memento);
437: InputSource source = new InputSource(reader);
438: root = parser.parse(source).getDocumentElement();
439:
440: if (!root.getNodeName().equalsIgnoreCase(
441: "javaSourceLocator")) { //$NON-NLS-1$
442: abort(
443: LaunchingMessages.JavaSourceLocator_Unable_to_restore_Java_source_locator___invalid_format__6,
444: null);
445: }
446:
447: List sourceLocations = new ArrayList();
448: ClassLoader classLoader = LaunchingPlugin.getDefault()
449: .getDescriptor().getPluginClassLoader();
450:
451: NodeList list = root.getChildNodes();
452: int length = list.getLength();
453: for (int i = 0; i < length; ++i) {
454: Node node = list.item(i);
455: short type = node.getNodeType();
456: if (type == Node.ELEMENT_NODE) {
457: Element entry = (Element) node;
458: if (entry.getNodeName().equalsIgnoreCase(
459: "javaSourceLocation")) { //$NON-NLS-1$
460: String className = entry.getAttribute("class"); //$NON-NLS-1$
461: String data = entry.getAttribute("memento"); //$NON-NLS-1$
462: if (isEmpty(className)) {
463: abort(
464: LaunchingMessages.JavaSourceLocator_Unable_to_restore_Java_source_locator___invalid_format__10,
465: null);
466: }
467: Class clazz = null;
468: try {
469: clazz = classLoader.loadClass(className);
470: } catch (ClassNotFoundException e) {
471: abort(
472: MessageFormat
473: .format(
474: LaunchingMessages.JavaSourceLocator_Unable_to_restore_source_location___class_not_found___0__11,
475: new String[] { className }),
476: e);
477: }
478:
479: IJavaSourceLocation location = null;
480: try {
481: location = (IJavaSourceLocation) clazz
482: .newInstance();
483: } catch (IllegalAccessException e) {
484: abort(
485: LaunchingMessages.JavaSourceLocator_Unable_to_restore_source_location__12,
486: e);
487: } catch (InstantiationException e) {
488: abort(
489: LaunchingMessages.JavaSourceLocator_Unable_to_restore_source_location__12,
490: e);
491: }
492: location.initializeFrom(data);
493: sourceLocations.add(location);
494: } else {
495: abort(
496: LaunchingMessages.JavaSourceLocator_Unable_to_restore_Java_source_locator___invalid_format__14,
497: null);
498: }
499: }
500: }
501: setSourceLocations((IJavaSourceLocation[]) sourceLocations
502: .toArray(new IJavaSourceLocation[sourceLocations
503: .size()]));
504: return;
505: } catch (ParserConfigurationException e) {
506: ex = e;
507: } catch (SAXException e) {
508: ex = e;
509: } catch (IOException e) {
510: ex = e;
511: }
512: abort(
513: LaunchingMessages.JavaSourceLocator_Exception_occurred_initializing_source_locator__15,
514: ex);
515: }
516:
517: /**
518: * Returns source locations that are associated with the given runtime classpath
519: * entries.
520: */
521: private static IJavaSourceLocation[] getSourceLocations(
522: IRuntimeClasspathEntry[] entries) {
523: List locations = new ArrayList(entries.length);
524: for (int i = 0; i < entries.length; i++) {
525: IRuntimeClasspathEntry entry = entries[i];
526: IJavaSourceLocation location = null;
527: switch (entry.getType()) {
528: case IRuntimeClasspathEntry.PROJECT:
529: IProject project = (IProject) entry.getResource();
530: if (project != null && project.exists()
531: && project.isOpen()) {
532: location = new JavaProjectSourceLocation(JavaCore
533: .create(project));
534: }
535: break;
536: case IRuntimeClasspathEntry.ARCHIVE:
537: // check if the archive is in the workspace as a package fragment root
538: location = getArchiveSourceLocation(entry);
539: if (location == null) {
540: String path = entry.getSourceAttachmentLocation();
541: if (path == null) {
542: // if there is no source attachment, look in the archive itself
543: path = entry.getLocation();
544: }
545: if (path != null) {
546: File file = new File(path);
547: if (file.exists()) {
548: if (file.isDirectory()) {
549: location = new DirectorySourceLocation(
550: file);
551: } else {
552: location = new ArchiveSourceLocation(
553: path,
554: entry
555: .getSourceAttachmentRootLocation());
556: }
557: }
558: }
559: }
560: break;
561: case IRuntimeClasspathEntry.VARIABLE:
562: String source = entry.getSourceAttachmentLocation();
563: if (source != null) {
564: location = new ArchiveSourceLocation(source, entry
565: .getSourceAttachmentRootLocation());
566: }
567: break;
568: case IRuntimeClasspathEntry.CONTAINER:
569: throw new IllegalArgumentException(
570: LaunchingMessages.JavaSourceLocator_Illegal_to_have_a_container_resolved_to_a_container_1);
571: }
572: if (location != null) {
573: locations.add(location);
574: }
575: }
576: return (IJavaSourceLocation[]) locations
577: .toArray(new IJavaSourceLocation[locations.size()]);
578: }
579:
580: private boolean isEmpty(String string) {
581: return string == null || string.length() == 0;
582: }
583:
584: /**
585: * Throws an internal error exception
586: */
587: private void abort(String message, Throwable e)
588: throws CoreException {
589: IStatus s = new Status(IStatus.ERROR, LaunchingPlugin
590: .getUniqueIdentifier(),
591: IJavaLaunchConfigurationConstants.ERR_INTERNAL_ERROR,
592: message, e);
593: throw new CoreException(s);
594: }
595:
596: /**
597: * Returns whether the given objects are equal, allowing
598: * for <code>null</code>.
599: *
600: * @param a
601: * @param b
602: * @return whether the given objects are equal, allowing
603: * for <code>null</code>
604: */
605: private static boolean equalOrNull(Object a, Object b) {
606: if (a == null) {
607: return b == null;
608: }
609: if (b == null) {
610: return false;
611: }
612: return a.equals(b);
613: }
614:
615: /**
616: * Returns whether the source attachments of the given package fragment
617: * root and runtime classpath entry are equal.
618: *
619: * @param root package fragment root
620: * @param entry runtime classpath entry
621: * @return whether the source attachments of the given package fragment
622: * root and runtime classpath entry are equal
623: * @throws JavaModelException
624: */
625: private static boolean isSourceAttachmentEqual(
626: IPackageFragmentRoot root, IRuntimeClasspathEntry entry)
627: throws JavaModelException {
628: return equalOrNull(root.getSourceAttachmentPath(), entry
629: .getSourceAttachmentPath());
630: }
631:
632: /**
633: * Determines if the given archive runtime classpath entry exists
634: * in the workspace as a package fragment root. Returns the associated
635: * package fragment root source location if possible, otherwise
636: * <code>null</code>.
637: *
638: * @param entry archive runtime classpath entry
639: * @return IJavaSourceLocation or <code>null</code>
640: */
641: private static IJavaSourceLocation getArchiveSourceLocation(
642: IRuntimeClasspathEntry entry) {
643: IResource resource = entry.getResource();
644: if (resource == null) {
645: // Check all package fragment roots for case of external archive.
646: // External jars are shared, so it does not matter which project it
647: // originates from
648: IJavaModel model = JavaCore.create(ResourcesPlugin
649: .getWorkspace().getRoot());
650: try {
651: IJavaProject[] jps = model.getJavaProjects();
652: for (int i = 0; i < jps.length; i++) {
653: IPackageFragmentRoot[] allRoots = jps[i]
654: .getPackageFragmentRoots();
655: for (int j = 0; j < allRoots.length; j++) {
656: IPackageFragmentRoot root = allRoots[j];
657: if (root.isExternal()
658: && root.getPath().equals(
659: new Path(entry.getLocation()))) {
660: if (isSourceAttachmentEqual(root, entry)) {
661: // use package fragment root
662: return new PackageFragmentRootSourceLocation(
663: root);
664: }
665: }
666: }
667: }
668: } catch (JavaModelException e) {
669: LaunchingPlugin.log(e);
670: }
671: } else {
672: // check if the archive is a package fragment root
673: IProject project = resource.getProject();
674: IJavaProject jp = JavaCore.create(project);
675: try {
676: if (jp != null && jp.exists()) {
677: IPackageFragmentRoot root = jp
678: .getPackageFragmentRoot(resource);
679: IPackageFragmentRoot[] allRoots = jp
680: .getPackageFragmentRoots();
681: for (int j = 0; j < allRoots.length; j++) {
682: if (allRoots[j].equals(root)) {
683: // ensure source attachment paths match
684: if (isSourceAttachmentEqual(root, entry)) {
685: // use package fragment root
686: return new PackageFragmentRootSourceLocation(
687: root);
688: }
689: }
690: }
691:
692: }
693: // check all other java projects to see if another project references
694: // the archive
695: IJavaModel model = JavaCore.create(ResourcesPlugin
696: .getWorkspace().getRoot());
697: IJavaProject[] jps = model.getJavaProjects();
698: for (int i = 0; i < jps.length; i++) {
699: IPackageFragmentRoot[] allRoots = jps[i]
700: .getPackageFragmentRoots();
701: for (int j = 0; j < allRoots.length; j++) {
702: IPackageFragmentRoot root = allRoots[j];
703: if (!root.isExternal()
704: && root.getPath().equals(
705: entry.getPath())) {
706: if (isSourceAttachmentEqual(root, entry)) {
707: // use package fragment root
708: return new PackageFragmentRootSourceLocation(
709: root);
710: }
711: }
712: }
713: }
714: } catch (JavaModelException e) {
715: LaunchingPlugin.log(e);
716: }
717: }
718: return null;
719: }
720:
721: }
|