001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 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.internal.launching;
011:
012: import java.io.File;
013: import java.util.ArrayList;
014: import java.util.List;
015:
016: import org.eclipse.core.resources.IContainer;
017: import org.eclipse.core.resources.IProject;
018: import org.eclipse.core.resources.IResource;
019: import org.eclipse.core.resources.ResourcesPlugin;
020: import org.eclipse.core.runtime.IPath;
021: import org.eclipse.core.runtime.Path;
022: import org.eclipse.debug.core.sourcelookup.ISourceContainer;
023: import org.eclipse.debug.core.sourcelookup.containers.DirectorySourceContainer;
024: import org.eclipse.debug.core.sourcelookup.containers.ExternalArchiveSourceContainer;
025: import org.eclipse.debug.core.sourcelookup.containers.FolderSourceContainer;
026: import org.eclipse.debug.core.sourcelookup.containers.ProjectSourceContainer;
027: import org.eclipse.jdt.core.IJavaModel;
028: import org.eclipse.jdt.core.IJavaProject;
029: import org.eclipse.jdt.core.IPackageFragmentRoot;
030: import org.eclipse.jdt.core.JavaCore;
031: import org.eclipse.jdt.core.JavaModelException;
032: import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
033: import org.eclipse.jdt.launching.sourcelookup.containers.JavaProjectSourceContainer;
034: import org.eclipse.jdt.launching.sourcelookup.containers.PackageFragmentRootSourceContainer;
035:
036: /**
037: * Private source lookup utils. Translates runtime classpath entries
038: * to source containers.
039: *
040: * @since 3.0
041: */
042: public class JavaSourceLookupUtil {
043:
044: /**
045: * Translates the given runtime classpath entries into associated source
046: * containers.
047: *
048: * @param entries entries to translate
049: * @return source containers corresponding to the given runtime classpath entries
050: */
051: public static ISourceContainer[] translate(
052: IRuntimeClasspathEntry[] entries) {
053: List containers = new ArrayList(entries.length);
054: for (int i = 0; i < entries.length; i++) {
055: IRuntimeClasspathEntry entry = entries[i];
056: switch (entry.getType()) {
057: case IRuntimeClasspathEntry.ARCHIVE:
058: IPackageFragmentRoot root = getPackageFragmentRoot(entry);
059: if (root == null) {
060: String path = entry.getSourceAttachmentLocation();
061: ISourceContainer container = null;
062: if (path == null) {
063: // use the archive itself
064: path = entry.getLocation();
065: }
066: if (path != null) {
067: // check if file or folder
068: File file = new File(path);
069: if (file.isDirectory()) {
070: IResource resource = entry.getResource();
071: if (resource instanceof IContainer) {
072: container = new FolderSourceContainer(
073: (IContainer) resource, false);
074: } else {
075: container = new DirectorySourceContainer(
076: file, false);
077: }
078: } else {
079: container = new ExternalArchiveSourceContainer(
080: path, true);
081: }
082: if (!containers.contains(container)) {
083: containers.add(container);
084: }
085: }
086: } else {
087: ISourceContainer container = new PackageFragmentRootSourceContainer(
088: root);
089: if (!containers.contains(container)) {
090: containers.add(container);
091: }
092: }
093: break;
094: case IRuntimeClasspathEntry.PROJECT:
095: IResource resource = entry.getResource();
096: if (resource != null
097: && resource.getType() == IResource.PROJECT) {
098: IJavaProject javaProject = JavaCore
099: .create((IProject) resource);
100: ISourceContainer container = null;
101: if (javaProject.exists()) {
102: container = new JavaProjectSourceContainer(
103: javaProject);
104: } else if (resource.exists()) {
105: container = new ProjectSourceContainer(
106: (IProject) resource, false);
107: }
108: if (container != null
109: && !containers.contains(container)) {
110: containers.add(container);
111: }
112: }
113: break;
114: default:
115: // no other classpath types are valid in a resolved path
116: break;
117: }
118: }
119: return (ISourceContainer[]) containers
120: .toArray(new ISourceContainer[containers.size()]);
121: }
122:
123: /**
124: * Returns whether the source attachments of the given package fragment
125: * root and runtime classpath entry are equal.
126: * <p>
127: * NOTE: If the runtime classpath entry's source attachment is not specified,
128: * then it is considered equal. This way, the corresponding package fragment
129: * root is used for source lookup if it has a source attachment or not.
130: * </p>
131: *
132: * @param root package fragment root
133: * @param entry runtime classpath entry
134: * @return whether the source attachments of the given package fragment
135: * root and runtime classpath entry are equal
136: * @throws JavaModelException
137: */
138: private static boolean isSourceAttachmentEqual(
139: IPackageFragmentRoot root, IRuntimeClasspathEntry entry)
140: throws JavaModelException {
141: IPath entryPath = entry.getSourceAttachmentPath();
142: if (entryPath == null) {
143: return true;
144: }
145: IPath rootPath = root.getSourceAttachmentPath();
146: if (rootPath == null) {
147: // entry has a source attachment that the pkg root does not
148: return false;
149: }
150: return rootPath.equals(entryPath);
151:
152: }
153:
154: /**
155: * Determines if the given archive runtime classpath entry exists
156: * in the workspace as a package fragment root. Returns the associated
157: * package fragment root or <code>null</code> if none.
158: *
159: * @param entry archive runtime classpath entry
160: * @return package fragment root or <code>null</code>
161: */
162: private static IPackageFragmentRoot getPackageFragmentRoot(
163: IRuntimeClasspathEntry entry) {
164: IResource resource = entry.getResource();
165: if (resource == null) {
166: // Check all package fragment roots for case of external archive.
167: // External jars are shared, so it does not matter which project it
168: // originates from
169: IJavaModel model = JavaCore.create(ResourcesPlugin
170: .getWorkspace().getRoot());
171: try {
172: IJavaProject[] jps = model.getJavaProjects();
173: for (int i = 0; i < jps.length; i++) {
174: IJavaProject jp = jps[i];
175: IProject p = jp.getProject();
176: if (p.isOpen()) {
177: IPackageFragmentRoot[] allRoots = jp
178: .getPackageFragmentRoots();
179: for (int j = 0; j < allRoots.length; j++) {
180: IPackageFragmentRoot root = allRoots[j];
181: if (root.isExternal()
182: && root.getPath().equals(
183: new Path(entry
184: .getLocation()))) {
185: if (isSourceAttachmentEqual(root, entry)) {
186: // use package fragment root
187: return root;
188: }
189: }
190: }
191: }
192: }
193: } catch (JavaModelException e) {
194: LaunchingPlugin.log(e);
195: }
196: } else {
197: // check if the archive is a package fragment root
198: IProject project = resource.getProject();
199: IJavaProject jp = JavaCore.create(project);
200: try {
201: if (project.isOpen() && jp.exists()) {
202: IPackageFragmentRoot root = jp
203: .getPackageFragmentRoot(resource);
204: IPackageFragmentRoot[] allRoots = jp
205: .getPackageFragmentRoots();
206: for (int j = 0; j < allRoots.length; j++) {
207: if (allRoots[j].equals(root)) {
208: // ensure source attachment paths match
209: if (isSourceAttachmentEqual(root, entry)) {
210: // use package fragment root
211: return root;
212: }
213: }
214: }
215:
216: }
217: // check all other java projects to see if another project references
218: // the archive
219: IJavaModel model = JavaCore.create(ResourcesPlugin
220: .getWorkspace().getRoot());
221: IJavaProject[] jps = model.getJavaProjects();
222: for (int i = 0; i < jps.length; i++) {
223: IJavaProject jp1 = jps[i];
224: IProject p = jp1.getProject();
225: if (p.isOpen()) {
226: IPackageFragmentRoot[] allRoots = jp1
227: .getPackageFragmentRoots();
228: for (int j = 0; j < allRoots.length; j++) {
229: IPackageFragmentRoot root = allRoots[j];
230: if (!root.isExternal()
231: && root.getPath().equals(
232: entry.getPath())) {
233: if (isSourceAttachmentEqual(root, entry)) {
234: // use package fragment root
235: return root;
236: }
237: }
238: }
239: }
240: }
241: } catch (JavaModelException e) {
242: LaunchingPlugin.log(e);
243: }
244: }
245: return null;
246: }
247: }
|