KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > debug > internal > core > LaunchManager


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  * Sebastian Davids - bug 50567 Eclipse native environment support on Win98
11  * Pawel Piech - Bug 82001: When shutting down the IDE, the debugger should first
12  * attempt to disconnect debug targets before terminating them
13  *******************************************************************************/

14 package org.eclipse.debug.internal.core;
15
16
17 import java.io.BufferedInputStream JavaDoc;
18 import java.io.BufferedReader JavaDoc;
19 import java.io.ByteArrayOutputStream JavaDoc;
20 import java.io.File JavaDoc;
21 import java.io.FileInputStream JavaDoc;
22 import java.io.FileNotFoundException JavaDoc;
23 import java.io.FilenameFilter JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.InputStreamReader JavaDoc;
27 import java.util.ArrayList JavaDoc;
28 import java.util.Arrays JavaDoc;
29 import java.util.Collection JavaDoc;
30 import java.util.Comparator JavaDoc;
31 import java.util.Enumeration JavaDoc;
32 import java.util.HashMap JavaDoc;
33 import java.util.HashSet JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Map JavaDoc;
37 import java.util.Properties JavaDoc;
38 import java.util.Set JavaDoc;
39 import java.util.Map.Entry;
40
41 import javax.xml.parsers.DocumentBuilder JavaDoc;
42 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
43 import javax.xml.parsers.ParserConfigurationException JavaDoc;
44 import javax.xml.transform.OutputKeys JavaDoc;
45 import javax.xml.transform.Transformer JavaDoc;
46 import javax.xml.transform.TransformerException JavaDoc;
47 import javax.xml.transform.TransformerFactory JavaDoc;
48 import javax.xml.transform.dom.DOMSource JavaDoc;
49 import javax.xml.transform.stream.StreamResult JavaDoc;
50
51 import org.eclipse.core.resources.IContainer;
52 import org.eclipse.core.resources.IFile;
53 import org.eclipse.core.resources.IProject;
54 import org.eclipse.core.resources.IResource;
55 import org.eclipse.core.resources.IResourceChangeEvent;
56 import org.eclipse.core.resources.IResourceChangeListener;
57 import org.eclipse.core.resources.IResourceDelta;
58 import org.eclipse.core.resources.IResourceDeltaVisitor;
59 import org.eclipse.core.resources.IResourceProxy;
60 import org.eclipse.core.resources.IResourceProxyVisitor;
61 import org.eclipse.core.resources.ResourcesPlugin;
62 import org.eclipse.core.runtime.CoreException;
63 import org.eclipse.core.runtime.IConfigurationElement;
64 import org.eclipse.core.runtime.IExtensionPoint;
65 import org.eclipse.core.runtime.IPath;
66 import org.eclipse.core.runtime.ISafeRunnable;
67 import org.eclipse.core.runtime.IStatus;
68 import org.eclipse.core.runtime.ListenerList;
69 import org.eclipse.core.runtime.Platform;
70 import org.eclipse.core.runtime.PlatformObject;
71 import org.eclipse.core.runtime.Preferences;
72 import org.eclipse.core.runtime.SafeRunner;
73 import org.eclipse.core.runtime.Status;
74 import org.eclipse.core.variables.VariablesPlugin;
75 import org.eclipse.debug.core.DebugException;
76 import org.eclipse.debug.core.DebugPlugin;
77 import org.eclipse.debug.core.ILaunch;
78 import org.eclipse.debug.core.ILaunchConfiguration;
79 import org.eclipse.debug.core.ILaunchConfigurationListener;
80 import org.eclipse.debug.core.ILaunchConfigurationType;
81 import org.eclipse.debug.core.ILaunchDelegate;
82 import org.eclipse.debug.core.ILaunchListener;
83 import org.eclipse.debug.core.ILaunchManager;
84 import org.eclipse.debug.core.ILaunchMode;
85 import org.eclipse.debug.core.ILaunchesListener;
86 import org.eclipse.debug.core.ILaunchesListener2;
87 import org.eclipse.debug.core.model.IDebugTarget;
88 import org.eclipse.debug.core.model.IDisconnect;
89 import org.eclipse.debug.core.model.IPersistableSourceLocator;
90 import org.eclipse.debug.core.model.IProcess;
91 import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector;
92 import org.eclipse.debug.core.sourcelookup.ISourceContainerType;
93 import org.eclipse.debug.core.sourcelookup.ISourcePathComputer;
94 import org.eclipse.debug.internal.core.sourcelookup.SourceContainerType;
95 import org.eclipse.debug.internal.core.sourcelookup.SourcePathComputer;
96 import org.eclipse.osgi.service.environment.Constants;
97 import org.w3c.dom.Document JavaDoc;
98 import org.w3c.dom.Element JavaDoc;
99 import org.w3c.dom.Node JavaDoc;
100 import org.w3c.dom.NodeList JavaDoc;
101 import org.xml.sax.InputSource JavaDoc;
102 import org.xml.sax.SAXException JavaDoc;
103 import org.xml.sax.helpers.DefaultHandler JavaDoc;
104
105 import com.ibm.icu.text.MessageFormat;
106
107 /**
108  * Manages launch configurations, launch configuration types, and registered launches.
109  *
110  * @see ILaunchManager
111  */

112 public class LaunchManager extends PlatformObject implements ILaunchManager, IResourceChangeListener {
113     
114     protected static final String JavaDoc PREF_PREFERRED_DELEGATES = DebugPlugin.getUniqueIdentifier() + ".PREFERRED_DELEGATES"; //$NON-NLS-1$
115

116     /**
117      * Boolean preference on whether to delete associated configurations when a project is deleted.
118      *
119      * @since 3.3
120      */

121     public static final String JavaDoc PREF_DELETE_CONFIGS_ON_PROJECT_DELETE = DebugPlugin.getUniqueIdentifier() + ".PREF_DELETE_CONFIGS_ON_PROJECT_DELETE"; //$NON-NLS-1$
122

123     /**
124      * Constant to define debug.ui for the status codes
125      *
126      * @since 3.2
127      */

128     private static final String JavaDoc DEBUG_UI = "org.eclipse.debug.ui"; //$NON-NLS-1$
129

130     /**
131      * Constant to represent the empty string
132      *
133      * @since 3.2
134      */

135     protected static final String JavaDoc EMPTY_STRING = ""; //$NON-NLS-1$
136

137     /**
138      * Status code for which a UI prompter is registered.
139      *
140      * @since 3.2
141      */

142     protected static final IStatus promptStatus = new Status(IStatus.INFO, DEBUG_UI, 200, EMPTY_STRING, null);
143     
144     /**
145      * Step filter manager
146      */

147     private StepFilterManager fStepFilterManager = null;
148     
149     /**
150      * Notifies a launch config listener in a safe runnable to handle
151      * exceptions.
152      */

153     class ConfigurationNotifier implements ISafeRunnable {
154         
155         private ILaunchConfigurationListener fListener;
156         private int fType;
157         private ILaunchConfiguration fConfiguration;
158         
159         /**
160          * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
161          */

162         public void handleException(Throwable JavaDoc exception) {
163             IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during launch configuration change notification.", exception); //$NON-NLS-1$
164
DebugPlugin.log(status);
165         }
166
167         /**
168          * Notifies the given listener of the add/change/remove
169          *
170          * @param configuration the configuration that has changed
171          * @param update the type of change
172          */

173         public void notify(ILaunchConfiguration configuration, int update) {
174             fConfiguration = configuration;
175             fType = update;
176             if (fLaunchConfigurationListeners.size() > 0) {
177                 Object JavaDoc[] listeners = fLaunchConfigurationListeners.getListeners();
178                 for (int i = 0; i < listeners.length; i++) {
179                     fListener = (ILaunchConfigurationListener)listeners[i];
180                     SafeRunner.run(this);
181                 }
182             }
183             fConfiguration = null;
184             fListener = null;
185         }
186
187         /**
188          * @see org.eclipse.core.runtime.ISafeRunnable#run()
189          */

190         public void run() throws Exception JavaDoc {
191             switch (fType) {
192                 case ADDED:
193                     fListener.launchConfigurationAdded(fConfiguration);
194                     break;
195                 case REMOVED:
196                     fListener.launchConfigurationRemoved(fConfiguration);
197                     break;
198                 case CHANGED:
199                     fListener.launchConfigurationChanged(fConfiguration);
200                     break;
201             }
202         }
203     }
204     
205     /**
206      * Notifies a launch listener (multiple launches) in a safe runnable to
207      * handle exceptions.
208      */

209     class LaunchesNotifier implements ISafeRunnable {
210         
211         private ILaunchesListener fListener;
212         private int fType;
213         private ILaunch[] fNotifierLaunches;
214         private ILaunch[] fRegistered;
215         
216         /**
217          * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
218          */

219         public void handleException(Throwable JavaDoc exception) {
220             IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during launch change notification.", exception); //$NON-NLS-1$
221
DebugPlugin.log(status);
222         }
223
224         /**
225          * Notifies the given listener of the adds/changes/removes
226          *
227          * @param launches the launches that changed
228          * @param update the type of change
229          */

230         public void notify(ILaunch[] launches, int update) {
231             fNotifierLaunches = launches;
232             fType = update;
233             fRegistered = null;
234             Object JavaDoc[] copiedListeners= fLaunchesListeners.getListeners();
235             for (int i= 0; i < copiedListeners.length; i++) {
236                 fListener = (ILaunchesListener)copiedListeners[i];
237                 SafeRunner.run(this);
238             }
239             fNotifierLaunches = null;
240             fRegistered = null;
241             fListener = null;
242         }
243
244         /**
245          * @see org.eclipse.core.runtime.ISafeRunnable#run()
246          */

247         public void run() throws Exception JavaDoc {
248             switch (fType) {
249                 case ADDED:
250                     fListener.launchesAdded(fNotifierLaunches);
251                     break;
252                 case REMOVED:
253                     fListener.launchesRemoved(fNotifierLaunches);
254                     break;
255                 case CHANGED:
256                 case TERMINATE:
257                     if (fRegistered == null) {
258                         List JavaDoc registered = null;
259                         for (int j = 0; j < fNotifierLaunches.length; j++) {
260                             if (isRegistered(fNotifierLaunches[j])) {
261                                 if (registered != null) {
262                                     registered.add(fNotifierLaunches[j]);
263                                 }
264                             } else {
265                                 if (registered == null) {
266                                     registered = new ArrayList JavaDoc(fNotifierLaunches.length);
267                                     for (int k = 0; k < j; k++) {
268                                         registered.add(fNotifierLaunches[k]);
269                                     }
270                                 }
271                             }
272                         }
273                         if (registered == null) {
274                             fRegistered = fNotifierLaunches;
275                         } else {
276                             fRegistered = (ILaunch[])registered.toArray(new ILaunch[registered.size()]);
277                         }
278                     }
279                     if (fRegistered.length > 0) {
280                         if (fType == CHANGED) {
281                             fListener.launchesChanged(fRegistered);
282                         }
283                         if (fType == TERMINATE && fListener instanceof ILaunchesListener2) {
284                             ((ILaunchesListener2)fListener).launchesTerminated(fRegistered);
285                         }
286                     }
287                     break;
288             }
289         }
290     }
291     
292     /**
293      * Visitor for handling resource deltas.
294      */

295     class LaunchManagerVisitor implements IResourceDeltaVisitor {
296         
297         /**
298          * Map of files to associated (shared) launch configurations in a project
299          * that is going to be deleted.
300          */

301         private Map JavaDoc fFileToConfig = new HashMap JavaDoc();
302         
303         
304         /**
305          * Builds a cache of configurations that will be deleted in the given project
306          *
307          * @param project project that is going to be deleted
308          */

309         public void preDelete(IProject project) {
310             List JavaDoc list = findLaunchConfigurations(project);
311             Iterator JavaDoc configs = list.iterator();
312             while (configs.hasNext()) {
313                 ILaunchConfiguration configuration = (ILaunchConfiguration) configs.next();
314                 IFile file = configuration.getFile();
315                 if (file != null) {
316                     fFileToConfig.put(file, configuration);
317                 }
318             }
319         }
320         
321         /**
322          * Resets this resource delta visitor for a new pass.
323          */

324         public void reset() {
325               fFileToConfig.clear();
326         }
327
328         /**
329          * @see IResourceDeltaVisitor#visit(IResourceDelta)
330          */

331         public boolean visit(IResourceDelta delta) {
332             if (delta == null) {
333                 return false;
334             }
335             if (0 != (delta.getFlags() & IResourceDelta.OPEN)) {
336                 if (delta.getResource() instanceof IProject) {
337                     IProject project = (IProject)delta.getResource();
338                     
339                     if (project.isOpen()) {
340                         LaunchManager.this.projectOpened(project);
341                     } else {
342                         LaunchManager.this.projectClosed(project);
343                     }
344                 }
345                 return false;
346             }
347             IResource resource = delta.getResource();
348             if (resource instanceof IFile) {
349                 IFile file = (IFile)resource;
350                 if (ILaunchConfiguration.LAUNCH_CONFIGURATION_FILE_EXTENSION.equals(file.getFileExtension())) {
351                     IPath configPath = file.getLocation();
352                     ILaunchConfiguration handle = null;
353                     // If the file has already been deleted, reconstruct the handle from our cache
354
if (configPath == null) {
355                         handle = (ILaunchConfiguration) fFileToConfig.get(file);
356                     } else {
357                         handle = new LaunchConfiguration(configPath);
358                     }
359                     if (handle != null) {
360                         switch (delta.getKind()) {
361                             case IResourceDelta.ADDED :
362                                 LaunchManager.this.launchConfigurationAdded(handle);
363                                 break;
364                             case IResourceDelta.REMOVED :
365                                 LaunchManager.this.launchConfigurationDeleted(handle);
366                                 break;
367                             case IResourceDelta.CHANGED :
368                                 LaunchManager.this.launchConfigurationChanged(handle);
369                                 break;
370                         }
371                     }
372                 }
373                 return false;
374             } else if (resource instanceof IProject) {
375                 if (isDeleteConfigurations()) {
376                     if(delta.getKind() == IResourceDelta.REMOVED && delta.getFlags() != IResourceDelta.MOVED_TO) {
377                         IProject project = (IProject) resource;
378                         ArrayList JavaDoc configs = collectAssociatedLaunches(project);
379                         if(configs.size() > 0) {
380                             for(Iterator JavaDoc iter = configs.iterator(); iter.hasNext();) {
381                                 try {
382                                     ((ILaunchConfiguration)iter.next()).delete();
383                                 } catch (CoreException e) {
384                                     DebugPlugin.log(e.getStatus());
385                                 }
386                             }
387                         }
388                     }
389                 }
390             }
391             return true;
392         }
393     }
394     
395     /**
396      * Notifies a launch listener (single launch) in a safe runnable to handle
397      * exceptions.
398      */

399     class LaunchNotifier implements ISafeRunnable {
400         
401         private ILaunchListener fListener;
402         private int fType;
403         private ILaunch fLaunch;
404         
405         /**
406          * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable)
407          */

408         public void handleException(Throwable JavaDoc exception) {
409             IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.INTERNAL_ERROR, "An exception occurred during launch change notification.", exception); //$NON-NLS-1$
410
DebugPlugin.log(status);
411         }
412
413         /**
414          * Notifies listeners of the add/change/remove
415          *
416          * @param launch the launch that has changed
417          * @param update the type of change
418          */

419         public void notify(ILaunch launch, int update) {
420             fLaunch = launch;
421             fType = update;
422             Object JavaDoc[] copiedListeners= fListeners.getListeners();
423             for (int i= 0; i < copiedListeners.length; i++) {
424                 fListener = (ILaunchListener)copiedListeners[i];
425                 SafeRunner.run(this);
426             }
427             fLaunch = null;
428             fListener = null;
429         }
430
431         /**
432          * @see org.eclipse.core.runtime.ISafeRunnable#run()
433          */

434         public void run() throws Exception JavaDoc {
435             switch (fType) {
436                 case ADDED:
437                     fListener.launchAdded(fLaunch);
438                     break;
439                 case REMOVED:
440                     fListener.launchRemoved(fLaunch);
441                     break;
442                 case CHANGED:
443                     if (isRegistered(fLaunch)) {
444                         fListener.launchChanged(fLaunch);
445                     }
446                     break;
447             }
448         }
449     }
450     
451     /**
452      * Collects files whose extension matches the launch configuration file
453      * extension.
454      */

455     class ResourceProxyVisitor implements IResourceProxyVisitor {
456         
457         private List JavaDoc fList;
458         
459         protected ResourceProxyVisitor(List JavaDoc list) {
460             fList= list;
461         }
462         /**
463          * @see org.eclipse.core.resources.IResourceProxyVisitor#visit(org.eclipse.core.resources.IResourceProxy)
464          */

465         public boolean visit(IResourceProxy proxy) {
466             if (proxy.getType() == IResource.FILE) {
467                 if (ILaunchConfiguration.LAUNCH_CONFIGURATION_FILE_EXTENSION.equalsIgnoreCase(proxy.requestFullPath().getFileExtension())) {
468                     fList.add(proxy.requestResource());
469                 }
470                 return false;
471             }
472             return true;
473         }
474     }
475     
476     /**
477      * Internal class used to hold information about a preferred delegate
478      *
479      * @since 3.3
480      */

481     class PreferredDelegate {
482         private ILaunchDelegate fDelegate = null;
483         private String JavaDoc fTypeid = null;
484         private Set JavaDoc fModes = null;
485         
486         public PreferredDelegate(ILaunchDelegate delegate, String JavaDoc typeid, Set JavaDoc modes) {
487             fDelegate = delegate;
488             fTypeid = typeid;
489             fModes = modes;
490         }
491         
492         public String JavaDoc getTypeId() {
493             return fTypeid;
494         }
495         
496         public Set JavaDoc getModes() {
497             return fModes;
498         }
499         
500         public ILaunchDelegate getDelegate() {
501             return fDelegate;
502         }
503     }
504     
505     /**
506      * Types of notifications
507      */

508     public static final int ADDED = 0;
509     public static final int REMOVED= 1;
510     public static final int CHANGED= 2;
511     public static final int TERMINATE= 3;
512     
513     /**
514      * The collection of native environment variables on the user's system. Cached
515      * after being computed once as the environment cannot change.
516      */

517     private static HashMap JavaDoc fgNativeEnv= null;
518     private static HashMap JavaDoc fgNativeEnvCasePreserved= null;
519     
520     /**
521      * Path to the local directory where local launch configurations
522      * are stored with the workspace.
523      */

524     protected static final IPath LOCAL_LAUNCH_CONFIGURATION_CONTAINER_PATH =
525         DebugPlugin.getDefault().getStateLocation().append(".launches"); //$NON-NLS-1$
526
/**
527      * Returns a Document that can be used to build a DOM tree
528      * @return the Document
529      * @throws ParserConfigurationException if an exception occurs creating the document builder
530      * @since 3.0
531      */

532     public static Document JavaDoc getDocument() throws ParserConfigurationException JavaDoc {
533         DocumentBuilderFactory JavaDoc dfactory= DocumentBuilderFactory.newInstance();
534         DocumentBuilder JavaDoc docBuilder= dfactory.newDocumentBuilder();
535         Document JavaDoc doc= docBuilder.newDocument();
536         return doc;
537     }
538
539     /**
540      * Serializes a XML document into a string - encoded in UTF8 format,
541      * with platform line separators.
542      *
543      * @param doc document to serialize
544      * @return the document as a string
545      * @throws TransformerException if an unrecoverable error occurs during the serialization
546      * @throws IOException if the encoding attempted to be used is not supported
547      */

548     public static String JavaDoc serializeDocument(Document JavaDoc doc) throws TransformerException JavaDoc, IOException JavaDoc {
549         ByteArrayOutputStream JavaDoc s = new ByteArrayOutputStream JavaDoc();
550         TransformerFactory JavaDoc factory = TransformerFactory.newInstance();
551         Transformer JavaDoc transformer = factory.newTransformer();
552         transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
553
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
554
DOMSource JavaDoc source = new DOMSource JavaDoc(doc);
555         StreamResult JavaDoc outputTarget = new StreamResult JavaDoc(s);
556         transformer.transform(source, outputTarget);
557         return s.toString("UTF8"); //$NON-NLS-1$
558
}
559     
560     /**
561      * Collection of defined launch configuration type
562      * extensions.
563      */

564     private List JavaDoc fLaunchConfigurationTypes = null;
565
566     /**
567      * Launch configuration cache. Keys are <code>LaunchConfiguration</code>,
568      * values are <code>LaunchConfigurationInfo</code>.
569      */

570     private Map JavaDoc fLaunchConfigurations = new HashMap JavaDoc(10);
571     
572     /**
573      * A cache of launch configuration names currently in the workspace.
574      */

575     private String JavaDoc[] fSortedConfigNames = null;
576     
577     /**
578      * Collection of all launch configurations in the workspace.
579      * <code>List</code> of <code>ILaunchConfiguration</code>.
580      */

581     private List JavaDoc fLaunchConfigurationIndex = null;
582     
583     /**
584      * Launch configuration comparator extensions,
585      * keyed by attribute name.
586      */

587     private Map JavaDoc fComparators = null;
588     
589     /**
590      * Registered launch modes, or <code>null</code> if not initialized.
591      * Keys are mode identifiers, values are <code>ILaunchMode</code>s.
592      */

593     private Map JavaDoc fLaunchModes = null;
594         
595     /**
596      * A map of LaunchDelegate objects stored by id of delegate, or launch config type
597      */

598     private HashMap JavaDoc fLaunchDelegates = null;
599     
600     /**
601      * Initial startup cache of preferred delegate so that the debug preferences are only parsed once
602      *
603      * @since 3.3
604      */

605     private Set JavaDoc fPreferredDelegates = null;
606     
607     /**
608      * Collection of launches
609      */

610     private List JavaDoc fLaunches= new ArrayList JavaDoc(10);
611     /**
612      * Set of launches for efficient 'isRegistered()' check
613      */

614     private Set JavaDoc fLaunchSet = new HashSet JavaDoc(10);
615     
616     /**
617      * Collection of listeners
618      */

619     private ListenerList fListeners = new ListenerList();
620     
621     /**
622      * Collection of "plural" listeners.
623      * @since 2.1
624      */

625     private ListenerList fLaunchesListeners = new ListenerList();
626     
627     /**
628      * Visitor used to process resource deltas,
629      * to update launch configuration index.
630      */

631     private LaunchManagerVisitor fgVisitor;
632     
633     /**
634      * Whether this manager is listening for resource change events
635      */

636     private boolean fListening = false;
637     
638     /**
639      * Launch configuration listeners
640      */

641     private ListenerList fLaunchConfigurationListeners = new ListenerList();
642             
643     /**
644      * Table of source locator extensions. Keys
645      * are identifiers, and values are associated
646      * configuration elements.
647      */

648     private Map JavaDoc fSourceLocators = null;
649
650     /**
651      * The handles of launch configurations being moved, or <code>null</code>
652      */

653     private ILaunchConfiguration fFrom;
654     
655     private ILaunchConfiguration fTo;
656
657     /**
658      * Map of source container type extensions. Keys are extension ids
659      * and values are associated configuration elements.
660      */

661     private Map JavaDoc sourceContainerTypes;
662     
663     /**
664      * Map of source path computer extensions. Keys are extension ids
665      * and values are associated configuration elements.
666      */

667     private Map JavaDoc sourcePathComputers;
668
669     /**
670      * @see ILaunchManager#addLaunch(ILaunch)
671      */

672     public void addLaunch(ILaunch launch) {
673         if (internalAddLaunch(launch)) {
674             fireUpdate(launch, ADDED);
675             fireUpdate(new ILaunch[] {launch}, ADDED);
676         }
677     }
678         
679     /**
680      * @see ILaunchManager#addLaunchConfigurationListener(ILaunchConfigurationListener)
681      */

682     public void addLaunchConfigurationListener(ILaunchConfigurationListener listener) {
683         fLaunchConfigurationListeners.add(listener);
684     }
685     
686     /**
687      * @see org.eclipse.debug.core.ILaunchManager#addLaunches(org.eclipse.debug.core.ILaunch[])
688      */

689     public void addLaunches(ILaunch[] launches) {
690         List JavaDoc added = new ArrayList JavaDoc(launches.length);
691         for (int i = 0; i < launches.length; i++) {
692             if (internalAddLaunch(launches[i])) {
693                 added.add(launches[i]);
694             }
695         }
696         if (!added.isEmpty()) {
697             ILaunch[] addedLaunches = (ILaunch[])added.toArray(new ILaunch[added.size()]);
698             fireUpdate(addedLaunches, ADDED);
699             for (int i = 0; i < addedLaunches.length; i++) {
700                 fireUpdate(launches[i], ADDED);
701             }
702         }
703     }
704     
705     /**
706      * @see org.eclipse.debug.core.ILaunchManager#addLaunchListener(org.eclipse.debug.core.ILaunchesListener)
707      */

708     public void addLaunchListener(ILaunchesListener listener) {
709         fLaunchesListeners.add(listener);
710     }
711     
712     /**
713      * @see ILaunchManager#addLaunchListener(ILaunchListener)
714      */

715     public void addLaunchListener(ILaunchListener listener) {
716         fListeners.add(listener);
717     }
718     
719     /**
720      * Computes and caches the native system environment variables as a map of
721      * variable names and values (Strings) in the given map.
722      * <p>
723      * Note that WIN32 system environment preserves
724      * the case of variable names but is otherwise case insensitive.
725      * Depending on what you intend to do with the environment, the
726      * lack of normalization may or may not be create problems. This
727      * method preserves mixed-case keys using the variable names
728      * recorded by the OS.
729      * </p>
730      * @since 3.1
731      */

732     private void cacheNativeEnvironment(Map JavaDoc cache) {
733         try {
734             String JavaDoc nativeCommand= null;
735             boolean isWin9xME= false; //see bug 50567
736
String JavaDoc fileName= null;
737             if (Platform.getOS().equals(Constants.OS_WIN32)) {
738                 String JavaDoc osName= System.getProperty("os.name"); //$NON-NLS-1$
739
isWin9xME= osName != null && (osName.startsWith("Windows 9") || osName.startsWith("Windows ME")); //$NON-NLS-1$ //$NON-NLS-2$
740
if (isWin9xME) {
741                     // Win 95, 98, and ME
742
// SET might not return therefore we pipe into a file
743
IPath stateLocation= DebugPlugin.getDefault().getStateLocation();
744                     fileName= stateLocation.toOSString() + File.separator + "env.txt"; //$NON-NLS-1$
745
nativeCommand= "command.com /C set > " + fileName; //$NON-NLS-1$
746
} else {
747                     // Win NT, 2K, XP
748
nativeCommand= "cmd.exe /C set"; //$NON-NLS-1$
749
}
750             } else if (!Platform.getOS().equals(Constants.OS_UNKNOWN)){
751                 nativeCommand= "env"; //$NON-NLS-1$
752
}
753             if (nativeCommand == null) {
754                 return;
755             }
756             Process JavaDoc process= Runtime.getRuntime().exec(nativeCommand);
757             if (isWin9xME) {
758                 //read piped data on Win 95, 98, and ME
759
Properties JavaDoc p= new Properties JavaDoc();
760                 File JavaDoc file= new File JavaDoc(fileName);
761                 InputStream JavaDoc stream = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(file));
762                 p.load(stream);
763                 stream.close();
764                 if (!file.delete()) {
765                     file.deleteOnExit(); // if delete() fails try again on VM close
766
}
767                 for (Enumeration JavaDoc enumeration = p.keys(); enumeration.hasMoreElements();) {
768                     // Win32's environment variables are case insensitive. Put everything
769
// to uppercase so that (for example) the "PATH" variable will match
770
// "pAtH" correctly on Windows.
771
String JavaDoc key= (String JavaDoc) enumeration.nextElement();
772                     //no need to cast value
773
cache.put(key, p.get(key));
774                 }
775             } else {
776                 //read process directly on other platforms
777
//we need to parse out matching '{' and '}' for function declarations in .bash environments
778
// pattern is [func name]=() { and we must find the '}' on its own line with no trailing ';'
779
InputStream JavaDoc stream = process.getInputStream();
780                 InputStreamReader JavaDoc isreader = new InputStreamReader JavaDoc(stream);
781                 BufferedReader JavaDoc reader = new BufferedReader JavaDoc(isreader);
782                 String JavaDoc line = reader.readLine();
783                 String JavaDoc key = null;
784                 String JavaDoc value = null;
785                 while (line != null) {
786                     int func = line.indexOf("=()"); //$NON-NLS-1$
787
if(func > 0) {
788                         key = line.substring(0, func);
789                         //scan until we find the closing '}' with no following chars
790
value = line.substring(func+1);
791                         while(line != null && !line.equals("}")) { //$NON-NLS-1$
792
line = reader.readLine();
793                             if(line != null) {
794                                 value += line;
795                             }
796                         }
797                         line = reader.readLine();
798                     }
799                     else {
800                         int separator = line.indexOf('=');
801                         if (separator > 0) {
802                             key = line.substring(0, separator);
803                             value = line.substring(separator + 1);
804                             line = reader.readLine();
805                             if(line != null) {
806                                 //this line has a '=' read ahead to check next line for '=', might be broken on more than one line
807
separator = line.indexOf('=');
808                                 while(separator < 0) {
809                                     value += line.trim();
810                                     line = reader.readLine();
811                                     if(line == null) {
812                                         //if next line read is the end of the file quit the loop
813
break;
814                                     }
815                                     separator = line.indexOf('=');
816                                 }
817                             }
818                         }
819                     }
820                     if(key != null) {
821                         cache.put(key, value);
822                         key = null;
823                         value = null;
824                     }
825                     else {
826                         line = reader.readLine();
827                     }
828                 }
829                 reader.close();
830             }
831         } catch (IOException JavaDoc e) {
832             // Native environment-fetching code failed.
833
// This can easily happen and is not useful to log.
834
}
835     }
836
837     /**
838      * Clears all launch configurations (if any have been accessed)
839      */

840     private void clearAllLaunchConfigurations() {
841         if (fLaunchConfigurationTypes != null) {
842             fLaunchConfigurationTypes.clear();
843         }
844         if (fLaunchConfigurationIndex != null) {
845             fLaunchConfigurationIndex.clear();
846         }
847     }
848             
849     /**
850      * The launch config name cache is cleared when a config is added, deleted or changed.
851      */

852     protected void clearConfigNameCache() {
853         fSortedConfigNames = null;
854     }
855
856     /**
857      * Return an instance of DebugException containing the specified message and Throwable.
858      */

859     protected DebugException createDebugException(String JavaDoc message, Throwable JavaDoc throwable) {
860         return new DebugException(
861                     new Status(
862                      IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
863                      DebugException.REQUEST_FAILED, message, throwable
864                     )
865                 );
866     }
867     
868     /**
869      * Return a LaunchConfigurationInfo object initialized from XML contained in
870      * the specified stream. Simply pass out any exceptions encountered so that
871      * caller can deal with them. This is important since caller may need access to the
872      * actual exception.
873      */

874     protected LaunchConfigurationInfo createInfoFromXML(InputStream JavaDoc stream) throws CoreException,
875                                                                              ParserConfigurationException JavaDoc,
876                                                                              IOException JavaDoc,
877                                                                              SAXException JavaDoc {
878         Element root = null;
879         DocumentBuilder JavaDoc parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
880         parser.setErrorHandler(new DefaultHandler JavaDoc());
881         root = parser.parse(new InputSource JavaDoc(stream)).getDocumentElement();
882         LaunchConfigurationInfo info = new LaunchConfigurationInfo();
883         info.initializeFromXML(root);
884         return info;
885     }
886     
887     /**
888      * Finds and returns all launch configurations in the given
889      * container (and sub-containers)
890      *
891      * @param container the container to search
892      * @exception CoreException an exception occurs traversing
893      * the container.
894      * @return all launch configurations in the given container
895      */

896     protected List JavaDoc findLaunchConfigurations(IContainer container) {
897         List JavaDoc list = new ArrayList JavaDoc(10);
898         if (container instanceof IProject && !((IProject)container).isOpen()) {
899             return list;
900         }
901         ResourceProxyVisitor visitor= new ResourceProxyVisitor(list);
902         try {
903             container.accept(visitor, IResource.NONE);
904         } catch (CoreException ce) {
905             //Closed project...should not be possible with previous check
906
}
907         Iterator JavaDoc iter = list.iterator();
908         List JavaDoc configs = new ArrayList JavaDoc(list.size());
909         IFile file = null;
910         while (iter.hasNext()) {
911             file = (IFile)iter.next();
912             configs.add(getLaunchConfiguration(file));
913         }
914         return configs;
915     }
916     
917     /**
918      * Finds and returns all local launch configurations.
919      *
920      * @return all local launch configurations
921      * @exception CoreException if there is a lower level
922      * IO exception
923      */

924     protected List JavaDoc findLocalLaunchConfigurations() {
925         IPath containerPath = LOCAL_LAUNCH_CONFIGURATION_CONTAINER_PATH;
926         List JavaDoc configs = new ArrayList JavaDoc(10);
927         final File JavaDoc directory = containerPath.toFile();
928         if (directory.isDirectory()) {
929             FilenameFilter JavaDoc filter = new FilenameFilter JavaDoc() {
930                 public boolean accept(File JavaDoc dir, String JavaDoc name) {
931                     return dir.equals(directory) &&
932                             name.endsWith(ILaunchConfiguration.LAUNCH_CONFIGURATION_FILE_EXTENSION);
933                 }
934             };
935             String JavaDoc[] files = directory.list(filter);
936             LaunchConfiguration config = null;
937             for (int i = 0; i < files.length; i++) {
938                 config = new LaunchConfiguration(containerPath.append(files[i]));
939                 configs.add(config);
940             }
941         }
942         return configs;
943     }
944         
945     /**
946      * Fires notification to (single) listeners that a launch has been
947      * added/changed/removed.
948      *
949      * @param launch launch that has changed
950      * @param update type of change
951      */

952     public void fireUpdate(ILaunch launch, int update) {
953         new LaunchNotifier().notify(launch, update);
954     }
955
956     /**
957      * Fires notification to (plural) listeners that a launch has been
958      * added/changed/removed.
959      *
960      * @param launches launches that have changed
961      * @param update type of change
962      */

963     public void fireUpdate(ILaunch[] launches, int update) {
964         new LaunchesNotifier().notify(launches, update);
965     }
966     
967     /**
968      * @see org.eclipse.debug.core.ILaunchManager#generateUniqueLaunchConfigurationNameFrom(String)
969      */

970     public String JavaDoc generateUniqueLaunchConfigurationNameFrom(String JavaDoc baseName) {
971         int index = 1;
972         int length= baseName.length();
973         int copyIndex = baseName.lastIndexOf(" ("); //$NON-NLS-1$
974
if (copyIndex > -1 && length > copyIndex + 2 && baseName.charAt(length - 1) == ')') {
975             String JavaDoc trailer = baseName.substring(copyIndex + 2, length -1);
976             if (isNumber(trailer)) {
977                 try {
978                     index = Integer.parseInt(trailer);
979                     baseName = baseName.substring(0, copyIndex);
980                 }
981                 catch (NumberFormatException JavaDoc nfe) {}
982             }
983         }
984         String JavaDoc newName = baseName;
985         while (isExistingLaunchConfigurationName(newName)) {
986             newName = MessageFormat.format(DebugCoreMessages.LaunchManager_31, new String JavaDoc[] {baseName, Integer.toString(index)});
987             index++;
988         }
989             
990         return newName;
991     }
992     
993     /**
994      * Return a String that can be used as the name of a launch configuration. The name
995      * is guaranteed to be unique (no existing or temporary launch configurations will have this name).
996      * The name that is returned uses the <code>basename</code> as a starting point. If
997      * there is no existing launch configuration with this name, then <code>basename</code>
998      * is returned. Otherwise, the value returned consists of the specified base plus
999      * some suffix that guarantees uniqueness. Passing <code>null</code> as the set of reserved names will cause this
1000     * method to return <code>generateUniqueLaunchConfigurationNameFrom(String baseName)</code>.
1001     *
1002     * By specifying a set of reserved names, you can further constrain the name that will be generated
1003     * by this method. For example you can give a base name of 'test' and a reserved set of [test(1), test(2)],
1004     * which will result in a name of 'test(3)' being returned iff a configuration with the name 'test' already exists.
1005     *
1006     * @return launch configuration name
1007     * @param basename the String that the returned name must begin with
1008     * @param reservednames a set of strings that is further used to constrain what names can be generated
1009     * @since 3.3
1010     */

1011    public String JavaDoc generateUniqueLaunchConfigurationNameFrom(String JavaDoc basename, Set JavaDoc reservednames) {
1012        if(reservednames == null) {
1013            return generateUniqueLaunchConfigurationNameFrom(basename);
1014        }
1015        int index = 1;
1016        int length= basename.length();
1017        String JavaDoc base = basename;
1018        int copyIndex = base.lastIndexOf(" ("); //$NON-NLS-1$
1019
if (copyIndex > -1 && length > copyIndex + 2 && base.charAt(length - 1) == ')') {
1020            String JavaDoc trailer = base.substring(copyIndex + 2, length -1);
1021            if (isNumber(trailer)) {
1022                try {
1023                    index = Integer.parseInt(trailer);
1024                    base = base.substring(0, copyIndex);
1025                }
1026                catch (NumberFormatException JavaDoc nfe) {}
1027            }
1028        }
1029        String JavaDoc newname = base;
1030        StringBuffer JavaDoc buffer = null;
1031        while (isExistingLaunchConfigurationName(newname) || reservednames.contains(newname)) {
1032            buffer = new StringBuffer JavaDoc(base);
1033            buffer.append(" ("); //$NON-NLS-1$
1034
buffer.append(String.valueOf(index));
1035            index++;
1036            buffer.append(')');
1037            newname = buffer.toString();
1038        }
1039        return newname;
1040    }
1041    
1042    /**
1043     * Returns a collection of all launch configuration handles in
1044     * the workspace. This collection is initialized lazily.
1045     *
1046     * @return all launch configuration handles
1047     */

1048    private synchronized List JavaDoc getAllLaunchConfigurations() {
1049        if (fLaunchConfigurationIndex == null) {
1050            try {
1051                fLaunchConfigurationIndex = new ArrayList JavaDoc(20);
1052                List JavaDoc configs = findLocalLaunchConfigurations();
1053                verifyConfigurations(configs, fLaunchConfigurationIndex);
1054                configs = findLaunchConfigurations(ResourcesPlugin.getWorkspace().getRoot());
1055                verifyConfigurations(configs, fLaunchConfigurationIndex);
1056            } finally {
1057                hookResourceChangeListener();
1058            }
1059        }
1060        return fLaunchConfigurationIndex;
1061    }
1062    
1063    /**
1064     * Return a sorted array of the names of all <code>ILaunchConfiguration</code>s in
1065     * the workspace. These are cached, and cache is cleared when a new config is added,
1066     * deleted or changed.
1067     */

1068    protected String JavaDoc[] getAllSortedConfigNames() {
1069        if (fSortedConfigNames == null) {
1070            ILaunchConfiguration[] configs = getLaunchConfigurations();
1071            fSortedConfigNames = new String JavaDoc[configs.length];
1072            for (int i = 0; i < configs.length; i++) {
1073                fSortedConfigNames[i] = configs[i].getName();
1074            }
1075            Arrays.sort(fSortedConfigNames);
1076        }
1077        return fSortedConfigNames;
1078    }
1079    
1080    /**
1081     * Returns the comparator registered for the given attribute, or
1082     * <code>null</code> if none.
1083     *
1084     * @param attributeName attribute for which a comparator is required
1085     * @return comparator, or <code>null</code> if none
1086     */

1087    protected Comparator JavaDoc getComparator(String JavaDoc attributeName) {
1088         Map JavaDoc map = getComparators();
1089         return (Comparator JavaDoc)map.get(attributeName);
1090    }
1091    
1092    /**
1093     * Returns comparators, loading if required
1094     */

1095    protected Map JavaDoc getComparators() {
1096        initializeComparators();
1097        return fComparators;
1098    }
1099    
1100    /**
1101     * Returns the launch configurations specified by the given
1102     * XML document.
1103     *
1104     * @param root XML document
1105     * @return list of launch configurations
1106     * @exception IOException if an exception occurs reading the XML
1107     */

1108    protected List JavaDoc getConfigsFromXML(Element root) throws CoreException {
1109        DebugException invalidFormat =
1110            new DebugException(
1111                new Status(
1112                 IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
1113                 DebugException.REQUEST_FAILED, DebugCoreMessages.LaunchManager_Invalid_launch_configuration_index__18, null
1114                )
1115            );
1116            
1117        if (!root.getNodeName().equalsIgnoreCase("launchConfigurations")) { //$NON-NLS-1$
1118
throw invalidFormat;
1119        }
1120        
1121        // read each launch configuration
1122
List JavaDoc configs = new ArrayList JavaDoc(4);
1123        NodeList JavaDoc list = root.getChildNodes();
1124        int length = list.getLength();
1125        Node JavaDoc node = null;
1126        Element entry = null;
1127        String JavaDoc memento = null;
1128        for (int i = 0; i < length; ++i) {
1129            node = list.item(i);
1130            short type = node.getNodeType();
1131            if (type == Node.ELEMENT_NODE) {
1132                entry = (Element) node;
1133                if (!entry.getNodeName().equals("launchConfiguration")) { //$NON-NLS-1$
1134
throw invalidFormat;
1135                }
1136                memento = entry.getAttribute("memento"); //$NON-NLS-1$
1137
if (memento == null) {
1138                    throw invalidFormat;
1139                }
1140                configs.add(getLaunchConfiguration(memento));
1141            }
1142        }
1143        return configs;
1144    }
1145    
1146    protected ConfigurationNotifier getConfigurationNotifier() {
1147        return new ConfigurationNotifier();
1148    }
1149    
1150    /**
1151     * @see ILaunchManager#getDebugTargets()
1152     */

1153    public IDebugTarget[] getDebugTargets() {
1154        synchronized (fLaunches) {
1155            List JavaDoc allTargets= new ArrayList JavaDoc(fLaunches.size());
1156            if (fLaunches.size() > 0) {
1157                Iterator JavaDoc e = fLaunches.iterator();
1158                IDebugTarget[] targets = null;
1159                while (e.hasNext()) {
1160                    targets = ((ILaunch) e.next()).getDebugTargets();
1161                    for (int i = 0; i < targets.length; i++) {
1162                        allTargets.add(targets[i]);
1163                    }
1164                }
1165            }
1166            return (IDebugTarget[])allTargets.toArray(new IDebugTarget[allTargets.size()]);
1167        }
1168    }
1169    
1170    /**
1171     * Returns the resource delta visitor for the launch manager.
1172     *
1173     * @return the resource delta visitor for the launch manager
1174     */

1175    private LaunchManagerVisitor getDeltaVisitor() {
1176        if (fgVisitor == null) {
1177            fgVisitor= new LaunchManagerVisitor();
1178        }
1179        return fgVisitor;
1180    }
1181    
1182
1183    /* (non-Javadoc)
1184     * @see org.eclipse.debug.core.ILaunchManager#getEnvironment(org.eclipse.debug.core.ILaunchConfiguration)
1185     */

1186    public String JavaDoc[] getEnvironment(ILaunchConfiguration configuration) throws CoreException {
1187        Map JavaDoc configEnv = configuration.getAttribute(ATTR_ENVIRONMENT_VARIABLES, (Map JavaDoc) null);
1188        if (configEnv == null) {
1189            return null;
1190        }
1191        Map JavaDoc env = new HashMap JavaDoc();
1192        // build base environment
1193
boolean append = configuration.getAttribute(ATTR_APPEND_ENVIRONMENT_VARIABLES, true);
1194        if (append) {
1195            env.putAll(getNativeEnvironmentCasePreserved());
1196        }
1197        
1198        // Add variables from config
1199
Iterator JavaDoc iter= configEnv.entrySet().iterator();
1200        boolean win32= Platform.getOS().equals(Constants.OS_WIN32);
1201        Map.Entry JavaDoc entry = null;
1202        String JavaDoc key = null;
1203        String JavaDoc value = null;
1204        Object JavaDoc nativeValue = null;
1205        Iterator JavaDoc envIter = null;
1206        Map.Entry JavaDoc nativeEntry = null;
1207        String JavaDoc nativeKey = null;
1208        while (iter.hasNext()) {
1209            entry = (Map.Entry JavaDoc) iter.next();
1210            key = (String JavaDoc) entry.getKey();
1211            value = (String JavaDoc) entry.getValue();
1212            // translate any string substitution variables
1213
if (value != null) {
1214                value = VariablesPlugin.getDefault().getStringVariableManager().performStringSubstitution(value);
1215            }
1216            boolean added= false;
1217            if (win32) {
1218                // First, check if the key is an exact match for an existing key.
1219
nativeValue = env.get(key);
1220                if (nativeValue != null) {
1221                    // If an exact match is found, just replace the value
1222
env.put(key, value);
1223                } else {
1224                    // Win32 variables are case-insensitive. If an exact match isn't found, iterate to
1225
// check for a case-insensitive match. We maintain the key's case (see bug 86725),
1226
// but do a case-insensitive comparison (for example, "pAtH" will still override "PATH").
1227
envIter = env.entrySet().iterator();
1228                    while (envIter.hasNext()) {
1229                        nativeEntry = (Map.Entry JavaDoc) envIter.next();
1230                        nativeKey = (String JavaDoc) (nativeEntry).getKey();
1231                        if (nativeKey.equalsIgnoreCase(key)) {
1232                            nativeEntry.setValue(value);
1233                            added = true;
1234                            break;
1235                        }
1236                    }
1237                }
1238            }
1239            if (!added) {
1240                env.put(key, value);
1241            }
1242        }
1243        
1244        iter = env.entrySet().iterator();
1245        List JavaDoc strings = new ArrayList JavaDoc(env.size());
1246        StringBuffer JavaDoc buffer = null;
1247        while (iter.hasNext()) {
1248            entry = (Map.Entry JavaDoc) iter.next();
1249            buffer = new StringBuffer JavaDoc((String JavaDoc) entry.getKey());
1250            buffer.append('=').append((String JavaDoc) entry.getValue());
1251            strings.add(buffer.toString());
1252        }
1253        return (String JavaDoc[]) strings.toArray(new String JavaDoc[strings.size()]);
1254    }
1255    
1256    /**
1257     * Returns the info object for the specified launch configuration.
1258     * If the configuration exists, but is not yet in the cache,
1259     * an info object is built and added to the cache.
1260     *
1261     * @exception CoreException if an exception occurs building
1262     * the info object
1263     * @exception DebugException if the config does not exist
1264     */

1265    protected LaunchConfigurationInfo getInfo(ILaunchConfiguration config) throws CoreException {
1266        LaunchConfigurationInfo info = (LaunchConfigurationInfo)fLaunchConfigurations.get(config);
1267        if (info == null) {
1268            if (config.exists()) {
1269                InputStream JavaDoc stream = null;
1270                try {
1271                    if (config.isLocal()) {
1272                        IPath path = config.getLocation();
1273                        File JavaDoc file = path.toFile();
1274                        stream = new BufferedInputStream JavaDoc(new FileInputStream JavaDoc(file));
1275                    } else {
1276                        IFile file = ((LaunchConfiguration) config).getFile();
1277                        if (file == null) {
1278                            throw createDebugException(MessageFormat.format(DebugCoreMessages.LaunchManager_30, new String JavaDoc[] {config.getName()}), null);
1279                        }
1280                        stream = file.getContents(true);
1281                    }
1282                    info = createInfoFromXML(stream);
1283                    synchronized (this) {
1284                        fLaunchConfigurations.put(config, info);
1285                    }
1286                } catch (FileNotFoundException JavaDoc e) {
1287                    throwException(config, e);
1288                } catch (SAXException JavaDoc e) {
1289                    throwException(config, e);
1290                } catch (ParserConfigurationException JavaDoc e) {
1291                    throwException(config, e);
1292                } catch (IOException JavaDoc e) {
1293                    throwException(config, e);
1294                } finally {
1295                    if (stream != null) {
1296                        try {
1297                            stream.close();
1298                        } catch (IOException JavaDoc e) {
1299                            throwException(config, e);
1300                        }
1301                    }
1302                }
1303        
1304            } else {
1305                throw createDebugException(
1306                    MessageFormat.format(DebugCoreMessages.LaunchManager_does_not_exist, new String JavaDoc[]{config.getName(), config.getLocation().toOSString()}), null);
1307            }
1308        }
1309        return info;
1310    }
1311    
1312    /**
1313     * @see ILaunchManager#getLaunchConfiguration(IFile)
1314     */

1315    public ILaunchConfiguration getLaunchConfiguration(IFile file) {
1316        hookResourceChangeListener();
1317        return new LaunchConfiguration(file.getLocation());
1318    }
1319    
1320    /**
1321     * @see ILaunchManager#getLaunchConfiguration(String)
1322     */

1323    public ILaunchConfiguration getLaunchConfiguration(String JavaDoc memento) throws CoreException {
1324        hookResourceChangeListener();
1325        return new LaunchConfiguration(memento);
1326    }
1327    
1328    /**
1329     * @see ILaunchManager#getLaunchConfigurations()
1330     */

1331    public synchronized ILaunchConfiguration[] getLaunchConfigurations() {
1332        List JavaDoc allConfigs = getAllLaunchConfigurations();
1333        return (ILaunchConfiguration[])allConfigs.toArray(new ILaunchConfiguration[allConfigs.size()]);
1334    }
1335    
1336    /**
1337     * @see ILaunchManager#getLaunchConfigurations(ILaunchConfigurationType)
1338     */

1339    public synchronized ILaunchConfiguration[] getLaunchConfigurations(ILaunchConfigurationType type) throws CoreException {
1340        Iterator JavaDoc iter = getAllLaunchConfigurations().iterator();
1341        List JavaDoc configs = new ArrayList JavaDoc();
1342        ILaunchConfiguration config = null;
1343        while (iter.hasNext()) {
1344            config = (ILaunchConfiguration)iter.next();
1345            if (config.getType().equals(type)) {
1346                configs.add(config);
1347            }
1348        }
1349        return (ILaunchConfiguration[])configs.toArray(new ILaunchConfiguration[configs.size()]);
1350    }
1351    
1352    /**
1353     * Returns all launch configurations that are stored as resources
1354     * in the given project.
1355     *
1356     * @param project a project
1357     * @return collection of launch configurations that are stored as resources
1358     * in the given project
1359     */

1360    protected synchronized List JavaDoc getLaunchConfigurations(IProject project) {
1361        Iterator JavaDoc iter = getAllLaunchConfigurations().iterator();
1362        List JavaDoc configs = new ArrayList JavaDoc();
1363        ILaunchConfiguration config = null;
1364        IFile file = null;
1365        while (iter.hasNext()) {
1366            config = (ILaunchConfiguration)iter.next();
1367            file = config.getFile();
1368            if (file != null && file.getProject().equals(project)) {
1369                configs.add(config);
1370            }
1371        }
1372        return configs;
1373    }
1374    
1375    /**
1376     * @see ILaunchManager#getLaunchConfigurationType(String)
1377     */

1378    public ILaunchConfigurationType getLaunchConfigurationType(String JavaDoc id) {
1379        ILaunchConfigurationType[] types = getLaunchConfigurationTypes();
1380        for(int i = 0; i < types.length; i++) {
1381            if (types[i].getIdentifier().equals(id)) {
1382                return types[i];
1383            }
1384        }
1385        return null;
1386    }
1387
1388    /**
1389     * @see ILaunchManager#getLaunchConfigurationTypes()
1390     */

1391    public ILaunchConfigurationType[] getLaunchConfigurationTypes() {
1392        initializeLaunchConfigurationTypes();
1393        return (ILaunchConfigurationType[])fLaunchConfigurationTypes.toArray(new ILaunchConfigurationType[fLaunchConfigurationTypes.size()]);
1394    }
1395    
1396    /**
1397     * @see ILaunchManager#getLaunches()
1398     */

1399    public ILaunch[] getLaunches() {
1400        synchronized (fLaunches) {
1401            return (ILaunch[])fLaunches.toArray(new ILaunch[fLaunches.size()]);
1402        }
1403    }
1404    
1405    /**)
1406     * @see org.eclipse.debug.core.ILaunchManager#getLaunchMode(java.lang.String)
1407     */

1408    public ILaunchMode getLaunchMode(String JavaDoc mode) {
1409        initializeLaunchModes();
1410        return (ILaunchMode) fLaunchModes.get(mode);
1411    }
1412    
1413    /**
1414     * @see org.eclipse.debug.core.ILaunchManager#getLaunchModes()
1415     */

1416    public ILaunchMode[] getLaunchModes() {
1417        initializeLaunchModes();
1418        Collection JavaDoc collection = fLaunchModes.values();
1419        return (ILaunchMode[]) collection.toArray(new ILaunchMode[collection.size()]);
1420    }
1421    
1422    /**
1423     * Returns all of the launch delegates. The returned listing of delegates cannot be directly used to launch,
1424     * instead the method <code>IlaunchDelegate.getDelegate</code> must be used to acquire an executable form of
1425     * the delegate, allowing us to maintain lazy loading of the delegates themselves.
1426     * @return all of the launch delegates
1427     *
1428     * @since 3.3
1429     */

1430    public ILaunchDelegate[] getLaunchDelegates() {
1431        initializeLaunchDelegates();
1432        Collection JavaDoc col = fLaunchDelegates.values();
1433        return (ILaunchDelegate[]) col.toArray(new ILaunchDelegate[col.size()]);
1434    }
1435    
1436    /**
1437     * Returns the listing of launch delegates that apply to the specified
1438     * <code>ILaunchConfigurationType</code> id
1439     * @param typeid the id of the launch configuration type to get delegates for
1440     * @return An array of <code>LaunchDelegate</code>s that apply to the specified launch configuration
1441     * type, or an empty array, never <code>null</code>
1442     *
1443     * @since 3.3
1444     */

1445    public LaunchDelegate[] getLaunchDelegates(String JavaDoc typeid) {
1446        initializeLaunchDelegates();
1447        ArrayList JavaDoc list = new ArrayList JavaDoc();
1448        LaunchDelegate ld = null;
1449        for(Iterator JavaDoc iter = fLaunchDelegates.keySet().iterator(); iter.hasNext();) {
1450            ld = (LaunchDelegate) fLaunchDelegates.get(iter.next());
1451            if(ld.getLaunchConfigurationTypeId().equals(typeid)) {
1452                list.add(ld);
1453            }
1454        }
1455        return (LaunchDelegate[]) list.toArray(new LaunchDelegate[list.size()]);
1456    }
1457    
1458    /**
1459     * This method returns the <code>ILaunchDelegate</code> instance corresponding to the id
1460     * of the launch delegate specified
1461     * @param id the id of the <code>ILaunchDelegate</code> to find
1462     * @return the <code>ILaunchDelegate</code> or <code>null</code> if not found
1463     *
1464     * @since 3.3
1465     */

1466    public ILaunchDelegate getLaunchDelegate(String JavaDoc id) {
1467        if(id != null) {
1468            ILaunchDelegate[] delegates = getLaunchDelegates();
1469            for(int i = 0; i < delegates.length; i++) {
1470                if(id.equals(delegates[i].getId())) {
1471                    return delegates[i];
1472                }
1473            }
1474        }
1475        return null;
1476    }
1477    
1478    /**
1479     * Initializes the listing of delegates available to the launching framework
1480     *
1481     * @since 3.3
1482     */

1483    private synchronized void initializeLaunchDelegates() {
1484        if(fLaunchDelegates == null) {
1485            fLaunchDelegates = new HashMap JavaDoc();
1486            //get all launch delegate contributions
1487
IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_LAUNCH_DELEGATES);
1488            IConfigurationElement[] infos = extensionPoint.getConfigurationElements();
1489            LaunchDelegate delegate = null;
1490            for(int i = 0; i < infos.length; i++) {
1491                delegate = new LaunchDelegate(infos[i]);
1492                fLaunchDelegates.put(delegate.getId(), delegate);
1493            }
1494            //get all delegates from launch configuration type contributions
1495
extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_LAUNCH_CONFIGURATION_TYPES);
1496            infos = extensionPoint.getConfigurationElements();
1497            for(int i = 0; i < infos.length; i++) {
1498                //must check to see if delegate is provided in contribution
1499
if(infos[i].getAttribute(IConfigurationElementConstants.DELEGATE) != null) {
1500                    delegate = new LaunchDelegate(infos[i]);
1501                    fLaunchDelegates.put(delegate.getId(), delegate);
1502                }
1503            }
1504        }
1505    }
1506    
1507    /**
1508     * This method is used to initialize a simple listing of all preferred delegates, which is then used by each
1509     * <code>ILaunchConfigurationType</code> to find if they have preferred delegates. Once an <code>ILaunchConfigurationType</code>
1510     * has used this listing to initialize its preferred delegates it will maintain changes to its preferred delegate, which are
1511     * then written back to the preference store only when the launch manager shuts down.
1512     * <p>
1513     * This cache is not synchronized with the runtime preferred delegates stored in launch configuration types.
1514     * </p>
1515     * @since 3.3
1516     */

1517    private synchronized void initializePreferredDelegates() {
1518        if(fPreferredDelegates == null) {
1519            fPreferredDelegates = new HashSet JavaDoc();
1520            Preferences prefs = DebugPlugin.getDefault().getPluginPreferences();
1521            String JavaDoc preferred = prefs.getString(LaunchManager.PREF_PREFERRED_DELEGATES);
1522            if(!EMPTY_STRING.equals(preferred)) {
1523                try {
1524                    Element root = DebugPlugin.parseDocument(preferred);
1525                    NodeList JavaDoc nodes = root.getElementsByTagName(IConfigurationElementConstants.DELEGATE);
1526                    Element element = null;
1527                    String JavaDoc typeid = null;
1528                    Set JavaDoc modeset = null;
1529                    List JavaDoc modesets = null;
1530                    LaunchDelegate[] extensions = null;
1531                    ILaunchDelegate delegate = null;
1532                    for(int i = 0; i < nodes.getLength(); i++) {
1533                        element = (Element) nodes.item(i);
1534                        typeid = element.getAttribute(IConfigurationElementConstants.TYPE_ID);
1535                        extensions = getLaunchDelegates(typeid);
1536                        for(int j = 0; j < extensions.length; j++) {
1537                            if(element.getAttribute(IConfigurationElementConstants.ID).equals(extensions[j].getId())) {
1538                                modesets = extensions[j].getModes();
1539                                String JavaDoc[] modes = element.getAttribute(IConfigurationElementConstants.MODES).split(","); //$NON-NLS-1$
1540
modeset = new HashSet JavaDoc(Arrays.asList(modes));
1541                                if(modesets.contains(modeset)) {
1542                                    delegate = extensions[j];
1543                                    break;
1544                                }
1545                            }
1546                        }
1547                        //take type id, modeset, delegate and create entry
1548
if(delegate != null & !EMPTY_STRING.equals(typeid) & modeset != null) {
1549                            fPreferredDelegates.add(new PreferredDelegate(delegate, typeid, modeset));
1550                        }
1551                        delegate = null;
1552                    }
1553                }
1554                catch (CoreException e) {DebugPlugin.log(e);}
1555            }
1556        }
1557    }
1558    
1559    /**
1560     * Allows internal access to a preferred delegate for a given type and mode set
1561     * @param typeid the id of the <code>ILaunchConfigurationType</code> to find a delegate for
1562     * @param modes the set of modes for the delegate
1563     * @return the preferred delegate for the specified type id and mode set, or <code>null</code> if none
1564     *
1565     * @since 3.3
1566     */

1567    protected ILaunchDelegate getPreferredDelegate(String JavaDoc typeid, Set JavaDoc modes) {
1568        initializePreferredDelegates();
1569        PreferredDelegate pd = null;
1570        for(Iterator JavaDoc iter = fPreferredDelegates.iterator(); iter.hasNext();) {
1571            pd = (PreferredDelegate) iter.next();
1572            if(pd.getModes().equals(modes) & pd.getTypeId().equals(typeid)) {
1573                return pd.getDelegate();
1574            }
1575        }
1576        return null;
1577    }
1578    
1579    /**
1580     * Returns all launch configurations that are stored locally.
1581     *
1582     * @return collection of launch configurations stored locally
1583     */

1584    protected synchronized List JavaDoc getLocalLaunchConfigurations() {
1585        Iterator JavaDoc iter = getAllLaunchConfigurations().iterator();
1586        List JavaDoc configs = new ArrayList JavaDoc();
1587        ILaunchConfiguration config = null;
1588        while (iter.hasNext()) {
1589            config = (ILaunchConfiguration)iter.next();
1590            if (config.isLocal()) {
1591                configs.add(config);
1592            }
1593        }
1594        return configs;
1595    }
1596    
1597    /**
1598     * Returns the launch configurations mapping to the specified resource
1599     * @param resource the resource to collect mapped launch configurations for
1600     * @return a list of launch configurations if found or an empty list, never null
1601     * @since 3.2
1602     */

1603    public ILaunchConfiguration[] getMappedConfigurations(IResource resource) {
1604        List JavaDoc configurations = new ArrayList JavaDoc();
1605        try {
1606            ILaunchConfiguration[] configs = getLaunchConfigurations();
1607            IResource[] resources = null;
1608            for(int i = 0; i < configs.length; i++) {
1609                resources = configs[i].getMappedResources();
1610                if(resources != null) {
1611                    for(int j = 0; j < resources.length; j++) {
1612                        if(resources[j].equals(resource)) {
1613                            configurations.add(configs[i]);
1614                        }
1615                    }
1616                }
1617            }
1618        }
1619        catch(CoreException e) {DebugPlugin.log(e);}
1620        return (ILaunchConfiguration[])configurations.toArray(new ILaunchConfiguration[configurations.size()]);
1621    }
1622    
1623    /* (non-Javadoc)
1624     * @see org.eclipse.debug.core.ILaunchManager#getMigrationCandidates()
1625     */

1626    public ILaunchConfiguration[] getMigrationCandidates() throws CoreException {
1627        List JavaDoc configs = new ArrayList JavaDoc();
1628        ILaunchConfiguration[] candidates = getLaunchConfigurations();
1629        for(int i = 0; i < candidates.length; i++) {
1630            if(candidates[i].isMigrationCandidate()) {
1631                configs.add(candidates[i]);
1632            }
1633        }
1634        return (ILaunchConfiguration[])configs.toArray(new ILaunchConfiguration[configs.size()]);
1635    }
1636    
1637    /**
1638     * @see org.eclipse.debug.core.ILaunchManager#getMovedFrom(org.eclipse.debug.core.ILaunchConfiguration)
1639     */

1640    public ILaunchConfiguration getMovedFrom(ILaunchConfiguration addedConfiguration) {
1641        if (addedConfiguration.equals(fTo)) {
1642            return fFrom;
1643        }
1644        return null;
1645    }
1646    
1647    /**
1648     * @see org.eclipse.debug.core.ILaunchManager#getMovedTo(org.eclipse.debug.core.ILaunchConfiguration)
1649     */

1650    public ILaunchConfiguration getMovedTo(ILaunchConfiguration removedConfiguration) {
1651        if (removedConfiguration.equals(fFrom)) {
1652            return fTo;
1653        }
1654        return null;
1655    }
1656    
1657    /* (non-Javadoc)
1658     * @see org.eclipse.debug.core.ILaunchManager#getNativeEnvironment()
1659     */

1660    public synchronized Map JavaDoc getNativeEnvironment() {
1661        if (fgNativeEnv == null) {
1662            Map JavaDoc casePreserved = getNativeEnvironmentCasePreserved();
1663            if (Platform.getOS().equals(Constants.OS_WIN32)) {
1664                fgNativeEnv= new HashMap JavaDoc();
1665                Iterator JavaDoc entries = casePreserved.entrySet().iterator();
1666                Map.Entry JavaDoc entry = null;
1667                String JavaDoc key = null;
1668                while (entries.hasNext()) {
1669                    entry = (Entry) entries.next();
1670                    key = ((String JavaDoc)entry.getKey()).toUpperCase();
1671                    fgNativeEnv.put(key, entry.getValue());
1672                }
1673            } else {
1674                fgNativeEnv = new HashMap JavaDoc(casePreserved);
1675            }
1676        }
1677        return new HashMap JavaDoc(fgNativeEnv);
1678    }
1679    
1680    /* (non-Javadoc)
1681     * @see org.eclipse.debug.core.ILaunchManager#getNativeEnvironmentCasePreserved()
1682     */

1683    public synchronized Map JavaDoc getNativeEnvironmentCasePreserved() {
1684        if (fgNativeEnvCasePreserved == null) {
1685            fgNativeEnvCasePreserved= new HashMap JavaDoc();
1686            cacheNativeEnvironment(fgNativeEnvCasePreserved);
1687        }
1688        return new HashMap JavaDoc(fgNativeEnvCasePreserved);
1689    }
1690    
1691    /**
1692     * @see ILaunchManager#getProcesses()
1693     */

1694    public IProcess[] getProcesses() {
1695        synchronized (fLaunches) {
1696            List JavaDoc allProcesses = new ArrayList JavaDoc(fLaunches.size());
1697            Iterator JavaDoc e = fLaunches.iterator();
1698            IProcess[] processes = null;
1699            while (e.hasNext()) {
1700                processes = ((ILaunch) e.next()).getProcesses();
1701                for (int i= 0; i < processes.length; i++) {
1702                    allProcesses.add(processes[i]);
1703                }
1704            }
1705            return (IProcess[])allProcesses.toArray(new IProcess[allProcesses.size()]);
1706        }
1707    }
1708    
1709    /* (non-Javadoc)
1710     * @see org.eclipse.debug.core.ILaunchManager#getSourceContainerType(java.lang.String)
1711     */

1712    public ISourceContainerType getSourceContainerType(String JavaDoc id) {
1713        initializeSourceContainerTypes();
1714        return (ISourceContainerType) sourceContainerTypes.get(id);
1715    }
1716    
1717    /* (non-Javadoc)
1718     * @see org.eclipse.debug.core.ILaunchManager#getSourceContainerTypes()
1719     */

1720    public ISourceContainerType[] getSourceContainerTypes() {
1721        initializeSourceContainerTypes();
1722        Collection JavaDoc containers = sourceContainerTypes.values();
1723        return (ISourceContainerType[]) containers.toArray(new ISourceContainerType[containers.size()]);
1724    }
1725
1726    /* (non-Javadoc)
1727     * @see org.eclipse.debug.core.ILaunchManager#newSourcePathComputer(org.eclipse.debug.core.ILaunchConfiguration)
1728     */

1729    public ISourcePathComputer getSourcePathComputer(ILaunchConfiguration configuration) throws CoreException {
1730        String JavaDoc id = null;
1731        id = configuration.getAttribute(ISourcePathComputer.ATTR_SOURCE_PATH_COMPUTER_ID, (String JavaDoc)null);
1732        
1733        if (id == null) {
1734            //use default computer for configuration type, if any
1735
return configuration.getType().getSourcePathComputer();
1736        }
1737        return getSourcePathComputer(id);
1738    }
1739
1740    /* (non-Javadoc)
1741     * @see org.eclipse.debug.core.ILaunchManager#getSourcePathComputer(java.lang.String)
1742     */

1743    public ISourcePathComputer getSourcePathComputer(String JavaDoc id) {
1744        initializeSourceContainerTypes();
1745        return (ISourcePathComputer) sourcePathComputers.get(id);
1746    }
1747
1748    /**
1749     * Starts listening for resource change events
1750     */

1751    private synchronized void hookResourceChangeListener() {
1752        if (!fListening) {
1753            ResourcesPlugin.getWorkspace().addResourceChangeListener(this, IResourceChangeEvent.POST_CHANGE | IResourceChangeEvent.PRE_DELETE);
1754            fListening = true;
1755        }
1756    }
1757    
1758    /**
1759     * Load comparator extensions.
1760     */

1761    private synchronized void initializeComparators() {
1762        if (fComparators == null) {
1763            IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_LAUNCH_CONFIGURATION_COMPARATORS);
1764            IConfigurationElement[] infos= extensionPoint.getConfigurationElements();
1765            fComparators = new HashMap JavaDoc(infos.length);
1766            IConfigurationElement configurationElement = null;
1767            String JavaDoc attr = null;
1768            for (int i= 0; i < infos.length; i++) {
1769                configurationElement = infos[i];
1770                attr = configurationElement.getAttribute("attribute"); //$NON-NLS-1$
1771
if (attr != null) {
1772                    fComparators.put(attr, new LaunchConfigurationComparator(configurationElement));
1773                } else {
1774                    // invalid status handler
1775
IStatus s = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugException.INTERNAL_ERROR,
1776                    MessageFormat.format("Invalid launch configuration comparator extension defined by plug-in {0} - attribute not specified.", new String JavaDoc[] {configurationElement.getContributor().getName()}), null); //$NON-NLS-1$
1777
DebugPlugin.log(s);
1778                }
1779            }
1780        }
1781    }
1782
1783    /**
1784     * Initializes the listing of <code>LaunchConfigurationType</code>s.
1785     */

1786    private synchronized void initializeLaunchConfigurationTypes() {
1787        if (fLaunchConfigurationTypes == null) {
1788            hookResourceChangeListener();
1789            IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_LAUNCH_CONFIGURATION_TYPES);
1790            IConfigurationElement[] infos = extensionPoint.getConfigurationElements();
1791            fLaunchConfigurationTypes = new ArrayList JavaDoc(infos.length);
1792            for (int i= 0; i < infos.length; i++) {
1793                fLaunchConfigurationTypes.add(new LaunchConfigurationType(infos[i]));
1794            }
1795        }
1796    }
1797    
1798    /**
1799     * Load comparator extensions.
1800     *
1801     * @exception CoreException if an exception occurs reading
1802     * the extensions
1803     *
1804     */

1805    private synchronized void initializeLaunchModes() {
1806        if (fLaunchModes == null) {
1807            try {
1808                IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_LAUNCH_MODES);
1809                IConfigurationElement[] infos= extensionPoint.getConfigurationElements();
1810                fLaunchModes = new HashMap JavaDoc();
1811                ILaunchMode mode = null;
1812                for (int i= 0; i < infos.length; i++) {
1813                    mode = new LaunchMode(infos[i]);
1814                    fLaunchModes.put(mode.getIdentifier(), mode);
1815                }
1816            }
1817            catch (CoreException e) {DebugPlugin.log(e);}
1818        }
1819    }
1820    
1821    /**
1822     * Initializes source container type and source path computer extensions.
1823     */

1824    private synchronized void initializeSourceContainerTypes() {
1825        if (sourceContainerTypes == null) {
1826            IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_SOURCE_CONTAINER_TYPES);
1827            IConfigurationElement[] extensions = extensionPoint.getConfigurationElements();
1828            sourceContainerTypes = new HashMap JavaDoc();
1829            for (int i = 0; i < extensions.length; i++) {
1830                sourceContainerTypes.put(
1831                        extensions[i].getAttribute(IConfigurationElementConstants.ID),
1832                        new SourceContainerType(extensions[i]));
1833            }
1834            extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_SOURCE_PATH_COMPUTERS);
1835            extensions = extensionPoint.getConfigurationElements();
1836            sourcePathComputers = new HashMap JavaDoc();
1837            for (int i = 0; i < extensions.length; i++) {
1838                sourcePathComputers.put(
1839                        extensions[i].getAttribute(IConfigurationElementConstants.ID),
1840                        new SourcePathComputer(extensions[i]));
1841            }
1842        }
1843    }
1844
1845    /**
1846     * Register source locators.
1847     *
1848     * @exception CoreException if an exception occurs reading
1849     * the extensions
1850     */

1851    private synchronized void initializeSourceLocators() {
1852        if (fSourceLocators == null) {
1853            IExtensionPoint extensionPoint= Platform.getExtensionRegistry().getExtensionPoint(DebugPlugin.getUniqueIdentifier(), DebugPlugin.EXTENSION_POINT_SOURCE_LOCATORS);
1854            IConfigurationElement[] infos= extensionPoint.getConfigurationElements();
1855            fSourceLocators= new HashMap JavaDoc(infos.length);
1856            IConfigurationElement configurationElement = null;
1857            String JavaDoc id = null;
1858            for (int i= 0; i < infos.length; i++) {
1859                configurationElement = infos[i];
1860                id = configurationElement.getAttribute(IConfigurationElementConstants.ID);
1861                if (id != null) {
1862                    fSourceLocators.put(id,configurationElement);
1863                } else {
1864                    // invalid status handler
1865
IStatus s = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugException.INTERNAL_ERROR,
1866                    MessageFormat.format("Invalid source locator extension defined by plug-in \"{0}\": \"id\" not specified.", new String JavaDoc[] {configurationElement.getContributor().getName()} ), null); //$NON-NLS-1$
1867
DebugPlugin.log(s);
1868                }
1869            }
1870        }
1871    }
1872
1873    /**
1874     * Adds the given launch object to the list of registered launches,
1875     * and returns whether the launch was added.
1876     *
1877     * @param launch launch to register
1878     * @return whether the launch was added
1879     */

1880    protected boolean internalAddLaunch(ILaunch launch) {
1881        // ensure the step filter manager is created on the first launch
1882
getStepFilterManager();
1883        synchronized (fLaunches) {
1884            if (fLaunches.contains(launch)) {
1885                return false;
1886            }
1887            fLaunches.add(launch);
1888            fLaunchSet.add(launch);
1889            return true;
1890        }
1891    }
1892
1893    /**
1894     * Removes the given launch object from the collection of registered
1895     * launches. Returns whether the launch was removed.
1896     *
1897     * @param launch the launch to remove
1898     * @return whether the launch was removed
1899     */

1900    protected boolean internalRemoveLaunch(ILaunch launch) {
1901        if (launch == null) {
1902            return false;
1903        }
1904        synchronized (fLaunches) {
1905            fLaunchSet.remove(launch);
1906            return fLaunches.remove(launch);
1907        }
1908    }
1909    /**
1910     * @see ILaunchManager#isExistingLaunchConfigurationName(String)
1911     */

1912    public boolean isExistingLaunchConfigurationName(String JavaDoc name) {
1913        String JavaDoc[] sortedConfigNames = getAllSortedConfigNames();
1914        int index = Arrays.binarySearch(sortedConfigNames, name);
1915        if (index < 0) {
1916            return false;
1917        }
1918        return true;
1919    }
1920    
1921    /**
1922     * Returns whether the given String is composed solely of digits
1923     */

1924    private boolean isNumber(String JavaDoc string) {
1925        int numChars= string.length();
1926        if (numChars == 0) {
1927            return false;
1928        }
1929        for (int i= 0; i < numChars; i++) {
1930            if (!Character.isDigit(string.charAt(i))) {
1931                return false;
1932            }
1933        }
1934        return true;
1935    }
1936    
1937    /**
1938     * Returns whether the user has selected to delete associated configurations when a
1939     * project is deleted.
1940     *
1941     * @return whether to auto-delete configurations
1942     */

1943    private boolean isDeleteConfigurations() {
1944        return DebugPlugin.getDefault().getPluginPreferences().getBoolean(PREF_DELETE_CONFIGS_ON_PROJECT_DELETE);
1945    }
1946    
1947    /* (non-Javadoc)
1948     * @see org.eclipse.debug.core.ILaunchManager#isRegistered(org.eclipse.debug.core.ILaunch)
1949     */

1950    public boolean isRegistered(ILaunch launch) {
1951        synchronized (fLaunches) {
1952            return fLaunchSet.contains(launch);
1953        }
1954    }
1955
1956    /**
1957     * Returns whether the given launch configuration passes a basic
1958     * integrity test by retrieving its type.
1959     *
1960     * @param config the configuration to verify
1961     * @return whether the config meets basic integrity constraints
1962     */

1963    protected boolean isValid(ILaunchConfiguration config) {
1964        try {
1965            config.getType();
1966        } catch (CoreException e) {
1967            if (e.getStatus().getCode() != DebugException.MISSING_LAUNCH_CONFIGURATION_TYPE) {
1968                // only log warnings due to something other than a missing
1969
// launch config type
1970
DebugPlugin.log(e);
1971            }
1972            return false;
1973        }
1974        return true;
1975    }
1976    
1977    /**
1978     * Notifies the launch manager that a launch configuration
1979     * has been added. The configuration is added to the index of
1980     * configurations by project, and listeners are notified.
1981     *
1982     * @param config the launch configuration that was added
1983     */

1984    protected void launchConfigurationAdded(ILaunchConfiguration config) {
1985        if (config.isWorkingCopy()) {
1986            return;
1987        }
1988        if (isValid(config)) {
1989            boolean added = false;
1990            synchronized (this) {
1991                List JavaDoc allConfigs = getAllLaunchConfigurations();
1992                if (!allConfigs.contains(config)) {
1993                    allConfigs.add(config);
1994                    added = true;
1995                }
1996            }
1997            if (added) {
1998                getConfigurationNotifier().notify(config, ADDED);
1999                clearConfigNameCache();
2000            }
2001        } else {
2002            launchConfigurationDeleted(config);
2003        }
2004    }
2005    
2006    /**
2007     * Notifies the launch manager that a launch configuration
2008     * has been changed. The configuration is removed from the
2009     * cache of info objects such that the new attributes will
2010     * be updated on the next access. Listeners are notified of
2011     * the change.
2012     *
2013     * @param config the launch configuration that was changed
2014     */

2015    protected void launchConfigurationChanged(ILaunchConfiguration config) {
2016        synchronized(this) {
2017            fLaunchConfigurations.remove(config);
2018        }
2019        clearConfigNameCache();
2020        if (isValid(config)) {
2021            // in case the config has been refreshed and it was removed from the
2022
// index due to 'out of synch with local file system' (see bug 36147),
2023
// add it back (will only add if required)
2024
launchConfigurationAdded(config);
2025            getConfigurationNotifier().notify(config, CHANGED);
2026        } else {
2027            launchConfigurationDeleted(config);
2028        }
2029    }
2030    
2031    /**
2032     * Notifies the launch manager that a launch configuration
2033     * has been deleted. The configuration is removed from the
2034     * cache of info and from the index of configurations by
2035     * project, and listeners are notified.
2036     *
2037     * @param config the launch configuration that was deleted
2038     */

2039    protected void launchConfigurationDeleted(ILaunchConfiguration config) {
2040        synchronized (this) {
2041            fLaunchConfigurations.remove(config);
2042            getAllLaunchConfigurations().remove(config);
2043        }
2044        getConfigurationNotifier().notify(config, REMOVED);
2045        clearConfigNameCache();
2046    }
2047    
2048    /**
2049     * @see ILaunchManager#newSourceLocator(String)
2050     */

2051    public IPersistableSourceLocator newSourceLocator(String JavaDoc identifier) throws CoreException {
2052        initializeSourceLocators();
2053        IConfigurationElement config = (IConfigurationElement)fSourceLocators.get(identifier);
2054        if (config == null) {
2055            throw new CoreException(new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugException.INTERNAL_ERROR,
2056                MessageFormat.format(DebugCoreMessages.LaunchManager_Source_locator_does_not_exist___0__13, new String JavaDoc[] {identifier} ), null));
2057        }
2058        IPersistableSourceLocator sourceLocator = (IPersistableSourceLocator)config.createExecutableExtension("class"); //$NON-NLS-1$
2059
if (sourceLocator instanceof AbstractSourceLookupDirector) {
2060            ((AbstractSourceLookupDirector)sourceLocator).setId(identifier);
2061        }
2062        return sourceLocator;
2063    }
2064    
2065    /**
2066     * The specified project has just closed - remove its
2067     * launch configurations from the cached index.
2068     *
2069     * @param project the project that has been closed
2070     * @exception CoreException if writing the index fails
2071     */

2072    protected void projectClosed(IProject project) {
2073        List JavaDoc configs = getLaunchConfigurations(project);
2074        if (!configs.isEmpty()) {
2075            Iterator JavaDoc iterator = configs.iterator();
2076            while (iterator.hasNext()) {
2077                launchConfigurationDeleted((ILaunchConfiguration)iterator.next());
2078            }
2079        }
2080        //bug 12134
2081
terminateMappedConfigurations(project);
2082    }
2083    
2084    /**
2085     * The specified project has just opened - add all launch
2086     * configs in the project to the index of all configs.
2087     *
2088     * @param project the project that has been opened
2089     * @exception CoreException if reading the index fails
2090     */

2091    protected void projectOpened(IProject project) {
2092        List JavaDoc configs = findLaunchConfigurations(project);
2093        if (!configs.isEmpty()) {
2094            Iterator JavaDoc iterator = configs.iterator();
2095            while (iterator.hasNext()) {
2096                launchConfigurationAdded((ILaunchConfiguration) iterator.next());
2097            }
2098        }
2099    }
2100    
2101    /**
2102     * @see ILaunchManager#removeLaunch(ILaunch)
2103     */

2104    public void removeLaunch(final ILaunch launch) {
2105        if (internalRemoveLaunch(launch)) {
2106            fireUpdate(launch, REMOVED);
2107            fireUpdate(new ILaunch[] {launch}, REMOVED);
2108        }
2109    }
2110    
2111    /**
2112     * @see ILaunchManager#removeLaunchConfigurationListener(ILaunchConfigurationListener)
2113     */

2114    public void removeLaunchConfigurationListener(ILaunchConfigurationListener listener) {
2115        fLaunchConfigurationListeners.remove(listener);
2116    }
2117    
2118    /**
2119     * @see org.eclipse.debug.core.ILaunchManager#removeLaunches(org.eclipse.debug.core.ILaunch[])
2120     */

2121    public void removeLaunches(ILaunch[] launches) {
2122        List JavaDoc removed = new ArrayList JavaDoc(launches.length);
2123        for (int i = 0; i < launches.length; i++) {
2124            if (internalRemoveLaunch(launches[i])) {
2125                removed.add(launches[i]);
2126            }
2127        }
2128        if (!removed.isEmpty()) {
2129            ILaunch[] removedLaunches = (ILaunch[])removed.toArray(new ILaunch[removed.size()]);
2130            fireUpdate(removedLaunches, REMOVED);
2131            for (int i = 0; i < removedLaunches.length; i++) {
2132                fireUpdate(removedLaunches[i], REMOVED);
2133            }
2134        }
2135    }
2136    /**
2137     * @see org.eclipse.debug.core.ILaunchManager#removeLaunchListener(org.eclipse.debug.core.ILaunchesListener)
2138     */

2139    public void removeLaunchListener(ILaunchesListener listener) {
2140        fLaunchesListeners.remove(listener);
2141    }
2142    
2143    /**
2144     * @see ILaunchManager#removeLaunchListener(ILaunchListener)
2145     */

2146    public void removeLaunchListener(ILaunchListener listener) {
2147        fListeners.remove(listener);
2148    }
2149    
2150    /**
2151     * Traverses the delta looking for added/removed/changed launch
2152     * configuration files.
2153     *
2154     * @see IResourceChangeListener#resourceChanged(IResourceChangeEvent)
2155     */

2156    public void resourceChanged(IResourceChangeEvent event) {
2157        IResourceDelta delta = event.getDelta();
2158        if (delta == null) {
2159            // pre-delete
2160
LaunchManagerVisitor visitor = getDeltaVisitor();
2161            IResource resource = event.getResource();
2162            if (resource instanceof IProject) {
2163                IProject project = (IProject) resource;
2164                visitor.preDelete(project);
2165            }
2166        } else {
2167            LaunchManagerVisitor visitor = getDeltaVisitor();
2168            try {
2169                delta.accept(visitor);
2170            } catch (CoreException e) {
2171                DebugPlugin.log(e.getStatus());
2172            }
2173            visitor.reset();
2174        }
2175    }
2176    
2177    /**
2178     * Gets the launch configuration associated with the specified project.
2179     * This method relies on the resource mapping existing, if no such mapping
2180     * exists the launch configuration is ignored.
2181     *
2182     * @param project the project to collect launch configurations for
2183     * @return the list of associated launch configurations
2184     */

2185    private ArrayList JavaDoc collectAssociatedLaunches(IProject project) {
2186        ArrayList JavaDoc list = new ArrayList JavaDoc();
2187        try {
2188            ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations();
2189            IResource[] resources = null;
2190            for(int i = 0; i < configs.length; i++) {
2191                if(configs[i].isLocal()) {
2192                    resources = configs[i].getMappedResources();
2193                    if(resources != null) {
2194                        for(int j = 0; j < resources.length; j++){
2195                            if(project.equals(resources[j].getProject())) {
2196                                list.add(configs[i]);
2197                            }
2198                        }
2199                    }
2200                }
2201            }
2202        } catch (CoreException e) {
2203            DebugPlugin.log(e);
2204        }
2205        return list;
2206    }
2207    
2208    /**
2209     * Indicates the given launch configuration is being moved from the given
2210     * location to the new location.
2211     *
2212     * @param from the location a launch configuration is being moved from, or
2213     * <code>null</code>
2214     * @param to the location a launch configuration is being moved to,
2215     * or <code>null</code>
2216     */

2217    protected void setMovedFromTo(ILaunchConfiguration from, ILaunchConfiguration to) {
2218        fFrom = from;
2219        fTo = to;
2220    }
2221    /**
2222     * Terminates/Disconnects any active debug targets/processes.
2223     * Clears launch configuration types.
2224     */

2225    public void shutdown() {
2226        fListeners = new ListenerList();
2227        fLaunchesListeners = new ListenerList();
2228        fLaunchConfigurationListeners = new ListenerList();
2229        ILaunch[] launches = getLaunches();
2230        ILaunch launch = null;
2231        for (int i= 0; i < launches.length; i++) {
2232            launch = launches[i];
2233            try {
2234                if (launch instanceof IDisconnect) {
2235                    IDisconnect disconnect = (IDisconnect)launch;
2236                    if (disconnect.canDisconnect()) {
2237                        disconnect.disconnect();
2238                    }
2239                }
2240                if (launch.canTerminate()) {
2241                    launch.terminate();
2242                }
2243            } catch (DebugException e) {
2244                DebugPlugin.log(e);
2245            }
2246        }
2247        
2248        persistPreferredLaunchDelegates();
2249        clearAllLaunchConfigurations();
2250        fStepFilterManager = null;
2251        ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
2252    }
2253
2254    /**
2255     * Saves the listings of preferred launch delegates from all of the launch configuration types
2256     *
2257     * @since 3.3
2258     */

2259    private void persistPreferredLaunchDelegates() {
2260        Preferences prefs = DebugPlugin.getDefault().getPluginPreferences();
2261        try {
2262            Document JavaDoc doc = DebugPlugin.newDocument();
2263            Element root = doc.createElement(IConfigurationElementConstants.PREFERRED_DELEGATES);
2264            doc.appendChild(root);
2265            ILaunchConfigurationType[] types = getLaunchConfigurationTypes();
2266            Map JavaDoc preferred = null;
2267            Element child = null;
2268            ILaunchDelegate delegate = null;
2269            Set JavaDoc modes = null;
2270            String JavaDoc modestr = EMPTY_STRING;
2271            for(int i = 0; i < types.length; i++) {
2272                preferred = ((LaunchConfigurationType)types[i]).getPreferredDelegates();
2273                if(preferred != null && preferred.size() > 0) {
2274                    for(Iterator JavaDoc iter = preferred.keySet().iterator(); iter.hasNext();) {
2275                        modes = (Set JavaDoc) iter.next();
2276                        delegate = (ILaunchDelegate) preferred.get(modes);
2277                        if(delegate != null) {
2278                            child = doc.createElement(IConfigurationElementConstants.DELEGATE);
2279                            child.setAttribute(IConfigurationElementConstants.ID, delegate.getId());
2280                            child.setAttribute(IConfigurationElementConstants.TYPE_ID, types[i].getIdentifier());
2281                            for(Iterator JavaDoc iter2 = modes.iterator(); iter2.hasNext();) {
2282                                modestr += iter2.next();
2283                                if(iter2.hasNext()) {
2284                                    modestr += ","; //$NON-NLS-1$
2285
}
2286                            }
2287                            child.setAttribute(IConfigurationElementConstants.MODES, modestr);
2288                            modestr = EMPTY_STRING;
2289                            root.appendChild(child);
2290                        }
2291                    }
2292                }
2293            }
2294            String JavaDoc pref = null;
2295            if(root.hasChildNodes()) {
2296                pref = serializeDocument(doc);
2297            }
2298            if(pref != null) {
2299                prefs.setValue(PREF_PREFERRED_DELEGATES, pref);
2300            }
2301        }
2302        catch (CoreException e) {DebugPlugin.log(e);}
2303        catch (IOException JavaDoc ioe) {DebugPlugin.log(ioe);}
2304        catch (TransformerException JavaDoc te) {DebugPlugin.log(te);}
2305    }
2306    
2307    /**
2308     * finds and terminates any running launch configurations associated with the given resource
2309     * @param resource the resource to search for launch configurations and hence launches for
2310     * @since 3.2
2311     */

2312    protected void terminateMappedConfigurations(IResource resource) {
2313        ILaunch[] launches = getLaunches();
2314        ILaunchConfiguration[] configs = getMappedConfigurations(resource);
2315        try {
2316            for(int i = 0; i < launches.length; i++) {
2317                for(int j = 0; j < configs.length; j++) {
2318                    if(configs[j].equals(launches[i].getLaunchConfiguration()) & launches[i].canTerminate()) {
2319                        launches[i].terminate();
2320                    }
2321                }
2322            }
2323        }
2324        catch(CoreException e) {DebugPlugin.log(e);}
2325    }
2326    
2327    /**
2328     * Throws a debug exception with the given throwable that occurred
2329     * while processing the given configuration.
2330     */

2331    private void throwException(ILaunchConfiguration config, Throwable JavaDoc e) throws DebugException {
2332        IPath path = config.getLocation();
2333        throw createDebugException(MessageFormat.format(DebugCoreMessages.LaunchManager__0__occurred_while_reading_launch_configuration_file__1___1, new String JavaDoc[]{e.toString(), path.toOSString()}), e);
2334    }
2335
2336    /**
2337     * Verify basic integrity of launch configurations in the given list,
2338     * adding valid configurations to the collection of all launch configurations.
2339     * Exceptions are logged for invalid configurations.
2340     *
2341     * @param verify the list of configurations to verify
2342     * @param valid the list to place valid configurations in
2343     */

2344    protected void verifyConfigurations(List JavaDoc verify, List JavaDoc valid) {
2345        Iterator JavaDoc configs = verify.iterator();
2346        ILaunchConfiguration config = null;
2347        while (configs.hasNext()) {
2348            config = (ILaunchConfiguration)configs.next();
2349            if (isValid(config)) {
2350                valid.add(config);
2351            }
2352        }
2353    }
2354    
2355    /**
2356     * Returns the name of the given launch mode with accelerators removed,
2357     * or <code>null</code> if none.
2358     *
2359     * @param id launch mode identifier
2360     * @return launch mode name with accelerators removed or <code>null</code>
2361     */

2362    public String JavaDoc getLaunchModeName(String JavaDoc id) {
2363        ILaunchMode launchMode = getLaunchMode(id);
2364        if (launchMode != null) {
2365            return removeAccelerators(launchMode.getLabel());
2366        }
2367        return null;
2368    }
2369    /**
2370     * Returns the label with any accelerators removed.
2371     *
2372     * @param label label to process
2373     * @return label without accelerators
2374     */

2375    public static String JavaDoc removeAccelerators(String JavaDoc label) {
2376        String JavaDoc title = label;
2377        if (title != null) {
2378            // strip out any '&' (accelerators)
2379
int index = title.indexOf('&');
2380            if (index == 0) {
2381                title = title.substring(1);
2382            } else if (index > 0) {
2383                //DBCS languages use "(&X)" format
2384
if (title.charAt(index - 1) == '(' && title.length() >= index + 3 && title.charAt(index + 2) == ')') {
2385                    String JavaDoc first = title.substring(0, index - 1);
2386                    String JavaDoc last = title.substring(index + 3);
2387                    title = first + last;
2388                } else if (index < (title.length() - 1)) {
2389                    String JavaDoc first = title.substring(0, index);
2390                    String JavaDoc last = title.substring(index + 1);
2391                    title = first + last;
2392                }
2393            }
2394        }
2395        return title;
2396    }
2397    
2398    /**
2399     * Returns the singleton step filter manager.
2400     *
2401     * @return the step filter manager
2402     */

2403    public synchronized StepFilterManager getStepFilterManager() {
2404        if (fStepFilterManager == null) {
2405            fStepFilterManager = new StepFilterManager();
2406        }
2407        return fStepFilterManager;
2408    }
2409    
2410}
2411
Popular Tags