KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > debug > core > DebugPlugin


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.debug.core;
12
13
14 import java.io.ByteArrayInputStream JavaDoc;
15 import java.io.File JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.io.InputStream JavaDoc;
18 import java.util.ArrayList JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22
23 import javax.xml.parsers.DocumentBuilder JavaDoc;
24 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
25 import javax.xml.parsers.FactoryConfigurationError JavaDoc;
26 import javax.xml.parsers.ParserConfigurationException JavaDoc;
27 import javax.xml.transform.TransformerException JavaDoc;
28
29 import org.eclipse.core.resources.ISaveContext;
30 import org.eclipse.core.resources.ISaveParticipant;
31 import org.eclipse.core.resources.ResourcesPlugin;
32 import org.eclipse.core.runtime.CoreException;
33 import org.eclipse.core.runtime.IAdapterManager;
34 import org.eclipse.core.runtime.IConfigurationElement;
35 import org.eclipse.core.runtime.IExtensionPoint;
36 import org.eclipse.core.runtime.IProgressMonitor;
37 import org.eclipse.core.runtime.ISafeRunnable;
38 import org.eclipse.core.runtime.IStatus;
39 import org.eclipse.core.runtime.ListenerList;
40 import org.eclipse.core.runtime.Platform;
41 import org.eclipse.core.runtime.Plugin;
42 import org.eclipse.core.runtime.SafeRunner;
43 import org.eclipse.core.runtime.Status;
44 import org.eclipse.core.runtime.jobs.Job;
45 import org.eclipse.debug.core.model.IDebugElement;
46 import org.eclipse.debug.core.model.IDisconnect;
47 import org.eclipse.debug.core.model.IDropToFrame;
48 import org.eclipse.debug.core.model.IProcess;
49 import org.eclipse.debug.core.model.IStep;
50 import org.eclipse.debug.core.model.IStepFilters;
51 import org.eclipse.debug.core.model.ISuspendResume;
52 import org.eclipse.debug.core.model.ITerminate;
53 import org.eclipse.debug.core.model.IValue;
54 import org.eclipse.debug.core.model.RuntimeProcess;
55 import org.eclipse.debug.internal.core.BreakpointManager;
56 import org.eclipse.debug.internal.core.DebugCoreMessages;
57 import org.eclipse.debug.internal.core.DebugOptions;
58 import org.eclipse.debug.internal.core.ExpressionManager;
59 import org.eclipse.debug.internal.core.LaunchManager;
60 import org.eclipse.debug.internal.core.LogicalStructureManager;
61 import org.eclipse.debug.internal.core.MemoryBlockManager;
62 import org.eclipse.debug.internal.core.StepFilterManager;
63 import org.eclipse.debug.internal.core.commands.CommandAdapterFactory;
64 import org.eclipse.debug.internal.core.sourcelookup.SourceLookupMessages;
65 import org.eclipse.debug.internal.core.sourcelookup.SourceLookupUtils;
66 import org.eclipse.osgi.service.environment.Constants;
67 import org.osgi.framework.BundleContext;
68 import org.w3c.dom.Document JavaDoc;
69 import org.w3c.dom.Element JavaDoc;
70 import org.xml.sax.SAXException JavaDoc;
71 import org.xml.sax.helpers.DefaultHandler JavaDoc;
72
73 import com.ibm.icu.text.MessageFormat;
74
75 /**
76  * There is one instance of the debug plug-in available from
77  * <code>DebugPlugin.getDefault()</code>. The debug plug-in provides:
78  * <ul>
79  * <li>access to the breakpoint manager</li>
80  * <li>access to the launch manager</li>
81  * <li>access to the expression manager</li>
82  * <li>access to the registered launcher extensions</li>
83  * <li>access to the memory block manager</li>
84  * <li>debug event notification</li>
85  * <li>status handlers</li>
86  * </ul>
87  * <p>
88  * Clients may not instantiate or subclass this class.
89  * </p>
90  */

91 public class DebugPlugin extends Plugin {
92     
93     /**
94      * Unique identifier constant (value <code>"org.eclipse.debug.core"</code>)
95      * for the Debug Core plug-in.
96      */

97     private static final String JavaDoc PI_DEBUG_CORE = "org.eclipse.debug.core"; //$NON-NLS-1$
98

99     /**
100      * Simple identifier constant (value <code>"launchConfigurationTypes"</code>)
101      * for the launch configuration types extension point.
102      *
103      * @since 2.0
104      */

105     public static final String JavaDoc EXTENSION_POINT_LAUNCH_CONFIGURATION_TYPES= "launchConfigurationTypes"; //$NON-NLS-1$
106

107     /**
108      * Simple identifier constant (value <code>"launchConfigurationComparators"</code>)
109      * for the launch configuration comparators extension point.
110      *
111      * @since 2.0
112      */

113     public static final String JavaDoc EXTENSION_POINT_LAUNCH_CONFIGURATION_COMPARATORS= "launchConfigurationComparators"; //$NON-NLS-1$
114

115     /**
116      * Simple identifier constant (value <code>"breakpoints"</code>) for the
117      * breakpoints extension point.
118      *
119      * @since 2.0
120      */

121     public static final String JavaDoc EXTENSION_POINT_BREAKPOINTS= "breakpoints"; //$NON-NLS-1$
122

123     /**
124      * Simple identifier constant (value <code>"statusHandlers"</code>) for the
125      * status handlers extension point.
126      *
127      * @since 2.0
128      */

129     public static final String JavaDoc EXTENSION_POINT_STATUS_HANDLERS= "statusHandlers"; //$NON-NLS-1$
130

131     /**
132      * Simple identifier constant (value <code>"sourceLocators"</code>) for the
133      * source locators extension point.
134      *
135      * @since 2.0
136      */

137     public static final String JavaDoc EXTENSION_POINT_SOURCE_LOCATORS= "sourceLocators"; //$NON-NLS-1$
138

139     /**
140      * Simple identifier constant (value <code>"launchModes"</code>) for the
141      * source modes extension point.
142      *
143      * @since 3.0
144      */

145     public static final String JavaDoc EXTENSION_POINT_LAUNCH_MODES= "launchModes"; //$NON-NLS-1$
146

147     /**
148      * Simple identifier constant (value <code>"launchDelegates"</code>) for the
149      * launch delegates extension point.
150      *
151      * @since 3.0
152      */

153     public static final String JavaDoc EXTENSION_POINT_LAUNCH_DELEGATES= "launchDelegates"; //$NON-NLS-1$
154

155     /**
156      * Simple identifier constant (value <code>"processFactories"</code>) for the
157      * process factories extension point.
158      *
159      * @since 3.0
160      */

161     public static final String JavaDoc EXTENSION_POINT_PROCESS_FACTORIES = "processFactories"; //$NON-NLS-1$
162

163     /**
164      * Simple identifier constant (value <code>"logicalStructureTypes"</code>) for the
165      * logical structure types extension point.
166      *
167      * @since 3.0
168      */

169     public static final String JavaDoc EXTENSION_POINT_LOGICAL_STRUCTURE_TYPES = "logicalStructureTypes"; //$NON-NLS-1$
170

171     /**
172      * Simple identifier constant (value <code>"logicalStructureProviders"</code>) for the
173      * logical structure types extension point.
174      *
175      * @since 3.1
176      */

177     public static final String JavaDoc EXTENSION_POINT_LOGICAL_STRUCTURE_PROVIDERS = "logicalStructureProviders"; //$NON-NLS-1$
178

179     /**
180      * Simple identifier constant (value <code>"sourceContainerTypes"</code>) for the
181      * source container types extension point.
182      *
183      * @since 3.0
184      */

185     public static final String JavaDoc EXTENSION_POINT_SOURCE_CONTAINER_TYPES = "sourceContainerTypes"; //$NON-NLS-1$
186

187     /**
188      * Simple identifier constant (value <code>"sourcePathComputers"</code>) for the
189      * source path computers extension point.
190      *
191      * @since 3.0
192      */

193     public static final String JavaDoc EXTENSION_POINT_SOURCE_PATH_COMPUTERS = "sourcePathComputers"; //$NON-NLS-1$
194

195     /**
196      * Simple identifier constant for the launch options extension point
197      *
198      * @since 3.3
199      */

200     public static final String JavaDoc EXTENSION_POINT_LAUNCH_OPTIONS = "launchOptions"; //$NON-NLS-1$
201

202     /**
203      * Status code indicating an unexpected internal error.
204      */

205     public static final int INTERNAL_ERROR = 120;
206
207     /**
208      * Status code indicating that the Eclipse runtime does not support
209      * launching a program with a working directory. This feature is only
210      * available if Eclipse is run on a 1.3 runtime or higher.
211      * <p>
212      * A status handler may be registered for this error condition,
213      * and should return a <code>Boolean</code> indicating whether the program
214      * should be re-launched with the default working directory.
215      * </p>
216      */

217     public static final int ERR_WORKING_DIRECTORY_NOT_SUPPORTED = 115;
218     
219     /**
220      * The launch configuration attribute that designates the process factory ID
221      * for the process factory to be used when creating a new process as a result of launching
222      * the launch configuration.
223      * @since 3.0
224      */

225     public static final String JavaDoc ATTR_PROCESS_FACTORY_ID = "process_factory_id"; //$NON-NLS-1$
226

227     /**
228      * The launch attribute that designates whether or not it's associated
229      * launch should capture output. Value is a string representing a boolean -
230      * <code>true</code> or <code>false</code>. When unspecified, the default
231      * value is considered <code>true</code>.
232      *
233      * @since 3.1
234      */

235     public static final String JavaDoc ATTR_CAPTURE_OUTPUT = PI_DEBUG_CORE + ".capture_output"; //$NON-NLS-1$
236

237     
238     /**
239      * This launch attribute designates the encoding to be used by the console
240      * associated with the launch. When unspecified, the platform's default
241      * encoding will be used.
242      * <p>
243      * Value of this constant is the same as the value of the old
244      * <code>IDebugUIConstants.ATTR_CONSOLE_ENCODING</code> constant for backward
245      * compatibility.
246      * </p>
247      * @since 3.3
248      */

249     public static final String JavaDoc ATTR_CONSOLE_ENCODING = "org.eclipse.debug.ui.ATTR_CONSOLE_ENCODING"; //$NON-NLS-1$
250

251     /**
252      * The singleton debug plug-in instance.
253      */

254     private static DebugPlugin fgDebugPlugin= null;
255
256     /**
257      * The singleton breakpoint manager.
258      */

259     private BreakpointManager fBreakpointManager;
260     
261     /**
262      * The singleton expression manager.
263      */

264     private ExpressionManager fExpressionManager;
265
266     /**
267      * The singleton launch manager.
268      */

269     private LaunchManager fLaunchManager;
270
271     /**
272      * The singleton memory block manager.
273      * @since 3.1
274      */

275     private MemoryBlockManager fMemoryBlockManager;
276     
277     /**
278      * The collection of debug event listeners.
279      */

280     private ListenerList fEventListeners = new ListenerList();
281     
282     /**
283      * Event filters, or <code>null</code> if none.
284      */

285     private ListenerList fEventFilters = null;
286
287     /**
288      * Whether this plug-in is in the process of shutting
289      * down.
290      */

291     private boolean fShuttingDown= false;
292     
293     /**
294      * Table of status handlers. Keys are {plug-in identifier, status code}
295      * pairs, and values are associated <code>IConfigurationElement</code>s.
296      */

297     private HashMap JavaDoc fStatusHandlers = null;
298     
299     /**
300      * Map of process factories. Keys are process factory IDs
301      * and values are associated <code>IConfigurationElement</code>s.
302      * @since 3.0
303      */

304     private HashMap JavaDoc fProcessFactories = null;
305     
306     /**
307      * Mode constants for the event notifier
308      */

309     private static final int NOTIFY_FILTERS = 0;
310     private static final int NOTIFY_EVENTS = 1;
311
312         
313     /**
314      * Queue of debug events to fire to listeners and asynchronous runnables to execute
315      * in the order received.
316      *
317      * @since 3.1
318      */

319     private List JavaDoc fEventQueue = new ArrayList JavaDoc();
320     
321     /**
322      * Job to fire events to listeners.
323      * @since 3.1
324      */

325     private EventDispatchJob fEventDispatchJob = new EventDispatchJob();
326     
327     /**
328      * Event dispatch job. Processes event queue of debug events and runnables.
329      *
330      * @since 3.1
331      */

332     class EventDispatchJob extends Job {
333         
334         EventNotifier fNotifier = new EventNotifier();
335         AsynchRunner fRunner = new AsynchRunner();
336
337         /**
338          * Creates a new event dispatch job.
339          */

340         public EventDispatchJob() {
341             super(DebugCoreMessages.DebugPlugin_1);
342             setPriority(Job.INTERACTIVE);
343             setSystem(true);
344         }
345         /* (non-Javadoc)
346          * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
347          */

348         protected IStatus run(IProgressMonitor monitor) {
349             
350             while (!fEventQueue.isEmpty()) {
351                 Object JavaDoc next = null;
352                 synchronized (fEventQueue) {
353                     if (!fEventQueue.isEmpty()) {
354                         next = fEventQueue.remove(0);
355                     }
356                 }
357                 if (next instanceof Runnable JavaDoc) {
358                     fRunner.async((Runnable JavaDoc) next);
359                 } else if (next != null) {
360                     fNotifier.dispatch((DebugEvent[]) next);
361                 }
362             }
363             return Status.OK_STATUS;
364         }
365         
366         /* (non-Javadoc)
367          * @see org.eclipse.core.runtime.jobs.Job#shouldRun()
368          */

369         public boolean shouldRun() {
370             return shouldSchedule();
371         }
372         /* (non-Javadoc)
373          * @see org.eclipse.core.internal.jobs.InternalJob#shouldSchedule()
374          */

375         public boolean shouldSchedule() {
376             return !(isShuttingDown() || fEventListeners.isEmpty());
377         }
378         
379     }
380
381     /**
382      * Returns the singleton instance of the debug plug-in.
383      *
384      * @return the debug plug-in
385      */

386     public static DebugPlugin getDefault() {
387         return fgDebugPlugin;
388     }
389     
390     /**
391      * Sets the singleton instance of the debug plug-in.
392      *
393      * @param plugin the debug plug-in, or <code>null</code>
394      * when shutting down
395      */

396     private static void setDefault(DebugPlugin plugin) {
397         fgDebugPlugin = plugin;
398     }
399     
400     /**
401      * Convenience method which returns the unique identifier of this plug-in.
402      *
403      * @return debug plug-in identifier
404      */

405     public static String JavaDoc getUniqueIdentifier() {
406         return PI_DEBUG_CORE;
407     }
408
409     /**
410      * Constructs the debug plug-in.
411      * <p>
412      * An instance of this plug-in runtime class is automatically created
413      * when the facilities provided by this plug-in are required.
414      * <b>Clients must never explicitly instantiate a plug-in runtime class.</b>
415      * </p>
416      */

417     public DebugPlugin() {
418         super();
419         setDefault(this);
420     }
421     
422     /**
423      * Adds the given listener to the collection of registered debug
424      * event listeners. Has no effect if an identical listener is already
425      * registered.
426      *
427      * @param listener the listener to add
428      * @since 2.0
429      */

430     public void addDebugEventListener(IDebugEventSetListener listener) {
431         fEventListeners.add(listener);
432     }
433     
434     /**
435      * Notifies all registered debug event set listeners of the given
436      * debug events. Events which are filtered by a registered debug event
437      * filter are not fired.
438      *
439      * @param events array of debug events to fire
440      * @see IDebugEventFilter
441      * @see IDebugEventSetListener
442      * @since 2.0
443      */

444     public void fireDebugEventSet(DebugEvent[] events) {
445         if (isShuttingDown() || events == null || fEventListeners.isEmpty())
446             return;
447         synchronized (fEventQueue) {
448             fEventQueue.add(events);
449         }
450         fEventDispatchJob.schedule();
451     }
452     
453     /**
454      * Asynchronously executes the given runnable in a separate
455      * thread, after debug event dispatch has completed. If debug
456      * events are not currently being dispatched, the runnable is
457      * scheduled to run in a separate thread immediately.
458      *
459      * @param r runnable to execute asynchronously
460      * @since 2.1
461      */

462     public void asyncExec(Runnable JavaDoc r) {
463         synchronized (fEventQueue) {
464             fEventQueue.add(r);
465         }
466         fEventDispatchJob.schedule();
467     }
468     
469     /**
470      * Returns the breakpoint manager.
471      *
472      * @return the breakpoint manager
473      * @see IBreakpointManager
474      */

475     public IBreakpointManager getBreakpointManager() {
476         if (fBreakpointManager == null) {
477             fBreakpointManager = new BreakpointManager();
478         }
479         return fBreakpointManager;
480     }
481     
482     /**
483      * Returns the launch manager.
484      *
485      * @return the launch manager
486      * @see ILaunchManager
487      */

488     public ILaunchManager getLaunchManager() {
489         if (fLaunchManager == null) {
490             fLaunchManager = new LaunchManager();
491         }
492         return fLaunchManager;
493     }
494     
495     /**
496      * Returns the memory block manager.
497      * @return the memory block manager.
498      * @see IMemoryBlockManager
499      * @since 3.1
500      */

501     public IMemoryBlockManager getMemoryBlockManager(){
502         if (fMemoryBlockManager == null) {
503             fMemoryBlockManager = new MemoryBlockManager();
504         }
505         return fMemoryBlockManager;
506     }
507     
508     /**
509      * Returns the status handler registered for the given
510      * status, or <code>null</code> if none.
511      *
512      * @param status status for which a status handler has been requested
513      * @return the status handler registered for the given
514      * status, or <code>null</code> if none
515      * @since 2.0
516      */

517     public IStatusHandler getStatusHandler(IStatus status) {
518         StatusHandlerKey key = new StatusHandlerKey(status.getPlugin(), status.getCode());
519         if (fStatusHandlers == null) {
520             initializeStatusHandlers();
521         }
522         IConfigurationElement config = (IConfigurationElement)fStatusHandlers.get(key);
523         if (config != null) {
524             try {
525                 Object JavaDoc handler = config.createExecutableExtension("class"); //$NON-NLS-1$
526
if (handler instanceof IStatusHandler) {
527                     return (IStatusHandler)handler;
528                 }
529                 invalidStatusHandler(null, MessageFormat.format("Registered status handler {0} does not implement required interface IStatusHandler.", new String JavaDoc[] {config.getDeclaringExtension().getUniqueIdentifier()})); //$NON-NLS-1$
530
} catch (CoreException e) {
531                 log(e);
532             }
533         }
534         return null;
535     }
536     
537     /**
538      * Returns the expression manager.
539      *
540      * @return the expression manager
541      * @see IExpressionManager
542      * @since 2.0
543      */

544     public IExpressionManager getExpressionManager() {
545         if (fExpressionManager == null) {
546             fExpressionManager = new ExpressionManager();
547         }
548         return fExpressionManager;
549     }
550         
551     /**
552      * Removes the given listener from the collection of registered debug
553      * event listeners. Has no effect if an identical listener is not already
554      * registered.
555      *
556      * @param listener the listener to remove
557      * @since 2.0
558      */

559     public void removeDebugEventListener(IDebugEventSetListener listener) {
560         fEventListeners.remove(listener);
561     }
562
563     /* (non-Javadoc)
564      * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
565      */

566     public void stop(BundleContext context) throws Exception JavaDoc {
567         try {
568             setShuttingDown(true);
569             
570             if (fLaunchManager != null) {
571                 fLaunchManager.shutdown();
572             }
573             if (fBreakpointManager != null) {
574                 fBreakpointManager.shutdown();
575             }
576             if (fMemoryBlockManager != null) {
577                 fMemoryBlockManager.shutdown();
578             }
579             
580             fEventListeners.clear();
581             
582             if (fEventFilters != null) {
583                 fEventFilters = null;
584             }
585             SourceLookupUtils.shutdown();
586             setDefault(null);
587             ResourcesPlugin.getWorkspace().removeSaveParticipant(this);
588             savePluginPreferences();
589         } finally {
590             super.stop(context);
591         }
592     }
593     
594     /* (non-Javadoc)
595      * @see org.eclipse.core.runtime.Plugin#start(org.osgi.framework.BundleContext)
596      */

597     public void start(BundleContext context) throws Exception JavaDoc {
598         super.start(context);
599         DebugOptions.initDebugOptions();
600         ResourcesPlugin.getWorkspace().addSaveParticipant(this,
601                 new ISaveParticipant() {
602                     public void saving(ISaveContext saveContext) throws CoreException {
603                         savePluginPreferences();
604                     }
605                     public void rollback(ISaveContext saveContext) {}
606                     public void prepareToSave(ISaveContext saveContext) throws CoreException {}
607                     public void doneSaving(ISaveContext saveContext) {}
608                 });
609         //command adapters
610
IAdapterManager manager= Platform.getAdapterManager();
611         CommandAdapterFactory actionFactory = new CommandAdapterFactory();
612         manager.registerAdapters(actionFactory, IDisconnect.class);
613         manager.registerAdapters(actionFactory, IDropToFrame.class);
614         manager.registerAdapters(actionFactory, IStep.class);
615         manager.registerAdapters(actionFactory, IStepFilters.class);
616         manager.registerAdapters(actionFactory, ISuspendResume.class);
617         manager.registerAdapters(actionFactory, ITerminate.class);
618         manager.registerAdapters(actionFactory, ILaunch.class);
619         manager.registerAdapters(actionFactory, IProcess.class);
620         manager.registerAdapters(actionFactory, IDebugElement.class);
621     }
622
623     /**
624      * Creates and returns a new process representing the given
625      * <code>java.lang.Process</code>. A streams proxy is created
626      * for the I/O streams in the system process. The process
627      * is added to the given launch.
628      * <p>
629      * If the launch configuration associated with the given launch
630      * specifies a process factory, it will be used to instantiate
631      * the new process.
632      * </p>
633      * @param launch the launch the process is contained in
634      * @param process the system process to wrap
635      * @param label the label assigned to the process
636      * @return the process
637      * @see IProcess
638      * @see IProcessFactory
639      */

640     public static IProcess newProcess(ILaunch launch, Process JavaDoc process, String JavaDoc label) {
641         return newProcess(launch, process, label, null);
642     }
643     
644     /**
645      * Creates and returns a new process representing the given
646      * <code>java.lang.Process</code>. A streams proxy is created
647      * for the I/O streams in the system process. The process
648      * is added to the given launch, and the process is initialized
649      * with the given attribute map.
650      * <p>
651      * If the launch configuration associated with the given launch
652      * specifies a process factory, it will be used to instantiate
653      * the new process.
654      * </p>
655      * @param launch the launch the process is contained in
656      * @param process the system process to wrap
657      * @param label the label assigned to the process
658      * @param attributes initial values for the attribute map
659      * @return the process <code>null</code> can be returned if errors occur dealing with the process factory
660      * designated to create the process.
661      * @see IProcess
662      * @see IProcessFactory
663      * @since 2.1
664      */

665     public static IProcess newProcess(ILaunch launch, Process JavaDoc process, String JavaDoc label, Map JavaDoc attributes) {
666         ILaunchConfiguration config= launch.getLaunchConfiguration();
667         String JavaDoc processFactoryID= null;
668         if (config != null) {
669             try {
670                 processFactoryID= config.getAttribute(ATTR_PROCESS_FACTORY_ID, (String JavaDoc)null);
671             } catch (CoreException e) {
672             }
673         }
674         if (processFactoryID != null) {
675             DebugPlugin plugin= DebugPlugin.getDefault();
676             if (plugin.fProcessFactories == null) {
677                 plugin.initializeProcessFactories();
678             }
679             IConfigurationElement element= (IConfigurationElement) plugin.fProcessFactories.get(processFactoryID);
680             if (element == null) {
681                 return null;
682             }
683             IProcessFactory processFactory= null;
684             try {
685                 processFactory = (IProcessFactory)element.createExecutableExtension("class"); //$NON-NLS-1$
686
} catch (CoreException exception) {
687                 log(exception);
688                 return null;
689             }
690             return processFactory.newProcess(launch, process, label, attributes);
691         }
692         return new RuntimeProcess(launch, process, label, attributes);
693     }
694     
695     /**
696      * Returns any logical structure types that have been contributed for the given
697      * value.
698      *
699      * @param value the value for which logical structure types have been requested
700      * @return logical structure types that have been contributed for the given
701      * value, possibly an empty collection
702      *
703      * @since 3.0
704      */

705     public static ILogicalStructureType[] getLogicalStructureTypes(IValue value) {
706         return LogicalStructureManager.getDefault().getLogicalStructureTypes(value);
707     }
708     
709     /**
710      * Returns the default logical structure type among the given combination of
711      * logical structure types, or <code>null</code> if none. When the given combination
712      * of logical structure type is applicable for a value, the default logical structure
713      * type is used to display a value.
714      *
715      * @param types a combination of structures applicable to a value
716      * @return the default structure that should be used to display the value
717      * or <code>null</code> if none
718      *
719      * @since 3.1
720      */

721     public static ILogicalStructureType getDefaultStructureType(ILogicalStructureType[] types) {
722         return LogicalStructureManager.getDefault().getSelectedStructureType(types);
723     }
724     
725     /**
726      * Sets the default logical structure type among the given combination of logical structure
727      * types. The logical structure types provided should all be applicable to a single
728      * value. Specifying <code>null</code> indicates there is no default logical structure
729      * for the given combination of types.
730      *
731      * @param types a combination of logical structure types applicable to a value
732      * @param def the default logical structure among the given combination of types
733      * or <code>null</code> if none
734      *
735      * @since 3.1
736      */

737     public static void setDefaultStructureType(ILogicalStructureType[] types, ILogicalStructureType def) {
738         LogicalStructureManager.getDefault().setEnabledType(types, def);
739     }
740     
741     /**
742      * Convenience method that performs a runtime exec on the given command line
743      * in the context of the specified working directory, and returns the
744      * resulting process. If the current runtime does not support the
745      * specification of a working directory, the status handler for error code
746      * <code>ERR_WORKING_DIRECTORY_NOT_SUPPORTED</code> is queried to see if the
747      * exec should be re-executed without specifying a working directory.
748      *
749      * @param cmdLine the command line
750      * @param workingDirectory the working directory, or <code>null</code>
751      * @return the resulting process or <code>null</code> if the exec is
752      * cancelled
753      * @exception CoreException if the exec fails
754      * @see Runtime
755      *
756      * @since 2.1
757      */

758     public static Process JavaDoc exec(String JavaDoc[] cmdLine, File JavaDoc workingDirectory) throws CoreException {
759         return exec(cmdLine, workingDirectory, null);
760     }
761
762     /**
763      * Convenience method that performs a runtime exec on the given command line
764      * in the context of the specified working directory, and returns the
765      * resulting process. If the current runtime does not support the
766      * specification of a working directory, the status handler for error code
767      * <code>ERR_WORKING_DIRECTORY_NOT_SUPPORTED</code> is queried to see if the
768      * exec should be re-executed without specifying a working directory.
769      *
770      * @param cmdLine the command line
771      * @param workingDirectory the working directory, or <code>null</code>
772      * @param envp the environment variables set in the process, or <code>null</code>
773      * @return the resulting process or <code>null</code> if the exec is
774      * cancelled
775      * @exception CoreException if the exec fails
776      * @see Runtime
777      *
778      * @since 3.0
779      */

780     public static Process JavaDoc exec(String JavaDoc[] cmdLine, File JavaDoc workingDirectory, String JavaDoc[] envp) throws CoreException {
781         Process JavaDoc p= null;
782         try {
783             if (workingDirectory == null) {
784                 p= Runtime.getRuntime().exec(cmdLine, envp);
785             } else {
786                 p= Runtime.getRuntime().exec(cmdLine, envp, workingDirectory);
787             }
788         } catch (IOException JavaDoc e) {
789             Status status = new Status(IStatus.ERROR, getUniqueIdentifier(), INTERNAL_ERROR, DebugCoreMessages.DebugPlugin_Exception_occurred_executing_command_line__1, e);
790             throw new CoreException(status);
791         } catch (NoSuchMethodError JavaDoc e) {
792             //attempting launches on 1.2.* - no ability to set working directory
793
IStatus status = new Status(IStatus.ERROR, getUniqueIdentifier(), ERR_WORKING_DIRECTORY_NOT_SUPPORTED, DebugCoreMessages.DebugPlugin_Eclipse_runtime_does_not_support_working_directory_2, e);
794             IStatusHandler handler = DebugPlugin.getDefault().getStatusHandler(status);
795             
796             if (handler != null) {
797                 Object JavaDoc result = handler.handleStatus(status, null);
798                 if (result instanceof Boolean JavaDoc && ((Boolean JavaDoc)result).booleanValue()) {
799                     p= exec(cmdLine, null);
800                 }
801             }
802         }
803         return p;
804     }
805     
806     /**
807      * Returns whether this plug-in is in the process of
808      * being shutdown.
809      *
810      * @return whether this plug-in is in the process of
811      * being shutdown
812      */

813     private boolean isShuttingDown() {
814         return fShuttingDown;
815     }
816     
817     /**
818      * Sets whether this plug-in is in the process of
819      * being shutdown.
820      *
821      * @param value whether this plug-in is in the process of
822      * being shutdown
823      */

824     private void setShuttingDown(boolean value) {
825         fShuttingDown = value;
826     }
827     
828     /**
829      * Returns the collection of debug event listeners registered
830      * with this plug-in.
831      *
832      * @return list of registered debug event listeners, instances
833      * of <code>IDebugEventSetListeners</code>
834      */

835     private Object JavaDoc[] getEventListeners() {
836         return fEventListeners.getListeners();
837     }
838     
839     /**
840      * Adds the given debug event filter to the registered
841      * event filters. Has no effect if an identical filter
842      * is already registered.
843      *
844      * @param filter debug event filter
845      * @since 2.0
846      */

847     public void addDebugEventFilter(IDebugEventFilter filter) {
848         if (fEventFilters == null) {
849             fEventFilters = new ListenerList();
850         }
851         fEventFilters.add(filter);
852     }
853     
854     /**
855      * Removes the given debug event filter from the registered
856      * event filters. Has no effect if an identical filter
857      * is not already registered.
858      *
859      * @param filter debug event filter
860      * @since 2.0
861      */

862     public void removeDebugEventFilter(IDebugEventFilter filter) {
863         if (fEventFilters != null) {
864             fEventFilters.remove(filter);
865             if (fEventFilters.size() == 0) {
866                 fEventFilters = null;
867             }
868         }
869     }
870     
871     /**
872      * Logs the given message if in debug mode.
873      *
874      * @param message the message to log
875      * @since 2.0
876      */

877     public static void logDebugMessage(String JavaDoc message) {
878         if (getDefault().isDebugging()) {
879             // this message is intentionally not externalized, as an exception may
880
// be due to the resource bundle itself
881
log(new Status(IStatus.ERROR, getUniqueIdentifier(), INTERNAL_ERROR, "Internal message logged from Debug Core: " + message, null)); //$NON-NLS-1$
882
}
883     }
884     
885     /**
886      * Logs the given message with this plug-in's log and the given
887      * throwable or <code>null</code> if none.
888      * @param message the message to log
889      * @param throwable the exception that occurred or <code>null</code> if none
890      */

891     public static void logMessage(String JavaDoc message, Throwable JavaDoc throwable) {
892         log(new Status(IStatus.ERROR, getUniqueIdentifier(), INTERNAL_ERROR, message, throwable));
893     }
894     
895     /**
896      * Logs the specified status with this plug-in's log.
897      *
898      * @param status status to log
899      * @since 2.0
900      */

901     public static void log(IStatus status) {
902         getDefault().getLog().log(status);
903     }
904     
905     /**
906      * Logs the specified throwable with this plug-in's log.
907      *
908      * @param t throwable to log
909      * @since 2.0
910      */

911     public static void log(Throwable JavaDoc t) {
912         IStatus status= new Status(IStatus.ERROR, getUniqueIdentifier(), INTERNAL_ERROR, "Error logged from Debug Core: ", t); //$NON-NLS-1$
913
log(status);
914     }
915     
916     /**
917      * Register status handlers.
918      *
919      */

920     private void initializeStatusHandlers() {
921         IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.PI_DEBUG_CORE, EXTENSION_POINT_STATUS_HANDLERS);
922         IConfigurationElement[] infos= extensionPoint.getConfigurationElements();
923         fStatusHandlers = new HashMap JavaDoc(infos.length);
924         for (int i= 0; i < infos.length; i++) {
925             IConfigurationElement configurationElement = infos[i];
926             String JavaDoc id = configurationElement.getAttribute("plugin"); //$NON-NLS-1$
927
String JavaDoc code = configurationElement.getAttribute("code"); //$NON-NLS-1$
928

929             if (id != null && code != null) {
930                 try {
931                     StatusHandlerKey key = new StatusHandlerKey(id, Integer.parseInt(code));
932                     fStatusHandlers.put(key, configurationElement);
933                 } catch (NumberFormatException JavaDoc e) {
934                     // invalid status handler
935
invalidStatusHandler(e, configurationElement.getAttribute("id")); //$NON-NLS-1$
936
}
937             } else {
938                 // invalid status handler
939
invalidStatusHandler(null, configurationElement.getAttribute("id")); //$NON-NLS-1$
940
}
941         }
942     }
943     
944     /**
945      * Register process factories.
946      *
947      */

948     private void initializeProcessFactories() {
949         IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.PI_DEBUG_CORE, EXTENSION_POINT_PROCESS_FACTORIES);
950         IConfigurationElement[] infos= extensionPoint.getConfigurationElements();
951         fProcessFactories = new HashMap JavaDoc(infos.length);
952         for (int i= 0; i < infos.length; i++) {
953             IConfigurationElement configurationElement = infos[i];
954             String JavaDoc id = configurationElement.getAttribute("id"); //$NON-NLS-1$
955
String JavaDoc clss = configurationElement.getAttribute("class"); //$NON-NLS-1$
956
if (id != null && clss != null) {
957                     fProcessFactories.put(id, configurationElement);
958             } else {
959                 // invalid process factory
960
String JavaDoc badDefiner= infos[i].getContributor().getName();
961                 log(new Status(IStatus.ERROR, DebugPlugin.PI_DEBUG_CORE, INTERNAL_ERROR, MessageFormat.format("Invalid process factory extension contributed by {0}; id: {1}", new String JavaDoc[] {badDefiner, id}), null)); //$NON-NLS-1$
962
}
963         }
964     }
965     
966     private void invalidStatusHandler(Exception JavaDoc e, String JavaDoc id) {
967         log(new Status(IStatus.ERROR, DebugPlugin.PI_DEBUG_CORE, INTERNAL_ERROR, MessageFormat.format("Invalid status handler extension: {0}", new String JavaDoc[] {id}), e)); //$NON-NLS-1$
968
}
969     
970     /**
971      * Key for status handler extensions - a plug-in identifier/code pair
972      */

973     class StatusHandlerKey {
974         
975         String JavaDoc fPluginId;
976         int fCode;
977         
978         StatusHandlerKey(String JavaDoc pluginId, int code) {
979             fPluginId = pluginId;
980             fCode = code;
981         }
982         
983         public int hashCode() {
984             return fPluginId.hashCode() + fCode;
985         }
986         
987         public boolean equals(Object JavaDoc obj) {
988             if (obj instanceof StatusHandlerKey) {
989                 StatusHandlerKey s = (StatusHandlerKey)obj;
990                 return fCode == s.fCode && fPluginId.equals(s.fPluginId);
991             }
992             return false;
993         }
994     }
995
996     /**
997      * Returns whether any event filters are registered
998      *
999      * @return whether any event filters are registered
1000     */

1001    private boolean hasEventFilters() {
1002        return fEventFilters != null && fEventFilters.size() > 0;
1003    }
1004    
1005    /**
1006     * Executes runnables after event dispatch is complete.
1007     *
1008     * @since 3.0
1009     */

1010    class AsynchRunner implements ISafeRunnable {
1011        
1012        private Runnable JavaDoc fRunnable = null;
1013        
1014        void async(Runnable JavaDoc runnable) {
1015            fRunnable = runnable;
1016            SafeRunner.run(this);
1017            fRunnable = null;
1018            
1019        }
1020
1021        /* (non-Javadoc)
1022         * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
1023         */

1024        public void handleException(Throwable JavaDoc exception) {
1025            IStatus status = new Status(IStatus.ERROR, getUniqueIdentifier(), INTERNAL_ERROR, "An exception occurred in asynchronous runnable.", exception); //$NON-NLS-1$
1026
log(status);
1027        }
1028
1029        /* (non-Javadoc)
1030         * @see org.eclipse.core.runtime.ISafeRunnable#run()
1031         */

1032        public void run() throws Exception JavaDoc {
1033            fRunnable.run();
1034        }
1035
1036    }
1037    
1038    /**
1039     * Filters and dispatches events in a safe runnable to handle any
1040     * exceptions.
1041     */

1042    class EventNotifier implements ISafeRunnable {
1043        
1044        private DebugEvent[] fEvents;
1045        private IDebugEventSetListener fListener;
1046        private IDebugEventFilter fFilter;
1047        private int fMode;
1048        
1049        /**
1050         * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
1051         */

1052        public void handleException(Throwable JavaDoc exception) {
1053            switch (fMode) {
1054                case NOTIFY_FILTERS:
1055                    IStatus status = new Status(IStatus.ERROR, getUniqueIdentifier(), INTERNAL_ERROR, "An exception occurred while filtering debug events.", exception); //$NON-NLS-1$
1056
log(status);
1057                    break;
1058                case NOTIFY_EVENTS:
1059                    status = new Status(IStatus.ERROR, getUniqueIdentifier(), INTERNAL_ERROR, "An exception occurred while dispatching debug events.", exception); //$NON-NLS-1$
1060
log(status);
1061                    break;
1062            }
1063        }
1064
1065        /**
1066         * @see org.eclipse.core.runtime.ISafeRunnable#run()
1067         */

1068        public void run() throws Exception JavaDoc {
1069            switch (fMode) {
1070                case NOTIFY_FILTERS:
1071                    fEvents = fFilter.filterDebugEvents(fEvents);
1072                    break;
1073                case NOTIFY_EVENTS:
1074                    fListener.handleDebugEvents(fEvents);
1075                    break;
1076            }
1077        }
1078        
1079        /**
1080         * Filter and dispatch the given events. If an exception occurs in one
1081         * listener, events are still fired to subsequent listeners.
1082         *
1083         * @param events debug events
1084         */

1085        void dispatch(DebugEvent[] events) {
1086            fEvents = events;
1087            if (hasEventFilters()) {
1088                fMode = NOTIFY_FILTERS;
1089                Object JavaDoc[] filters = fEventFilters.getListeners();
1090                for (int i = 0; i < filters.length; i++) {
1091                    fFilter = (IDebugEventFilter)filters[i];
1092                    SafeRunner.run(this);
1093                    if (fEvents == null || fEvents.length == 0) {
1094                        return;
1095                    }
1096                }
1097            }
1098            
1099            fMode = NOTIFY_EVENTS;
1100            Object JavaDoc[] listeners= getEventListeners();
1101            if (DebugOptions.DEBUG_EVENTS) {
1102                for (int i = 0; i < fEvents.length; i++) {
1103                    System.out.println(fEvents[i]);
1104                }
1105            }
1106            for (int i= 0; i < listeners.length; i++) {
1107                fListener = (IDebugEventSetListener)listeners[i];
1108                SafeRunner.run(this);
1109            }
1110            fEvents = null;
1111            fFilter = null;
1112            fListener = null;
1113        }
1114
1115    }
1116
1117    /**
1118     * Creates and returns a new XML document.
1119     *
1120     * @return a new XML document
1121     * @throws CoreException if unable to create a new document
1122     * @since 3.0
1123     */

1124    public static Document JavaDoc newDocument()throws CoreException {
1125        try {
1126            return LaunchManager.getDocument();
1127        } catch (ParserConfigurationException JavaDoc e) {
1128            abort(SourceLookupMessages.SourceLookupUtils_3, e);
1129        }
1130        return null;
1131    }
1132    
1133    /**
1134     * Serializes the given XML document into a string.
1135     *
1136     * @param document XML document to serialize
1137     * @return a string representing the given document
1138     * @throws CoreException if unable to serialize the document
1139     * @since 3.0
1140     */

1141    public static String JavaDoc serializeDocument(Document JavaDoc document) throws CoreException {
1142        try {
1143            return LaunchManager.serializeDocument(document);
1144        } catch (TransformerException JavaDoc e) {
1145            abort(SourceLookupMessages.SourceLookupUtils_4, e);
1146        } catch (IOException JavaDoc e) {
1147            abort(SourceLookupMessages.SourceLookupUtils_5, e);
1148        }
1149        return null;
1150    }
1151
1152    /**
1153     * Parses the given string representing an XML document, returning its
1154     * root element.
1155     *
1156     * @param document XML document as a string
1157     * @return the document's root element
1158     * @throws CoreException if unable to parse the document
1159     * @since 3.0
1160     */

1161    public static Element parseDocument(String JavaDoc document) throws CoreException {
1162        Element root = null;
1163        InputStream JavaDoc stream = null;
1164        try{
1165            DocumentBuilder JavaDoc parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
1166            parser.setErrorHandler(new DefaultHandler JavaDoc());
1167            stream = new ByteArrayInputStream JavaDoc(document.getBytes());
1168            root = parser.parse(stream).getDocumentElement();
1169        } catch (ParserConfigurationException JavaDoc e) {
1170            abort(SourceLookupMessages.SourceLookupUtils_6, e);
1171        } catch (FactoryConfigurationError JavaDoc e) {
1172            abort(SourceLookupMessages.SourceLookupUtils_7, e);
1173        } catch (SAXException JavaDoc e) {
1174            abort(SourceLookupMessages.SourceLookupUtils_8, e);
1175        } catch (IOException JavaDoc e) {
1176            abort(SourceLookupMessages.SourceLookupUtils_9, e);
1177        } finally {
1178            try{
1179                if (stream != null) {
1180                    stream.close();
1181                }
1182            } catch(IOException JavaDoc e) {
1183                abort(SourceLookupMessages.SourceLookupUtils_10, e);
1184            }
1185        }
1186        return root;
1187    }
1188    
1189    /**
1190     * Throws an exception with the given message and underlying exception.
1191     *
1192     * @param message error message
1193     * @param exception underlying exception, or <code>null</code>
1194     * @throws CoreException
1195     */

1196    private static void abort(String JavaDoc message, Throwable JavaDoc exception) throws CoreException {
1197        IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, message, exception);
1198        throw new CoreException(status);
1199    }
1200    
1201    /**
1202     * Utility class to parse command line arguments.
1203     *
1204     * @since 3.1
1205     */

1206    private static class ArgumentParser {
1207        private String JavaDoc fArgs;
1208        private int fIndex= 0;
1209        private int ch= -1;
1210        
1211        public ArgumentParser(String JavaDoc args) {
1212            fArgs= args;
1213        }
1214        
1215        public String JavaDoc[] parseArguments() {
1216            List JavaDoc v= new ArrayList JavaDoc();
1217            
1218            ch= getNext();
1219            while (ch > 0) {
1220                if (Character.isWhitespace((char)ch)) {
1221                    ch= getNext();
1222                } else {
1223                    if (ch == '"') {
1224                        StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
1225                        buf.append(parseString());
1226                        if (buf.length() == 0 && Platform.getOS().equals(Constants.OS_WIN32)) {
1227                            // empty string on windows platform
1228
buf.append("\"\""); //$NON-NLS-1$
1229
}
1230                        v.add(buf.toString());
1231                    } else {
1232                        v.add(parseToken());
1233                    }
1234                }
1235            }
1236    
1237            String JavaDoc[] result= new String JavaDoc[v.size()];
1238            v.toArray(result);
1239            return result;
1240        }
1241        
1242        private int getNext() {
1243            if (fIndex < fArgs.length())
1244                return fArgs.charAt(fIndex++);
1245            return -1;
1246        }
1247        
1248        private String JavaDoc parseString() {
1249            ch= getNext();
1250            if (ch == '"') {
1251                ch= getNext();
1252                return ""; //$NON-NLS-1$
1253
}
1254            StringBuffer JavaDoc buf= new StringBuffer JavaDoc();
1255            while (ch > 0 && ch != '"') {
1256                if (ch == '\\') {
1257                    ch= getNext();
1258                    if (ch != '"') { // Only escape double quotes
1259
buf.append('\\');
1260                    } else {
1261                        if (Platform.getOS().equals(Constants.OS_WIN32)) {
1262                            // @see Bug 26870. Windows requires an extra escape for embedded strings
1263
buf.append('\\');
1264                        }
1265                    }
1266                }
1267                if (ch > 0) {
1268                    buf.append((char)ch);
1269                    ch= getNext();
1270                }
1271            }
1272            ch= getNext();
1273            return buf.toString();
1274        }
1275        
1276        private String JavaDoc parseToken() {
1277            StringBuffer JavaDoc buf= new StringBuffer JavaDoc();
1278            
1279            while (ch > 0 && !Character.isWhitespace((char)ch)) {
1280                if (ch == '\\') {
1281                    ch= getNext();
1282                    if (Character.isWhitespace((char)ch)) {
1283                        // end of token, don't lose trailing backslash
1284
buf.append('\\');
1285                        return buf.toString();
1286                    }
1287                    if (ch > 0) {
1288                        if (ch != '"') { // Only escape double quotes
1289
buf.append('\\');
1290                        } else {
1291                            if (Platform.getOS().equals(Constants.OS_WIN32)) {
1292                                // @see Bug 26870. Windows requires an extra escape for embedded strings
1293
buf.append('\\');
1294                            }
1295                        }
1296                        buf.append((char)ch);
1297                        ch= getNext();
1298                    } else if (ch == -1) { // Don't lose a trailing backslash
1299
buf.append('\\');
1300                    }
1301                } else if (ch == '"') {
1302                    buf.append(parseString());
1303                } else {
1304                    buf.append((char)ch);
1305                    ch= getNext();
1306                }
1307            }
1308            return buf.toString();
1309        }
1310    }
1311    
1312    /**
1313     * Parses the given command line into separate arguments that can be passed to
1314     * <code>DebugPlugin.exec(String[], File)</code>. Embedded quotes and slashes
1315     * are escaped.
1316     *
1317     * @param args command line arguments as a single string
1318     * @return individual arguments
1319     * @since 3.1
1320     */

1321    public static String JavaDoc[] parseArguments(String JavaDoc args) {
1322        if (args == null)
1323            return new String JavaDoc[0];
1324        ArgumentParser parser= new ArgumentParser(args);
1325        String JavaDoc[] res= parser.parseArguments();
1326        
1327        return res;
1328    }
1329    
1330    /**
1331     * Sets whether step filters should be applied to step commands. This
1332     * setting is a global option applied to all registered debug targets.
1333     *
1334     * @param useStepFilters whether step filters should be applied to step
1335     * commands
1336     * @since 3.3
1337     * @see org.eclipse.debug.core.model.IStepFilters
1338     */

1339    public static void setUseStepFilters(boolean useStepFilters) {
1340        getStepFilterManager().setUseStepFilters(useStepFilters);
1341    }
1342        
1343    /**
1344     * Returns whether step filters are applied to step commands.
1345     *
1346     * @return whether step filters are applied to step commands
1347     * @since 3.3
1348     * @see org.eclipse.debug.core.model.IStepFilters
1349     * @see org.eclipse.debug.core.commands.IStepFiltersHandler
1350     */

1351    public static boolean isUseStepFilters() {
1352        return getStepFilterManager().isUseStepFilters();
1353    }
1354    
1355    /**
1356     * Returns the step filter manager.
1357     *
1358     * @return step filter manager
1359     */

1360    private static StepFilterManager getStepFilterManager() {
1361        return ((LaunchManager)getDefault().getLaunchManager()).getStepFilterManager();
1362    }
1363    
1364}
1365
1366
1367
Popular Tags