001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 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.wizards.imports;
011:
012: import java.io.BufferedInputStream;
013: import java.io.File;
014: import java.io.FileInputStream;
015: import java.io.IOException;
016: import java.io.InputStream;
017: import java.lang.reflect.InvocationTargetException;
018: import java.util.ArrayList;
019:
020: import org.eclipse.core.runtime.IPath;
021: import org.eclipse.core.runtime.IProgressMonitor;
022: import org.eclipse.core.runtime.IStatus;
023: import org.eclipse.core.runtime.MultiStatus;
024: import org.eclipse.core.runtime.Path;
025: import org.eclipse.core.runtime.Preferences;
026: import org.eclipse.core.runtime.Status;
027: import org.eclipse.jface.dialogs.Dialog;
028: import org.eclipse.jface.dialogs.IDialogSettings;
029: import org.eclipse.jface.dialogs.IMessageProvider;
030: import org.eclipse.jface.operation.IRunnableWithProgress;
031: import org.eclipse.jface.viewers.CheckboxTableViewer;
032: import org.eclipse.jface.viewers.IStructuredContentProvider;
033: import org.eclipse.jface.viewers.StructuredViewer;
034: import org.eclipse.jface.wizard.WizardPage;
035: import org.eclipse.osgi.util.NLS;
036: import org.eclipse.pde.internal.core.ICoreConstants;
037: import org.eclipse.pde.internal.core.PDECore;
038: import org.eclipse.pde.internal.core.feature.ExternalFeatureModel;
039: import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
040: import org.eclipse.pde.internal.ui.IHelpContextIds;
041: import org.eclipse.pde.internal.ui.IPDEUIConstants;
042: import org.eclipse.pde.internal.ui.PDEPlugin;
043: import org.eclipse.pde.internal.ui.PDEUIMessages;
044: import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
045: import org.eclipse.pde.internal.ui.parts.WizardCheckboxTablePart;
046: import org.eclipse.pde.internal.ui.util.SWTUtil;
047: import org.eclipse.pde.internal.ui.wizards.ListUtil;
048: import org.eclipse.swt.SWT;
049: import org.eclipse.swt.events.ModifyEvent;
050: import org.eclipse.swt.events.ModifyListener;
051: import org.eclipse.swt.events.SelectionAdapter;
052: import org.eclipse.swt.events.SelectionEvent;
053: import org.eclipse.swt.layout.GridData;
054: import org.eclipse.swt.layout.GridLayout;
055: import org.eclipse.swt.widgets.Button;
056: import org.eclipse.swt.widgets.Combo;
057: import org.eclipse.swt.widgets.Composite;
058: import org.eclipse.swt.widgets.Control;
059: import org.eclipse.swt.widgets.DirectoryDialog;
060: import org.eclipse.swt.widgets.Label;
061: import org.eclipse.ui.PlatformUI;
062: import org.eclipse.ui.forms.widgets.FormToolkit;
063: import org.eclipse.ui.progress.IProgressService;
064:
065: public class FeatureImportWizardPage extends WizardPage {
066:
067: private static final String SETTINGS_DROPLOCATION = "droplocation"; //$NON-NLS-1$
068: private static final String SETTINGS_DOOTHER = "doother"; //$NON-NLS-1$
069: private static final String SETTINGS_NOT_BINARY = "notbinary"; //$NON-NLS-1$
070:
071: private Label fOtherLocationLabel;
072: private Button fRuntimeLocationButton;
073: private Button fBrowseButton;
074: private Combo fDropLocation;
075: private boolean fSelfSetLocation;
076: private String fCurrDropLocation;
077:
078: private CheckboxTableViewer fFeatureViewer;
079: private TablePart fTablePart;
080: private IFeatureModel[] fModels;
081:
082: private Button fBinaryButton;
083:
084: class ContentProvider extends DefaultContentProvider implements
085: IStructuredContentProvider {
086: public Object[] getElements(Object parent) {
087: if (fModels != null)
088: return fModels;
089: return new Object[0];
090: }
091: }
092:
093: class TablePart extends WizardCheckboxTablePart {
094: public TablePart() {
095: super (null, new String[] {
096: PDEUIMessages.FeatureImportWizardPage_reload,
097: PDEUIMessages.WizardCheckboxTablePart_selectAll,
098: PDEUIMessages.WizardCheckboxTablePart_deselectAll });
099: setSelectAllIndex(1);
100: setDeselectAllIndex(2);
101: }
102:
103: public void updateCounter(int count) {
104: super .updateCounter(count);
105: dialogChanged();
106: }
107:
108: protected StructuredViewer createStructuredViewer(
109: Composite parent, int style, FormToolkit toolkit) {
110: StructuredViewer viewer = super .createStructuredViewer(
111: parent, style, toolkit);
112: viewer.setComparator(ListUtil.FEATURE_COMPARATOR);
113: return viewer;
114: }
115:
116: protected void buttonSelected(Button button, int index) {
117: if (index == 0)
118: loadFeatureTable();
119: else
120: super .buttonSelected(button, index);
121: }
122: }
123:
124: public FeatureImportWizardPage() {
125: super ("FeatureImportWizardPage"); //$NON-NLS-1$
126: setTitle(PDEUIMessages.FeatureImportWizard_FirstPage_title);
127: setDescription(PDEUIMessages.FeatureImportWizard_FirstPage_desc);
128: fTablePart = new TablePart();
129: PDEPlugin.getDefault().getLabelProvider().connect(this );
130: }
131:
132: /*
133: * @see IDialogPage#createControl(Composite)
134: */
135: public void createControl(Composite parent) {
136: initializeDialogUnits(parent);
137:
138: Composite composite = new Composite(parent, SWT.NONE);
139: composite.setLayout(new GridLayout(3, false));
140:
141: fRuntimeLocationButton = new Button(composite, SWT.CHECK);
142: fillHorizontal(fRuntimeLocationButton, 3, false);
143: fRuntimeLocationButton
144: .setText(PDEUIMessages.FeatureImportWizard_FirstPage_runtimeLocation);
145:
146: fOtherLocationLabel = new Label(composite, SWT.NULL);
147: fOtherLocationLabel
148: .setText(PDEUIMessages.FeatureImportWizard_FirstPage_otherFolder);
149:
150: fDropLocation = new Combo(composite, SWT.DROP_DOWN);
151: fillHorizontal(fDropLocation, 1, true);
152:
153: fBrowseButton = new Button(composite, SWT.PUSH);
154: fBrowseButton
155: .setText(PDEUIMessages.FeatureImportWizard_FirstPage_browse);
156: fBrowseButton.setLayoutData(new GridData());
157: SWTUtil.setButtonDimensionHint(fBrowseButton);
158:
159: creatFeatureTable(composite);
160:
161: fBinaryButton = new Button(composite, SWT.CHECK);
162: GridData gd = fillHorizontal(fBinaryButton, 3, false);
163: gd.verticalIndent = 5;
164: fBinaryButton
165: .setText(PDEUIMessages.FeatureImportWizard_FirstPage_binaryImport);
166:
167: initializeFields(getDialogSettings());
168: hookListeners();
169:
170: setControl(composite);
171: dialogChanged();
172: Dialog.applyDialogFont(composite);
173: PlatformUI.getWorkbench().getHelpSystem().setHelp(composite,
174: IHelpContextIds.FEATURE_IMPORT_FIRST_PAGE);
175: }
176:
177: private String getTargetHome() {
178: Preferences preferences = PDECore.getDefault()
179: .getPluginPreferences();
180: return preferences.getString(ICoreConstants.PLATFORM_PATH);
181: }
182:
183: private void hookListeners() {
184: fRuntimeLocationButton
185: .addSelectionListener(new SelectionAdapter() {
186: public void widgetSelected(SelectionEvent e) {
187: setOtherEnabled(!fRuntimeLocationButton
188: .getSelection());
189: setLocation(fRuntimeLocationButton
190: .getSelection() ? getTargetHome()
191: : fCurrDropLocation);
192: loadFeatureTable();
193: }
194: });
195: fDropLocation.addModifyListener(new ModifyListener() {
196: public void modifyText(ModifyEvent e) {
197: validateDropLocation();
198: if (!fRuntimeLocationButton.getSelection()) {
199: String newLoc = fDropLocation.getText();
200: if (getMessageType() != WARNING
201: && !newLoc.equals(fCurrDropLocation)
202: && !fSelfSetLocation)
203: setMessage(
204: PDEUIMessages.FeatureImportWizardPage_reloadLocation,
205: WARNING);
206: fCurrDropLocation = newLoc;
207: }
208: }
209: });
210: fBrowseButton.addSelectionListener(new SelectionAdapter() {
211: public void widgetSelected(SelectionEvent e) {
212: IPath chosen = chooseDropLocation();
213: if (chosen != null) {
214: setLocation(chosen.toOSString());
215: loadFeatureTable();
216: }
217: }
218: });
219: }
220:
221: private GridData fillHorizontal(Control control, int span,
222: boolean grab) {
223: GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
224: gd.horizontalSpan = span;
225: gd.grabExcessHorizontalSpace = grab;
226: control.setLayoutData(gd);
227: return gd;
228: }
229:
230: private void initializeFields(IDialogSettings initialSettings) {
231: String[] dropItems = new String[0];
232: boolean doOther = false;
233: boolean binary = true;
234:
235: if (initialSettings != null) {
236: doOther = initialSettings.getBoolean(SETTINGS_DOOTHER);
237: binary = !initialSettings.getBoolean(SETTINGS_NOT_BINARY);
238:
239: ArrayList items = new ArrayList();
240: for (int i = 0; i < 6; i++) {
241: String curr = initialSettings.get(SETTINGS_DROPLOCATION
242: + String.valueOf(i));
243: if (curr != null && !items.contains(curr))
244: items.add(curr);
245: }
246: if (items.size() == 0)
247: items.add(""); //$NON-NLS-1$
248: dropItems = (String[]) items.toArray(new String[items
249: .size()]);
250: }
251: fDropLocation.setItems(dropItems);
252: fRuntimeLocationButton.setSelection(!doOther);
253: setOtherEnabled(doOther);
254: fCurrDropLocation = doOther ? dropItems[0] : getTargetHome();
255: setLocation(fCurrDropLocation);
256: fBinaryButton.setSelection(binary);
257:
258: validateDropLocation();
259:
260: loadFeatureTable();
261: }
262:
263: private void setOtherEnabled(boolean enabled) {
264: fOtherLocationLabel.setEnabled(enabled);
265: fDropLocation.setEnabled(enabled);
266: fBrowseButton.setEnabled(enabled);
267: }
268:
269: public void storeSettings(boolean finishPressed) {
270: IDialogSettings settings = getDialogSettings();
271: boolean other = !fRuntimeLocationButton.getSelection();
272: boolean binary = fBinaryButton.getSelection();
273: if (finishPressed || fDropLocation.getText().length() > 0
274: && other) {
275: settings.put(SETTINGS_DROPLOCATION + String.valueOf(0),
276: fDropLocation.getText());
277: String[] items = fDropLocation.getItems();
278: int nEntries = Math.min(items.length, 5);
279: for (int i = 0; i < nEntries; i++)
280: settings.put(SETTINGS_DROPLOCATION
281: + String.valueOf(i + 1), items[i]);
282: }
283: if (finishPressed) {
284: settings.put(SETTINGS_DOOTHER, other);
285: settings.put(SETTINGS_NOT_BINARY, !binary);
286: }
287: }
288:
289: /**
290: * Browses for a drop location.
291: */
292: private IPath chooseDropLocation() {
293: DirectoryDialog dialog = new DirectoryDialog(getShell());
294: dialog.setFilterPath(fDropLocation.getText());
295: dialog
296: .setText(PDEUIMessages.FeatureImportWizard_messages_folder_title);
297: dialog
298: .setMessage(PDEUIMessages.FeatureImportWizard_messages_folder_message);
299: String res = dialog.open();
300: return res != null ? new Path(res) : null;
301: }
302:
303: private void validateDropLocation() {
304: String errorMessage = null;
305: if (isOtherLocation()) {
306: IPath curr = getDropLocation();
307: if (curr.segmentCount() == 0)
308: errorMessage = PDEUIMessages.FeatureImportWizard_errors_locationMissing;
309: else if (!Path.ROOT.isValidPath(fDropLocation.getText()))
310: errorMessage = PDEUIMessages.FeatureImportWizard_errors_buildFolderInvalid;
311: else {
312: File file = curr.toFile();
313: if (!file.exists() || !file.isDirectory())
314: errorMessage = PDEUIMessages.FeatureImportWizard_errors_buildFolderMissing;
315: }
316: }
317: setErrorMessage(errorMessage);
318: setPageComplete(errorMessage == null);
319: fTablePart.setButtonEnabled(0, errorMessage == null);
320: }
321:
322: public boolean isBinary() {
323: return fBinaryButton.getSelection();
324: }
325:
326: /**
327: * Returns the drop location.
328: */
329: public IPath getDropLocation() {
330: return new Path(fDropLocation.getText().trim());
331: }
332:
333: public boolean isOtherLocation() {
334: return !fRuntimeLocationButton.getSelection();
335: }
336:
337: private void loadFeatureTable() {
338: IFeatureModel[] models = getModels();
339: fFeatureViewer.setInput(PDEPlugin.getDefault());
340: if (models != null) {
341: // warning had been issued for unreloaded location
342: if (getMessageType() == WARNING)
343: setMessage(null, WARNING);
344: if (!fRuntimeLocationButton.getSelection()) {
345: String currItem = fDropLocation.getText();
346: if (fDropLocation.indexOf(currItem) == -1) {
347: fDropLocation.add(currItem, 0);
348: if (fDropLocation.getItemCount() > 6)
349: fDropLocation.remove(6);
350: storeSettings(false);
351: }
352: }
353: fFeatureViewer.setCheckedElements(models);
354: }
355: fTablePart.updateCounter(models != null ? models.length : 0);
356: fTablePart.getTableViewer().refresh();
357:
358: fTablePart.setButtonEnabled(1, models != null
359: && models.length > 0);
360: fTablePart.setButtonEnabled(2, models != null
361: && models.length > 0);
362:
363: dialogChanged();
364: }
365:
366: public void creatFeatureTable(Composite parent) {
367: Composite container = new Composite(parent, SWT.NONE);
368: GridLayout layout = new GridLayout();
369: layout.numColumns = 2;
370: layout.marginHeight = layout.marginWidth = 0;
371: container.setLayout(layout);
372: GridData gd = new GridData(GridData.FILL_HORIZONTAL);
373: gd.horizontalSpan = 3;
374: gd.verticalIndent = 5;
375: gd.heightHint = gd.widthHint = 300;
376: container.setLayoutData(gd);
377:
378: fTablePart.createControl(container);
379: fFeatureViewer = fTablePart.getTableViewer();
380: fFeatureViewer.setContentProvider(new ContentProvider());
381: fFeatureViewer.setLabelProvider(PDEPlugin.getDefault()
382: .getLabelProvider());
383: }
384:
385: public void dispose() {
386: super .dispose();
387: PDEPlugin.getDefault().getLabelProvider().disconnect(this );
388: }
389:
390: public IFeatureModel[] getModels() {
391: final IPath home = getDropLocation();
392: final boolean useRuntimeLocation = fRuntimeLocationButton
393: .getSelection()
394: || getTargetHome().equals(
395: fDropLocation.getText().trim());
396: IRunnableWithProgress runnable = new IRunnableWithProgress() {
397: public void run(IProgressMonitor monitor)
398: throws InvocationTargetException,
399: InterruptedException {
400: monitor
401: .beginTask(
402: PDEUIMessages.FeatureImportWizard_messages_updating,
403: IProgressMonitor.UNKNOWN);
404: ArrayList result = new ArrayList();
405: if (useRuntimeLocation) {
406: IFeatureModel[] allModels = PDECore.getDefault()
407: .getFeatureModelManager().getModels();
408: for (int i = 0; i < allModels.length; i++)
409: if (allModels[i].getUnderlyingResource() == null)
410: result.add(allModels[i]);
411: } else {
412: MultiStatus errors = doLoadFeatures(result,
413: createPath(home));
414: if (errors != null
415: && errors.getChildren().length > 0)
416: PDEPlugin.log(errors);
417: }
418: fModels = (IFeatureModel[]) result
419: .toArray(new IFeatureModel[result.size()]);
420: monitor.done();
421: }
422: };
423: IProgressService pservice = PlatformUI.getWorkbench()
424: .getProgressService();
425: try {
426: pservice.busyCursorWhile(runnable);
427: } catch (InvocationTargetException e) {
428: } catch (InterruptedException e) {
429: }
430: return fModels;
431: }
432:
433: private File createPath(IPath dropLocation) {
434: File featuresDir = new File(dropLocation.toFile(), "features"); //$NON-NLS-1$
435: if (featuresDir.exists())
436: return featuresDir;
437: return null;
438: }
439:
440: private MultiStatus doLoadFeatures(ArrayList result, File path) {
441: if (path == null)
442: return null;
443: File[] dirs = path.listFiles();
444: if (dirs == null)
445: return null;
446: ArrayList resultStatus = new ArrayList();
447: for (int i = 0; i < dirs.length; i++) {
448: File dir = dirs[i];
449: if (dir.isDirectory()) {
450: File manifest = new File(dir, "feature.xml"); //$NON-NLS-1$
451: if (manifest.exists()) {
452: IStatus status = doLoadFeature(dir, manifest,
453: result);
454: if (status != null)
455: resultStatus.add(status);
456: }
457: }
458: }
459: return new MultiStatus(
460: IPDEUIConstants.PLUGIN_ID,
461: IStatus.OK,
462: (IStatus[]) resultStatus
463: .toArray(new IStatus[resultStatus.size()]),
464: PDEUIMessages.FeatureImportWizard_DetailedPage_problemsLoading,
465: null);
466: }
467:
468: private IStatus doLoadFeature(File dir, File manifest,
469: ArrayList result) {
470: ExternalFeatureModel model = new ExternalFeatureModel();
471: model.setInstallLocation(dir.getAbsolutePath());
472: IStatus status = null;
473:
474: InputStream stream = null;
475:
476: try {
477: stream = new BufferedInputStream(new FileInputStream(
478: manifest));
479: model.load(stream, false);
480: if (!model.isValid()) {
481: status = new Status(
482: IStatus.WARNING,
483: IPDEUIConstants.PLUGIN_ID,
484: IStatus.OK,
485: NLS
486: .bind(
487: PDEUIMessages.FeatureImportWizardPage_importHasInvalid,
488: dir), null);
489: }
490: } catch (Exception e) {
491: // Errors in the file
492: status = new Status(IStatus.ERROR,
493: IPDEUIConstants.PLUGIN_ID, IStatus.OK, e
494: .getMessage(), e);
495: }
496: if (stream != null) {
497: try {
498: stream.close();
499: } catch (IOException e) {
500: }
501: }
502: if (status == null)
503: result.add(model);
504: return status;
505: }
506:
507: public IFeatureModel[] getSelectedModels() {
508: Object[] selected = fFeatureViewer.getCheckedElements();
509: IFeatureModel[] result = new IFeatureModel[selected.length];
510: System.arraycopy(selected, 0, result, 0, selected.length);
511: return result;
512: }
513:
514: private void dialogChanged() {
515: String message = null;
516: if (fFeatureViewer != null
517: && fFeatureViewer.getTable().getItemCount() == 0)
518: message = PDEUIMessages.FeatureImportWizard_messages_noFeatures;
519:
520: setMessage(message, IMessageProvider.INFORMATION);
521: setPageComplete(fTablePart.getSelectionCount() > 0);
522: }
523:
524: /* (non-Javadoc)
525: * @see org.eclipse.jface.wizard.WizardPage#isPageComplete()
526: */
527: public boolean isPageComplete() {
528: return fTablePart.getSelectionCount() > 0;
529: }
530:
531: private void setLocation(String location) {
532: fSelfSetLocation = true;
533: fDropLocation.setText(location);
534: fSelfSetLocation = false;
535: }
536: }
|