KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > debug > ui > JavaUISourceLocator


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.debug.ui;
12
13
14 import com.ibm.icu.text.MessageFormat;
15 import java.util.HashMap JavaDoc;
16
17 import org.eclipse.core.runtime.CoreException;
18 import org.eclipse.debug.core.DebugException;
19 import org.eclipse.debug.core.ILaunchConfiguration;
20 import org.eclipse.debug.core.model.IPersistableSourceLocator;
21 import org.eclipse.debug.core.model.IStackFrame;
22 import org.eclipse.jdt.core.IJavaProject;
23 import org.eclipse.jdt.core.JavaCore;
24 import org.eclipse.jdt.core.JavaModelException;
25 import org.eclipse.jdt.debug.core.IJavaReferenceType;
26 import org.eclipse.jdt.debug.core.IJavaStackFrame;
27 import org.eclipse.jdt.debug.core.IJavaThread;
28 import org.eclipse.jdt.internal.debug.ui.DebugUIMessages;
29 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
30 import org.eclipse.jdt.internal.debug.ui.launcher.LauncherMessages;
31 import org.eclipse.jdt.internal.debug.ui.launcher.SourceElementLabelProvider;
32 import org.eclipse.jdt.internal.debug.ui.launcher.SourceElementQualifierProvider;
33 import org.eclipse.jdt.launching.JavaRuntime;
34 import org.eclipse.jdt.launching.sourcelookup.IJavaSourceLocation;
35 import org.eclipse.jdt.launching.sourcelookup.JavaSourceLocator;
36 import org.eclipse.jface.window.Window;
37 import org.eclipse.ui.dialogs.TwoPaneElementSelector;
38
39 /**
40  * A source locator that prompts the user to find source when source cannot
41  * be found on the current source lookup path.
42  * <p>
43  * This class is intended to be instantiated. This class is not
44  * intended to be subclassed.
45  * </p>
46  * @since 2.0
47  * @deprecated In 3.0, the debug platform provides source lookup facilities that
48  * should be used in place of the Java source lookup support provided in 2.0.
49  * The new facilities provide a source lookup director that coordinates source
50  * lookup among a set of participants, searching a set of source containers.
51  * See the following packages: <code>org.eclipse.debug.core.sourcelookup</code>
52  * and <code>org.eclipse.debug.core.sourcelookup.containers</code>. This class
53  * has been replaced by a Java source lookup director and Java source lookup
54  * participant. To migrate to the new source lookup support clients should
55  * add two new attributes to their launch configuration type extensions:<ul>
56  * <li>sourceLocatorId="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"</li>
57  * <li>sourcePathComputerId="org.eclipse.jdt.launching.sourceLookup.javaSourcePathComputer"</li>
58  * </ul>
59  * The source locator id attribute specifies to use the Java source lookup director
60  * for launch configurations of the associated type, and the source path computer id
61  * attribute specifies the class to use when computing a default source lookup
62  * path for a launch configuration. The path computer referenced/provided (by the
63  * above id), computes a default source lookup path based on the support provided in
64  * the 2.0 release - i.e. a configuration's <code>ATTR_SOURCE_PATH_PROVIDER</code>
65  * attribute (if present), or a default source lookup path based on a configuration's
66  * runtime classpath. This class has been replaced by the Java source lookup
67  * director which is an internal class, but can be used via the
68  * <code>sourceLocatorId</code> attribute on a launch configuration type extension.
69  */

70
71 public class JavaUISourceLocator implements IPersistableSourceLocator {
72
73     /**
74      * Identifier for the 'Prompting Java Source Locator' extension
75      * (value <code>"org.eclipse.jdt.debug.ui.javaSourceLocator"</code>).
76      */

77     public static final String JavaDoc ID_PROMPTING_JAVA_SOURCE_LOCATOR = IJavaDebugUIConstants.PLUGIN_ID + ".javaSourceLocator"; //$NON-NLS-1$
78

79     /**
80      * Launch configuration attribute indicating that this source locator should
81      * locate all source elements that correspond to a stack frame, rather than
82      * the first match. Default value is <code>false</code>.
83      *
84      * @since 2.1
85      */

86     public static final String JavaDoc ATTR_FIND_ALL_SOURCE_ELEMENTS = IJavaDebugUIConstants.PLUGIN_ID + ".ATTR_FIND_ALL_SOURCE_ELEMENTS"; //$NON-NLS-1$
87

88     /**
89      * The project being debugged.
90      */

91     private IJavaProject fJavaProject;
92
93     /**
94      * Underlying source locator.
95      */

96     private JavaSourceLocator fSourceLocator;
97
98     /**
99      * Whether the user should be prompted for source.
100      * Initially true, until the user checks the 'do not
101      * ask again' box.
102      */

103     private boolean fAllowedToAsk;
104
105     /**
106      * Whether to find all source elements for a stack frame (in case of
107      * duplicates), or just the first match.
108      */

109     private boolean fIsFindAllSourceElements = false;
110     
111     /**
112      * A cache of types to associated source elements (when duplicates arise and
113      * the users chooses a source element, it is remembered).
114      */

115     private HashMap JavaDoc fTypesToSource = null;
116
117     /**
118      * Constructs an empty source locator.
119      */

120     public JavaUISourceLocator() {
121         fSourceLocator = new JavaSourceLocator();
122         fAllowedToAsk = true;
123     }
124
125     /**
126      * Constructs a new source locator that looks in the
127      * specified project for source, and required projects, if
128      * <code>includeRequired</code> is <code>true</code>.
129      *
130      * @param projects the projects in which to look for source
131      * @param includeRequired whether to look in required projects
132      * as well
133      */

134     public JavaUISourceLocator(
135         IJavaProject[] projects,
136         boolean includeRequired)
137         throws JavaModelException {
138         fSourceLocator = new JavaSourceLocator(projects, includeRequired);
139         fAllowedToAsk = true;
140     }
141
142     /**
143      * Constructs a source locator that searches for source
144      * in the given Java project, and all of its required projects,
145      * as specified by its build path or default source lookup
146      * settings.
147      *
148      * @param project Java project
149      * @exception CoreException if unable to read the project's
150      * build path
151      */

152     public JavaUISourceLocator(IJavaProject project) throws CoreException {
153         fJavaProject = project;
154         IJavaSourceLocation[] sls =
155             JavaSourceLocator.getDefaultSourceLocations(project);
156         fSourceLocator = new JavaSourceLocator(project);
157         if (sls != null) {
158             fSourceLocator.setSourceLocations(sls);
159         }
160         fAllowedToAsk = true;
161     }
162
163     /**
164      * @see org.eclipse.debug.core.model.ISourceLocator#getSourceElement(IStackFrame)
165      */

166     public Object JavaDoc getSourceElement(IStackFrame stackFrame) {
167         Object JavaDoc res = findSourceElement(stackFrame);
168         if (res == null && fAllowedToAsk) {
169             IJavaStackFrame frame =
170                 (IJavaStackFrame) stackFrame.getAdapter(IJavaStackFrame.class);
171             if (frame != null) {
172                 try {
173                     if (!frame.isObsolete()) {
174                         showDebugSourcePage(frame);
175                         res = fSourceLocator.getSourceElement(stackFrame);
176                     }
177                 } catch (DebugException e) {
178                 }
179             }
180         }
181         return res;
182     }
183
184     private Object JavaDoc findSourceElement(IStackFrame stackFrame) {
185         if (isFindAllSourceElements()) {
186             Object JavaDoc[] sourceElements = fSourceLocator.getSourceElements(stackFrame);
187             if (sourceElements == null || sourceElements.length == 0) {
188                 return null;
189             }
190             if (sourceElements.length == 1) {
191                 return sourceElements[0];
192             }
193             try {
194                 IJavaStackFrame frame = (IJavaStackFrame)stackFrame;
195                 IJavaReferenceType type = frame.getReferenceType();
196                 Object JavaDoc cachedSource = getSourceElement(type);
197                 if (cachedSource != null) {
198                     return cachedSource;
199                 }
200                 // prompt
201
TwoPaneElementSelector dialog = new TwoPaneElementSelector(JDIDebugUIPlugin.getActiveWorkbenchShell(), new SourceElementLabelProvider(),new SourceElementQualifierProvider());
202                 dialog.setTitle(DebugUIMessages.JavaUISourceLocator_Select_Source_1);
203                 dialog.setMessage(MessageFormat.format(DebugUIMessages.JavaUISourceLocator__Select_the_source_that_corresponds_to__0__2, new String JavaDoc[]{type.getName()}));
204                 dialog.setElements(sourceElements);
205                 dialog.setMultipleSelection(false);
206                 dialog.setUpperListLabel(DebugUIMessages.JavaUISourceLocator__Matching_files__3);
207                 dialog.setLowerListLabel(DebugUIMessages.JavaUISourceLocator__Location__4);
208                 dialog.open();
209                 Object JavaDoc[] result = dialog.getResult();
210                 if (result == null) {
211                     return null;
212                 }
213                 Object JavaDoc sourceElement = result[0];
214                 cacheSourceElement(sourceElement, type);
215                 return sourceElement;
216             } catch (CoreException e) {
217                 JDIDebugUIPlugin.log(e);
218                 return sourceElements[0];
219             }
220         }
221         return fSourceLocator.getSourceElement(stackFrame);
222     }
223     
224     private Object JavaDoc getSourceElement(IJavaReferenceType type) {
225         if (fTypesToSource == null) {
226             return null;
227         }
228         return fTypesToSource.get(type);
229     }
230     
231     private void cacheSourceElement(Object JavaDoc sourceElement, IJavaReferenceType type) {
232         if (fTypesToSource == null) {
233             fTypesToSource = new HashMap JavaDoc();
234         }
235         fTypesToSource.put(type, sourceElement);
236     }
237
238     /**
239      * Prompts to locate the source of the given type. Prompts in the UI
240      * thread, since a source lookup could be the result of a conditional
241      * breakpoint looking up source for an evaluation, from the event
242      * dispatch thread.
243      *
244      * @param typeName the name of the type for which source
245      * could not be located
246      */

247     private void showDebugSourcePage(final IJavaStackFrame frame) {
248         Runnable JavaDoc prompter = new Runnable JavaDoc() {
249             public void run() {
250                 try {
251                     String JavaDoc message = MessageFormat.format(LauncherMessages.JavaUISourceLocator_selectprojects_message, new String JavaDoc[] {frame.getDeclaringTypeName()});
252
253                     ILaunchConfiguration configuration =
254                         frame.getLaunch().getLaunchConfiguration();
255                     JavaSourceLookupDialog dialog =
256                         new JavaSourceLookupDialog(
257                             JDIDebugUIPlugin.getActiveWorkbenchShell(),
258                             message,
259                             configuration);
260                     int result = dialog.open();
261                     if (result == Window.OK) {
262                         fAllowedToAsk = !dialog.isNotAskAgain();
263                         JavaUISourceLocator.this.initializeDefaults(
264                             configuration);
265                     }
266                 } catch (CoreException e) {
267                     // only report an error if the thread has not resumed
268
if (e.getStatus().getCode()
269                         != IJavaThread.ERR_THREAD_NOT_SUSPENDED) {
270                         JDIDebugUIPlugin.log(e);
271                     }
272                 }
273             }
274         };
275         JDIDebugUIPlugin.getStandardDisplay().syncExec(prompter);
276     }
277
278     /**
279      * @see IPersistableSourceLocator#getMemento()
280      */

281     public String JavaDoc getMemento() throws CoreException {
282         String JavaDoc memento = fSourceLocator.getMemento();
283         String JavaDoc handle = fJavaProject.getHandleIdentifier();
284         String JavaDoc findAll = Boolean.valueOf(isFindAllSourceElements()).toString();
285
286         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
287         buffer.append("<project>"); //$NON-NLS-1$
288
buffer.append(handle);
289         buffer.append("</project>"); //$NON-NLS-1$
290
buffer.append("<findAll>"); //$NON-NLS-1$
291
buffer.append(findAll);
292         buffer.append("</findAll>"); //$NON-NLS-1$
293
buffer.append(memento);
294         return buffer.toString();
295     }
296
297     /**
298      * @see IPersistableSourceLocator#initializeDefaults(ILaunchConfiguration)
299      */

300     public void initializeDefaults(ILaunchConfiguration configuration)
301         throws CoreException {
302         fSourceLocator.initializeDefaults(configuration);
303         fJavaProject = JavaRuntime.getJavaProject(configuration);
304         fIsFindAllSourceElements =
305             configuration.getAttribute(ATTR_FIND_ALL_SOURCE_ELEMENTS, false);
306     }
307
308     /**
309      * @see IPersistableSourceLocator#initializeFromMemento(String)
310      */

311     public void initializeFromMemento(String JavaDoc memento) throws CoreException {
312         if (memento.startsWith("<project>")) { //$NON-NLS-1$
313
int index = memento.indexOf("</project>"); //$NON-NLS-1$
314
if (index > 0) {
315                 String JavaDoc handle = memento.substring(9, index);
316                 int start = index + 19;
317                 index = memento.indexOf("</findAll>", start); //$NON-NLS-1$
318
if (index > 0) {
319                     String JavaDoc findAll = memento.substring(start, index);
320                     Boolean JavaDoc all = Boolean.valueOf(findAll);
321                     String JavaDoc rest = memento.substring(index + 10);
322                     fJavaProject = (IJavaProject) JavaCore.create(handle);
323                     fIsFindAllSourceElements = all.booleanValue();
324                     fSourceLocator.initializeFromMemento(rest);
325                 }
326             }
327         } else {
328             // OLD FORMAT
329
int index = memento.indexOf('\n');
330             String JavaDoc handle = memento.substring(0, index);
331             String JavaDoc rest = memento.substring(index + 1);
332             fJavaProject = (IJavaProject) JavaCore.create(handle);
333             fIsFindAllSourceElements = false;
334             fSourceLocator.initializeFromMemento(rest);
335         }
336     }
337
338     /**
339      * @see JavaSourceLocator#getSourceLocations()
340      */

341     public IJavaSourceLocation[] getSourceLocations() {
342         return fSourceLocator.getSourceLocations();
343     }
344
345     /**
346      * @see JavaSourceLocator#setSourceLocations(IJavaSourceLocation[])
347      */

348     public void setSourceLocations(IJavaSourceLocation[] locations) {
349         fSourceLocator.setSourceLocations(locations);
350     }
351
352     /**
353      * Returns whether this source locator is configured to search for all
354      * source elements that correspond to a stack frame. When <code>false</code>
355      * is returned, searching stops on the first match. If there is more than
356      * one source element that corresponds to a stack frame, the user is
357      * prompted to choose a source element to open.
358      *
359      * @return whether this source locator is configured to search for all
360      * source elements that correspond to a stack frame
361      * @since 2.1
362      */

363     public boolean isFindAllSourceElements() {
364         return fIsFindAllSourceElements;
365     }
366
367     /**
368      * Sets whether this source locator is configured to search for all source
369      * elements that correspond to a stack frame, or the first match.
370      *
371      * @param findAll whether this source locator should search for all source
372      * elements that correspond to a stack frame
373      * @since 2.1
374      */

375     public void setFindAllSourceElement(boolean findAll) {
376         fIsFindAllSourceElements = findAll;
377     }
378
379 }
380
Popular Tags