001: /*******************************************************************************
002: * Copyright (c) 2005, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.launcher;
011:
012: import java.util.ArrayList;
013: import java.util.HashSet;
014: import java.util.Iterator;
015: import java.util.Locale;
016: import java.util.Set;
017: import java.util.TreeSet;
018:
019: import org.eclipse.core.resources.IProject;
020: import org.eclipse.core.resources.IResource;
021: import org.eclipse.core.runtime.CoreException;
022: import org.eclipse.core.runtime.IAdaptable;
023: import org.eclipse.core.runtime.NullProgressMonitor;
024: import org.eclipse.core.runtime.Preferences;
025: import org.eclipse.debug.core.ILaunchConfiguration;
026: import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
027: import org.eclipse.jdt.core.IJavaProject;
028: import org.eclipse.jface.dialogs.MessageDialog;
029: import org.eclipse.jface.viewers.CheckStateChangedEvent;
030: import org.eclipse.jface.viewers.CheckboxTreeViewer;
031: import org.eclipse.jface.viewers.ICheckStateListener;
032: import org.eclipse.jface.viewers.ILabelProvider;
033: import org.eclipse.jface.viewers.ITreeContentProvider;
034: import org.eclipse.jface.window.Window;
035: import org.eclipse.osgi.util.NLS;
036: import org.eclipse.pde.core.plugin.IPluginModelBase;
037: import org.eclipse.pde.core.plugin.ModelEntry;
038: import org.eclipse.pde.core.plugin.PluginRegistry;
039: import org.eclipse.pde.internal.core.DependencyManager;
040: import org.eclipse.pde.internal.core.ICoreConstants;
041: import org.eclipse.pde.internal.core.PDECore;
042: import org.eclipse.pde.internal.ui.PDEPlugin;
043: import org.eclipse.pde.internal.ui.PDEPluginImages;
044: import org.eclipse.pde.internal.ui.PDEUIMessages;
045: import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
046: import org.eclipse.pde.internal.ui.elements.NamedElement;
047: import org.eclipse.pde.internal.ui.util.PersistablePluginObject;
048: import org.eclipse.pde.internal.ui.util.SWTUtil;
049: import org.eclipse.pde.internal.ui.wizards.ListUtil;
050: import org.eclipse.pde.ui.launcher.AbstractLauncherTab;
051: import org.eclipse.pde.ui.launcher.IPDELauncherConstants;
052: import org.eclipse.swt.SWT;
053: import org.eclipse.swt.SWTException;
054: import org.eclipse.swt.events.SelectionAdapter;
055: import org.eclipse.swt.events.SelectionEvent;
056: import org.eclipse.swt.graphics.Image;
057: import org.eclipse.swt.layout.GridData;
058: import org.eclipse.swt.layout.GridLayout;
059: import org.eclipse.swt.widgets.Button;
060: import org.eclipse.swt.widgets.Composite;
061: import org.eclipse.swt.widgets.Control;
062: import org.eclipse.swt.widgets.Label;
063: import org.eclipse.swt.widgets.Shell;
064: import org.eclipse.ui.IWorkingSet;
065: import org.eclipse.ui.IWorkingSetManager;
066: import org.eclipse.ui.PlatformUI;
067: import org.eclipse.ui.dialogs.IWorkingSetSelectionDialog;
068:
069: public abstract class AbstractPluginBlock {
070:
071: protected AbstractLauncherTab fTab;
072:
073: protected CheckboxTreeViewer fPluginTreeViewer;
074: protected NamedElement fWorkspacePlugins;
075: protected NamedElement fExternalPlugins;
076: protected IPluginModelBase[] fExternalModels;
077: protected IPluginModelBase[] fWorkspaceModels;
078: protected int fNumExternalChecked;
079: protected int fNumWorkspaceChecked;
080:
081: private Button fIncludeOptionalButton;
082: protected Button fAddWorkspaceButton;
083: private Button fAutoValidate;
084:
085: private Button fSelectAllButton;
086: private Button fDeselectButton;
087: private Button fWorkingSetButton;
088: private Button fAddRequiredButton;
089: private Button fDefaultsButton;
090:
091: private Listener fListener = new Listener();
092:
093: private Label fCounter;
094:
095: private LaunchValidationOperation fOperation;
096: private PluginStatusDialog fDialog;
097:
098: private Button fValidateButton;
099:
100: class Listener extends SelectionAdapter {
101: public void widgetSelected(SelectionEvent e) {
102: Object source = e.getSource();
103: if (source == fSelectAllButton) {
104: toggleGroups(true);
105: } else if (source == fDeselectButton) {
106: toggleGroups(false);
107: } else if (source == fWorkingSetButton) {
108: handleWorkingSets();
109: } else if (source == fAddRequiredButton) {
110: computeSubset();
111: } else if (source == fDefaultsButton) {
112: handleRestoreDefaults();
113: } else if (source == fValidateButton) {
114: handleValidate();
115: }
116: fTab.updateLaunchConfigurationDialog();
117: }
118: }
119:
120: class PluginContentProvider extends DefaultContentProvider
121: implements ITreeContentProvider {
122: public boolean hasChildren(Object parent) {
123: return !(parent instanceof IPluginModelBase);
124: }
125:
126: public Object[] getChildren(Object parent) {
127: if (parent == fExternalPlugins)
128: return fExternalModels;
129: if (parent == fWorkspacePlugins)
130: return fWorkspaceModels;
131: return new Object[0];
132: }
133:
134: public Object getParent(Object child) {
135: if (child instanceof IPluginModelBase) {
136: IResource resource = ((IPluginModelBase) child)
137: .getUnderlyingResource();
138: return resource == null ? fExternalPlugins
139: : fWorkspacePlugins;
140: }
141: return null;
142: }
143:
144: public Object[] getElements(Object input) {
145: ArrayList list = new ArrayList();
146: if (fWorkspaceModels.length > 0)
147: list.add(fWorkspacePlugins);
148: if (fExternalModels.length > 0)
149: list.add(fExternalPlugins);
150: return list.toArray();
151: }
152: }
153:
154: public AbstractPluginBlock(AbstractLauncherTab tab) {
155: fTab = tab;
156: PDEPlugin.getDefault().getLabelProvider().connect(this );
157: fExternalModels = getExternalModels(); //PluginRegistry.getExternalModels(); //getExternalModels();
158: fWorkspaceModels = PluginRegistry.getWorkspaceModels();
159: }
160:
161: protected IPluginModelBase[] getExternalModels() {
162: Preferences pref = PDECore.getDefault().getPluginPreferences();
163: String saved = pref.getString(ICoreConstants.CHECKED_PLUGINS);
164: if (saved.equals(ICoreConstants.VALUE_SAVED_NONE))
165: return new IPluginModelBase[0];
166:
167: IPluginModelBase[] models = PluginRegistry.getExternalModels();
168: if (saved.equals(ICoreConstants.VALUE_SAVED_ALL))
169: return models;
170:
171: ArrayList list = new ArrayList(models.length);
172: for (int i = 0; i < models.length; i++) {
173: if (models[i].isEnabled()) {
174: list.add(models[i]);
175: }
176: }
177: return (IPluginModelBase[]) list
178: .toArray(new IPluginModelBase[list.size()]);
179: }
180:
181: protected void updateCounter() {
182: if (fCounter != null) {
183: int checked = fNumExternalChecked + fNumWorkspaceChecked;
184: int total = fWorkspaceModels.length
185: + fExternalModels.length;
186: fCounter.setText(NLS.bind(
187: PDEUIMessages.AbstractPluginBlock_counter,
188: new Integer(checked), new Integer(total)));
189: }
190: }
191:
192: public void createControl(Composite parent, int span, int indent) {
193: createPluginViewer(parent, span - 1, indent);
194: createButtonContainer(parent);
195: fIncludeOptionalButton = createButton(
196: parent,
197: span,
198: indent,
199: NLS
200: .bind(
201: PDEUIMessages.AdvancedLauncherTab_includeOptional,
202: fTab.getName().toLowerCase(
203: Locale.ENGLISH)));
204: fAddWorkspaceButton = createButton(parent, span, indent, NLS
205: .bind(PDEUIMessages.AdvancedLauncherTab_addNew, fTab
206: .getName().toLowerCase(Locale.ENGLISH)));
207:
208: GridData gd = new GridData(GridData.FILL_HORIZONTAL);
209: gd.horizontalSpan = span;
210: Label label = new Label(parent, SWT.SEPARATOR | SWT.HORIZONTAL);
211: label.setLayoutData(gd);
212:
213: fAutoValidate = createButton(
214: parent,
215: span - 1,
216: indent,
217: NLS
218: .bind(
219: PDEUIMessages.PluginsTabToolBar_auto_validate,
220: fTab
221: .getName()
222: .replaceAll("&", "").toLowerCase(Locale.ENGLISH))); //$NON-NLS-1$ //$NON-NLS-2$
223:
224: fValidateButton = new Button(parent, SWT.PUSH);
225: fValidateButton.setLayoutData(new GridData(
226: GridData.HORIZONTAL_ALIGN_END));
227: fValidateButton.setText(NLS.bind(
228: PDEUIMessages.PluginsTabToolBar_validate, fTab
229: .getName().replaceAll("&", ""))); //$NON-NLS-1$ //$NON-NLS-2$
230: SWTUtil.setButtonDimensionHint(fValidateButton);
231: fValidateButton.addSelectionListener(fListener);
232: }
233:
234: private Button createButton(Composite parent, int span, int indent,
235: String text) {
236: Button button = new Button(parent, SWT.CHECK);
237: button.setText(text);
238:
239: GridData gd = new GridData();
240: gd.horizontalSpan = span;
241: gd.horizontalIndent = indent;
242: button.setLayoutData(gd);
243: button.addSelectionListener(fListener);
244:
245: return button;
246: }
247:
248: protected ILabelProvider getLabelProvider() {
249: return PDEPlugin.getDefault().getLabelProvider();
250: }
251:
252: protected void createPluginViewer(Composite composite, int span,
253: int indent) {
254: fPluginTreeViewer = new CheckboxTreeViewer(composite,
255: getTreeViewerStyle());
256: fPluginTreeViewer
257: .setContentProvider(new PluginContentProvider());
258: fPluginTreeViewer.setLabelProvider(getLabelProvider());
259: fPluginTreeViewer.setAutoExpandLevel(2);
260: fPluginTreeViewer
261: .addCheckStateListener(new ICheckStateListener() {
262: public void checkStateChanged(
263: final CheckStateChangedEvent event) {
264: Object element = event.getElement();
265: if (element instanceof IPluginModelBase) {
266: handleCheckStateChanged(event);
267: } else {
268: handleGroupStateChanged(element, event
269: .getChecked());
270: }
271: fTab.updateLaunchConfigurationDialog();
272: }
273: });
274: fPluginTreeViewer
275: .setComparator(new ListUtil.PluginComparator() {
276: public int category(Object obj) {
277: if (obj == fWorkspacePlugins)
278: return -1;
279: return 0;
280: }
281: });
282:
283: GridData gd = new GridData(GridData.FILL_BOTH);
284: gd.horizontalSpan = span;
285: gd.horizontalIndent = indent;
286: fPluginTreeViewer.getTree().setLayoutData(gd);
287:
288: Image siteImage = PDEPlugin.getDefault().getLabelProvider()
289: .get(PDEPluginImages.DESC_SITE_OBJ);
290:
291: fWorkspacePlugins = new NamedElement(
292: PDEUIMessages.AdvancedLauncherTab_workspacePlugins,
293: siteImage);
294: fExternalPlugins = new NamedElement(
295: PDEUIMessages.PluginsTab_target, siteImage);
296: }
297:
298: private void createButtonContainer(Composite parent) {
299: Composite composite = new Composite(parent, SWT.NONE);
300: GridLayout layout = new GridLayout();
301: layout.marginHeight = layout.marginWidth = 0;
302: composite.setLayout(layout);
303: composite.setLayoutData(new GridData(GridData.FILL_VERTICAL));
304:
305: new Label(composite, SWT.NONE);
306: fSelectAllButton = createButton(composite,
307: PDEUIMessages.AdvancedLauncherTab_selectAll);
308: fDeselectButton = createButton(composite,
309: PDEUIMessages.AdvancedLauncherTab_deselectAll);
310: fWorkingSetButton = createButton(composite,
311: PDEUIMessages.AdvancedLauncherTab_workingSet);
312: fAddRequiredButton = createButton(composite, NLS.bind(
313: PDEUIMessages.AdvancedLauncherTab_subset, fTab
314: .getName()));
315: fDefaultsButton = createButton(composite,
316: PDEUIMessages.AdvancedLauncherTab_defaults);
317:
318: fCounter = new Label(composite, SWT.NONE);
319: fCounter.setLayoutData(new GridData(GridData.FILL_BOTH
320: | GridData.VERTICAL_ALIGN_END));
321: updateCounter();
322: }
323:
324: protected int getTreeViewerStyle() {
325: return SWT.BORDER;
326: }
327:
328: private Button createButton(Composite composite, String text) {
329: Button button = new Button(composite, SWT.PUSH);
330: button.setText(text);
331: button.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
332: SWTUtil.setButtonDimensionHint(button);
333: button.addSelectionListener(fListener);
334: return button;
335: }
336:
337: protected void handleCheckStateChanged(CheckStateChangedEvent event) {
338: IPluginModelBase model = (IPluginModelBase) event.getElement();
339: if (model.getUnderlyingResource() == null) {
340: if (event.getChecked()) {
341: fNumExternalChecked += 1;
342: } else {
343: fNumExternalChecked -= 1;
344: }
345: } else {
346: if (event.getChecked()) {
347: fNumWorkspaceChecked += 1;
348: } else {
349: fNumWorkspaceChecked -= 1;
350: }
351: }
352: adjustGroupState();
353: }
354:
355: protected void handleGroupStateChanged(Object group, boolean checked) {
356: fPluginTreeViewer.setSubtreeChecked(group, checked);
357: fPluginTreeViewer.setGrayed(group, false);
358:
359: if (group == fWorkspacePlugins)
360: fNumWorkspaceChecked = checked ? fWorkspaceModels.length
361: : 0;
362: else if (group == fExternalPlugins)
363: fNumExternalChecked = checked ? fExternalModels.length : 0;
364:
365: }
366:
367: protected void toggleGroups(boolean select) {
368: handleGroupStateChanged(fWorkspacePlugins, select);
369: handleGroupStateChanged(fExternalPlugins, select);
370: }
371:
372: private void handleWorkingSets() {
373: IWorkingSetManager workingSetManager = PlatformUI
374: .getWorkbench().getWorkingSetManager();
375: IWorkingSetSelectionDialog dialog = workingSetManager
376: .createWorkingSetSelectionDialog(getShell(), true);
377: if (dialog.open() == Window.OK) {
378: String[] ids = getPluginIDs(dialog.getSelection());
379: for (int i = 0; i < ids.length; i++) {
380: IPluginModelBase model = PluginRegistry
381: .findModel(ids[i]);
382: if (model != null) {
383: if (!fPluginTreeViewer.getChecked(model)) {
384: setChecked(model, true);
385: if (model.getUnderlyingResource() == null)
386: fNumExternalChecked += 1;
387: else
388: fNumWorkspaceChecked += 1;
389: }
390: }
391: }
392: adjustGroupState();
393: }
394: }
395:
396: protected void setChecked(IPluginModelBase model, boolean checked) {
397: fPluginTreeViewer.setChecked(model, checked);
398: }
399:
400: private String[] getPluginIDs(IWorkingSet[] workingSets) {
401: HashSet set = new HashSet();
402: for (int i = 0; i < workingSets.length; i++) {
403: IAdaptable[] elements = workingSets[i].getElements();
404: for (int j = 0; j < elements.length; j++) {
405: Object element = elements[j];
406: if (element instanceof PersistablePluginObject) {
407: set.add(((PersistablePluginObject) element)
408: .getPluginID());
409: } else {
410: if (element instanceof IJavaProject)
411: element = ((IJavaProject) element).getProject();
412: if (element instanceof IProject) {
413: IPluginModelBase model = PluginRegistry
414: .findModel((IProject) element);
415: if (model != null)
416: set.add(model.getPluginBase().getId());
417: }
418: }
419: }
420: }
421: return (String[]) set.toArray(new String[set.size()]);
422: }
423:
424: public void initializeFrom(ILaunchConfiguration config)
425: throws CoreException {
426: fIncludeOptionalButton.setSelection(config.getAttribute(
427: IPDELauncherConstants.INCLUDE_OPTIONAL, true));
428: fAddWorkspaceButton.setSelection(config.getAttribute(
429: IPDELauncherConstants.AUTOMATIC_ADD, true));
430: fAutoValidate.setSelection(config.getAttribute(
431: IPDELauncherConstants.AUTOMATIC_VALIDATE, false));
432: if (fPluginTreeViewer.getInput() == null) {
433: fPluginTreeViewer.setUseHashlookup(true);
434: fPluginTreeViewer.setInput(PDEPlugin.getDefault());
435: fPluginTreeViewer.reveal(fWorkspacePlugins);
436: }
437: }
438:
439: protected void computeSubset() {
440: Object[] checked = fPluginTreeViewer.getCheckedElements();
441: ArrayList toCheck = new ArrayList(checked.length);
442: for (int i = 0; i < checked.length; i++)
443: if (checked[i] instanceof IPluginModelBase)
444: toCheck.add(checked[i]);
445:
446: Set additionalIds = DependencyManager.getDependencies(checked,
447: fIncludeOptionalButton.getSelection());
448:
449: Iterator it = additionalIds.iterator();
450: while (it.hasNext()) {
451: String id = (String) it.next();
452: if (findPlugin(id) == null) {
453: ModelEntry entry = PluginRegistry.findEntry(id);
454: if (entry != null) {
455: IPluginModelBase model = entry.getModel();
456: if (model != null)
457: toCheck.add(model);
458: }
459: }
460: }
461:
462: checked = toCheck.toArray();
463: setCheckedElements(checked);
464: fNumExternalChecked = 0;
465: fNumWorkspaceChecked = 0;
466: for (int i = 0; i < checked.length; i++) {
467: if (((IPluginModelBase) checked[i]).getUnderlyingResource() != null)
468: fNumWorkspaceChecked += 1;
469: else
470: fNumExternalChecked += 1;
471: }
472: adjustGroupState();
473: }
474:
475: protected void setCheckedElements(Object[] checked) {
476: fPluginTreeViewer.setCheckedElements(checked);
477: }
478:
479: protected IPluginModelBase findPlugin(String id) {
480: ModelEntry entry = PluginRegistry.findEntry(id);
481: if (entry != null) {
482: IPluginModelBase model = entry.getModel();
483: if (fPluginTreeViewer.getChecked(model))
484: return model;
485:
486: IPluginModelBase[] models = entry.getWorkspaceModels();
487: for (int i = 0; i < models.length; i++) {
488: if (fPluginTreeViewer.getChecked(models[i]))
489: return models[i];
490: }
491:
492: models = entry.getExternalModels();
493: for (int i = 0; i < models.length; i++) {
494: if (fPluginTreeViewer.getChecked(models[i]))
495: return models[i];
496: }
497: return null;
498: }
499: return null;
500: }
501:
502: protected void adjustGroupState() {
503: fPluginTreeViewer.setChecked(fExternalPlugins,
504: fNumExternalChecked > 0);
505: fPluginTreeViewer
506: .setGrayed(fExternalPlugins, fNumExternalChecked > 0
507: && fNumExternalChecked < fExternalModels.length);
508: fPluginTreeViewer.setChecked(fWorkspacePlugins,
509: fNumWorkspaceChecked > 0);
510: fPluginTreeViewer
511: .setGrayed(
512: fWorkspacePlugins,
513: fNumWorkspaceChecked > 0
514: && fNumWorkspaceChecked < fWorkspaceModels.length);
515: }
516:
517: public void performApply(ILaunchConfigurationWorkingCopy config) {
518: config.setAttribute(IPDELauncherConstants.INCLUDE_OPTIONAL,
519: fIncludeOptionalButton.getSelection());
520: config.setAttribute(IPDELauncherConstants.AUTOMATIC_ADD,
521: fAddWorkspaceButton.getSelection());
522: config.setAttribute(IPDELauncherConstants.AUTOMATIC_VALIDATE,
523: fAutoValidate.getSelection());
524: savePluginState(config);
525: updateCounter();
526: }
527:
528: protected abstract void savePluginState(
529: ILaunchConfigurationWorkingCopy config);
530:
531: public void setDefaults(ILaunchConfigurationWorkingCopy config) {
532: config.setAttribute(IPDELauncherConstants.INCLUDE_OPTIONAL,
533: true);
534: config.setAttribute(IPDELauncherConstants.AUTOMATIC_ADD, true);
535: config.setAttribute(IPDELauncherConstants.AUTOMATIC_VALIDATE,
536: false);
537: }
538:
539: public void enableViewer(boolean enable) {
540: fPluginTreeViewer.getTree().setEnabled(enable);
541: fAddRequiredButton.setEnabled(enable);
542: fDefaultsButton.setEnabled(enable);
543: fWorkingSetButton.setEnabled(enable);
544: fSelectAllButton.setEnabled(enable);
545: fDeselectButton.setEnabled(enable);
546: fIncludeOptionalButton.setEnabled(enable);
547: fAddWorkspaceButton.setEnabled(enable);
548: fCounter.setEnabled(enable);
549: }
550:
551: public void dispose() {
552: PDEPlugin.getDefault().getLabelProvider().disconnect(this );
553: }
554:
555: protected boolean isEnabled() {
556: return fPluginTreeViewer.getTree().isEnabled();
557: }
558:
559: protected void handleRestoreDefaults() {
560: TreeSet wtable = new TreeSet();
561: fNumWorkspaceChecked = 0;
562: fNumExternalChecked = 0;
563:
564: for (int i = 0; i < fWorkspaceModels.length; i++) {
565: IPluginModelBase model = fWorkspaceModels[i];
566: fNumWorkspaceChecked += 1;
567: String id = model.getPluginBase().getId();
568: if (id != null)
569: wtable.add(model.getPluginBase().getId());
570: }
571: fPluginTreeViewer.setSubtreeChecked(fWorkspacePlugins, true);
572:
573: fNumExternalChecked = 0;
574: for (int i = 0; i < fExternalModels.length; i++) {
575: IPluginModelBase model = fExternalModels[i];
576: boolean masked = wtable.contains(model.getPluginBase()
577: .getId());
578: if (!masked && model.isEnabled()) {
579: fPluginTreeViewer.setChecked(model, true);
580: fNumExternalChecked += 1;
581: }
582: }
583: adjustGroupState();
584: }
585:
586: protected Shell getShell() {
587: // use Shell of launcher window. If launcher window is disposed (not sure how it could happen), use workbenchwindow. Bug 168198
588: try {
589: Control c = fTab.getControl();
590: if (!c.isDisposed())
591: return c.getShell();
592: } catch (SWTException e) {
593: }
594: return PDEPlugin.getActiveWorkbenchShell();
595: }
596:
597: public void handleValidate() {
598: if (fOperation == null)
599: fOperation = createValidationOperation();
600: try {
601: fOperation.run(new NullProgressMonitor());
602: } catch (CoreException e) {
603: PDEPlugin.log(e);
604: }
605: if (fDialog == null) {
606: if (fOperation.hasErrors()) {
607: fDialog = new PluginStatusDialog(getShell(), SWT.CLOSE
608: | SWT.MODELESS | SWT.BORDER | SWT.TITLE
609: | SWT.RESIZE);
610: fDialog.setInput(fOperation.getInput());
611: fDialog.open();
612: fDialog = null;
613: } else if (fOperation.isEmpty()) {
614: MessageDialog
615: .openInformation(
616: PDEPlugin.getActiveWorkbenchShell(),
617: PDEUIMessages.PluginStatusDialog_pluginValidation,
618: NLS
619: .bind(
620: PDEUIMessages.AbstractLauncherToolbar_noSelection,
621: fTab
622: .getName()
623: .toLowerCase(
624: Locale.ENGLISH)));
625: } else {
626: MessageDialog
627: .openInformation(
628: PDEPlugin.getActiveWorkbenchShell(),
629: PDEUIMessages.PluginStatusDialog_pluginValidation,
630: PDEUIMessages.AbstractLauncherToolbar_noProblems);
631: }
632: } else {
633: fDialog.refresh(fOperation.getInput());
634: }
635: }
636:
637: protected abstract LaunchValidationOperation createValidationOperation();
638:
639: }
|