0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.jdt.internal.ui.jarpackager;
0011:
0012: import java.io.File;
0013: import java.lang.reflect.InvocationTargetException;
0014: import java.util.HashSet;
0015: import java.util.Iterator;
0016: import java.util.Set;
0017:
0018: import org.eclipse.core.runtime.IAdaptable;
0019: import org.eclipse.core.runtime.IPath;
0020: import org.eclipse.core.runtime.IProgressMonitor;
0021: import org.eclipse.core.runtime.IStatus;
0022: import org.eclipse.core.runtime.Path;
0023:
0024: import org.eclipse.core.resources.IFile;
0025: import org.eclipse.core.resources.IFolder;
0026: import org.eclipse.core.resources.IProject;
0027: import org.eclipse.core.resources.IResource;
0028: import org.eclipse.core.resources.IWorkspace;
0029: import org.eclipse.core.resources.ResourcesPlugin;
0030:
0031: import org.eclipse.swt.SWT;
0032: import org.eclipse.swt.custom.BusyIndicator;
0033: import org.eclipse.swt.events.SelectionAdapter;
0034: import org.eclipse.swt.events.SelectionEvent;
0035: import org.eclipse.swt.layout.GridData;
0036: import org.eclipse.swt.layout.GridLayout;
0037: import org.eclipse.swt.widgets.Button;
0038: import org.eclipse.swt.widgets.Combo;
0039: import org.eclipse.swt.widgets.Composite;
0040: import org.eclipse.swt.widgets.Event;
0041: import org.eclipse.swt.widgets.FileDialog;
0042: import org.eclipse.swt.widgets.Label;
0043: import org.eclipse.swt.widgets.Link;
0044: import org.eclipse.swt.widgets.TreeItem;
0045:
0046: import org.eclipse.jface.dialogs.Dialog;
0047: import org.eclipse.jface.dialogs.IDialogSettings;
0048: import org.eclipse.jface.dialogs.IMessageProvider;
0049: import org.eclipse.jface.operation.IRunnableWithProgress;
0050: import org.eclipse.jface.viewers.CheckStateChangedEvent;
0051: import org.eclipse.jface.viewers.DecoratingLabelProvider;
0052: import org.eclipse.jface.viewers.ICheckStateListener;
0053: import org.eclipse.jface.viewers.IStructuredSelection;
0054: import org.eclipse.jface.viewers.ITreeContentProvider;
0055: import org.eclipse.jface.wizard.IWizardPage;
0056:
0057: import org.eclipse.ui.PlatformUI;
0058: import org.eclipse.ui.dialogs.WizardExportResourcesPage;
0059:
0060: import org.eclipse.ltk.core.refactoring.RefactoringCore;
0061: import org.eclipse.ltk.core.refactoring.history.IRefactoringHistoryService;
0062: import org.eclipse.ltk.core.refactoring.history.RefactoringHistory;
0063:
0064: import org.eclipse.jdt.core.IClassFile;
0065: import org.eclipse.jdt.core.IClasspathEntry;
0066: import org.eclipse.jdt.core.ICompilationUnit;
0067: import org.eclipse.jdt.core.IJavaElement;
0068: import org.eclipse.jdt.core.IJavaModel;
0069: import org.eclipse.jdt.core.IPackageFragment;
0070: import org.eclipse.jdt.core.IPackageFragmentRoot;
0071: import org.eclipse.jdt.core.JavaCore;
0072: import org.eclipse.jdt.core.JavaModelException;
0073: import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
0074:
0075: import org.eclipse.jdt.ui.JavaElementComparator;
0076: import org.eclipse.jdt.ui.JavaElementLabelProvider;
0077: import org.eclipse.jdt.ui.ProblemsLabelDecorator;
0078: import org.eclipse.jdt.ui.StandardJavaElementContentProvider;
0079: import org.eclipse.jdt.ui.jarpackager.JarPackageData;
0080:
0081: import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
0082: import org.eclipse.jdt.internal.ui.filters.EmptyInnerPackageFilter;
0083: import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
0084: import org.eclipse.jdt.internal.ui.util.SWTUtil;
0085: import org.eclipse.jdt.internal.ui.viewsupport.LibraryFilter;
0086:
0087: /**
0088: * Page 1 of the JAR Package wizard
0089: */
0090: class JarPackageWizardPage extends WizardExportResourcesPage implements
0091: IJarPackageWizardPage {
0092:
0093: private JarPackageData fJarPackage;
0094: private IStructuredSelection fInitialSelection;
0095: private CheckboxTreeAndListGroup fInputGroup;
0096:
0097: // widgets
0098: private Button fExportClassFilesCheckbox;
0099: private Button fExportOutputFoldersCheckbox;
0100: private Button fExportJavaFilesCheckbox;
0101: private Button fExportRefactoringsCheckbox;
0102: private Link fRefactoringLink;
0103:
0104: private Combo fDestinationNamesCombo;
0105: private Button fDestinationBrowseButton;
0106:
0107: private Button fCompressCheckbox;
0108: private Button fOverwriteCheckbox;
0109: private Button fIncludeDirectoryEntriesCheckbox;
0110: private boolean fInitiallySelecting = true;
0111:
0112: // dialog store id constants
0113: private static final String PAGE_NAME = "JarPackageWizardPage"; //$NON-NLS-1$
0114:
0115: private static final String STORE_EXPORT_CLASS_FILES = PAGE_NAME
0116: + ".EXPORT_CLASS_FILES"; //$NON-NLS-1$
0117: private static final String STORE_EXPORT_OUTPUT_FOLDERS = PAGE_NAME
0118: + ".EXPORT_OUTPUT_FOLDER"; //$NON-NLS-1$
0119: private static final String STORE_EXPORT_JAVA_FILES = PAGE_NAME
0120: + ".EXPORT_JAVA_FILES"; //$NON-NLS-1$
0121:
0122: private static final String STORE_DESTINATION_NAMES = PAGE_NAME
0123: + ".DESTINATION_NAMES_ID"; //$NON-NLS-1$
0124:
0125: private static final String STORE_REFACTORINGS = PAGE_NAME
0126: + ".REFACTORINGS"; //$NON-NLS-1$
0127: private static final String STORE_COMPRESS = PAGE_NAME
0128: + ".COMPRESS"; //$NON-NLS-1$
0129: private final static String STORE_OVERWRITE = PAGE_NAME
0130: + ".OVERWRITE"; //$NON-NLS-1$
0131: private final static String STORE_INCLUDE_DIRECTORY_ENTRIES = PAGE_NAME
0132: + ".INCLUDE_DIRECTORY_ENTRIES"; //$NON-NLS-1$
0133:
0134: // other constants
0135: private static final int SIZING_SELECTION_WIDGET_WIDTH = 480;
0136: private static final int SIZING_SELECTION_WIDGET_HEIGHT = 150;
0137:
0138: /**
0139: * Create an instance of this class
0140: */
0141: public JarPackageWizardPage(JarPackageData jarPackage,
0142: IStructuredSelection selection) {
0143: super (PAGE_NAME, selection);
0144: setTitle(JarPackagerMessages.JarPackageWizardPage_title);
0145: setDescription(JarPackagerMessages.JarPackageWizardPage_description);
0146: fJarPackage = jarPackage;
0147: fInitialSelection = selection;
0148: }
0149:
0150: /*
0151: * Method declared on IDialogPage.
0152: */
0153: public void createControl(final Composite parent) {
0154:
0155: initializeDialogUnits(parent);
0156:
0157: Composite composite = new Composite(parent, SWT.NULL);
0158: composite.setLayout(new GridLayout());
0159: composite.setLayoutData(new GridData(
0160: GridData.VERTICAL_ALIGN_FILL
0161: | GridData.HORIZONTAL_ALIGN_FILL));
0162:
0163: createPlainLabel(
0164: composite,
0165: JarPackagerMessages.JarPackageWizardPage_whatToExport_label);
0166: createInputGroup(composite);
0167:
0168: createExportTypeGroup(composite);
0169:
0170: new Label(composite, SWT.NONE); // vertical spacer
0171:
0172: createPlainLabel(
0173: composite,
0174: JarPackagerMessages.JarPackageWizardPage_whereToExport_label);
0175: createDestinationGroup(composite);
0176:
0177: createPlainLabel(composite,
0178: JarPackagerMessages.JarPackageWizardPage_options_label);
0179: createOptionsGroup(composite);
0180:
0181: restoreResourceSpecificationWidgetValues(); // superclass API defines this hook
0182: restoreWidgetValues();
0183: if (fInitialSelection != null)
0184: BusyIndicator.showWhile(parent.getDisplay(),
0185: new Runnable() {
0186: public void run() {
0187: setupBasedOnInitialSelections();
0188: }
0189: });
0190:
0191: setControl(composite);
0192: update();
0193: fRefactoringLink.setEnabled(fExportRefactoringsCheckbox
0194: .getSelection());
0195: giveFocusToDestination();
0196:
0197: Dialog.applyDialogFont(composite);
0198: PlatformUI.getWorkbench().getHelpSystem().setHelp(composite,
0199: IJavaHelpContextIds.JARPACKAGER_WIZARD_PAGE);
0200: }
0201:
0202: /**
0203: * Create the export options specification widgets.
0204: *
0205: * @param parent org.eclipse.swt.widgets.Composite
0206: */
0207: protected void createOptionsGroup(Composite parent) {
0208: Composite optionsGroup = new Composite(parent, SWT.NONE);
0209: GridLayout layout = new GridLayout();
0210: layout.marginHeight = 0;
0211: optionsGroup.setLayout(layout);
0212:
0213: fCompressCheckbox = new Button(optionsGroup, SWT.CHECK
0214: | SWT.LEFT);
0215: fCompressCheckbox
0216: .setText(JarPackagerMessages.JarPackageWizardPage_compress_text);
0217: fCompressCheckbox.addListener(SWT.Selection, this );
0218:
0219: fIncludeDirectoryEntriesCheckbox = new Button(optionsGroup,
0220: SWT.CHECK | SWT.LEFT);
0221: fIncludeDirectoryEntriesCheckbox
0222: .setText(JarPackagerMessages.JarPackageWizardPage_includeDirectoryEntries_text);
0223: fIncludeDirectoryEntriesCheckbox.addListener(SWT.Selection,
0224: this );
0225:
0226: fOverwriteCheckbox = new Button(optionsGroup, SWT.CHECK
0227: | SWT.LEFT);
0228: fOverwriteCheckbox
0229: .setText(JarPackagerMessages.JarPackageWizardPage_overwrite_text);
0230: fOverwriteCheckbox.addListener(SWT.Selection, this );
0231: }
0232:
0233: /**
0234: * Answer the contents of the destination specification widget. If this
0235: * value does not have the required suffix then add it first.
0236: *
0237: * @return java.lang.String
0238: */
0239: protected String getDestinationValue() {
0240: String destinationText = fDestinationNamesCombo.getText()
0241: .trim();
0242: if (destinationText.indexOf('.') < 0)
0243: destinationText += getOutputSuffix();
0244: return destinationText;
0245: }
0246:
0247: /**
0248: * Answer the string to display in self as the destination type
0249: *
0250: * @return java.lang.String
0251: */
0252: protected String getDestinationLabel() {
0253: return JarPackagerMessages.JarPackageWizardPage_destination_label;
0254: }
0255:
0256: /**
0257: * Answer the suffix that files exported from this wizard must have.
0258: * If this suffix is a file extension (which is typically the case)
0259: * then it must include the leading period character.
0260: *
0261: * @return java.lang.String
0262: */
0263: protected String getOutputSuffix() {
0264: return "." + JarPackagerUtil.JAR_EXTENSION; //$NON-NLS-1$
0265: }
0266:
0267: /**
0268: * Returns an iterator over this page's collection of currently-specified
0269: * elements to be exported. This is the primary element selection facility
0270: * accessor for subclasses.
0271: *
0272: * @return an iterator over the collection of elements currently selected for export
0273: */
0274: protected Iterator getSelectedResourcesIterator() {
0275: return fInputGroup.getAllCheckedListItems();
0276: }
0277:
0278: /**
0279: * Persists resource specification control setting that are to be restored
0280: * in the next instance of this page. Subclasses wishing to persist
0281: * settings for their controls should extend the hook method
0282: * <code>internalSaveWidgetValues</code>.
0283: */
0284: public final void saveWidgetValues() {
0285: // update directory names history
0286: IDialogSettings settings = getDialogSettings();
0287: if (settings != null) {
0288: String[] directoryNames = settings
0289: .getArray(STORE_DESTINATION_NAMES);
0290: if (directoryNames == null)
0291: directoryNames = new String[0];
0292: directoryNames = addToHistory(directoryNames,
0293: getDestinationValue());
0294: settings.put(STORE_DESTINATION_NAMES, directoryNames);
0295:
0296: settings.put(STORE_EXPORT_CLASS_FILES, fJarPackage
0297: .areClassFilesExported());
0298: settings.put(STORE_EXPORT_OUTPUT_FOLDERS, fJarPackage
0299: .areOutputFoldersExported());
0300: settings.put(STORE_EXPORT_JAVA_FILES, fJarPackage
0301: .areJavaFilesExported());
0302:
0303: // options
0304: settings.put(STORE_REFACTORINGS, fJarPackage
0305: .isRefactoringAware());
0306: settings.put(STORE_COMPRESS, fJarPackage.isCompressed());
0307: settings.put(STORE_INCLUDE_DIRECTORY_ENTRIES, fJarPackage
0308: .areDirectoryEntriesIncluded());
0309: settings.put(STORE_OVERWRITE, fJarPackage.allowOverwrite());
0310: }
0311: // Allow subclasses to save values
0312: internalSaveWidgetValues();
0313: }
0314:
0315: /**
0316: * Hook method for subclasses to persist their settings.
0317: */
0318: protected void internalSaveWidgetValues() {
0319: }
0320:
0321: /**
0322: * Hook method for restoring widget values to the values that they held
0323: * last time this wizard was used to completion.
0324: */
0325: protected void restoreWidgetValues() {
0326: if (!((JarPackageWizard) getWizard())
0327: .isInitializingFromJarPackage())
0328: initializeJarPackage();
0329:
0330: fExportClassFilesCheckbox.setSelection(fJarPackage
0331: .areClassFilesExported());
0332: fExportOutputFoldersCheckbox.setSelection(fJarPackage
0333: .areOutputFoldersExported());
0334: fExportJavaFilesCheckbox.setSelection(fJarPackage
0335: .areJavaFilesExported());
0336:
0337: // destination
0338: if (fJarPackage.getJarLocation().isEmpty())
0339: fDestinationNamesCombo.setText(""); //$NON-NLS-1$
0340: else
0341: fDestinationNamesCombo.setText(fJarPackage.getJarLocation()
0342: .toOSString());
0343: IDialogSettings settings = getDialogSettings();
0344: if (settings != null) {
0345: String[] directoryNames = settings
0346: .getArray(STORE_DESTINATION_NAMES);
0347: if (directoryNames == null)
0348: return; // ie.- no settings stored
0349: if (!fDestinationNamesCombo.getText().equals(
0350: directoryNames[0]))
0351: fDestinationNamesCombo.add(fDestinationNamesCombo
0352: .getText());
0353: for (int i = 0; i < directoryNames.length; i++)
0354: fDestinationNamesCombo.add(directoryNames[i]);
0355: }
0356:
0357: // options
0358: if (fExportRefactoringsCheckbox != null)
0359: fExportRefactoringsCheckbox.setSelection(fJarPackage
0360: .isRefactoringAware());
0361: fCompressCheckbox.setSelection(fJarPackage.isCompressed());
0362: fIncludeDirectoryEntriesCheckbox.setSelection(fJarPackage
0363: .areDirectoryEntriesIncluded());
0364: fOverwriteCheckbox.setSelection(fJarPackage.allowOverwrite());
0365: }
0366:
0367: /**
0368: * Initializes the JAR package from last used wizard page values.
0369: */
0370: protected void initializeJarPackage() {
0371: IDialogSettings settings = getDialogSettings();
0372: if (settings != null) {
0373: // source
0374: fJarPackage.setElements(getSelectedElements());
0375: fJarPackage.setExportClassFiles(settings
0376: .getBoolean(STORE_EXPORT_CLASS_FILES));
0377: fJarPackage.setExportOutputFolders(settings
0378: .getBoolean(STORE_EXPORT_OUTPUT_FOLDERS));
0379: fJarPackage.setExportJavaFiles(settings
0380: .getBoolean(STORE_EXPORT_JAVA_FILES));
0381:
0382: // options
0383: fJarPackage.setRefactoringAware(settings
0384: .getBoolean(STORE_REFACTORINGS));
0385: fJarPackage
0386: .setCompress(settings.getBoolean(STORE_COMPRESS));
0387: fJarPackage.setIncludeDirectoryEntries(settings
0388: .getBoolean(STORE_INCLUDE_DIRECTORY_ENTRIES));
0389: fJarPackage.setOverwrite(settings
0390: .getBoolean(STORE_OVERWRITE));
0391:
0392: // destination
0393: String[] directoryNames = settings
0394: .getArray(STORE_DESTINATION_NAMES);
0395: if (directoryNames == null)
0396: return; // ie.- no settings stored
0397: fJarPackage.setJarLocation(Path
0398: .fromOSString(directoryNames[0]));
0399: }
0400: }
0401:
0402: /**
0403: * Stores the widget values in the JAR package.
0404: */
0405: protected void updateModel() {
0406: if (getControl() == null)
0407: return;
0408:
0409: // source
0410: if (fExportClassFilesCheckbox.getSelection()
0411: && !fJarPackage.areClassFilesExported())
0412: fExportOutputFoldersCheckbox.setSelection(false);
0413: if (fExportOutputFoldersCheckbox.getSelection()
0414: && !fJarPackage.areOutputFoldersExported())
0415: fExportClassFilesCheckbox.setSelection(false);
0416: fJarPackage.setExportClassFiles(fExportClassFilesCheckbox
0417: .getSelection());
0418: fJarPackage.setExportOutputFolders(fExportOutputFoldersCheckbox
0419: .getSelection());
0420: fJarPackage.setExportJavaFiles(fExportJavaFilesCheckbox
0421: .getSelection());
0422: fJarPackage.setElements(getSelectedElements());
0423:
0424: // destination
0425: String comboText = fDestinationNamesCombo.getText();
0426: IPath path = Path.fromOSString(comboText);
0427:
0428: if (path.segmentCount() > 0
0429: && ensureTargetFileIsValid(path.toFile())
0430: && path.getFileExtension() == null)
0431: // append .jar
0432: path = path.addFileExtension(JarPackagerUtil.JAR_EXTENSION);
0433:
0434: fJarPackage.setJarLocation(path);
0435:
0436: // options
0437: if (fExportRefactoringsCheckbox != null)
0438: fJarPackage.setRefactoringAware(fExportRefactoringsCheckbox
0439: .getSelection());
0440: else
0441: fJarPackage.setRefactoringAware(false);
0442: fJarPackage.setCompress(fCompressCheckbox.getSelection());
0443: fJarPackage
0444: .setIncludeDirectoryEntries(fIncludeDirectoryEntriesCheckbox
0445: .getSelection());
0446: fJarPackage.setOverwrite(fOverwriteCheckbox.getSelection());
0447: }
0448:
0449: /**
0450: * Returns a boolean indicating whether the passed File handle is
0451: * is valid and available for use.
0452: *
0453: * @return boolean
0454: */
0455: protected boolean ensureTargetFileIsValid(File targetFile) {
0456: if (targetFile.exists() && targetFile.isDirectory()
0457: && fDestinationNamesCombo.getText().length() > 0) {
0458: setErrorMessage(JarPackagerMessages.JarPackageWizardPage_error_exportDestinationMustNotBeDirectory);
0459: fDestinationNamesCombo.setFocus();
0460: return false;
0461: }
0462: if (targetFile.exists()) {
0463: if (!targetFile.canWrite()) {
0464: setErrorMessage(JarPackagerMessages.JarPackageWizardPage_error_jarFileExistsAndNotWritable);
0465: fDestinationNamesCombo.setFocus();
0466: return false;
0467: }
0468: }
0469: return true;
0470: }
0471:
0472: /*
0473: * Overrides method from WizardExportPage
0474: */
0475: protected void createDestinationGroup(Composite parent) {
0476:
0477: initializeDialogUnits(parent);
0478:
0479: // destination specification group
0480: Composite destinationSelectionGroup = new Composite(parent,
0481: SWT.NONE);
0482: GridLayout layout = new GridLayout();
0483: layout.numColumns = 3;
0484: destinationSelectionGroup.setLayout(layout);
0485: destinationSelectionGroup.setLayoutData(new GridData(
0486: GridData.HORIZONTAL_ALIGN_FILL
0487: | GridData.VERTICAL_ALIGN_FILL));
0488:
0489: new Label(destinationSelectionGroup, SWT.NONE)
0490: .setText(getDestinationLabel());
0491:
0492: // destination name entry field
0493: fDestinationNamesCombo = new Combo(destinationSelectionGroup,
0494: SWT.SINGLE | SWT.BORDER);
0495: fDestinationNamesCombo.addListener(SWT.Modify, this );
0496: fDestinationNamesCombo.addListener(SWT.Selection, this );
0497: GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL
0498: | GridData.GRAB_HORIZONTAL);
0499: data.widthHint = SIZING_TEXT_FIELD_WIDTH;
0500: fDestinationNamesCombo.setLayoutData(data);
0501:
0502: // destination browse button
0503: fDestinationBrowseButton = new Button(
0504: destinationSelectionGroup, SWT.PUSH);
0505: fDestinationBrowseButton
0506: .setText(JarPackagerMessages.JarPackageWizardPage_browseButton_text);
0507: fDestinationBrowseButton.setLayoutData(new GridData(
0508: GridData.HORIZONTAL_ALIGN_FILL));
0509: SWTUtil.setButtonDimensionHint(fDestinationBrowseButton);
0510: fDestinationBrowseButton
0511: .addSelectionListener(new SelectionAdapter() {
0512: public void widgetSelected(SelectionEvent e) {
0513: handleDestinationBrowseButtonPressed();
0514: }
0515: });
0516: }
0517:
0518: /**
0519: * Open an appropriate destination browser so that the user can specify a source
0520: * to import from
0521: */
0522: protected void handleDestinationBrowseButtonPressed() {
0523: FileDialog dialog = new FileDialog(getContainer().getShell(),
0524: SWT.SAVE);
0525: dialog.setFilterExtensions(new String[] { "*.jar", "*.zip" }); //$NON-NLS-1$ //$NON-NLS-2$
0526:
0527: String currentSourceString = getDestinationValue();
0528: int lastSeparatorIndex = currentSourceString
0529: .lastIndexOf(File.separator);
0530: if (lastSeparatorIndex != -1) {
0531: dialog.setFilterPath(currentSourceString.substring(0,
0532: lastSeparatorIndex));
0533: dialog.setFileName(currentSourceString.substring(
0534: lastSeparatorIndex + 1, currentSourceString
0535: .length()));
0536: } else
0537: dialog.setFileName(currentSourceString);
0538: String selectedFileName = dialog.open();
0539: if (selectedFileName != null)
0540: fDestinationNamesCombo.setText(selectedFileName);
0541: }
0542:
0543: /**
0544: * Returns the resource for the specified path.
0545: *
0546: * @param path the path for which the resource should be returned
0547: * @return the resource specified by the path or <code>null</code>
0548: */
0549: protected IResource findResource(IPath path) {
0550: IWorkspace workspace = ResourcesPlugin.getWorkspace();
0551: IStatus result = workspace.validatePath(path.toString(),
0552: IResource.ROOT | IResource.PROJECT | IResource.FOLDER
0553: | IResource.FILE);
0554: if (result.isOK() && workspace.getRoot().exists(path))
0555: return workspace.getRoot().findMember(path);
0556: return null;
0557: }
0558:
0559: /**
0560: * Creates the checkbox tree and list for selecting resources.
0561: *
0562: * @param parent the parent control
0563: */
0564: protected void createInputGroup(Composite parent) {
0565: int labelFlags = JavaElementLabelProvider.SHOW_BASICS
0566: | JavaElementLabelProvider.SHOW_OVERLAY_ICONS
0567: | JavaElementLabelProvider.SHOW_SMALL_ICONS;
0568: ITreeContentProvider treeContentProvider = new StandardJavaElementContentProvider() {
0569: public boolean hasChildren(Object element) {
0570: // prevent the + from being shown in front of packages
0571: return !(element instanceof IPackageFragment)
0572: && super .hasChildren(element);
0573: }
0574: };
0575: final DecoratingLabelProvider provider = new DecoratingLabelProvider(
0576: new JavaElementLabelProvider(labelFlags),
0577: new ProblemsLabelDecorator(null));
0578: fInputGroup = new CheckboxTreeAndListGroup(parent, JavaCore
0579: .create(ResourcesPlugin.getWorkspace().getRoot()),
0580: treeContentProvider, provider,
0581: new StandardJavaElementContentProvider(), provider,
0582: SWT.NONE, SIZING_SELECTION_WIDGET_WIDTH,
0583: SIZING_SELECTION_WIDGET_HEIGHT) {
0584:
0585: protected void setTreeChecked(final Object element,
0586: final boolean state) {
0587: if (fInitiallySelecting && element instanceof IResource) {
0588: final IResource resource = (IResource) element;
0589: if (resource.getName().charAt(0) == '.')
0590: return;
0591: }
0592: super .setTreeChecked(element, state);
0593: }
0594: };
0595: fInputGroup.addTreeFilter(new EmptyInnerPackageFilter());
0596: fInputGroup.setTreeComparator(new JavaElementComparator());
0597: fInputGroup.setListComparator(new JavaElementComparator());
0598: fInputGroup.addTreeFilter(new ContainerFilter(
0599: ContainerFilter.FILTER_NON_CONTAINERS));
0600: fInputGroup.addTreeFilter(new LibraryFilter());
0601: fInputGroup.addListFilter(new ContainerFilter(
0602: ContainerFilter.FILTER_CONTAINERS));
0603: fInputGroup.getTree().addListener(SWT.MouseUp, this );
0604: fInputGroup.getTable().addListener(SWT.MouseUp, this );
0605:
0606: ICheckStateListener listener = new ICheckStateListener() {
0607: public void checkStateChanged(CheckStateChangedEvent event) {
0608: update();
0609: }
0610: };
0611:
0612: fInputGroup.addCheckStateListener(listener);
0613: }
0614:
0615: /**
0616: * Creates the export type controls.
0617: *
0618: * @param parent
0619: * the parent control
0620: */
0621: protected void createExportTypeGroup(Composite parent) {
0622: Composite optionsGroup = new Composite(parent, SWT.NONE);
0623: GridLayout layout = new GridLayout();
0624: layout.marginHeight = 0;
0625: optionsGroup.setLayout(layout);
0626:
0627: fExportClassFilesCheckbox = new Button(optionsGroup, SWT.CHECK
0628: | SWT.LEFT);
0629: fExportClassFilesCheckbox
0630: .setText(JarPackagerMessages.JarPackageWizardPage_exportClassFiles_text);
0631: fExportClassFilesCheckbox.addListener(SWT.Selection, this );
0632:
0633: fExportOutputFoldersCheckbox = new Button(optionsGroup,
0634: SWT.CHECK | SWT.LEFT);
0635: fExportOutputFoldersCheckbox
0636: .setText(JarPackagerMessages.JarPackageWizardPage_exportOutputFolders_text);
0637: fExportOutputFoldersCheckbox.addListener(SWT.Selection, this );
0638:
0639: fExportJavaFilesCheckbox = new Button(optionsGroup, SWT.CHECK
0640: | SWT.LEFT);
0641: fExportJavaFilesCheckbox
0642: .setText(JarPackagerMessages.JarPackageWizardPage_exportJavaFiles_text);
0643: fExportJavaFilesCheckbox.addListener(SWT.Selection, this );
0644:
0645: Composite refactoringsGroup = new Composite(optionsGroup,
0646: SWT.NONE);
0647: layout = new GridLayout();
0648: layout.horizontalSpacing = 0;
0649: layout.marginWidth = 0;
0650: layout.marginHeight = 0;
0651: layout.numColumns = 2;
0652: refactoringsGroup.setLayout(layout);
0653:
0654: fExportRefactoringsCheckbox = new Button(refactoringsGroup,
0655: SWT.CHECK | SWT.LEFT);
0656: fExportRefactoringsCheckbox
0657: .setText(JarPackagerMessages.JarPackageWizardPage_refactorings_text);
0658: fExportRefactoringsCheckbox.addListener(SWT.Selection, this );
0659:
0660: fRefactoringLink = new Link(refactoringsGroup, SWT.WRAP);
0661: fRefactoringLink
0662: .setText(JarPackagerMessages.JarPackageWizardPage_configure_label);
0663: fRefactoringLink.addSelectionListener(new SelectionAdapter() {
0664:
0665: public void widgetSelected(SelectionEvent event) {
0666: openRefactoringDialog();
0667: }
0668:
0669: });
0670: fRefactoringLink
0671: .setToolTipText(JarPackagerMessages.JarPackageWizardPage_configure_tooltip);
0672: GridData data = new GridData(GridData.BEGINNING
0673: | GridData.GRAB_HORIZONTAL);
0674: fRefactoringLink.setLayoutData(data);
0675:
0676: fExportRefactoringsCheckbox
0677: .addSelectionListener(new SelectionAdapter() {
0678:
0679: public void widgetSelected(SelectionEvent event) {
0680: fRefactoringLink
0681: .setEnabled(fExportRefactoringsCheckbox
0682: .getSelection());
0683: }
0684: });
0685: }
0686:
0687: /**
0688: * Opens the dialog to configure refactorings.
0689: */
0690: protected void openRefactoringDialog() {
0691: final RefactoringHistory[] history = { null };
0692: final IRefactoringHistoryService service = RefactoringCore
0693: .getHistoryService();
0694: try {
0695: service.connect();
0696: final Set set = new HashSet();
0697: final Object[] elements = fJarPackage.getElements();
0698: for (int index = 0; index < elements.length; index++) {
0699: if (elements[index] instanceof IAdaptable) {
0700: final IAdaptable adaptable = (IAdaptable) elements[index];
0701: final IResource resource = (IResource) adaptable
0702: .getAdapter(IResource.class);
0703: if (resource != null)
0704: set.add(resource.getProject());
0705: }
0706: }
0707: try {
0708: getContainer().run(false, true,
0709: new IRunnableWithProgress() {
0710:
0711: public void run(
0712: final IProgressMonitor monitor)
0713: throws InvocationTargetException,
0714: InterruptedException {
0715: history[0] = service
0716: .getRefactoringHistory(
0717: (IProject[]) set
0718: .toArray(new IProject[set
0719: .size()]),
0720: 0,
0721: Long.MAX_VALUE,
0722: JavaRefactoringDescriptor.JAR_MIGRATION,
0723: monitor);
0724: }
0725: });
0726: } catch (InvocationTargetException exception) {
0727: ExceptionHandler
0728: .handle(
0729: exception,
0730: getShell(),
0731: JarPackagerMessages.JarPackageWizardPage_error_caption,
0732: JarPackagerMessages.JarPackageWizardPage_error_label);
0733: return;
0734: } catch (InterruptedException exception) {
0735: return;
0736: }
0737: new JarRefactoringDialog(getShell(), getDialogSettings(),
0738: fJarPackage, history[0]).open();
0739: updatePageCompletion();
0740: } finally {
0741: service.disconnect();
0742: }
0743: }
0744:
0745: /**
0746: * Updates the enablement of this page's controls. Subclasses may extend.
0747: */
0748: protected void updateWidgetEnablements() {
0749: if (fExportRefactoringsCheckbox != null) {
0750: final boolean selection = fExportRefactoringsCheckbox
0751: .getSelection();
0752: fIncludeDirectoryEntriesCheckbox.setEnabled(!selection);
0753: if (selection) {
0754: fIncludeDirectoryEntriesCheckbox.setSelection(true);
0755: fJarPackage.setIncludeDirectoryEntries(true);
0756: }
0757: }
0758: }
0759:
0760: /*
0761: * Overrides method from IJarPackageWizardPage
0762: */
0763: public boolean isPageComplete() {
0764: boolean complete = validateSourceGroup();
0765: complete = validateDestinationGroup() && complete;
0766: complete = validateOptionsGroup() && complete;
0767: if (complete)
0768: setErrorMessage(null);
0769: return complete;
0770: }
0771:
0772: /*
0773: * Implements method from Listener
0774: */
0775: public void handleEvent(Event e) {
0776: if (getControl() == null)
0777: return;
0778: update();
0779: }
0780:
0781: protected void update() {
0782: updateModel();
0783: updateWidgetEnablements();
0784: updatePageCompletion();
0785: }
0786:
0787: protected void updatePageCompletion() {
0788: boolean pageComplete = isPageComplete();
0789: setPageComplete(pageComplete);
0790: if (pageComplete)
0791: setErrorMessage(null);
0792: updateRefactoringMessage();
0793: }
0794:
0795: protected void updateRefactoringMessage() {
0796: String currentMessage = getMessage();
0797: if (fJarPackage.isRefactoringAware()
0798: && fJarPackage.getRefactoringDescriptors().length == 0) {
0799: if (currentMessage == null)
0800: setMessage(
0801: JarPackagerMessages.JarPackageWizardPage_no_refactorings_selected,
0802: IMessageProvider.INFORMATION);
0803: } else if (JarPackagerMessages.JarPackageWizardPage_no_refactorings_selected
0804: .equals(currentMessage))
0805: setMessage(null);
0806: }
0807:
0808: /*
0809: * Overrides method from WizardDataTransferPage
0810: */
0811: protected boolean validateDestinationGroup() {
0812: if (fDestinationNamesCombo.getText().length() == 0) {
0813: // Clear error
0814: if (getErrorMessage() != null)
0815: setErrorMessage(null);
0816: if (getMessage() != null)
0817: setMessage(null);
0818: return false;
0819: }
0820: if (fJarPackage.getAbsoluteJarLocation().toString().endsWith(
0821: "/")) { //$NON-NLS-1$
0822: setErrorMessage(JarPackagerMessages.JarPackageWizardPage_error_exportDestinationMustNotBeDirectory);
0823: fDestinationNamesCombo.setFocus();
0824: return false;
0825: }
0826: // Check if the Jar is put into the workspace and conflicts with the containers
0827: // exported. If the workspace isn't on the local files system we are fine since
0828: // the Jar is always created in the local file system
0829: IPath workspaceLocation = ResourcesPlugin.getWorkspace()
0830: .getRoot().getLocation();
0831: if (workspaceLocation != null
0832: && workspaceLocation.isPrefixOf(fJarPackage
0833: .getAbsoluteJarLocation())) {
0834: int segments = workspaceLocation
0835: .matchingFirstSegments(fJarPackage
0836: .getAbsoluteJarLocation());
0837: IPath path = fJarPackage.getAbsoluteJarLocation()
0838: .removeFirstSegments(segments);
0839: IResource resource = ResourcesPlugin.getWorkspace()
0840: .getRoot().findMember(path);
0841: if (resource != null
0842: && resource.getType() == IResource.FILE) {
0843: // test if included
0844: if (JarPackagerUtil.contains(JarPackagerUtil
0845: .asResources(fJarPackage.getElements()),
0846: (IFile) resource)) {
0847: setErrorMessage(JarPackagerMessages.JarPackageWizardPage_error_cantExportJARIntoItself);
0848: return false;
0849: }
0850: }
0851: }
0852: // Inform user about relative directory
0853: String currentMessage = getMessage();
0854: if (!(new File(fDestinationNamesCombo.getText()).isAbsolute())) {
0855: if (currentMessage == null)
0856: setMessage(
0857: JarPackagerMessages.JarPackageWizardPage_info_relativeExportDestination,
0858: IMessageProvider.INFORMATION);
0859: } else {
0860: if (currentMessage != null)
0861: setMessage(null);
0862: }
0863: return ensureTargetFileIsValid(fJarPackage
0864: .getAbsoluteJarLocation().toFile());
0865: }
0866:
0867: /*
0868: * Overrides method from WizardDataTransferPage
0869: */
0870: protected boolean validateOptionsGroup() {
0871: return true;
0872: }
0873:
0874: /*
0875: * Overrides method from WizardDataTransferPage
0876: */
0877: protected boolean validateSourceGroup() {
0878: if (!(fExportClassFilesCheckbox.getSelection()
0879: || fExportOutputFoldersCheckbox.getSelection() || fExportJavaFilesCheckbox
0880: .getSelection())) {
0881: setErrorMessage(JarPackagerMessages.JarPackageWizardPage_error_noExportTypeChecked);
0882: return false;
0883: }
0884:
0885: if (getSelectedResources().size() == 0) {
0886: if (getErrorMessage() != null)
0887: setErrorMessage(null);
0888: return false;
0889: }
0890: if (fExportClassFilesCheckbox.getSelection()
0891: || fExportOutputFoldersCheckbox.getSelection())
0892: return true;
0893:
0894: // Source file only export - check if there are source files
0895: Iterator iter = getSelectedResourcesIterator();
0896: while (iter.hasNext()) {
0897: Object element = iter.next();
0898: if (element instanceof IClassFile) {
0899: IPackageFragmentRoot root = (IPackageFragmentRoot) ((IClassFile) element)
0900: .getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
0901: if (root == null)
0902: continue;
0903: IClasspathEntry cpEntry;
0904: try {
0905: cpEntry = root.getRawClasspathEntry();
0906: } catch (JavaModelException e) {
0907: continue;
0908: }
0909: if (cpEntry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) {
0910: return true;
0911: }
0912: } else {
0913: return true;
0914: }
0915: }
0916:
0917: if (getErrorMessage() != null)
0918: setErrorMessage(null);
0919: return false;
0920: }
0921:
0922: /**
0923: * Creates a file resource handle for the file with the given workspace path.
0924: * This method does not create the file resource; this is the responsibility
0925: * of <code>createFile</code>.
0926: *
0927: * @param filePath the path of the file resource to create a handle for
0928: * @return the new file resource handle
0929: */
0930: protected IFile createFileHandle(IPath filePath) {
0931: if (filePath.isValidPath(filePath.toString())
0932: && filePath.segmentCount() >= 2)
0933: return ResourcesPlugin.getWorkspace().getRoot().getFile(
0934: filePath);
0935: else
0936: return null;
0937: }
0938:
0939: /**
0940: * Set the current input focus to self's destination entry field
0941: */
0942: protected void giveFocusToDestination() {
0943: fDestinationNamesCombo.setFocus();
0944: }
0945:
0946: /*
0947: * Overrides method from WizardExportResourcePage
0948: */
0949: protected void setupBasedOnInitialSelections() {
0950: Iterator iterator = fInitialSelection.iterator();
0951: while (iterator.hasNext()) {
0952: Object selectedElement = iterator.next();
0953:
0954: if (selectedElement instanceof IResource
0955: && !((IResource) selectedElement).isAccessible())
0956: continue;
0957:
0958: if (selectedElement instanceof IJavaElement
0959: && !((IJavaElement) selectedElement).exists())
0960: continue;
0961:
0962: if (selectedElement instanceof ICompilationUnit
0963: || selectedElement instanceof IClassFile
0964: || selectedElement instanceof IFile)
0965: fInputGroup.initialCheckListItem(selectedElement);
0966: else {
0967: if (selectedElement instanceof IFolder) {
0968: // Convert resource to Java element if possible
0969: IJavaElement je = JavaCore
0970: .create((IResource) selectedElement);
0971: if (je != null
0972: && je.exists()
0973: && je.getJavaProject().isOnClasspath(
0974: (IResource) selectedElement))
0975: selectedElement = je;
0976: }
0977: try {
0978: fInputGroup.initialCheckTreeItem(selectedElement);
0979: } finally {
0980: fInitiallySelecting = false;
0981: }
0982: }
0983: }
0984:
0985: TreeItem[] items = fInputGroup.getTree().getItems();
0986: int i = 0;
0987: while (i < items.length && !items[i].getChecked())
0988: i++;
0989: if (i < items.length) {
0990: fInputGroup.getTree().setSelection(
0991: new TreeItem[] { items[i] });
0992: fInputGroup.getTree().showSelection();
0993: fInputGroup.populateListViewer(items[i].getData());
0994: }
0995: }
0996:
0997: /*
0998: * Implements method from IJarPackageWizardPage.
0999: */
1000: public void finish() {
1001: saveWidgetValues();
1002: }
1003:
1004: /*
1005: * Method declared on IWizardPage.
1006: */
1007: public void setPreviousPage(IWizardPage page) {
1008: super .setPreviousPage(page);
1009: if (getControl() != null)
1010: updatePageCompletion();
1011: }
1012:
1013: Object[] getSelectedElementsWithoutContainedChildren() {
1014: Set closure = removeContainedChildren(fInputGroup
1015: .getWhiteCheckedTreeItems());
1016: closure.addAll(getExportedNonContainers());
1017: return closure.toArray();
1018: }
1019:
1020: private Set removeContainedChildren(Set elements) {
1021: Set newList = new HashSet(elements.size());
1022: Set javaElementResources = getCorrespondingContainers(elements);
1023: Iterator iter = elements.iterator();
1024: boolean removedOne = false;
1025: while (iter.hasNext()) {
1026: Object element = iter.next();
1027: Object parent;
1028: if (element instanceof IResource)
1029: parent = ((IResource) element).getParent();
1030: else if (element instanceof IJavaElement) {
1031: parent = ((IJavaElement) element).getParent();
1032: if (parent instanceof IPackageFragmentRoot) {
1033: IPackageFragmentRoot pkgRoot = (IPackageFragmentRoot) parent;
1034: try {
1035: if (pkgRoot.getCorrespondingResource() instanceof IProject)
1036: parent = pkgRoot.getJavaProject();
1037: } catch (JavaModelException ex) {
1038: // leave parent as is
1039: }
1040: }
1041: } else {
1042: // unknown type
1043: newList.add(element);
1044: continue;
1045: }
1046: if (element instanceof IJavaModel
1047: || ((!(parent instanceof IJavaModel)) && (elements
1048: .contains(parent) || javaElementResources
1049: .contains(parent))))
1050: removedOne = true;
1051: else
1052: newList.add(element);
1053: }
1054: if (removedOne)
1055: return removeContainedChildren(newList);
1056: else
1057: return newList;
1058: }
1059:
1060: private Set getExportedNonContainers() {
1061: Set whiteCheckedTreeItems = fInputGroup
1062: .getWhiteCheckedTreeItems();
1063: Set exportedNonContainers = new HashSet(whiteCheckedTreeItems
1064: .size());
1065: Set javaElementResources = getCorrespondingContainers(whiteCheckedTreeItems);
1066: Iterator iter = fInputGroup.getAllCheckedListItems();
1067: while (iter.hasNext()) {
1068: Object element = iter.next();
1069: Object parent = null;
1070: if (element instanceof IResource)
1071: parent = ((IResource) element).getParent();
1072: else if (element instanceof IJavaElement)
1073: parent = ((IJavaElement) element).getParent();
1074: if (!whiteCheckedTreeItems.contains(parent)
1075: && !javaElementResources.contains(parent))
1076: exportedNonContainers.add(element);
1077: }
1078: return exportedNonContainers;
1079: }
1080:
1081: /*
1082: * Create a list with the folders / projects that correspond
1083: * to the Java elements (Java project, package, package root)
1084: */
1085: private Set getCorrespondingContainers(Set elements) {
1086: Set javaElementResources = new HashSet(elements.size());
1087: Iterator iter = elements.iterator();
1088: while (iter.hasNext()) {
1089: Object element = iter.next();
1090: if (element instanceof IJavaElement) {
1091: IJavaElement je = (IJavaElement) element;
1092: int type = je.getElementType();
1093: if (type == IJavaElement.JAVA_PROJECT
1094: || type == IJavaElement.PACKAGE_FRAGMENT
1095: || type == IJavaElement.PACKAGE_FRAGMENT_ROOT) {
1096: // exclude default package since it is covered by the root
1097: if (!(type == IJavaElement.PACKAGE_FRAGMENT && ((IPackageFragment) element)
1098: .isDefaultPackage())) {
1099: Object resource;
1100: try {
1101: resource = je.getCorrespondingResource();
1102: } catch (JavaModelException ex) {
1103: resource = null;
1104: }
1105: if (resource != null)
1106: javaElementResources.add(resource);
1107: }
1108: }
1109: }
1110: }
1111: return javaElementResources;
1112: }
1113:
1114: private Object[] getSelectedElements() {
1115: return getSelectedResources().toArray();
1116: }
1117: }
|