KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > debug > ui > snippeteditor > ScrapbookLauncher


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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.internal.debug.ui.snippeteditor;
12  
13  
14 import java.io.File JavaDoc;
15 import java.io.IOException JavaDoc;
16 import java.net.MalformedURLException JavaDoc;
17 import java.net.URL JavaDoc;
18 import java.net.URLEncoder JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.StringTokenizer JavaDoc;
23
24 import org.eclipse.core.resources.IFile;
25 import org.eclipse.core.resources.IResource;
26 import org.eclipse.core.resources.IWorkspaceRoot;
27 import org.eclipse.core.resources.ResourcesPlugin;
28 import org.eclipse.core.runtime.CoreException;
29 import org.eclipse.core.runtime.FileLocator;
30 import org.eclipse.core.runtime.IPath;
31 import org.eclipse.core.runtime.Path;
32 import org.eclipse.core.runtime.QualifiedName;
33 import org.eclipse.debug.core.DebugEvent;
34 import org.eclipse.debug.core.DebugPlugin;
35 import org.eclipse.debug.core.IDebugEventSetListener;
36 import org.eclipse.debug.core.ILaunch;
37 import org.eclipse.debug.core.ILaunchConfiguration;
38 import org.eclipse.debug.core.ILaunchConfigurationType;
39 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
40 import org.eclipse.debug.core.ILaunchManager;
41 import org.eclipse.debug.core.model.IBreakpoint;
42 import org.eclipse.debug.core.model.IDebugTarget;
43 import org.eclipse.debug.ui.IDebugUIConstants;
44 import org.eclipse.jdt.core.IJavaProject;
45 import org.eclipse.jdt.core.JavaCore;
46 import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
47 import org.eclipse.jdt.debug.core.JDIDebugModel;
48 import org.eclipse.jdt.debug.ui.IJavaDebugUIConstants;
49 import org.eclipse.jdt.internal.debug.ui.JDIDebugUIPlugin;
50 import org.eclipse.jdt.internal.launching.JavaMigrationDelegate;
51 import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
52 import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
53 import org.eclipse.jdt.launching.IVMInstall;
54 import org.eclipse.jdt.launching.JavaRuntime;
55 import org.eclipse.jface.dialogs.MessageDialog;
56
57 import com.ibm.icu.text.MessageFormat;
58
59 /**
60  * Support for launching scrapbook using launch configurations.
61  */

62
63 public class ScrapbookLauncher implements IDebugEventSetListener {
64     
65     public static final String JavaDoc SCRAPBOOK_LAUNCH = IJavaDebugUIConstants.PLUGIN_ID + ".scrapbook_launch"; //$NON-NLS-1$
66

67     public static final String JavaDoc SCRAPBOOK_FILE_PATH = IJavaDebugUIConstants.PLUGIN_ID + ".scrapbook_file_path"; //$NON-NLS-1$
68

69     /**
70      * Persistent property associated with snippet files specifying working directory.
71      * Same format as the associated launch configuration attribute
72      * <code>ATTR_WORKING_DIR</code>.
73      */

74     public static final QualifiedName SNIPPET_EDITOR_LAUNCH_CONFIG_HANDLE_MEMENTO = new QualifiedName(IJavaDebugUIConstants.PLUGIN_ID, "snippet_editor_launch_config"); //$NON-NLS-1$
75

76     private IJavaLineBreakpoint fMagicBreakpoint;
77     
78     private HashMap JavaDoc fScrapbookToVMs = new HashMap JavaDoc(10);
79     private HashMap JavaDoc fVMsToBreakpoints = new HashMap JavaDoc(10);
80     private HashMap JavaDoc fVMsToScrapbooks = new HashMap JavaDoc(10);
81     
82     private static ScrapbookLauncher fgDefault = null;
83     
84     private ScrapbookLauncher() {
85         //see getDefault()
86
}
87     
88     public static ScrapbookLauncher getDefault() {
89         if (fgDefault == null) {
90             fgDefault = new ScrapbookLauncher();
91         }
92         return fgDefault;
93     }
94     
95     /**
96      * Launches a VM for the given srapbook page, in debug mode.
97      * Returns an existing launch if the page is already running.
98      *
99      * @param file scrapbook page file
100      * @return resulting launch, or <code>null</code> on failure
101      */

102     protected ILaunch launch(IFile page) {
103
104         // clean up orphaned launch configurations
105
cleanupLaunchConfigurations();
106                             
107         if (!page.getFileExtension().equals("jpage")) { //$NON-NLS-1$
108
showNoPageDialog();
109             return null;
110         }
111         
112         IDebugTarget vm = getDebugTarget(page);
113         if (vm != null) {
114             //already launched
115
return vm.getLaunch();
116         }
117         
118         IJavaProject javaProject= JavaCore.create(page.getProject());
119             
120         URL JavaDoc jarURL = null;
121         try {
122             jarURL = JDIDebugUIPlugin.getDefault().getBundle().getEntry("snippetsupport.jar"); //$NON-NLS-1$
123
jarURL = FileLocator.toFileURL(jarURL);
124         } catch (MalformedURLException JavaDoc e) {
125             JDIDebugUIPlugin.errorDialog(SnippetMessages.getString("ScrapbookLauncher.Unable_to_launch_scrapbook_VM_6"), e); //$NON-NLS-1$
126
return null;
127         } catch (IOException JavaDoc e) {
128             JDIDebugUIPlugin.errorDialog(SnippetMessages.getString("ScrapbookLauncher.Unable_to_launch_scrapbook_VM_6"), e); //$NON-NLS-1$
129
return null;
130         }
131         
132         List JavaDoc cp = new ArrayList JavaDoc(3);
133         IRuntimeClasspathEntry supportEntry = JavaRuntime.newArchiveRuntimeClasspathEntry(new Path(jarURL.getFile()));
134         cp.add(supportEntry);
135         // get bootpath entries
136
try {
137             IRuntimeClasspathEntry[] entries = JavaRuntime.computeUnresolvedRuntimeClasspath(javaProject);
138             for (int i = 0; i < entries.length; i++) {
139                 if (entries[i].getClasspathProperty() != IRuntimeClasspathEntry.USER_CLASSES) {
140                     cp.add(entries[i]);
141                 }
142             }
143             IRuntimeClasspathEntry[] classPath = (IRuntimeClasspathEntry[])cp.toArray(new IRuntimeClasspathEntry[cp.size()]);
144             
145             return doLaunch(javaProject, page, classPath);
146         } catch (CoreException e) {
147             JDIDebugUIPlugin.statusDialog(SnippetMessages.getString("ScrapbookLauncher.Unable_to_launch_scrapbook_VM_6"), e.getStatus()); //$NON-NLS-1$
148
}
149         return null;
150     }
151
152     private ILaunch doLaunch(IJavaProject p, IFile page, IRuntimeClasspathEntry[] classPath) {
153         try {
154             if (fVMsToScrapbooks.isEmpty()) {
155                 // register for debug events if a scrapbook is not currently running
156
DebugPlugin.getDefault().addDebugEventListener(this);
157             }
158             ILaunchConfiguration config = null;
159             ILaunchConfigurationWorkingCopy wc = null;
160             try {
161                 config = getLaunchConfigurationTemplate(page);
162                 if (config != null) {
163                     wc = config.getWorkingCopy();
164                 }
165             } catch (CoreException e) {
166                 config = null;
167                 JDIDebugUIPlugin.statusDialog(SnippetMessages.getString("ScrapbookLauncher.Unable_to_retrieve_settings"), e.getStatus()); //$NON-NLS-1$
168
}
169             
170             if (config == null) {
171                 config = createLaunchConfigurationTemplate(page);
172                 wc = config.getWorkingCopy();
173             }
174             
175             IPath outputLocation = p.getProject().getWorkingLocation(JDIDebugUIPlugin.getUniqueIdentifier());
176             File JavaDoc f = outputLocation.toFile();
177             URL JavaDoc u = null;
178             try {
179                 u = getEncodedURL(f);
180             } catch (MalformedURLException JavaDoc e) {
181                 JDIDebugUIPlugin.errorDialog(SnippetMessages.getString("ScrapbookLauncher.Unable_to_launch_scrapbook_VM_6"),e); //$NON-NLS-1$
182
return null;
183             }
184             String JavaDoc[] defaultClasspath = JavaRuntime.computeDefaultRuntimeClassPath(p);
185             String JavaDoc[] urls = new String JavaDoc[defaultClasspath.length + 1];
186             urls[0] = u.toExternalForm();
187             for (int i = 0; i < defaultClasspath.length; i++) {
188                 f = new File JavaDoc(defaultClasspath[i]);
189                 try {
190                     urls[i + 1] = getEncodedURL(f).toExternalForm();
191                 } catch (MalformedURLException JavaDoc e) {
192                     JDIDebugUIPlugin.errorDialog(SnippetMessages.getString("ScrapbookLauncher.Unable_to_launch_scrapbook_VM_6"), e); //$NON-NLS-1$
193
return null;
194                 }
195             }
196             
197             // convert to mementos
198
List JavaDoc classpathList= new ArrayList JavaDoc(classPath.length);
199             for (int i = 0; i < classPath.length; i++) {
200                 classpathList.add(classPath[i].getMemento());
201             }
202             
203             wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_DEFAULT_CLASSPATH, false);
204             wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_CLASSPATH, classpathList);
205             wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, p.getElementName());
206             if (wc.getAttribute(IJavaLaunchConfigurationConstants.ATTR_SOURCE_PATH_PROVIDER, (String JavaDoc)null) == null) {
207                 wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_SOURCE_PATH_PROVIDER, "org.eclipse.jdt.debug.ui.scrapbookSourcepathProvider"); //$NON-NLS-1$
208
}
209             
210             StringBuffer JavaDoc urlsString = new StringBuffer JavaDoc();
211             for (int i = 0; i < urls.length; i++) {
212                 urlsString.append(' ');
213                 urlsString.append(urls[i]);
214             }
215             wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, urlsString.toString());
216             wc.setAttribute(SCRAPBOOK_LAUNCH, SCRAPBOOK_LAUNCH);
217             
218             config = wc.doSave();
219             
220             ILaunch launch = config.launch(ILaunchManager.DEBUG_MODE, null);
221             if (launch != null) {
222                 IDebugTarget dt = launch.getDebugTarget();
223                 IBreakpoint magicBreakpoint = createMagicBreakpoint("org.eclipse.jdt.internal.debug.ui.snippeteditor.ScrapbookMain"); //$NON-NLS-1$
224
fScrapbookToVMs.put(page, dt);
225                 fVMsToScrapbooks.put(dt, page);
226                 fVMsToBreakpoints.put(dt, magicBreakpoint);
227                 dt.breakpointAdded(magicBreakpoint);
228                 launch.setAttribute(SCRAPBOOK_LAUNCH, SCRAPBOOK_LAUNCH);
229                 return launch;
230             }
231         } catch (CoreException e) {
232             JDIDebugUIPlugin.statusDialog(SnippetMessages.getString("ScrapbookLauncher.Unable_to_launch_scrapbook_VM_6"), e.getStatus()); //$NON-NLS-1$
233
}
234         return null;
235     }
236     
237     /**
238      * Creates an "invisible" line breakpoint.
239      */

240     IBreakpoint createMagicBreakpoint(String JavaDoc typeName) throws CoreException{
241         //set a breakpoint on the Thread.sleep(100); line of the nop method of ScrapbookMain
242
fMagicBreakpoint= JDIDebugModel.createLineBreakpoint(ResourcesPlugin.getWorkspace().getRoot(), typeName, 59, -1, -1, 0, false, null);
243         fMagicBreakpoint.setPersisted(false);
244         return fMagicBreakpoint;
245     }
246
247     /**
248      * @see IDebugEventSetListener#handleDebugEvents(DebugEvent[])
249      */

250     public void handleDebugEvents(DebugEvent[] events) {
251         for (int i = 0; i < events.length; i++) {
252             DebugEvent event = events[i];
253             if (event.getSource() instanceof IDebugTarget && event.getKind() == DebugEvent.TERMINATE) {
254                 cleanup((IDebugTarget)event.getSource());
255             }
256         }
257     }
258     
259     /**
260      * Returns the debug target associated with the given
261      * scrapbook page, or <code>null</code> if none.
262      *
263      * @param page file representing scrapbook page
264      * @return associated debug target or <code>null</code>
265      */

266     public IDebugTarget getDebugTarget(IFile page) {
267         return (IDebugTarget)fScrapbookToVMs.get(page);
268     }
269     
270     /**
271      * Returns the magic breakpoint associated with the given
272      * scrapbook VM. The magic breakpoint is the location at
273      * which an evaluation begins.
274      *
275      * @param target a scrapbook debug target
276      * @return the breakpoint at which an evaluation begins
277      * or <code>null</code> if none
278      */

279     public IBreakpoint getMagicBreakpoint(IDebugTarget target) {
280         return (IBreakpoint)fVMsToBreakpoints.get(target);
281     }
282     
283     protected void showNoPageDialog() {
284         String JavaDoc title= SnippetMessages.getString("ScrapbookLauncher.error.title"); //$NON-NLS-1$
285
String JavaDoc msg= SnippetMessages.getString("ScrapbookLauncher.error.pagenotfound"); //$NON-NLS-1$
286
MessageDialog.openError(JDIDebugUIPlugin.getActiveWorkbenchShell(),title, msg);
287     }
288     
289     protected void cleanup(IDebugTarget target) {
290         Object JavaDoc page = fVMsToScrapbooks.get(target);
291         if (page != null) {
292             fVMsToScrapbooks.remove(target);
293             fScrapbookToVMs.remove(page);
294             fVMsToBreakpoints.remove(target);
295             ILaunch launch = target.getLaunch();
296             if (launch != null) {
297                 getLaunchManager().removeLaunch(launch);
298             }
299             if (fVMsToScrapbooks.isEmpty()) {
300                 // no need to listen to events if no scrapbooks running
301
DebugPlugin.getDefault().removeDebugEventListener(this);
302             }
303         }
304     }
305     
306     protected URL JavaDoc getEncodedURL(File JavaDoc file) throws MalformedURLException JavaDoc {
307         //looking at File.toURL the delimiter is always '/'
308
// NOT File.separatorChar
309
String JavaDoc urlDelimiter= "/"; //$NON-NLS-1$
310
String JavaDoc unencoded= file.toURL().toExternalForm();
311         StringBuffer JavaDoc encoded= new StringBuffer JavaDoc();
312         StringTokenizer JavaDoc tokenizer= new StringTokenizer JavaDoc(unencoded, urlDelimiter);
313         
314         encoded.append(tokenizer.nextToken()); //file:
315
encoded.append(urlDelimiter);
316         encoded.append(tokenizer.nextToken()); //drive letter and ':'
317

318         while (tokenizer.hasMoreElements()) {
319             encoded.append(urlDelimiter);
320             String JavaDoc token= tokenizer.nextToken();
321             encoded.append(URLEncoder.encode(token));
322         }
323         if (file.isDirectory()) {
324             encoded.append(urlDelimiter);
325         }
326         return new URL JavaDoc(encoded.toString());
327     }
328     
329     /**
330      * Returns the launch configuration used as a template for launching the
331      * given scrapbook file, or <code>null</code> if none. The template contains
332      * working directory and JRE settings to use when launching the scrapbook.
333      */

334     public static ILaunchConfiguration getLaunchConfigurationTemplate(IFile file) throws CoreException {
335         String JavaDoc memento = getLaunchConfigMemento(file);
336         if (memento != null) {
337             return getLaunchManager().getLaunchConfiguration(memento);
338         }
339         return null;
340     }
341     
342     /**
343      * Creates and saves template launch configuration for the given scrapbook file.
344      */

345     public static ILaunchConfiguration createLaunchConfigurationTemplate(IFile page) throws CoreException {
346         ILaunchConfigurationType lcType = getLaunchManager().getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);
347         String JavaDoc name = MessageFormat.format(SnippetMessages.getString("ScrapbookLauncher.17"), new String JavaDoc[]{page.getName()}); //$NON-NLS-1$
348
ILaunchConfigurationWorkingCopy wc = lcType.newInstance(null, name);
349         wc.setAttribute(IDebugUIConstants.ATTR_PRIVATE, true);
350         wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_MAIN_TYPE_NAME, "org.eclipse.jdt.internal.debug.ui.snippeteditor.ScrapbookMain"); //$NON-NLS-1$
351
wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_PROJECT_NAME, page.getProject().getName());
352         wc.setAttribute(SCRAPBOOK_LAUNCH, SCRAPBOOK_LAUNCH);
353         wc.setAttribute(SCRAPBOOK_FILE_PATH, page.getFullPath().toString());
354         wc.setAttribute(IJavaLaunchConfigurationConstants.ATTR_SOURCE_PATH_PROVIDER, "org.eclipse.jdt.debug.ui.scrapbookSourcepathProvider"); //$NON-NLS-1$
355
JavaMigrationDelegate.updateResourceMapping(wc);
356         ILaunchConfiguration config = wc.doSave();
357         setLaunchConfigMemento(page, config.getMemento());
358         return config;
359     }
360         
361     /**
362      * Returns the handle memento for the given scrapbook's launch configuration
363      * template, or <code>null</code> if none.
364      */

365     private static String JavaDoc getLaunchConfigMemento(IFile file) {
366         try {
367             return file.getPersistentProperty(SNIPPET_EDITOR_LAUNCH_CONFIG_HANDLE_MEMENTO);
368         } catch (CoreException e) {
369             JDIDebugUIPlugin.log(e);
370         }
371         return null;
372     }
373     
374     /**
375      * Sets the handle memento for the given scrapbook's launch configuration
376      * template.
377      */

378     protected static void setLaunchConfigMemento(IFile file, String JavaDoc memento) {
379         try {
380             file.setPersistentProperty(SNIPPET_EDITOR_LAUNCH_CONFIG_HANDLE_MEMENTO, memento);
381         } catch (CoreException e) {
382             JDIDebugUIPlugin.log(e);
383         }
384     }
385
386     /**
387      * Returns the launch manager.
388      */

389     protected static ILaunchManager getLaunchManager() {
390         return DebugPlugin.getDefault().getLaunchManager();
391     }
392     
393     /**
394      * Returns the working directory attribute for the given snippet file,
395      * possibly <code>null</code>.
396      *
397      * @exception CoreException if unable to retrieve the attribute
398      */

399     public static String JavaDoc getWorkingDirectoryAttribute(IFile file) throws CoreException {
400         ILaunchConfiguration config = getLaunchConfigurationTemplate(file);
401         if (config != null) {
402             return config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_WORKING_DIRECTORY, (String JavaDoc)null);
403         }
404         return null;
405     }
406     
407     /**
408      * Returns the VM args attribute for the given snippet file,
409      * possibly <code>null</code>.
410      *
411      * @exception CoreException if unable to retrieve the attribute
412      */

413     public static String JavaDoc getVMArgsAttribute(IFile file) throws CoreException {
414         ILaunchConfiguration config = getLaunchConfigurationTemplate(file);
415         if (config != null) {
416             return config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_VM_ARGUMENTS, (String JavaDoc)null);
417         }
418         return null;
419     }
420     
421     /**
422      * Returns the VM install used to launch the given snippet file.
423      *
424      * @exception CoreException if unable to retrieve the attribute
425      */

426     public static IVMInstall getVMInstall(IFile file) throws CoreException {
427         ILaunchConfiguration config = getLaunchConfigurationTemplate(file);
428         if (config == null) {
429             IJavaProject pro = JavaCore.create(file.getProject());
430             return JavaRuntime.getVMInstall(pro);
431         }
432         return JavaRuntime.computeVMInstall(config);
433     }
434     
435     /**
436      * Deletes any scrapbook launch configurations for scrapbooks that
437      * have been deleted. Rather than listening to all resource deltas,
438      * configs are deleted each time a scrapbook is launched - which is
439      * infrequent.
440      */

441     public void cleanupLaunchConfigurations() {
442         try {
443             ILaunchConfigurationType lcType = getLaunchManager().getLaunchConfigurationType(IJavaLaunchConfigurationConstants.ID_JAVA_APPLICATION);
444             ILaunchConfiguration[] configs = getLaunchManager().getLaunchConfigurations(lcType);
445             IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
446             for (int i = 0; i < configs.length; i++) {
447                 String JavaDoc path = configs[i].getAttribute(SCRAPBOOK_FILE_PATH, (String JavaDoc)null);
448                 if (path != null) {
449                     IPath pagePath = new Path(path);
450                     IResource res = root.findMember(pagePath);
451                     if (res == null) {
452                         // config without a page - delete it
453
configs[i].delete();
454                     }
455                 }
456             }
457         } catch (CoreException e) {
458             // log quietly
459
JDIDebugUIPlugin.log(e);
460         }
461     }
462 }
463
Popular Tags