Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.apache.easyant4e.wizards; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import org.apache.easyant4e.Activator; import org.apache.easyant4e.natures.AddEasyAntNatureOperation; import org.apache.easyant4e.services.EasyantProjectService; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.CheckStateChangedEvent; import org.eclipse.jface.viewers.CheckboxTreeViewer; import org.eclipse.jface.viewers.ICheckStateListener; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerComparator; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.TraverseEvent; import org.eclipse.swt.events.TraverseListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.DirectoryDialog; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.eclipse.ui.dialogs.IOverwriteQuery; import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider; import org.eclipse.ui.wizards.datatransfer.ImportOperation; import com.google.inject.Inject; //import com.google.inject.Inject; /** * This wizard is used to import existing EasyAnt Projects * * Inspired from WizardProjectsImportPage */ public class EasyAntImportWizardPage extends WizardPage { private EasyantProjectService easyantProjectService; @Inject public void setEasyantProjectService(EasyantProjectService easyantProjectService) { this.easyantProjectService = easyantProjectService; } public EasyAntImportWizardPage() { super("Import EasyAnt projects"); setPageComplete(false); setTitle("Import EasyAnt projects"); setDescription("Select a directory to search for existing EasyAnt projects."); } /** * The name of the folder containing metadata information for the workspace. */ public static final String METADATA_FOLDER = ".metadata"; //$NON-NLS-1$ //FIXME hard coded the folder name ? public static final String TARGET_FOLDER = "target"; //$NON-NLS-1$ private Text directoryPathField; private CheckboxTreeViewer projectsList; private ProjectRecord[] selectedProjects = new ProjectRecord[0]; // Keep track of the directory that we browsed to last time // the wizard was invoked. private static String previouslyBrowsedDirectory = ""; //$NON-NLS-1$ private Button browseDirectoriesButton; private IProject[] wsProjects; // The last selected path to minimize searches private String lastPath; // The last time that the file or folder at the selected path was modified // to mimize searches private long lastModified; /* * (non-Javadoc) * * @see * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets * .Composite) */ public void createControl(Composite parent) { initializeDialogUnits(parent); Composite workArea = new Composite(parent, SWT.NONE); setControl(workArea); workArea.setLayout(new GridLayout()); workArea.setLayoutData( new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL)); createProjectsRoot(workArea); createProjectsList(workArea); createOptionsArea(workArea); Dialog.applyDialogFont(workArea); } /** * Create the area with the extra options. * * @param workArea */ private void createOptionsArea(Composite workArea) { Composite optionsGroup = new Composite(workArea, SWT.NONE); optionsGroup.setLayout(new GridLayout()); optionsGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); } /** * Create the checkbox list for the found projects. * * @param workArea */ private void createProjectsList(Composite workArea) { Label title = new Label(workArea, SWT.NONE); title.setText("EasyAnt Projects:"); Composite listComposite = new Composite(workArea, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 2; layout.marginWidth = 0; layout.makeColumnsEqualWidth = false; listComposite.setLayout(layout); listComposite.setLayoutData( new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH)); projectsList = new CheckboxTreeViewer(listComposite, SWT.BORDER); GridData listData = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL | GridData.FILL_BOTH); projectsList.getControl().setLayoutData(listData); projectsList.setContentProvider(new ITreeContentProvider() { public Object[] getChildren(Object parentElement) { return null; } public Object[] getElements(Object inputElement) { return getValidProjects(); } public boolean hasChildren(Object element) { return false; } public Object getParent(Object element) { return null; } public void dispose() { } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } }); projectsList.setLabelProvider(new LabelProvider() { public String getText(Object element) { return ((ProjectRecord) element).getProjectLabel(); } }); projectsList.addCheckStateListener(new ICheckStateListener() { public void checkStateChanged(CheckStateChangedEvent event) { setPageComplete(projectsList.getCheckedElements().length > 0); } }); projectsList.setInput(this); projectsList.setComparator(new ViewerComparator()); createSelectionButtons(listComposite); } /** * Create the selection buttons in the listComposite. * * @param listComposite */ private void createSelectionButtons(Composite listComposite) { Composite buttonsComposite = new Composite(listComposite, SWT.NONE); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; buttonsComposite.setLayout(layout); buttonsComposite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); Button selectAll = new Button(buttonsComposite, SWT.PUSH); selectAll.setText("Select All"); selectAll.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { projectsList.setCheckedElements(selectedProjects); setPageComplete(projectsList.getCheckedElements().length > 0); } }); Dialog.applyDialogFont(selectAll); setButtonLayoutData(selectAll); Button deselectAll = new Button(buttonsComposite, SWT.PUSH); deselectAll.setText("Deselect All"); deselectAll.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { projectsList.setCheckedElements(new Object[0]); setPageComplete(false); } }); Dialog.applyDialogFont(deselectAll); setButtonLayoutData(deselectAll); Button refresh = new Button(buttonsComposite, SWT.PUSH); refresh.setText("Refresh"); refresh.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { updateProjectsList(directoryPathField.getText().trim()); } }); Dialog.applyDialogFont(refresh); setButtonLayoutData(refresh); } /** * Create the area where you select the root directory for the projects. * * @param workArea * Composite */ private void createProjectsRoot(Composite workArea) { // project specification group Composite projectGroup = new Composite(workArea, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 3; layout.makeColumnsEqualWidth = false; layout.marginWidth = 0; projectGroup.setLayout(layout); projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); // project location entry field this.directoryPathField = new Text(projectGroup, SWT.BORDER); this.directoryPathField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); // browse button browseDirectoriesButton = new Button(projectGroup, SWT.PUSH); browseDirectoriesButton.setText("Browse"); setButtonLayoutData(browseDirectoriesButton); browseDirectoriesButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { handleLocationDirectoryButtonPressed(); } }); directoryPathField.addTraverseListener(new TraverseListener() { public void keyTraversed(TraverseEvent e) { if (e.detail == SWT.TRAVERSE_RETURN) { e.doit = false; updateProjectsList(directoryPathField.getText().trim()); } } }); directoryPathField.addFocusListener(new FocusAdapter() { public void focusLost(org.eclipse.swt.events.FocusEvent e) { updateProjectsList(directoryPathField.getText().trim()); } }); } /* * (non-Javadoc) Method declared on IDialogPage. Set the focus on path * fields when page becomes visible. */ public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { this.directoryPathField.setFocus(); } } /** * Update the list of projects based on path. Method declared public only * for test suite. * * @param path */ public void updateProjectsList(final String path) { // on an empty path empty selectedProjects if (path == null || path.length() == 0) { setMessage("Import Projects Description"); selectedProjects = new ProjectRecord[0]; projectsList.refresh(true); projectsList.setCheckedElements(selectedProjects); setPageComplete(projectsList.getCheckedElements().length > 0); lastPath = path; return; } final File directory = new File(path); long modified = directory.lastModified(); if (path.equals(lastPath) && lastModified == modified) { // since the file/folder was not modified and the path did not // change, no refreshing is required return; } lastPath = path; lastModified = modified; // We can't access the radio button from the inner class so get the // status beforehand // final boolean dirSelected = // this.projectFromDirectoryRadio.getSelection(); try { getContainer().run(true, true, new IRunnableWithProgress() { public void run(IProgressMonitor monitor) { monitor.beginTask("Searching", 100); selectedProjects = new ProjectRecord[0]; Collection files = new ArrayList(); monitor.worked(10); if (directory.isDirectory()) { if (!collectProjectFilesFromDirectory(files, directory, null, monitor)) { return; } Iterator filesIterator = files.iterator(); selectedProjects = new ProjectRecord[files.size()]; int index = 0; monitor.worked(50); monitor.subTask("Processing"); while (filesIterator.hasNext()) { File file = (File) filesIterator.next(); ProjectRecord projectRecord = new ProjectRecord(file, lastPath); selectedProjects[index] = projectRecord; index++; } } else { monitor.worked(60); } monitor.done(); } }); } catch (InvocationTargetException e) { Activator.getEasyAntPlugin().log(IStatus.ERROR, e.getMessage()); } catch (InterruptedException e) { // Nothing to do if the user interrupts. } projectsList.refresh(true); projectsList.setCheckedElements(getValidProjects()); if (getValidProjects().length < selectedProjects.length) { setMessage("Projects in workspace", WARNING); } else { setMessage("Import projects description"); } setPageComplete(projectsList.getCheckedElements().length > 0); } /** * Display an error dialog with the specified message. * * @param message * the error message */ protected void displayErrorDialog(String message) { MessageDialog.openError(getContainer().getShell(), getErrorDialogTitle(), message); } /** * Get the title for an error dialog. Subclasses should override. */ protected String getErrorDialogTitle() { // FIXME return "internalErrorTitle"; } /** * Collect the list of .project files that are under directory into files. * * @param files * @param directory * @param directoriesVisited * Set of canonical paths of directories, used as recursion guard * @param monitor * The monitor to report to * @return boolean <code>true</code> if the operation was completed. */ private boolean collectProjectFilesFromDirectory(Collection files, File directory, Set directoriesVisited, IProgressMonitor monitor) { if (monitor.isCanceled()) { return false; } monitor.subTask("Collect project files from " + directory.getPath()); File[] contents = directory.listFiles(); if (contents == null) { return false; } // Initialize recursion guard for recursive symbolic links if (directoriesVisited == null) { directoriesVisited = new HashSet(); try { directoriesVisited.add(directory.getCanonicalPath()); } catch (IOException exception) { Activator.getEasyAntPlugin().log(IStatus.ERROR, exception.getMessage(), exception); } } // first look for EasyAnt description files for (int i = 0; i < contents.length; i++) { File file = contents[i]; if (file.isFile() && file.getName().endsWith("ivy")) { files.add(file); } else if (contents[i].isDirectory()) { if (!contents[i].getName().equals(METADATA_FOLDER) && !contents[i].getName().equals(TARGET_FOLDER)) { try { String canonicalPath = contents[i].getCanonicalPath(); if (!directoriesVisited.add(canonicalPath)) { // already been here --> do not recurse continue; } } catch (IOException exception) { Activator.getEasyAntPlugin().log(IStatus.ERROR, exception.getMessage(), exception); } collectProjectFilesFromDirectory(files, contents[i], directoriesVisited, monitor); } } } return true; } /** * The browse button has been selected. Select the location. */ protected void handleLocationDirectoryButtonPressed() { DirectoryDialog dialog = new DirectoryDialog(directoryPathField.getShell()); dialog.setMessage("Select directory to scan"); String dirName = directoryPathField.getText().trim(); if (dirName.length() == 0) { dirName = previouslyBrowsedDirectory; } if (dirName.length() == 0) { dialog.setFilterPath( Activator.getEasyAntPlugin().getPluginWorkspace().getRoot().getLocation().toOSString()); } else { File path = new File(dirName); if (path.exists()) { dialog.setFilterPath(new Path(dirName).toOSString()); } } String selectedDirectory = dialog.open(); if (selectedDirectory != null) { previouslyBrowsedDirectory = selectedDirectory; directoryPathField.setText(previouslyBrowsedDirectory); updateProjectsList(selectedDirectory); } } /** * Create the selected projects * * @return boolean <code>true</code> if all project creations were * successful. */ public boolean createProjects() { final Object[] selected = projectsList.getCheckedElements(); WorkspaceModifyOperation op = new WorkspaceModifyOperation() { protected void execute(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { monitor.beginTask("", selected.length); //$NON-NLS-1$ if (monitor.isCanceled()) { throw new OperationCanceledException(); } for (int i = 0; i < selected.length; i++) { createExistingProject((ProjectRecord) selected[i], new SubProgressMonitor(monitor, 1)); } } finally { monitor.done(); } } }; // run the new project creation operation try { getContainer().run(true, true, op); } catch (InterruptedException e) { return false; } catch (InvocationTargetException e) { // one of the steps resulted in a core exception Throwable t = e.getTargetException(); Activator.getEasyAntPlugin().log(IStatus.ERROR, t.getMessage(), t); String message = "Cannot import project"; IStatus status; if (t instanceof CoreException) { status = ((CoreException) t).getStatus(); } else { status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 1, message, t); } ErrorDialog.openError(getShell(), message, null, status); return false; } return true; } /** * Create the project described in record. If it is successful return true. * * @param record * @return boolean <code>true</code> if successful * @throws InterruptedException */ private IProject createExistingProject(final ProjectRecord record, IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { return easyantProjectService.importProject(record.getDescription()/*, getShell()*/, monitor); } /** * Method used for test suite. * * @return CheckboxTreeViewer the viewer containing all the projects found */ public CheckboxTreeViewer getProjectsList() { return projectsList; } /** * Retrieve all the projects in the current workspace. * * @return IProject[] array of IProject in the current workspace */ private IProject[] getProjectsInWorkspace() { if (wsProjects == null) { wsProjects = Activator.getEasyAntPlugin().getPluginWorkspace().getRoot().getProjects(); } return wsProjects; } /** * Get the array of valid project records that can be imported from the * source workspace or archive, selected by the user. If a project with the * same name exists in both the source workspace and the current workspace, * it will not appear in the list of projects to import and thus cannot be * selected for import. * * Method declared public for test suite. * * @return ProjectRecord[] array of projects that can be imported into the * workspace */ public ProjectRecord[] getValidProjects() { List validProjects = new ArrayList(); for (int i = 0; i < selectedProjects.length; i++) { if (!isProjectInWorkspace(selectedProjects[i].getProjectName())) { validProjects.add(selectedProjects[i]); } } return (ProjectRecord[]) validProjects.toArray(new ProjectRecord[validProjects.size()]); } /** * Determine if the project with the given name is in the current workspace. * * @param projectName * String the project name to check * @return boolean true if the project with the given name is in this * workspace */ private boolean isProjectInWorkspace(String projectName) { if (projectName == null) { return false; } IProject[] workspaceProjects = getProjectsInWorkspace(); for (int i = 0; i < workspaceProjects.length; i++) { if (projectName.equals(workspaceProjects[i].getName())) { return true; } } return false; } }