blob: 64d7fc37f2fa4adf3dbe1cde4545781537619a19 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2013 Richard Hoefter and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Richard Hoefter (richard.hoefter@web.de) - initial API and implementation, bug 95296, bug 288830
* IBM Corporation - adapted to wizard export page
*******************************************************************************/
package org.eclipse.ant.internal.ui.datatransfer;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import org.eclipse.ant.internal.ui.AntUIPlugin;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jdt.core.IJavaModel;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
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.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import com.ibm.icu.text.MessageFormat;
public class AntBuildfileExportPage extends WizardPage {
private CheckboxTableViewer fTableViewer;
private List<IJavaProject> fSelectedJavaProjects = new ArrayList<>();
private Button compatibilityCheckbox;
private Button compilerCheckbox;
private Text buildfilenameText;
private Text junitdirText;
public AntBuildfileExportPage() {
super("AntBuildfileExportWizardPage"); //$NON-NLS-1$
setPageComplete(false);
setTitle(DataTransferMessages.AntBuildfileExportPage_0);
setDescription(DataTransferMessages.AntBuildfileExportPage_1);
}
@Override
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));
Label titel = new Label(workArea, SWT.NONE);
titel.setText(DataTransferMessages.AntBuildfileExportPage_2);
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));
// TODO set F1 help
Table table = new Table(listComposite, SWT.CHECK | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
fTableViewer = new CheckboxTableViewer(table);
table.setLayout(new TableLayout());
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
data.heightHint = 300;
table.setLayoutData(data);
fTableViewer.setContentProvider(new WorkbenchContentProvider() {
@Override
public Object[] getElements(Object element) {
if (element instanceof IJavaProject[]) {
return (IJavaProject[]) element;
}
return null;
}
});
fTableViewer.setLabelProvider(new WorkbenchLabelProvider());
fTableViewer.addCheckStateListener(event -> {
if (event.getChecked()) {
fSelectedJavaProjects.add((IJavaProject) event.getElement());
} else {
fSelectedJavaProjects.remove(event.getElement());
}
updateEnablement();
});
initializeProjects();
createSelectionButtons(listComposite);
createCheckboxes(workArea);
createTextFields(workArea);
setControl(workArea);
updateEnablement();
Dialog.applyDialogFont(parent);
}
private void createSelectionButtons(Composite composite) {
Composite buttonsComposite = new Composite(composite, 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(DataTransferMessages.AntBuildfileExportPage_11);
selectAll.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
for (int i = 0; i < fTableViewer.getTable().getItemCount(); i++) {
fSelectedJavaProjects.add((IJavaProject) fTableViewer.getElementAt(i));
}
fTableViewer.setAllChecked(true);
updateEnablement();
}
});
setButtonLayoutData(selectAll);
Button deselectAll = new Button(buttonsComposite, SWT.PUSH);
deselectAll.setText(DataTransferMessages.AntBuildfileExportPage_12);
deselectAll.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
fSelectedJavaProjects.clear();
fTableViewer.setAllChecked(false);
updateEnablement();
}
});
setButtonLayoutData(deselectAll);
}
private void createCheckboxes(Composite composite) {
compatibilityCheckbox = new Button(composite, SWT.CHECK);
compatibilityCheckbox.setSelection(true);
compatibilityCheckbox.setText(DataTransferMessages.AntBuildfileExportPage_13);
compatibilityCheckbox.setToolTipText(DataTransferMessages.AntBuildfileExportPage_14);
compilerCheckbox = new Button(composite, SWT.CHECK);
compilerCheckbox.setSelection(true);
compilerCheckbox.setText(DataTransferMessages.AntBuildfileExportPage_15);
}
private void createTextFields(Composite composite) {
// buildfilename and junitdir group
Composite containerGroup = new Composite(composite, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
containerGroup.setLayout(layout);
containerGroup.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
// label
Label buildfilenameLabel = new Label(containerGroup, SWT.NONE);
buildfilenameLabel.setText(DataTransferMessages.AntBuildfileExportPage_16);
// text field
buildfilenameText = new Text(containerGroup, SWT.SINGLE | SWT.BORDER);
buildfilenameText.setText("build.xml"); //$NON-NLS-1$
GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
buildfilenameText.setLayoutData(data);
// label
Label junitdirLabel = new Label(containerGroup, SWT.NONE);
junitdirLabel.setText(DataTransferMessages.AntBuildfileExportPage_17);
// text field
junitdirText = new Text(containerGroup, SWT.SINGLE | SWT.BORDER);
junitdirText.setText("junit"); //$NON-NLS-1$
junitdirText.setLayoutData(data);
ModifyListener listener = e -> updateEnablement();
buildfilenameText.addModifyListener(listener);
junitdirText.addModifyListener(listener);
}
private void initializeProjects() {
IWorkspaceRoot rootWorkspace = ResourcesPlugin.getWorkspace().getRoot();
IJavaModel javaModel = JavaCore.create(rootWorkspace);
IJavaProject[] javaProjects;
try {
javaProjects = javaModel.getJavaProjects();
}
catch (JavaModelException e) {
javaProjects = new IJavaProject[0];
}
fTableViewer.setInput(javaProjects);
// Check any necessary projects
if (fSelectedJavaProjects != null) {
fTableViewer.setCheckedElements(fSelectedJavaProjects.toArray(new IJavaProject[fSelectedJavaProjects.size()]));
}
}
private void updateEnablement() {
boolean complete = true;
if (fSelectedJavaProjects.isEmpty()) {
setErrorMessage(DataTransferMessages.AntBuildfileExportPage_18);
complete = false;
}
try {
List<String> projectsWithErrors = new ArrayList<>();
List<String> projectsWithWarnings = new ArrayList<>();
findCyclicProjects(getProjects(false), projectsWithErrors, projectsWithWarnings);
if (projectsWithErrors.size() > 0) {
String message = DataTransferMessages.AntBuildfileExportPage_cycle_error_in_projects;
if (projectsWithErrors.size() == 1) {
message = DataTransferMessages.AntBuildfileExportPage_cycle_error_in_project;
}
setErrorMessage(MessageFormat.format(message, new Object[] { ExportUtil.toString(projectsWithErrors, ", ") })); //$NON-NLS-1$
complete = false;
} else if (projectsWithWarnings.size() > 0) {
String message = DataTransferMessages.AntBuildfileExportPage_cycle_warning_in_projects;
if (projectsWithWarnings.size() == 1) {
message = DataTransferMessages.AntBuildfileExportPage_cycle_warning_in_project;
}
setMessage(MessageFormat.format(message, new Object[] { ExportUtil.toString(projectsWithWarnings, ", ") }), WARNING); //$NON-NLS-1$
} else {
setMessage(null);
}
}
catch (CoreException e) {
// do nothing
}
if (buildfilenameText.getText().length() == 0) {
setErrorMessage(DataTransferMessages.AntBuildfileExportPage_19);
complete = false;
}
if (junitdirText.getText().length() == 0) {
setErrorMessage(DataTransferMessages.AntBuildfileExportPage_20);
complete = false;
}
if (complete) {
setErrorMessage(null);
}
setPageComplete(complete);
}
@Override
public void setVisible(boolean visible) {
super.setVisible(visible);
if (visible) {
fTableViewer.getTable().setFocus();
}
}
protected void setSelectedProjects(List<IJavaProject> selectedJavaProjects) {
fSelectedJavaProjects.addAll(selectedJavaProjects);
}
/**
* Convert Eclipse Java projects to Ant build files. Displays error dialogs.
*/
public boolean generateBuildfiles() {
setErrorMessage(null);
final List<String> projectNames = new ArrayList<>();
final Set<IJavaProject> projects;
try {
projects = getProjects(true);
if (projects.isEmpty()) {
return false;
}
}
catch (JavaModelException e) {
AntUIPlugin.log(e);
setErrorMessage(MessageFormat.format(DataTransferMessages.AntBuildfileExportPage_10, new Object[] { e.toString() }));
return false;
}
IRunnableWithProgress runnable = pm -> {
SubMonitor localmonitor = SubMonitor.convert(pm, DataTransferMessages.AntBuildfileExportPage_creating_build_files, projects.size());
Exception problem = null;
try {
BuildFileCreator.setOptions(buildfilenameText.getText(), junitdirText.getText(), compatibilityCheckbox.getSelection(), compilerCheckbox.getSelection());
projectNames.addAll(BuildFileCreator.createBuildFiles(projects, getShell(), localmonitor.newChild(projects.size())));
}
catch (JavaModelException e1) {
problem = e1;
}
catch (TransformerConfigurationException e2) {
problem = e2;
}
catch (ParserConfigurationException e3) {
problem = e3;
}
catch (TransformerException e4) {
problem = e4;
}
catch (IOException e5) {
problem = e5;
}
catch (CoreException e6) {
problem = e6;
}
if (problem != null) {
AntUIPlugin.log(problem);
setErrorMessage(MessageFormat.format(DataTransferMessages.AntBuildfileExportPage_10, new Object[] { problem.toString() }));
}
};
try {
getContainer().run(false, false, runnable);
}
catch (InvocationTargetException e) {
AntUIPlugin.log(e);
return false;
}
catch (InterruptedException e) {
AntUIPlugin.log(e);
return false;
}
if (getErrorMessage() != null) {
return false;
}
return true;
}
/**
* Get projects to write buildfiles for. Opens confirmation dialog.
*
* @param displayConfirmation
* if set to true a dialog prompts for confirmation before overwriting files
* @return set of project names
*/
private Set<IJavaProject> getProjects(boolean displayConfirmation) throws JavaModelException {
// collect all projects to create buildfiles for
Set<IJavaProject> projects = new TreeSet<>(ExportUtil.getJavaProjectComparator());
Iterator<IJavaProject> javaProjects = fSelectedJavaProjects.iterator();
while (javaProjects.hasNext()) {
IJavaProject javaProject = javaProjects.next();
projects.addAll(ExportUtil.getClasspathProjectsRecursive(javaProject));
projects.add(javaProject);
}
// confirm overwrite
List<String> confirmOverwrite = getConfirmOverwriteSet(projects);
if (displayConfirmation && confirmOverwrite.size() > 0) {
String message = DataTransferMessages.AntBuildfileExportPage_3 + ExportUtil.NEWLINE
+ ExportUtil.toString(confirmOverwrite, ExportUtil.NEWLINE);
if (!MessageDialog.openQuestion(getShell(), DataTransferMessages.AntBuildfileExportPage_4, message)) {
return new TreeSet<>(ExportUtil.getJavaProjectComparator());
}
}
return projects;
}
/**
* Splits a set of given projects into a list of projects that have cyclic dependency errors and a list of projects that have cyclic dependency
* warnings.
*/
private void findCyclicProjects(Set<IJavaProject> projects, List<String> errors, List<String> warnings) throws CoreException {
for (IJavaProject javaProject : projects) {
IMarker marker = ExportUtil.getCyclicDependencyMarker(javaProject);
if (marker != null) {
Integer severityAttr = (Integer) marker.getAttribute(IMarker.SEVERITY);
if (severityAttr != null) {
switch (severityAttr.intValue()) {
case IMarker.SEVERITY_ERROR:
errors.add(javaProject.getProject().getName());
break;
case IMarker.SEVERITY_WARNING:
warnings.add(javaProject.getProject().getName());
break;
default:
break;
}
}
}
}
}
/**
* Get list of projects which have already a buildfile that was not created by the buildfile export.
*
* @param javaProjects
* list of IJavaProject objects
* @return set of project names
*/
private List<String> getConfirmOverwriteSet(Set<IJavaProject> javaProjects) {
List<String> result = new ArrayList<>(javaProjects.size());
for (IJavaProject project : javaProjects) {
String projectRoot = ExportUtil.getProjectRoot(project);
if (ExportUtil.existsUserFile(projectRoot + buildfilenameText.getText())) {
result.add(project.getProject().getName());
}
}
return result;
}
}