001: /*******************************************************************************
002: * Copyright (c) 2005, 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.pde.internal.ui.launcher;
011:
012: import java.io.File;
013: import java.util.ArrayList;
014: import java.util.HashMap;
015: import java.util.HashSet;
016: import java.util.Iterator;
017: import java.util.Map;
018: import java.util.Set;
019:
020: import org.eclipse.core.resources.IFile;
021: import org.eclipse.core.resources.IProject;
022: import org.eclipse.core.resources.IResource;
023: import org.eclipse.core.resources.IWorkspaceRoot;
024: import org.eclipse.core.runtime.CoreException;
025: import org.eclipse.core.runtime.IPath;
026: import org.eclipse.core.runtime.Path;
027: import org.eclipse.core.runtime.SafeRunner;
028: import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector;
029: import org.eclipse.debug.core.sourcelookup.ISourceContainer;
030: import org.eclipse.debug.core.sourcelookup.ISourceContainerType;
031: import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
032: import org.eclipse.debug.core.sourcelookup.containers.ArchiveSourceContainer;
033: import org.eclipse.debug.core.sourcelookup.containers.ExternalArchiveSourceContainer;
034: import org.eclipse.debug.core.sourcelookup.containers.ProjectSourceContainer;
035: import org.eclipse.debug.core.sourcelookup.containers.WorkspaceSourceContainer;
036: import org.eclipse.debug.ui.sourcelookup.WorkingSetSourceContainer;
037: import org.eclipse.jdt.core.IClasspathEntry;
038: import org.eclipse.jdt.core.IJavaElement;
039: import org.eclipse.jdt.core.IJavaProject;
040: import org.eclipse.jdt.core.IPackageFragmentRoot;
041: import org.eclipse.jdt.core.JavaCore;
042: import org.eclipse.jdt.core.JavaModelException;
043: import org.eclipse.jdt.debug.core.IJavaObject;
044: import org.eclipse.jdt.debug.core.IJavaReferenceType;
045: import org.eclipse.jdt.debug.core.IJavaStackFrame;
046: import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
047: import org.eclipse.jdt.launching.JavaRuntime;
048: import org.eclipse.jdt.launching.sourcelookup.containers.JavaSourceLookupParticipant;
049: import org.eclipse.pde.core.plugin.IPluginModelBase;
050: import org.eclipse.pde.core.plugin.ModelEntry;
051: import org.eclipse.pde.core.plugin.PluginRegistry;
052: import org.eclipse.pde.internal.core.PDEClasspathContainer;
053: import org.eclipse.pde.internal.ui.PDEPlugin;
054:
055: public class PDESourceLookupDirector extends
056: AbstractSourceLookupDirector {
057:
058: /**
059: * Cache of source containers by location and id (String & String)
060: */
061: private Map fSourceContainerMap = new HashMap();
062:
063: private static Set fFilteredTypes;
064:
065: static {
066: fFilteredTypes = new HashSet(3);
067: fFilteredTypes.add(ProjectSourceContainer.TYPE_ID);
068: fFilteredTypes.add(WorkspaceSourceContainer.TYPE_ID);
069: fFilteredTypes.add(WorkingSetSourceContainer.TYPE_ID); //$NON-NLS-1$
070: }
071:
072: /* (non-Javadoc)
073: * @see org.eclipse.debug.internal.core.sourcelookup.ISourceLookupDirector#initializeParticipants()
074: */
075: public void initializeParticipants() {
076: addParticipants(new ISourceLookupParticipant[] { new JavaSourceLookupParticipant() });
077: }
078:
079: /* (non-Javadoc)
080: * @see org.eclipse.debug.internal.core.sourcelookup.ISourceLookupDirector#supportsSourceContainerType(org.eclipse.debug.internal.core.sourcelookup.ISourceContainerType)
081: */
082: public boolean supportsSourceContainerType(ISourceContainerType type) {
083: return !fFilteredTypes.contains(type.getId());
084: }
085:
086: /* (non-Javadoc)
087: * @see org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector#getSourceElement(java.lang.Object)
088: */
089: public Object getSourceElement(Object element) {
090: PDESourceLookupQuery query = new PDESourceLookupQuery(this ,
091: element);
092: SafeRunner.run(query);
093: Object result = query.getResult();
094: return result != null ? result : super
095: .getSourceElement(element);
096: }
097:
098: /* (non-Javadoc)
099: * @see org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector#findSourceElements(java.lang.Object)
100: */
101: public Object[] findSourceElements(Object object)
102: throws CoreException {
103: Object[] sourceElements = null;
104: if (object instanceof IJavaStackFrame
105: || object instanceof IJavaObject
106: || object instanceof IJavaReferenceType) {
107: sourceElements = new Object[] { getSourceElement(object) };
108: }
109: if (sourceElements == null) {
110: sourceElements = super .findSourceElements(object);
111: }
112: return sourceElements;
113: }
114:
115: ISourceContainer[] getSourceContainers(String location, String id)
116: throws CoreException {
117:
118: ISourceContainer[] containers = (ISourceContainer[]) fSourceContainerMap
119: .get(location);
120: if (containers != null) {
121: return containers;
122: }
123:
124: ArrayList result = new ArrayList();
125: ModelEntry entry = PluginRegistry.findEntry(id);
126:
127: boolean match = false;
128:
129: IPluginModelBase[] models = entry.getWorkspaceModels();
130: for (int i = 0; i < models.length; i++) {
131: if (isPerfectMatch(models[i], new Path(location))) {
132: IResource resource = models[i].getUnderlyingResource();
133: // if the plug-in matches a workspace model,
134: // add the project and any libraries not coming via a container
135: // to the list of source containers, in that order
136: if (resource != null) {
137: addProjectSourceContainers(resource.getProject(),
138: result);
139: }
140: match = true;
141: break;
142: }
143: }
144:
145: if (!match) {
146: File file = new File(location);
147: if (file.isFile()) {
148: // in case of linked plug-in projects that map to an external JARd plug-in,
149: // use source container that maps to the library in the linked project.
150: ISourceContainer container = getArchiveSourceContainer(location);
151: if (container != null) {
152: containers = new ISourceContainer[] { container };
153: fSourceContainerMap.put(location, containers);
154: return containers;
155: }
156: }
157:
158: models = entry.getExternalModels();
159: for (int i = 0; i < models.length; i++) {
160: if (isPerfectMatch(models[i], new Path(location))) {
161: // try all source zips found in the source code locations
162: IClasspathEntry[] entries = PDEClasspathContainer
163: .getExternalEntries(models[i]);
164: for (int j = 0; j < entries.length; j++) {
165: IRuntimeClasspathEntry rte = convertClasspathEntry(entries[j]);
166: if (rte != null)
167: result.add(rte);
168: }
169: break;
170: }
171: }
172: }
173:
174: IRuntimeClasspathEntry[] entries = (IRuntimeClasspathEntry[]) result
175: .toArray(new IRuntimeClasspathEntry[result.size()]);
176: containers = JavaRuntime.getSourceContainers(entries);
177: fSourceContainerMap.put(location, containers);
178: return containers;
179: }
180:
181: private boolean isPerfectMatch(IPluginModelBase model, IPath path) {
182: return model == null ? false : path.equals(new Path(model
183: .getInstallLocation()));
184: }
185:
186: private IRuntimeClasspathEntry convertClasspathEntry(
187: IClasspathEntry entry) {
188: if (entry == null)
189: return null;
190:
191: IPath srcPath = entry.getSourceAttachmentPath();
192: if (srcPath != null && srcPath.segmentCount() > 0) {
193: IRuntimeClasspathEntry rte = JavaRuntime
194: .newArchiveRuntimeClasspathEntry(entry.getPath());
195: rte.setSourceAttachmentPath(srcPath);
196: rte.setSourceAttachmentRootPath(entry
197: .getSourceAttachmentRootPath());
198: return rte;
199: }
200: return null;
201: }
202:
203: private ISourceContainer getArchiveSourceContainer(String location)
204: throws JavaModelException {
205: IWorkspaceRoot root = PDEPlugin.getWorkspace().getRoot();
206: IFile[] containers = root.findFilesForLocation(new Path(
207: location));
208: for (int i = 0; i < containers.length; i++) {
209: IJavaElement element = JavaCore.create(containers[i]);
210: if (element instanceof IPackageFragmentRoot) {
211: IPackageFragmentRoot archive = (IPackageFragmentRoot) element;
212: IPath path = archive.getSourceAttachmentPath();
213: if (path == null || path.segmentCount() == 0)
214: continue;
215:
216: IPath rootPath = archive.getSourceAttachmentRootPath();
217: boolean detectRootPath = rootPath != null
218: && rootPath.segmentCount() > 0;
219:
220: IFile archiveFile = root.getFile(path);
221: if (archiveFile.exists())
222: return new ArchiveSourceContainer(archiveFile,
223: detectRootPath);
224:
225: File file = path.toFile();
226: if (file.exists())
227: return new ExternalArchiveSourceContainer(file
228: .getAbsolutePath(), detectRootPath);
229: }
230: }
231: return null;
232: }
233:
234: private void addProjectSourceContainers(IProject project,
235: ArrayList result) throws CoreException {
236: if (project == null || !project.hasNature(JavaCore.NATURE_ID))
237: return;
238:
239: IJavaProject jProject = JavaCore.create(project);
240: result.add(JavaRuntime
241: .newProjectRuntimeClasspathEntry(jProject));
242:
243: IClasspathEntry[] entries = jProject.getRawClasspath();
244: for (int i = 0; i < entries.length; i++) {
245: IClasspathEntry entry = entries[i];
246: if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
247: IRuntimeClasspathEntry rte = convertClasspathEntry(entry);
248: if (rte != null)
249: result.add(rte);
250: }
251: }
252: }
253:
254: /* (non-Javadoc)
255: * @see org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector#dispose()
256: */
257: public synchronized void dispose() {
258: Iterator iterator = fSourceContainerMap.values().iterator();
259: while (iterator.hasNext()) {
260: ISourceContainer[] containers = (ISourceContainer[]) iterator
261: .next();
262: for (int i = 0; i < containers.length; i++) {
263: containers[i].dispose();
264: }
265: }
266: fSourceContainerMap.clear();
267: super.dispose();
268: }
269:
270: }
|