KickJava   Java API By Example, From Geeks To Geeks.

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


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

11 package org.eclipse.debug.internal.core;
12
13  
14 import java.io.ByteArrayInputStream JavaDoc;
15 import java.io.File JavaDoc;
16 import java.io.FileOutputStream JavaDoc;
17 import java.io.IOException JavaDoc;
18 import java.io.UnsupportedEncodingException JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.List JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.Set JavaDoc;
24
25 import javax.xml.parsers.ParserConfigurationException JavaDoc;
26 import javax.xml.transform.TransformerException JavaDoc;
27
28 import org.eclipse.core.resources.IContainer;
29 import org.eclipse.core.resources.IFile;
30 import org.eclipse.core.resources.IResource;
31 import org.eclipse.core.resources.IWorkspaceRunnable;
32 import org.eclipse.core.resources.ResourcesPlugin;
33 import org.eclipse.core.runtime.CoreException;
34 import org.eclipse.core.runtime.IPath;
35 import org.eclipse.core.runtime.IProgressMonitor;
36 import org.eclipse.core.runtime.IStatus;
37 import org.eclipse.core.runtime.NullProgressMonitor;
38 import org.eclipse.core.runtime.Status;
39 import org.eclipse.core.runtime.SubProgressMonitor;
40 import org.eclipse.debug.core.DebugException;
41 import org.eclipse.debug.core.DebugPlugin;
42 import org.eclipse.debug.core.ILaunchConfiguration;
43 import org.eclipse.debug.core.ILaunchConfigurationType;
44 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
45
46 import com.ibm.icu.text.MessageFormat;
47
48 /**
49  * A working copy launch configuration
50  */

51 public class LaunchConfigurationWorkingCopy extends LaunchConfiguration implements ILaunchConfigurationWorkingCopy {
52     
53     /**
54      * Handle of original launch configuration this
55      * working copy is based on
56      */

57     private LaunchConfiguration fOriginal;
58     
59     /**
60      * Handle to a parent working copy
61      * @since 3.3
62      */

63     private LaunchConfigurationWorkingCopy fParent = null;
64     
65     /**
66      * Working copy of attributes.
67      */

68     private LaunchConfigurationInfo fInfo;
69     
70     /**
71      * Whether this working copy has been modified since
72      * it was created
73      */

74     private boolean fDirty = false;
75     
76     /**
77      * The name for this configuration.
78      */

79     private String JavaDoc fName;
80     
81     /**
82      * Indicates whether this working copy has been explicitly renamed.
83      */

84     private boolean fRenamed = false;
85     
86     /**
87      * Suppress change notification until created
88      */

89     private boolean fSuppressChange = true;
90     
91     /**
92      * The container this working copy will be
93      * stored in when saved.
94      */

95     private IContainer fContainer;
96     
97     /**
98      * Constructs a working copy of the specified launch
99      * configuration.
100      *
101      * @param original launch configuration to make
102      * a working copy of
103      * @exception CoreException if unable to initialize this
104      * working copy's attributes based on the original configuration
105      */

106     protected LaunchConfigurationWorkingCopy(LaunchConfiguration original) throws CoreException {
107         super(original.getLocation());
108         setName(original.getName());
109         copyFrom(original);
110         setOriginal(original);
111         fSuppressChange = false;
112     }
113     
114     /**
115      * Constructs a working copy of the specified launch configuration as its parent.
116      *
117      * @param parent launch configuration to make
118      * a working copy of
119      * @exception CoreException if unable to initialize this
120      * working copy's attributes based on the original configuration
121      */

122     protected LaunchConfigurationWorkingCopy(LaunchConfigurationWorkingCopy parent) throws CoreException {
123         super(parent.getLocation());
124         setName(parent.getName());
125         copyFrom(parent);
126         setOriginal((LaunchConfiguration) parent.getOriginal());
127         fParent = parent;
128         fSuppressChange = false;
129     }
130     
131     /**
132      * Constructs a copy of the specified launch
133      * configuration, with the given (new) name.
134      *
135      * @param original launch configuration to make
136      * a working copy of
137      * @param name the new name for the copy of the launch
138      * configuration
139      * @exception CoreException if unable to initialize this
140      * working copy's attributes based on the original configuration
141      */

142     protected LaunchConfigurationWorkingCopy(LaunchConfiguration original, String JavaDoc name) throws CoreException {
143         super(original.getLocation());
144         copyFrom(original);
145         setName(name);
146         fSuppressChange = false;
147     }
148     
149     /**
150      * Constructs a new working copy to be created in the specified
151      * location.
152      *
153      * @param container the container that the configuration will be created in
154      * or <code>null</code> if to be local
155      * @param name the name of the new launch configuration
156      * @param type the type of this working copy
157      */

158     protected LaunchConfigurationWorkingCopy(IContainer container, String JavaDoc name, ILaunchConfigurationType type) {
159         super((IPath)null);
160         setName(name);
161         setInfo(new LaunchConfigurationInfo());
162         getInfo().setType(type);
163         setContainer(container);
164         fSuppressChange = false;
165     }
166
167     /**
168      * @see ILaunchConfigurationWorkingCopy#isDirty()
169      */

170     public boolean isDirty() {
171         return fDirty;
172     }
173
174     /**
175      * @see ILaunchConfigurationWorkingCopy#doSave()
176      */

177     public synchronized ILaunchConfiguration doSave() throws CoreException {
178         return doSave(new NullProgressMonitor());
179     }
180
181     /**
182      * Saves with progress.
183      *
184      * @param monitor
185      * @return the saved <code>ILaunchConfiguration</code>
186      * @throws CoreException
187      *
188      * @since 3.3
189      */

190     public synchronized ILaunchConfiguration doSave(IProgressMonitor monitor) throws CoreException {
191         if (getParent() != null) {
192             // save to parent working copy
193
LaunchConfigurationWorkingCopy wc = (LaunchConfigurationWorkingCopy) getParent();
194             if(isMoved()) {
195                 wc.rename(getName());
196                 wc.setContainer(getContainer());
197             }
198             wc.setAttributes(getInfo().getAttributes());
199             return wc;
200         }
201         else {
202             boolean useRunnable= true;
203             if (isLocal()) {
204                 if (isMoved()) {
205                     // If this config was moved from a shared location, saving
206
// it will delete the original from the workspace. Use runnable.
207
useRunnable= !isNew() && !getOriginal().isLocal();
208                 } else {
209                     useRunnable= false;
210                 }
211             }
212             if (useRunnable) {
213                 IWorkspaceRunnable wr = new IWorkspaceRunnable() {
214                     public void run(IProgressMonitor pm) throws CoreException {
215                         doSave0(pm);
216                     }
217                 };
218                 ResourcesPlugin.getWorkspace().run(wr, null, 0, monitor);
219             } else {
220                 //file is persisted in the metadata not the workspace
221
doSave0(monitor);
222             }
223             getLaunchManager().setMovedFromTo(null, null);
224         }
225         return new LaunchConfiguration(getLocation());
226     }
227     
228     /**
229      * Performs the actual saving of the launch configuration.
230      * @throws CoreException
231      */

232     private void doSave0(IProgressMonitor monitor) throws CoreException {
233         // set up from/to information if this is a move
234
boolean moved = (!isNew() && isMoved());
235         if (moved) {
236             ILaunchConfiguration to = new LaunchConfiguration(getLocation());
237             ILaunchConfiguration from = getOriginal();
238             getLaunchManager().setMovedFromTo(from, to);
239         }
240         // delete the old file if this is not a new configuration
241
// or the file was renamed/moved
242
if (moved) {
243             getOriginal().delete();
244         }
245         // write the new file
246
if(monitor == null) {
247             monitor = new NullProgressMonitor();
248         }
249         monitor.beginTask(MessageFormat.format(DebugCoreMessages.LaunchConfigurationWorkingCopy_0, new String JavaDoc[] {getName()}), 2);
250         writeNewFile(monitor);
251         monitor.done();
252         fDirty = false;
253     }
254     
255     /**
256      * Writes the new configuration information to a file.
257      *
258      * @exception CoreException if writing the file fails
259      */

260     protected void writeNewFile(IProgressMonitor monitor) throws CoreException {
261         String JavaDoc xml = null;
262         Exception JavaDoc e= null;
263         try {
264             xml = getInfo().getAsXML();
265         } catch (IOException JavaDoc ioe) {
266             e= ioe;
267         } catch (ParserConfigurationException JavaDoc pce) {
268             e= pce;
269         } catch (TransformerException JavaDoc te) {
270             e= te;
271         }
272         if (e != null) {
273             throw new DebugException(
274                 new Status(
275                     IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
276                     DebugException.REQUEST_FAILED, MessageFormat.format(DebugCoreMessages.LaunchConfigurationWorkingCopy__0__occurred_generating_launch_configuration_XML__1, new String JavaDoc[]{e.toString()}), null
277                     )
278                 );
279         }
280         
281         if (isLocal()) {
282             // use java.io to update configuration file
283
try {
284                 boolean added = false;
285                 monitor.subTask(DebugCoreMessages.LaunchConfigurationWorkingCopy_1);
286                 File JavaDoc file = getLocation().toFile();
287                 File JavaDoc dir = getLocation().removeLastSegments(1).toFile();
288                 dir.mkdirs();
289                 if (!file.exists()) {
290                     added = true;
291                     file.createNewFile();
292                     monitor.worked(1);
293                 }
294                 FileOutputStream JavaDoc stream = new FileOutputStream JavaDoc(file);
295                 stream.write(xml.getBytes("UTF8")); //$NON-NLS-1$
296
stream.close();
297                 
298                 if (added) {
299                     getLaunchManager().launchConfigurationAdded(new LaunchConfiguration(getLocation()));
300                 } else {
301                     getLaunchManager().launchConfigurationChanged(new LaunchConfiguration(getLocation()));
302                 }
303                 //notify file saved
304
monitor.worked(1);
305             } catch (IOException JavaDoc ie) {
306                 monitor.setCanceled(true);
307                 throw new DebugException(
308                     new Status(
309                      IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
310                      DebugException.REQUEST_FAILED, MessageFormat.format(DebugCoreMessages.LaunchConfigurationWorkingCopy__0__occurred_generating_launch_configuration_XML__1, new String JavaDoc[]{ie.toString()}), null
311                     )
312                 );
313             }
314         } else {
315             // use resource API to update configuration file
316
IFile file = getFile();
317             if (file == null) {
318                 monitor.setCanceled(true);
319                 throw new DebugException(
320                         new Status(
321                              IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
322                              DebugException.REQUEST_FAILED, DebugCoreMessages.LaunchConfigurationWorkingCopy_5, null
323                         ));
324             }
325             IContainer dir = file.getParent();
326             if (!dir.exists()) {
327                 monitor.setCanceled(true);
328                 throw new DebugException(
329                     new Status(
330                      IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
331                      DebugException.REQUEST_FAILED, DebugCoreMessages.LaunchConfigurationWorkingCopy_Specified_container_for_launch_configuration_does_not_exist_2, null
332                     )
333                 );
334             }
335             ByteArrayInputStream JavaDoc stream = null;
336             try {
337                 stream = new ByteArrayInputStream JavaDoc(xml.getBytes("UTF8")); //$NON-NLS-1$
338
} catch (UnsupportedEncodingException JavaDoc ue) {
339                 monitor.setCanceled(true);
340                 throw new DebugException(
341                     new Status(
342                          IStatus.ERROR, DebugPlugin.getUniqueIdentifier(),
343                          DebugException.REQUEST_FAILED, DebugCoreMessages.LaunchConfigurationWorkingCopy_5, ue
344                     ));
345             }
346             SubProgressMonitor spm = null;
347             if (!file.exists()) {
348     //create file input stream: work one unit in a sub monitor
349
spm = new SubProgressMonitor(monitor, 1);
350                 spm.setTaskName(MessageFormat.format(DebugCoreMessages.LaunchConfigurationWorkingCopy_2, new String JavaDoc[] {getName()}));
351                 file.create(stream, false, spm);
352             } else {
353                 // validate edit
354
if (file.isReadOnly()) {
355                     IStatus status = ResourcesPlugin.getWorkspace().validateEdit(new IFile[] {file}, null);
356                     if (!status.isOK()) {
357                         monitor.setCanceled(true);
358                         throw new CoreException(status);
359                     }
360                 }
361     //set the contents of the file: work 1 unit in a sub monitor
362
spm = new SubProgressMonitor(monitor, 1);
363                 spm.setTaskName(MessageFormat.format(DebugCoreMessages.LaunchConfigurationWorkingCopy_3, new String JavaDoc[] {getName()}));
364                 file.setContents(stream, true, false, spm);
365             }
366         }
367         if(monitor.isCanceled()) {
368             return;
369         }
370     }
371
372     /**
373      * @see ILaunchConfigurationWorkingCopy#setAttribute(String, int)
374      */

375     public void setAttribute(String JavaDoc attributeName, int value) {
376         getInfo().setAttribute(attributeName, new Integer JavaDoc(value));
377         setDirty();
378     }
379
380     /**
381      * @see ILaunchConfigurationWorkingCopy#setAttribute(String, String)
382      */

383     public void setAttribute(String JavaDoc attributeName, String JavaDoc value) {
384         getInfo().setAttribute(attributeName, value);
385         setDirty();
386     }
387
388     /**
389      * @see ILaunchConfigurationWorkingCopy#setAttribute(String, boolean)
390      */

391     public void setAttribute(String JavaDoc attributeName, boolean value) {
392         getInfo().setAttribute(attributeName, Boolean.valueOf(value));
393         setDirty();
394     }
395
396     /**
397      * @see ILaunchConfigurationWorkingCopy#setAttribute(String, List)
398      */

399     public void setAttribute(String JavaDoc attributeName, List JavaDoc value) {
400         getInfo().setAttribute(attributeName, value);
401         setDirty();
402     }
403
404     /**
405      * @see ILaunchConfigurationWorkingCopy#setAttribute(String, Map)
406      */

407     public void setAttribute(String JavaDoc attributeName, Map JavaDoc value) {
408         getInfo().setAttribute(attributeName, value);
409         setDirty();
410     }
411
412     /**
413      * @see ILaunchConfigurationWorkingCopy#getOriginal()
414      */

415     public ILaunchConfiguration getOriginal() {
416         ILaunchConfiguration config = fOriginal;
417         ILaunchConfigurationWorkingCopy parent = fParent;
418         while(parent != null) {
419             config = parent.getOriginal();
420             parent = parent.getParent();
421         }
422         return config;
423     }
424     
425     /**
426      * @see org.eclipse.debug.core.ILaunchConfigurationWorkingCopy#getParent()
427      */

428     public ILaunchConfigurationWorkingCopy getParent() {
429         return fParent;
430     }
431     
432     /**
433      * Sets the launch configuration this working copy
434      * is based on. Initializes the attributes of this
435      * working copy to the current values of the given
436      * configuration.
437      *
438      * @param original the launch configuration this working
439      * copy is based on.
440      * @exception CoreException if unable to initialize this
441      * working copy based on the original's current attribute
442      * set
443      */

444     private void copyFrom(LaunchConfiguration original) throws CoreException {
445         LaunchConfigurationInfo info = original.getInfo();
446         setInfo(info.getCopy());
447         setContainer(original.getContainer());
448         fDirty = false;
449     }
450     
451     /**
452      * Sets the launch configuration this working copy
453      * is based on.
454      *
455      * @param original the launch configuration this working
456      * copy is based on.
457      */

458     private void setOriginal(LaunchConfiguration original) {
459         fOriginal = original;
460     }
461     
462     /**
463      * Sets the working copy info object for this working copy.
464      *
465      * @param info a copy of attributes from this working copy's
466      * original launch configuration
467      */

468     protected void setInfo(LaunchConfigurationInfo info) {
469         fInfo = info;
470     }
471
472     /**
473      * @see ILaunchConfiguration#isWorkingCopy()
474      */

475     public boolean isWorkingCopy() {
476         return true;
477     }
478     
479     /**
480      * A working copy keeps a local info object that is not
481      * cached with the launch manager.
482      *
483      * @see LaunchConfiguration#getInfo()
484      */

485     protected LaunchConfigurationInfo getInfo() {
486         return fInfo;
487     }
488     
489     /**
490      * Sets this working copy's state to dirty.
491      * Notifies listeners that this working copy has
492      * changed.
493      */

494     private void setDirty() {
495         fDirty = true;
496         if (!suppressChangeNotification()) {
497             getLaunchManager().getConfigurationNotifier().notify(this, LaunchManager.CHANGED);
498         }
499     }
500         
501     /**
502      * @see org.eclipse.debug.core.ILaunchConfigurationWorkingCopy#setModes(java.util.Set)
503      */

504     public void setModes(Set JavaDoc modes) {
505         getInfo().setAttribute(ATTR_LAUNCH_MODES, (modes.size() > 0 ? modes : null));
506         setDirty();
507     }
508
509     /**
510      * @see org.eclipse.debug.core.ILaunchConfigurationWorkingCopy#addModes(java.util.Set)
511      */

512     public void addModes(Set JavaDoc modes) {
513         try {
514             Set JavaDoc opts = getModes();
515             if(opts.addAll(modes)) {
516                 getInfo().setAttribute(ATTR_LAUNCH_MODES, opts);
517                 setDirty();
518             }
519         }
520         catch (CoreException e) {
521             DebugPlugin.log(e);
522         }
523     }
524     
525     /**
526      * @see org.eclipse.debug.core.ILaunchConfigurationWorkingCopy#removeModes(java.util.Set)
527      */

528     public void removeModes(Set JavaDoc options) {
529         try {
530             Set JavaDoc opts = getModes();
531             if(opts.removeAll(options)) {
532                 getInfo().setAttribute(ATTR_LAUNCH_MODES, (opts.size() < 1 ? null : opts));
533                 setDirty();
534             }
535         }
536         catch (CoreException e) {
537             DebugPlugin.log(e);
538         }
539     }
540     
541     /**
542      * @see ILaunchConfigurationWorkingCopy#rename(String)
543      */

544     public void rename(String JavaDoc name) {
545         if (!getName().equals(name)) {
546             setName(name);
547             fRenamed = isNew() || !(getOriginal().getName().equals(name));
548         }
549     }
550
551     /**
552      * Sets the new name for this configuration.
553      *
554      * @param name the new name for this configuration
555      */

556     private void setName(String JavaDoc name) {
557         fName = name;
558         setDirty();
559     }
560     
561     /**
562      * @see ILaunchConfiguration#getName()
563      */

564     public String JavaDoc getName() {
565         return fName;
566     }
567     
568     /**
569      * @see ILaunchConfiguration#isLocal()
570      */

571     public boolean isLocal() {
572         return getContainer() == null;
573     }
574     
575     /**
576      * Returns the location this launch configuration will reside at
577      * when saved.
578      *
579      * @see ILaunchConfiguration#getLocation()
580      */

581     public IPath getLocation() {
582         if (isMoved()) {
583             IPath path = null;
584             if (isLocal()) {
585                 path = LaunchManager.LOCAL_LAUNCH_CONFIGURATION_CONTAINER_PATH;
586             } else {
587                 path = getContainer().getLocation();
588             }
589             path = path.append(getName() + "." + LAUNCH_CONFIGURATION_FILE_EXTENSION); //$NON-NLS-1$
590
return path;
591         }
592         return getOriginal().getLocation();
593     }
594     
595     /**
596      * Returns whether this working copy is new, or is a
597      * working copy of another launch configuration.
598      *
599      * @return whether this working copy is new, or is a
600      * working copy of another launch configuration
601      */

602     protected boolean isNew() {
603         return getOriginal() == null;
604     }
605     
606     /**
607      * Returns whether this working copy is new or if its
608      * location has changed from that of its original.
609      *
610      * @return whether this working copy is new or if its
611      * location has changed from that of its original
612      */

613     protected boolean isMoved() {
614         if (isNew() || fRenamed) {
615             return true;
616         }
617         IContainer newContainer = getContainer();
618         IContainer originalContainer = ((LaunchConfiguration)getOriginal()).getContainer();
619         if (newContainer == originalContainer) {
620             return false;
621         }
622         if (newContainer == null) {
623             return !originalContainer.equals(newContainer);
624         }
625         return !newContainer.equals(originalContainer);
626     }
627     
628     /**
629      * A working copy cannot generate a memento.
630      *
631      * @see ILaunchConfiguration#getMemento()
632      */

633     public String JavaDoc getMemento() {
634         return null;
635     }
636     
637     /**
638      * Returns whether change notification should be
639      * suppressed
640      */

641     protected boolean suppressChangeNotification() {
642         return fSuppressChange;
643     }
644     
645     /**
646      * @see ILaunchConfigurationWorkingCopy#setContainer(IContainer)
647      */

648     public void setContainer(IContainer container) {
649         if (container == fContainer) {
650             return;
651         }
652         if (container != null) {
653             if (container.equals(fContainer)) {
654                 return;
655             }
656         } else {
657             if (fContainer.equals(container)) {
658                 return;
659             }
660         }
661         fContainer = container;
662         setDirty();
663     }
664     
665     /**
666      * Returns the container this working copy will be
667      * stored in when saved, or <code>null</code> if
668      * this working copy is local.
669      *
670      * @return the container this working copy will be
671      * stored in when saved, or <code>null</code> if
672      * this working copy is local
673      */

674     protected IContainer getContainer() {
675         return fContainer;
676     }
677     
678     /**
679      * @see org.eclipse.debug.core.ILaunchConfigurationWorkingCopy#setAttributes(java.util.Map)
680      */

681     public void setAttributes(Map JavaDoc attributes) {
682         getInfo().setAttributes(attributes);
683         setDirty();
684     }
685
686     /* (non-Javadoc)
687      * @see org.eclipse.debug.core.ILaunchConfigurationWorkingCopy#setResource(org.eclipse.core.resources.IResource)
688      */

689     public void setMappedResources(IResource[] resources) {
690         ArrayList JavaDoc paths = null;
691         ArrayList JavaDoc types = null;
692         if(resources != null && resources.length > 0) {
693             paths = new ArrayList JavaDoc(resources.length);
694             types = new ArrayList JavaDoc(resources.length);
695             for (int i = 0; i < resources.length; i++) {
696                 IResource resource = resources[i];
697                 if(resource != null) {
698                     paths.add(resource.getFullPath().toPortableString());
699                     types.add(new Integer JavaDoc(resource.getType()).toString());
700                 }
701             }
702         }
703         setAttribute(LaunchConfiguration.ATTR_MAPPED_RESOURCE_PATHS, paths);
704         setAttribute(LaunchConfiguration.ATTR_MAPPED_RESOURCE_TYPES, types);
705     }
706
707     /**
708      * @see org.eclipse.debug.core.ILaunchConfigurationWorkingCopy#setPreferredLaunchDelegate(java.util.Set, java.lang.String)
709      */

710     public void setPreferredLaunchDelegate(Set JavaDoc modes, String JavaDoc delegateId) {
711         if(modes != null) {
712             try {
713                 Map JavaDoc delegates = getAttribute(LaunchConfiguration.ATTR_PREFERRED_LAUNCHERS, (Map JavaDoc)null);
714                     //copy map to avoid pointer issues
715
Map JavaDoc map = new HashMap JavaDoc();
716                     if(delegates != null) {
717                         map.putAll(delegates);
718                     }
719                     if(delegateId == null) {
720                         map.remove(modes.toString());
721                     }
722                     else {
723                         map.put(modes.toString(), delegateId);
724                     }
725                     setAttribute(LaunchConfiguration.ATTR_PREFERRED_LAUNCHERS, map);
726             }
727             catch (CoreException ce) {DebugPlugin.log(ce);}
728         }
729     }
730     
731     /* (non-Javadoc)
732      * @see org.eclipse.debug.internal.core.LaunchConfiguration#getWorkingCopy()
733      * CONTEXTLAUNCHING
734      */

735     public ILaunchConfigurationWorkingCopy getWorkingCopy() throws CoreException {
736         return new LaunchConfigurationWorkingCopy(this);
737     }
738 }
739
740
Popular Tags