org.eclipse.ant.internal.ui.datatransfer.AntNewJavaProjectPage.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.ant.internal.ui.datatransfer.AntNewJavaProjectPage.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2013 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Martin Karpisek (martin.karpisek@gmail.com) - bug 229474
 *******************************************************************************/
package org.eclipse.ant.internal.ui.datatransfer;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.apache.tools.ant.Task;
import org.apache.tools.ant.UnknownElement;
import org.apache.tools.ant.taskdefs.Javac;
import org.eclipse.ant.internal.core.IAntCoreConstants;
import org.eclipse.ant.internal.ui.AntUIPlugin;
import org.eclipse.ant.internal.ui.AntUtil;
import org.eclipse.ant.internal.ui.model.AntModelContentProvider;
import org.eclipse.ant.internal.ui.model.AntProjectNode;
import org.eclipse.ant.internal.ui.model.AntTargetNode;
import org.eclipse.ant.internal.ui.model.AntTaskNode;
import org.eclipse.ant.internal.ui.model.IAntElement;
import org.eclipse.ant.internal.ui.model.IAntModel;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
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.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
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.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
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.IImportStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;

public class AntNewJavaProjectPage extends WizardPage {

    private static class ImportOverwriteQuery implements IOverwriteQuery {
        @Override
        public String queryOverwrite(String file) {
            return ALL;
        }
    }

    private Text fProjectNameField;
    private Text fLocationPathField;
    private Button fBrowseButton;
    private Button fLinkButton;

    private IAntModel fAntModel;

    private ModifyListener fLocationModifyListener = new ModifyListener() {
        @Override
        public void modifyText(ModifyEvent e) {
            // no lexical or position, has task info
            fAntModel = AntUtil.getAntModel(getProjectLocationFieldValue(), false, false, true);
            AntProjectNode projectNode = fAntModel == null ? null : fAntModel.getProjectNode();
            if (fAntModel != null && projectNode != null) {
                setProjectName(); // page will be validated on setting the project name
                List<AntTaskNode> javacNodes = new ArrayList<>();
                getJavacNodes(javacNodes, projectNode);
                fTableViewer.setInput(javacNodes.toArray());
                if (!javacNodes.isEmpty()) {
                    fTableViewer.setSelection(new StructuredSelection(javacNodes.get(0)));
                }
                fTableViewer.getControl().setEnabled(true);
            } else {
                fTableViewer.setInput(new Object[] {});
                fTableViewer.getControl().setEnabled(false);
            }
            setPageComplete(validatePage());
        }
    };

    private ModifyListener fNameModifyListener = new ModifyListener() {
        @Override
        public void modifyText(ModifyEvent e) {
            setPageComplete(validatePage());
        }
    };

    private static final int SIZING_TEXT_FIELD_WIDTH = 250;
    private TableViewer fTableViewer;

    public AntNewJavaProjectPage() {
        super("newPage"); //$NON-NLS-1$
        setPageComplete(false);
        setTitle(DataTransferMessages.AntNewJavaProjectPage_9);
        setDescription(DataTransferMessages.AntNewJavaProjectPage_10);

    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
     */
    @Override
    public void createControl(Composite parent) {
        initializeDialogUnits(parent);
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.marginHeight = IDialogConstants.VERTICAL_MARGIN;
        layout.marginWidth = IDialogConstants.HORIZONTAL_MARGIN;
        layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
        layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
        layout.numColumns = 3;
        composite.setLayout(layout);
        composite.setLayoutData(new GridData(GridData.FILL_BOTH));
        composite.setFont(parent.getFont());

        createProjectNameGroup(composite);
        createProjectLocationGroup(composite);
        createTargetsTable(composite);

        fLinkButton = new Button(composite, SWT.CHECK);
        fLinkButton.setText(DataTransferMessages.AntNewJavaProjectPage_24);
        fLinkButton.setFont(parent.getFont());
        GridData gd = new GridData();
        gd.horizontalAlignment = GridData.FILL;
        gd.grabExcessHorizontalSpace = false;
        gd.horizontalSpan = 2;
        fLinkButton.setLayoutData(gd);

        validatePage();
        // Show description on opening
        setErrorMessage(null);
        setMessage(null);
        setControl(composite);
    }

    /**
     * Creates the project location specification controls.
     * 
     * @param parent
     *            the parent composite
     */
    private final void createProjectLocationGroup(Composite parent) {
        // new project label
        Label projectContentsLabel = new Label(parent, SWT.NONE);
        projectContentsLabel.setText(DataTransferMessages.AntNewJavaProjectPage_11);
        projectContentsLabel.setFont(parent.getFont());

        createUserSpecifiedProjectLocationGroup(parent);
    }

    /**
     * Creates the project name specification controls.
     * 
     * @param parent
     *            the parent composite
     */
    private final void createProjectNameGroup(Composite parent) {

        Font dialogFont = parent.getFont();

        // new project label
        Label projectLabel = new Label(parent, SWT.NONE);
        projectLabel.setText(DataTransferMessages.AntNewJavaProjectPage_12);
        projectLabel.setFont(dialogFont);
        GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        projectLabel.setLayoutData(gd);

        // new project name entry field
        fProjectNameField = new Text(parent, SWT.BORDER);
        gd = new GridData();
        gd.horizontalAlignment = GridData.FILL;
        gd.grabExcessHorizontalSpace = false;
        gd.horizontalSpan = 2;
        fProjectNameField.setLayoutData(gd);
        fProjectNameField.setFont(dialogFont);

        fProjectNameField.addModifyListener(fNameModifyListener);
    }

    /**
     * Creates the project location specification controls.
     * 
     * @param projectGroup
     *            the parent composite
     */
    private void createUserSpecifiedProjectLocationGroup(Composite projectGroup) {

        Font dialogFont = projectGroup.getFont();

        // project location entry field
        fLocationPathField = new Text(projectGroup, SWT.BORDER);
        GridData data = new GridData(GridData.FILL_HORIZONTAL);
        data.widthHint = SIZING_TEXT_FIELD_WIDTH;
        fLocationPathField.setLayoutData(data);
        fLocationPathField.setFont(dialogFont);

        // browse button
        fBrowseButton = new Button(projectGroup, SWT.PUSH);
        fBrowseButton.setText(DataTransferMessages.AntNewJavaProjectPage_13);
        fBrowseButton.setFont(dialogFont);
        setButtonLayoutData(fBrowseButton);

        fBrowseButton.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent event) {
                handleBrowseButtonPressed();
            }
        });

        fLocationPathField.addModifyListener(fLocationModifyListener);
    }

    /**
     * Returns the current project name
     * 
     * @return the project name
     */
    private String getProjectName(AntProjectNode projectNode) {
        String projectName = projectNode.getLabel();
        if (projectName == null) {
            projectName = DataTransferMessages.AntNewJavaProjectPage_14;
        }
        return projectName;
    }

    /**
     * Returns the value of the project name field with leading and trailing spaces removed.
     * 
     * @return the project name in the field
     */
    private String getProjectNameFieldValue() {
        if (fProjectNameField == null) {
            return IAntCoreConstants.EMPTY_STRING;
        }
        return fProjectNameField.getText().trim();
    }

    /**
     * Returns the value of the project location field with leading and trailing spaces removed.
     * 
     * @return the project location directory in the field
     */
    private String getProjectLocationFieldValue() {
        return fLocationPathField.getText().trim();
    }

    /**
     * Determine the buildfile the user wishes to operate from
     */
    private void handleBrowseButtonPressed() {

        String lastUsedPath = IAntCoreConstants.EMPTY_STRING;
        FileDialog dialog = new FileDialog(getShell(), SWT.SINGLE);
        dialog.setFilterExtensions(new String[] { "*.xml" }); //$NON-NLS-1$;
        dialog.setFilterPath(lastUsedPath);

        String result = dialog.open();
        if (result == null) {
            return;
        }
        IPath filterPath = new Path(dialog.getFilterPath());
        String buildFileName = dialog.getFileName();
        IPath path = filterPath.append(buildFileName).makeAbsolute();

        fLocationPathField.setText(path.toOSString());
    }

    /**
     * Returns whether this page's controls currently all contain valid values.
     * 
     * @return <code>true</code> if all controls are valid, and <code>false</code> if at least one is invalid
     */
    private boolean validatePage() {

        String locationFieldContents = getProjectLocationFieldValue();

        if (locationFieldContents.equals(IAntCoreConstants.EMPTY_STRING)) {
            setErrorMessage(null);
            setMessage(DataTransferMessages.AntNewJavaProjectPage_15);
            return false;
        }

        IPath path = new Path(IAntCoreConstants.EMPTY_STRING);
        if (!path.isValidPath(locationFieldContents)) {
            setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_16);
            return false;
        }

        if (fAntModel == null) {
            if (getBuildFile(locationFieldContents) == null) {
                setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_0);
                return false;
            }
            setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_17);
            return false;
        }

        if (fAntModel.getProjectNode() == null) {
            setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_2);
            return false;
        }

        if (getProjectNameFieldValue().length() == 0) {
            setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_18);
            return false;
        }
        try {
            IProject existingProject = ResourcesPlugin.getWorkspace().getRoot()
                    .getProject(getProjectNameFieldValue());
            if (existingProject.exists()) {
                setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_19);
                return false;
            }
        } catch (IllegalArgumentException e) {
            setErrorMessage(NLS.bind(DataTransferMessages.AntNewJavaProjectPage_23, e.getLocalizedMessage()));
            return false;
        }

        if (fTableViewer.getTable().getItemCount() == 0) {
            setErrorMessage(DataTransferMessages.AntNewJavaProjectPage_1);
            setPageComplete(false);
            return false;
        }

        setErrorMessage(null);
        setMessage(null);
        return true;
    }

    /**
     * Set the project name using either the name of the parent of the file or the name entry in the xml for the file
     */
    private void setProjectName() {
        AntProjectNode node = fAntModel.getProjectNode();
        String projectName = getProjectName(node);

        fProjectNameField.setText(projectName);
    }

    /**
     * Return a .xml file from the specified location. If there isn't one return null.
     */
    private File getBuildFile(String locationFieldContents) {
        File buildFile = new File(locationFieldContents);
        if (!buildFile.isFile() || !buildFile.exists()) {
            return null;
        }

        return buildFile;
    }

    /**
     * Creates a new project resource based on the Ant buildfile. The classpath is configured based on the classpath of the javac declaration in the
     * buildfile.
     * 
     * @return the created project resource, or <code>null</code> if the project was not created
     */
    protected IJavaProject createProject() {
        final IJavaProject[] result = new IJavaProject[1];
        final String projectName = getProjectNameFieldValue();
        final File buildFile = getBuildFile(getProjectLocationFieldValue());
        final List<?> selectedJavacs = ((IStructuredSelection) fTableViewer.getSelection()).toList();
        final boolean link = fLinkButton.getSelection();
        WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
            @Override
            protected void execute(IProgressMonitor monitor) throws CoreException {
                List<?> javacTasks = resolveJavacTasks(selectedJavacs);
                ProjectCreator creator = new ProjectCreator();
                Iterator<?> iter = javacTasks.iterator();
                while (iter.hasNext()) {
                    Javac javacTask = (Javac) iter.next();
                    IJavaProject javaProject = creator.createJavaProjectFromJavacNode(projectName, javacTask,
                            monitor);
                    importBuildFile(monitor, javaProject, buildFile, link);
                    result[0] = javaProject;
                }
            }
        };

        // run the new project creation operation
        try {
            getContainer().run(true, true, op);
        } catch (InterruptedException e) {
            return null;
        } catch (InvocationTargetException e) {
            // ie.- one of the steps resulted in a core exception
            Throwable t = e.getTargetException();
            IStatus status = null;
            if (t instanceof CoreException) {
                status = ((CoreException) t).getStatus();
            } else {
                status = new Status(IStatus.ERROR, AntUIPlugin.PI_ANTUI, IStatus.OK,
                        "Error occurred. Check log for details ", t); //$NON-NLS-1$
                AntUIPlugin.log(t);
            }
            ErrorDialog.openError(getShell(), DataTransferMessages.AntNewJavaProjectPage_21, null, status);
        }

        return result[0];
    }

    protected void importBuildFile(IProgressMonitor monitor, IJavaProject javaProject, File buildFile,
            boolean link) {
        if (link) {
            IProject project = javaProject.getProject();
            IFile iBuildFile = project.getFile(buildFile.getName());
            if (!iBuildFile.exists()) {
                try {
                    iBuildFile.createLink(new Path(buildFile.getAbsolutePath()), IResource.ALLOW_MISSING_LOCAL,
                            monitor);
                } catch (CoreException e) {
                    ErrorDialog.openError(getShell(), DataTransferMessages.AntNewJavaProjectPage_22, null,
                            e.getStatus());
                }
            }
        } else {
            IImportStructureProvider structureProvider = FileSystemStructureProvider.INSTANCE;
            File rootDir = buildFile.getParentFile();
            try {
                ImportOperation op = new ImportOperation(javaProject.getPath(), rootDir, structureProvider,
                        new ImportOverwriteQuery(), Collections.singletonList(buildFile));
                op.setCreateContainerStructure(false);
                op.run(monitor);
            } catch (InterruptedException e) {
                // should not happen
            } catch (InvocationTargetException e) {
                Throwable t = e.getTargetException();
                if (t instanceof CoreException) {
                    ErrorDialog.openError(getShell(), DataTransferMessages.AntNewJavaProjectPage_22, null,
                            ((CoreException) t).getStatus());
                }
            }
        }
    }

    private List<?> resolveJavacTasks(List<?> javacNodes) {
        List<Object> resolvedJavacTasks = new ArrayList<>(javacNodes.size());
        Iterator<?> nodes = javacNodes.iterator();
        while (nodes.hasNext()) {
            AntTaskNode taskNode = (AntTaskNode) nodes.next();
            Task javacTask = taskNode.getTask();
            if (javacTask instanceof UnknownElement) {
                if (((UnknownElement) javacTask).getRealThing() == null) {
                    javacTask.maybeConfigure();
                }

                resolvedJavacTasks.add(((UnknownElement) javacTask).getRealThing());
            } else {
                resolvedJavacTasks.add(javacTask);
            }
        }
        return resolvedJavacTasks;
    }

    private void getJavacNodes(List<AntTaskNode> javacNodes, IAntElement parent) {
        if (!parent.hasChildren()) {
            return;
        }
        List<IAntElement> children = parent.getChildNodes();
        for (IAntElement node : children) {
            if (node instanceof AntTargetNode) {
                getJavacNodes(javacNodes, node);
            } else if (node instanceof AntTaskNode) {
                AntTaskNode task = (AntTaskNode) node;
                if ("javac".equals(task.getName())) { //$NON-NLS-1$
                    javacNodes.add(task);
                }
            }
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
     */
    @Override
    public void setVisible(boolean visible) {
        super.setVisible(visible);
        if (visible) {
            fLocationPathField.setFocus();
        }
    }

    /**
     * Creates the table which displays the available targets
     * 
     * @param parent
     *            the parent composite
     */
    private void createTargetsTable(Composite parent) {
        Font font = parent.getFont();
        Label label = new Label(parent, SWT.NONE);
        label.setFont(font);
        label.setText(DataTransferMessages.AntNewJavaProjectPage_3);
        GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
        gd.horizontalSpan = 3;
        label.setLayoutData(gd);

        Table table = new Table(parent, SWT.SINGLE | SWT.BORDER | SWT.FULL_SELECTION);

        GridData data = new GridData(GridData.FILL_BOTH);
        int availableRows = availableRows(parent);
        data.heightHint = table.getItemHeight() * (availableRows / 20);
        data.widthHint = 250;
        data.horizontalSpan = 3;
        table.setLayoutData(data);
        table.setFont(font);

        fTableViewer = new TableViewer(table);
        fTableViewer.setLabelProvider(new JavacTableLabelProvider());
        fTableViewer.setContentProvider(new AntModelContentProvider());
        fTableViewer.getControl().setEnabled(false);
    }

    /**
     * Return the number of rows available in the current display using the current font.
     * 
     * @param parent
     *            The Composite whose Font will be queried.
     * @return int The result of the display size divided by the font size.
     */
    private int availableRows(Composite parent) {

        int fontHeight = (parent.getFont().getFontData())[0].getHeight();
        int displayHeight = parent.getDisplay().getClientArea().height;

        return displayHeight / fontHeight;
    }
}