blob: 25632d1846342178fb41f9d8d00c52c82398238d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2004 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ant.internal.ui.demo;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
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.ui.editor.model.AntElementNode;
import org.eclipse.ant.internal.ui.editor.model.AntProjectNode;
import org.eclipse.ant.internal.ui.editor.model.AntTargetNode;
import org.eclipse.ant.internal.ui.editor.model.AntTaskNode;
import org.eclipse.ant.internal.ui.editor.outline.AntModel;
import org.eclipse.ant.internal.ui.editor.outline.LocationProvider;
import org.eclipse.ant.internal.ui.editor.outline.XMLCore;
import org.eclipse.ant.internal.ui.model.AntUIPlugin;
import org.eclipse.core.resources.IProject;
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.Path;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
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.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.ui.help.WorkbenchHelp;
import org.eclipse.ui.internal.ide.IHelpContextIds;
import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;
public class ExternalAntBuildfileImportPage extends WizardPage {
private static class ImportOverwriteQuery implements IOverwriteQuery {
public String queryOverwrite(String file) {
return ALL;
}
}
//private static String previouslyBrowsedDirectory = ""; //$NON-NLS-1$
private Text projectNameField;
private Text locationPathField;
private Button browseButton;
private AntModel fAntModel;
private Listener locationModifyListener = new Listener() {
public void handleEvent(Event e) {
fAntModel= getAntModel(getBuildFile(getProjectLocationFieldValue()));
setProjectName();
setPageComplete(validatePage());
}
};
private Listener nameModifyListener = new Listener() {
public void handleEvent(Event e) {
setPageComplete(validatePage());
}
};
private static final int SIZING_TEXT_FIELD_WIDTH = 250;
public ExternalAntBuildfileImportPage() {
super("externalAntBuildfilePage"); //$NON-NLS-1$
setPageComplete(false);
setTitle("Import a Project from an Ant Buildfile");
setDescription("Creates a new project based on the specification in the javac task of the Ant buildfile. This does not copy the source contents to the workspace.");
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
*/
public void createControl(Composite parent) {
initializeDialogUnits(parent);
Composite composite = new Composite(parent, SWT.NULL);
WorkbenchHelp.setHelp(composite, IHelpContextIds.NEW_PROJECT_WIZARD_PAGE);
composite.setLayout(new GridLayout());
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
composite.setFont(parent.getFont());
createProjectNameGroup(composite);
createProjectLocationGroup(composite);
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) {
// project specification group
Composite projectGroup = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 3;
projectGroup.setLayout(layout);
projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
projectGroup.setFont(parent.getFont());
// new project label
Label projectContentsLabel = new Label(projectGroup, SWT.NONE);
projectContentsLabel.setText("&Ant Buildfile:");
projectContentsLabel.setFont(parent.getFont());
createUserSpecifiedProjectLocationGroup(projectGroup);
}
/**
* Creates the project name specification controls.
*
* @param parent the parent composite
*/
private final void createProjectNameGroup(Composite parent) {
Font dialogFont = parent.getFont();
// project specification group
Composite projectGroup = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
projectGroup.setFont(dialogFont);
projectGroup.setLayout(layout);
projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// new project label
Label projectLabel = new Label(projectGroup, SWT.NONE);
projectLabel.setText("&Project Name:");
projectLabel.setFont(dialogFont);
// new project name entry field
projectNameField = new Text(projectGroup, SWT.BORDER);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
data.widthHint = SIZING_TEXT_FIELD_WIDTH;
projectNameField.setLayoutData(data);
projectNameField.setFont(dialogFont);
projectNameField.addListener(SWT.Modify, nameModifyListener);
}
/**
* Creates the project location specification controls.
*
* @param projectGroup the parent composite
* @param boolean - the initial enabled state of the widgets created
*/
private void createUserSpecifiedProjectLocationGroup(Composite projectGroup) {
Font dialogFont = projectGroup.getFont();
// project location entry field
this.locationPathField = new Text(projectGroup, SWT.BORDER);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
data.widthHint = SIZING_TEXT_FIELD_WIDTH;
this.locationPathField.setLayoutData(data);
this.locationPathField.setFont(dialogFont);
// browse button
this.browseButton = new Button(projectGroup, SWT.PUSH);
this.browseButton.setText("B&rowse...");
this.browseButton.setFont(dialogFont);
setButtonLayoutData(this.browseButton);
this.browseButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
handleBrowseButtonPressed();
}
});
locationPathField.addListener(SWT.Modify, locationModifyListener);
}
/**
* Returns the current project name as entered by the user, or its anticipated
* initial value.
*
* @return the project name, its anticipated initial value, or <code>null</code>
* if no project name is known
*/
private String getProjectName(AntProjectNode projectNode) {
String userSpecifiedName= getProjectNameFieldValue();
if (userSpecifiedName.length() > 0) {
return userSpecifiedName;
}
String projectName= projectNode.getLabel();
if (projectName == null) {
projectName= "Ant Project";
}
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 (projectNameField == null) {
return ""; //$NON-NLS-1$
} else {
return projectNameField.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 locationPathField.getText().trim();
}
/**
* Determine the buildfile the user wishes to operate from
*/
private void handleBrowseButtonPressed() {
String lastUsedPath= null;
//lastUsedPath= dialogSettings.get(IAntUIConstants.DIALOGSTORE_LASTEXTFILE);
if (lastUsedPath == null) {
lastUsedPath= ""; //$NON-NLS-1$
}
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();
// previouslyBrowsedDirectory = selectedDirectory;
locationPathField.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("")) { //$NON-NLS-1$
setErrorMessage(null);
setMessage("No buildfile selected");
return false;
}
IPath path = new Path(""); //$NON-NLS-1$
if (!path.isValidPath(locationFieldContents)) {
setErrorMessage("Location error");
return false;
}
if (fAntModel == null) {
setErrorMessage("Specified buildfile could not be parsed successfully");
return false;
}
if (getProjectNameFieldValue().length() == 0) {
setErrorMessage("Project name must be specified");
return false;
} else {
IProject existingProject= ResourcesPlugin.getWorkspace().getRoot().getProject(getProjectNameFieldValue());
if (existingProject.exists()) {
setErrorMessage("A project with the specified name already exists");
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() {
if (fAntModel == null) {
return;
}
AntProjectNode node= fAntModel.getProjectNode();
String projectName= getProjectName(node);
projectNameField.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.
*
* @return the created project resource, or <code>null</code> if the project
* was not created
*/
protected IJavaProject createProject() {
AntProjectNode projectNode= fAntModel.getProjectNode();
final List javacNodes= new ArrayList();
getJavacNodes(javacNodes, projectNode);
final IJavaProject[] result= new IJavaProject[1];
final String projectName= getProjectNameFieldValue();
final File buildFile= getBuildFile(getProjectLocationFieldValue());
if (javacNodes.size() > 1) {
setErrorMessage("Currently only supports creating a project from a single javac declaration");
return null;
}
WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
protected void execute(IProgressMonitor monitor) throws CoreException {
List javacTasks= resolveJavacTasks(javacNodes);
//TODO no javactasks...throw CoreException
ProjectCreator creator= new ProjectCreator();
Iterator iter= javacTasks.iterator();
while (iter.hasNext()) {
Javac javacTask = (Javac) iter.next();
IJavaProject javaProject= creator.createJavaProjectFromJavacNode(projectName, javacTask);
importBuildFile(monitor, javaProject.getPath(), buildFile);
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();
if (t instanceof CoreException) {
ErrorDialog.openError(getShell(), "Error occurred creating project",
null, ((CoreException) t).getStatus());
}
}
return result[0];
}
protected void importBuildFile(IProgressMonitor monitor, IPath destPath, File buildFile) {
IImportStructureProvider structureProvider = FileSystemStructureProvider.INSTANCE;
List files = new ArrayList(1);
files.add(buildFile);
File rootDir= buildFile.getParentFile();
try {
ImportOperation op= new ImportOperation(destPath, rootDir, structureProvider, new ImportOverwriteQuery(), files);
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(), "Error occurred importing buildfile",
null, ((CoreException) t).getStatus());
}
}
}
private List resolveJavacTasks(List javacNodes) {
List 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 AntModel getAntModel(final File buildFile) {
IDocument doc= getDocument(buildFile);
if (doc == null) {
return null;
}
AntModel model= new AntModel(XMLCore.getDefault(), doc, null, new LocationProvider(null) {
/* (non-Javadoc)
* @see org.eclipse.ant.internal.ui.editor.outline.ILocationProvider#getLocation()
*/
public IPath getLocation() {
return new Path(buildFile.getAbsolutePath());
}
});
model.reconcile(null);
return model;
}
private IDocument getDocument(File buildFile) {
InputStream in;
try {
in = new FileInputStream(buildFile);
} catch (FileNotFoundException e) {
return null;
}
String initialContent= getStreamContentAsString(in);
return new Document(initialContent);
}
private String getStreamContentAsString(InputStream inputStream) {
InputStreamReader reader;
try {
reader = new InputStreamReader(inputStream, ResourcesPlugin.getEncoding());
} catch (UnsupportedEncodingException e) {
AntUIPlugin.log(e);
return ""; //$NON-NLS-1$
}
return getReaderContentAsString( new BufferedReader(reader));
}
private String getReaderContentAsString(BufferedReader bufferedReader) {
StringBuffer result = new StringBuffer();
try {
String line= bufferedReader.readLine();
while(line != null) {
if(result.length() != 0) {
result.append("\n"); //$NON-NLS-1$
}
result.append(line);
line = bufferedReader.readLine();
}
} catch (IOException e) {
AntUIPlugin.log(e);
return null;
}
return result.toString();
}
private void getJavacNodes(List javacNodes, AntElementNode parent) {
if (!parent.hasChildren()) {
return;
}
List children= parent.getChildNodes();
for (Iterator iter = children.iterator(); iter.hasNext();) {
AntElementNode node = (AntElementNode) iter.next();
if (node instanceof AntTargetNode) {
getJavacNodes(javacNodes, node);
} else if (node instanceof AntTaskNode) {
AntTaskNode task= (AntTaskNode)node;
if (task.getName() == "javac") { //$NON-NLS-1$
javacNodes.add(task);
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean)
*/
public void setVisible(boolean visible) {
super.setVisible(visible);
if(visible)
this.locationPathField.setFocus();
}
}