| /******************************************************************************* |
| * Copyright (c) 2000, 2004 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.launching.sourcelookup; |
| |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.transform.TransformerException; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationType; |
| import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; |
| import org.eclipse.debug.core.model.IPersistableSourceLocator; |
| import org.eclipse.debug.core.model.IStackFrame; |
| import org.eclipse.jdt.core.IClasspathEntry; |
| import org.eclipse.jdt.core.IJavaModel; |
| import org.eclipse.jdt.core.IJavaProject; |
| import org.eclipse.jdt.core.IPackageFragmentRoot; |
| import org.eclipse.jdt.core.JavaCore; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.debug.core.IJavaStackFrame; |
| import org.eclipse.jdt.debug.core.IJavaThread; |
| import org.eclipse.jdt.internal.launching.JavaLaunchConfigurationUtils; |
| import org.eclipse.jdt.internal.launching.LaunchingMessages; |
| import org.eclipse.jdt.internal.launching.LaunchingPlugin; |
| import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants; |
| import org.eclipse.jdt.launching.IRuntimeClasspathEntry; |
| import org.eclipse.jdt.launching.JavaRuntime; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| |
| |
| /** |
| * Locates source for a Java debug session by searching |
| * a configurable set of source locations. |
| * <p> |
| * This class may be instantiated; it is not intended to be subclassed. |
| * </p> |
| * @see org.eclipse.debug.core.model.ISourceLocator |
| * @since 2.0 |
| * @deprecated In 3.0, the debug platform provides source lookup facilities that |
| * should be used in place of the Java source lookup support provided in 2.0. |
| * The new facilities provide a source lookup director that coordinates source |
| * lookup among a set of participants, searching a set of source containers. |
| * See the following packages: <code>org.eclipse.debug.core.sourcelookup</code> |
| * and <code>org.eclipse.debug.core.sourcelookup.containers</code>. This class |
| * has been replaced by a Java source lookup director and Java source lookup |
| * participant. To migrate to the new source lookup support clients should |
| * add two new attributes to their launch configuration type extensions:<ul> |
| * <li>sourceLocatorId="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"</li> |
| * <li>sourcePathComputerId="org.eclipse.jdt.launching.sourceLookup.javaSourcePathComputer"</li> |
| * </ul> |
| * The source locator id attribute specifies to use the Java source lookup director |
| * for launch configurations of the associated type, and the source path computer id |
| * attribute specifies the class to use when computing a default source lookup |
| * path for a launch configuration. The path computer referenced/provided (by the |
| * above id), computes a default source lookup path based on the support provided in |
| * the 2.0 release - i.e. a configuration's <code>ATTR_SOURCE_PATH_PROVIDER</code> |
| * attribute (if present), or a default source lookup path based on a configuration's |
| * runtime classpath. This class has been replaced by the Java source lookup |
| * director which is an internal class, but can be used via the |
| * <code>sourceLocatorId</code> attribute on a launch configuration type extension. |
| */ |
| public class JavaSourceLocator implements IPersistableSourceLocator { |
| |
| /** |
| * Identifier for the 'Java Source Locator' extension |
| * (value <code>"org.eclipse.jdt.launching.javaSourceLocator"</code>). |
| */ |
| public static final String ID_JAVA_SOURCE_LOCATOR = LaunchingPlugin.getUniqueIdentifier() + ".javaSourceLocator"; //$NON-NLS-1$ |
| |
| /** |
| * A collection of the source locations to search |
| */ |
| private IJavaSourceLocation[] fLocations; |
| |
| /** |
| * Constructs a new empty JavaSourceLocator. |
| */ |
| public JavaSourceLocator() { |
| setSourceLocations(new IJavaSourceLocation[0]); |
| } |
| |
| /** |
| * Constructs a new Java source locator that looks in the |
| * specified project for source, and required projects, if |
| * <code>includeRequired</code> is <code>true</code>. |
| * |
| * @param projects the projects in which to look for source |
| * @param includeRequired whether to look in required projects |
| * as well |
| */ |
| public JavaSourceLocator(IJavaProject[] projects, boolean includeRequired) throws JavaModelException { |
| ArrayList requiredProjects = new ArrayList(); |
| for (int i= 0; i < projects.length; i++) { |
| if (includeRequired) { |
| collectRequiredProjects(projects[i], requiredProjects); |
| } else { |
| if (!requiredProjects.contains(projects[i])) { |
| requiredProjects.add(projects[i]); |
| } |
| } |
| } |
| |
| // only add external entires with the same location once |
| HashMap external = new HashMap(); |
| ArrayList list = new ArrayList(); |
| // compute the default locations for each project, and add unique ones |
| Iterator iter = requiredProjects.iterator(); |
| while (iter.hasNext()) { |
| IJavaProject p = (IJavaProject)iter.next(); |
| try { |
| IPackageFragmentRoot[] roots = p.getPackageFragmentRoots(); |
| for (int i = 0; i < roots.length; i++) { |
| if (roots[i].isExternal()) { |
| IPath location = roots[i].getPath(); |
| if (external.get(location) == null) { |
| external.put(location, location); |
| list.add(new PackageFragmentRootSourceLocation(roots[i])); |
| } |
| } else { |
| list.add(new PackageFragmentRootSourceLocation(roots[i])); |
| } |
| } |
| } catch (CoreException e) { |
| if (e instanceof JavaModelException) { |
| throw (JavaModelException)e; |
| } |
| throw new JavaModelException(e); |
| } |
| } |
| IJavaSourceLocation[] locations = (IJavaSourceLocation[])list.toArray(new IJavaSourceLocation[list.size()]); |
| setSourceLocations(locations); |
| } |
| |
| /** |
| * Constructs a new JavaSourceLocator that searches the |
| * specified set of source locations for source elements. |
| * |
| * @param locations the source locations to search for |
| * source, in the order they should be searched |
| */ |
| public JavaSourceLocator(IJavaSourceLocation[] locations) { |
| setSourceLocations(locations); |
| } |
| |
| /** |
| * Constructs a new JavaSourceLocator that searches the |
| * default set of source locations for the given Java project. |
| * |
| * @param project Java project |
| * @exception CoreException if an exception occurs reading |
| * the classpath of the given or any required project |
| */ |
| public JavaSourceLocator(IJavaProject project) throws CoreException { |
| setSourceLocations(getDefaultSourceLocations(project)); |
| } |
| |
| /** |
| * Sets the locations that will be searched, in the order |
| * to be searched. |
| * |
| * @param locations the locations that will be searched, in the order |
| * to be searched |
| */ |
| public void setSourceLocations(IJavaSourceLocation[] locations) { |
| fLocations = locations; |
| } |
| |
| /** |
| * Returns the locations that this source locator is currently |
| * searching, in the order that they are searched. |
| * |
| * @return the locations that this source locator is currently |
| * searching, in the order that they are searched |
| */ |
| public IJavaSourceLocation[] getSourceLocations() { |
| return fLocations; |
| } |
| |
| /** |
| * Returns all source elements that correspond to the type associated with |
| * the given stack frame, or <code>null</code> if none. |
| * |
| * @param stackFrame stack frame |
| * @return all source elements that correspond to the type associated with |
| * the given stack frame, or <code>null</code> if none |
| * @since 2.1 |
| */ |
| public Object[] getSourceElements(IStackFrame stackFrame) { |
| if (stackFrame instanceof IJavaStackFrame) { |
| IJavaStackFrame frame = (IJavaStackFrame)stackFrame; |
| String name = null; |
| try { |
| name = getFullyQualfiedName(frame); |
| if (name == null) { |
| return null; |
| } |
| } catch (CoreException e) { |
| // if the thread has since resumed, return null |
| if (e.getStatus().getCode() != IJavaThread.ERR_THREAD_NOT_SUSPENDED) { |
| LaunchingPlugin.log(e); |
| } |
| return null; |
| } |
| List list = new ArrayList(); |
| IJavaSourceLocation[] locations = getSourceLocations(); |
| for (int i = 0; i < locations.length; i++) { |
| try { |
| Object sourceElement = locations[i].findSourceElement(name); |
| if (sourceElement != null) { |
| list.add(sourceElement); |
| } |
| } catch (CoreException e) { |
| // log the error and try the next source location |
| LaunchingPlugin.log(e); |
| } |
| } |
| return list.toArray(); |
| } |
| return null; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.model.ISourceLocator#getSourceElement(org.eclipse.debug.core.model.IStackFrame) |
| */ |
| public Object getSourceElement(IStackFrame stackFrame) { |
| if (stackFrame instanceof IJavaStackFrame) { |
| IJavaStackFrame frame = (IJavaStackFrame)stackFrame; |
| String name = null; |
| try { |
| name = getFullyQualfiedName(frame); |
| if (name == null) { |
| return null; |
| } |
| } catch (CoreException e) { |
| // if the thread has since resumed, return null |
| if (e.getStatus().getCode() != IJavaThread.ERR_THREAD_NOT_SUSPENDED) { |
| LaunchingPlugin.log(e); |
| } |
| return null; |
| } |
| IJavaSourceLocation[] locations = getSourceLocations(); |
| for (int i = 0; i < locations.length; i++) { |
| try { |
| Object sourceElement = locations[i].findSourceElement(name); |
| if (sourceElement != null) { |
| return sourceElement; |
| } |
| } catch (CoreException e) { |
| // log the error and try the next source location |
| LaunchingPlugin.log(e); |
| } |
| } |
| } |
| return null; |
| } |
| |
| private String getFullyQualfiedName(IJavaStackFrame frame) throws CoreException { |
| String name = null; |
| if (frame.isObsolete()) { |
| return null; |
| } |
| String sourceName = frame.getSourceName(); |
| if (sourceName == null) { |
| // no debug attributes, guess at source name |
| name = frame.getDeclaringTypeName(); |
| } else { |
| // build source name from debug attributes using |
| // the source file name and the package of the declaring |
| // type |
| |
| // @see bug# 21518 - remove absolute path prefix |
| int index = sourceName.lastIndexOf('\\'); |
| if (index == -1) { |
| index = sourceName.lastIndexOf('/'); |
| } |
| if (index >= 0) { |
| sourceName = sourceName.substring(index + 1); |
| } |
| |
| String declName= frame.getDeclaringTypeName(); |
| index = declName.lastIndexOf('.'); |
| if (index >= 0) { |
| name = declName.substring(0, index + 1); |
| } else { |
| name = ""; //$NON-NLS-1$ |
| } |
| index = sourceName.lastIndexOf('.'); |
| if (index >= 0) { |
| name += sourceName.substring(0, index) ; |
| } |
| } |
| return name; |
| } |
| |
| /** |
| * Adds all projects required by <code>proj</code> to the list |
| * <code>res</code> |
| * |
| * @param proj the project for which to compute required |
| * projects |
| * @param res the list to add all required projects too |
| */ |
| protected static void collectRequiredProjects(IJavaProject proj, ArrayList res) throws JavaModelException { |
| if (!res.contains(proj)) { |
| res.add(proj); |
| |
| IJavaModel model= proj.getJavaModel(); |
| |
| IClasspathEntry[] entries= proj.getRawClasspath(); |
| for (int i= 0; i < entries.length; i++) { |
| IClasspathEntry curr= entries[i]; |
| if (curr.getEntryKind() == IClasspathEntry.CPE_PROJECT) { |
| IJavaProject ref= model.getJavaProject(curr.getPath().segment(0)); |
| if (ref.exists()) { |
| collectRequiredProjects(ref, res); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Returns a default collection of source locations for |
| * the given Java project. Default source locations consist |
| * of the given project and all of its required projects . |
| * |
| * @param project Java project |
| * @return a collection of source locations for all required |
| * projects |
| * @exception CoreException if an exception occurs reading |
| * computing the default locations |
| */ |
| public static IJavaSourceLocation[] getDefaultSourceLocations(IJavaProject project) throws CoreException { |
| // create a temporary launch config |
| ILaunchConfigurationType type = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION); |
| ILaunchConfigurationWorkingCopy config = type.newInstance(null, project.getElementName()); |
| config.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, project.getElementName()); |
| JavaSourceLocator locator = new JavaSourceLocator(); |
| locator.initializeDefaults(config); |
| return locator.getSourceLocations(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.model.IPersistableSourceLocator#getMemento() |
| */ |
| public String getMemento() throws CoreException { |
| try { |
| Document doc = LaunchingPlugin.getDocument(); |
| Element node = doc.createElement("javaSourceLocator"); //$NON-NLS-1$ |
| doc.appendChild(node); |
| |
| IJavaSourceLocation[] locations = getSourceLocations(); |
| for (int i = 0; i < locations.length; i++) { |
| Element child = doc.createElement("javaSourceLocation"); //$NON-NLS-1$ |
| child.setAttribute("class", locations[i].getClass().getName()); //$NON-NLS-1$ |
| child.setAttribute("memento", locations[i].getMemento()); //$NON-NLS-1$ |
| node.appendChild(child); |
| } |
| |
| return JavaLaunchConfigurationUtils.serializeDocument(doc); |
| } catch (IOException e) { |
| abort(LaunchingMessages.getString("JavaSourceLocator.Unable_to_create_memento_for_Java_source_locator._4"), e); //$NON-NLS-1$ |
| } catch (ParserConfigurationException e) { |
| abort(LaunchingMessages.getString("JavaSourceLocator.Unable_to_create_memento_for_Java_source_locator._4"), e); //$NON-NLS-1$ |
| } catch (TransformerException e) { |
| abort(LaunchingMessages.getString("JavaSourceLocator.Unable_to_create_memento_for_Java_source_locator._4"), e); //$NON-NLS-1$ |
| } |
| // execution will not reach here |
| return null; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.model.IPersistableSourceLocator#initializeDefaults(org.eclipse.debug.core.ILaunchConfiguration) |
| */ |
| public void initializeDefaults(ILaunchConfiguration configuration) throws CoreException { |
| IRuntimeClasspathEntry[] entries = JavaRuntime.computeUnresolvedSourceLookupPath(configuration); |
| IRuntimeClasspathEntry[] resolved = JavaRuntime.resolveSourceLookupPath(entries, configuration); |
| setSourceLocations(getSourceLocations(resolved)); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.model.IPersistableSourceLocator#initializeFromMemento(java.lang.String) |
| */ |
| public void initializeFromMemento(String memento) throws CoreException { |
| Exception ex = null; |
| try { |
| Element root = null; |
| DocumentBuilder parser = |
| DocumentBuilderFactory.newInstance().newDocumentBuilder(); |
| StringReader reader = new StringReader(memento); |
| InputSource source = new InputSource(reader); |
| root = parser.parse(source).getDocumentElement(); |
| |
| if (!root.getNodeName().equalsIgnoreCase("javaSourceLocator")) { //$NON-NLS-1$ |
| abort(LaunchingMessages.getString("JavaSourceLocator.Unable_to_restore_Java_source_locator_-_invalid_format._6"), null); //$NON-NLS-1$ |
| } |
| |
| List sourceLocations = new ArrayList(); |
| ClassLoader classLoader = LaunchingPlugin.getDefault().getDescriptor().getPluginClassLoader(); |
| |
| NodeList list = root.getChildNodes(); |
| int length = list.getLength(); |
| for (int i = 0; i < length; ++i) { |
| Node node = list.item(i); |
| short type = node.getNodeType(); |
| if (type == Node.ELEMENT_NODE) { |
| Element entry = (Element) node; |
| if (entry.getNodeName().equalsIgnoreCase("javaSourceLocation")) { //$NON-NLS-1$ |
| String className = entry.getAttribute("class"); //$NON-NLS-1$ |
| String data = entry.getAttribute("memento"); //$NON-NLS-1$ |
| if (isEmpty(className)) { |
| abort(LaunchingMessages.getString("JavaSourceLocator.Unable_to_restore_Java_source_locator_-_invalid_format._10"), null); //$NON-NLS-1$ |
| } |
| Class clazz = null; |
| try { |
| clazz = classLoader.loadClass(className); |
| } catch (ClassNotFoundException e) { |
| abort(MessageFormat.format(LaunchingMessages.getString("JavaSourceLocator.Unable_to_restore_source_location_-_class_not_found__{0}_11"), new String[] {className}), e); //$NON-NLS-1$ |
| } |
| |
| IJavaSourceLocation location = null; |
| try { |
| location = (IJavaSourceLocation)clazz.newInstance(); |
| } catch (IllegalAccessException e) { |
| abort(LaunchingMessages.getString("JavaSourceLocator.Unable_to_restore_source_location._12"), e); //$NON-NLS-1$ |
| } catch (InstantiationException e) { |
| abort(LaunchingMessages.getString("JavaSourceLocator.Unable_to_restore_source_location._12"), e); //$NON-NLS-1$ |
| } |
| location.initializeFrom(data); |
| sourceLocations.add(location); |
| } else { |
| abort(LaunchingMessages.getString("JavaSourceLocator.Unable_to_restore_Java_source_locator_-_invalid_format._14"), null); //$NON-NLS-1$ |
| } |
| } |
| } |
| setSourceLocations((IJavaSourceLocation[])sourceLocations.toArray(new IJavaSourceLocation[sourceLocations.size()])); |
| return; |
| } catch (ParserConfigurationException e) { |
| ex = e; |
| } catch (SAXException e) { |
| ex = e; |
| } catch (IOException e) { |
| ex = e; |
| } |
| abort(LaunchingMessages.getString("JavaSourceLocator.Exception_occurred_initializing_source_locator._15"), ex); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Returns source locations that are associted with the given runtime classpath |
| * entries. |
| */ |
| private static IJavaSourceLocation[] getSourceLocations(IRuntimeClasspathEntry[] entries) { |
| List locations = new ArrayList(entries.length); |
| for (int i = 0; i < entries.length; i++) { |
| IRuntimeClasspathEntry entry = entries[i]; |
| IJavaSourceLocation location = null; |
| switch (entry.getType()) { |
| case IRuntimeClasspathEntry.PROJECT: |
| IProject project = (IProject)entry.getResource(); |
| if (project != null && project.exists() && project.isOpen()) { |
| location = new JavaProjectSourceLocation(JavaCore.create(project)); |
| } |
| break; |
| case IRuntimeClasspathEntry.ARCHIVE: |
| // check if the archive is in the workspace as a package fragment root |
| location = getArchiveSourceLocation(entry); |
| if (location == null) { |
| String path = entry.getSourceAttachmentLocation(); |
| if (path == null) { |
| // if there is no source attachment, look in the archive itself |
| path = entry.getLocation(); |
| } |
| if (path != null) { |
| File file = new File(path); |
| if (file.exists()) { |
| if (file.isDirectory()) { |
| location = new DirectorySourceLocation(file); |
| } else { |
| location = new ArchiveSourceLocation(path, entry.getSourceAttachmentRootLocation()); |
| } |
| } |
| } |
| } |
| break; |
| case IRuntimeClasspathEntry.VARIABLE: |
| String source = entry.getSourceAttachmentLocation(); |
| if (source != null) { |
| location = new ArchiveSourceLocation(source, entry.getSourceAttachmentRootLocation()); |
| } |
| break; |
| case IRuntimeClasspathEntry.CONTAINER: |
| throw new IllegalArgumentException(LaunchingMessages.getString("JavaSourceLocator.Illegal_to_have_a_container_resolved_to_a_container_1")); //$NON-NLS-1$ |
| } |
| if (location != null) { |
| locations.add(location); |
| } |
| } |
| return (IJavaSourceLocation[])locations.toArray(new IJavaSourceLocation[locations.size()]); |
| } |
| |
| private boolean isEmpty(String string) { |
| return string == null || string.length() == 0; |
| } |
| |
| /** |
| * Throws an internal error exception |
| */ |
| private void abort(String message, Throwable e) throws CoreException { |
| IStatus s = new Status(IStatus.ERROR, LaunchingPlugin.getUniqueIdentifier(), IJavaLaunchConfigurationConstants.ERR_INTERNAL_ERROR, message, e); |
| throw new CoreException(s); |
| } |
| |
| /** |
| * Returns whether the given objects are equal, allowing |
| * for <code>null</code>. |
| * |
| * @param a |
| * @param b |
| * @return whether the given objects are equal, allowing |
| * for <code>null</code> |
| */ |
| private static boolean equalOrNull(Object a, Object b) { |
| if (a == null) { |
| return b == null; |
| } |
| if (b == null) { |
| return false; |
| } |
| return a.equals(b); |
| } |
| |
| /** |
| * Returns whether the source attachments of the given package fragment |
| * root and runtime classpath entry are equal. |
| * |
| * @param root package fragment root |
| * @param entry runtime classpath entry |
| * @return whether the source attachments of the given package fragment |
| * root and runtime classpath entry are equal |
| * @throws JavaModelException |
| */ |
| private static boolean isSourceAttachmentEqual(IPackageFragmentRoot root, IRuntimeClasspathEntry entry) throws JavaModelException { |
| return equalOrNull(root.getSourceAttachmentPath(), entry.getSourceAttachmentPath()); |
| } |
| |
| /** |
| * Determines if the given archive runtime classpath entry exists |
| * in the workspace as a package fragment root. Returns the associated |
| * package fragment root source location if possible, otherwise |
| * <code>null</code>. |
| * |
| * @param entry archive runtime classpath entry |
| * @return IJavaSourceLocation or <code>null</code> |
| */ |
| private static IJavaSourceLocation getArchiveSourceLocation(IRuntimeClasspathEntry entry) { |
| IResource resource = entry.getResource(); |
| if (resource == null) { |
| // Check all package fragment roots for case of external archive. |
| // External jars are shared, so it does not matter which project it |
| // originates from |
| IJavaModel model = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()); |
| try { |
| IJavaProject[] jps = model.getJavaProjects(); |
| for (int i = 0; i < jps.length; i++) { |
| IPackageFragmentRoot[] allRoots = jps[i].getPackageFragmentRoots(); |
| for (int j = 0; j < allRoots.length; j++) { |
| IPackageFragmentRoot root = allRoots[j]; |
| if (root.isExternal() && root.getPath().equals(new Path(entry.getLocation()))) { |
| if (isSourceAttachmentEqual(root, entry)) { |
| // use package fragment root |
| return new PackageFragmentRootSourceLocation(root); |
| } |
| } |
| } |
| } |
| } catch (JavaModelException e) { |
| LaunchingPlugin.log(e); |
| } |
| } else { |
| // check if the archive is a package fragment root |
| IProject project = resource.getProject(); |
| IJavaProject jp = JavaCore.create(project); |
| try { |
| if (jp != null && jp.exists()) { |
| IPackageFragmentRoot root = jp.getPackageFragmentRoot(resource); |
| IPackageFragmentRoot[] allRoots = jp.getPackageFragmentRoots(); |
| for (int j = 0; j < allRoots.length; j++) { |
| if (allRoots[j].equals(root)) { |
| // ensure source attachment paths match |
| if (isSourceAttachmentEqual(root, entry)) { |
| // use package fragment root |
| return new PackageFragmentRootSourceLocation(root); |
| } |
| } |
| } |
| |
| } |
| // check all other java projects to see if another project references |
| // the archive |
| IJavaModel model = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot()); |
| IJavaProject[] jps = model.getJavaProjects(); |
| for (int i = 0; i < jps.length; i++) { |
| IPackageFragmentRoot[] allRoots = jps[i].getPackageFragmentRoots(); |
| for (int j = 0; j < allRoots.length; j++) { |
| IPackageFragmentRoot root = allRoots[j]; |
| if (!root.isExternal() && root.getPath().equals(entry.getPath())) { |
| if (isSourceAttachmentEqual(root, entry)) { |
| // use package fragment root |
| return new PackageFragmentRootSourceLocation(root); |
| } |
| } |
| } |
| } |
| } catch (JavaModelException e) { |
| LaunchingPlugin.log(e); |
| } |
| } |
| return null; |
| } |
| |
| } |