/**
* <copyright>
*
* Copyright (c) 2006, 2010 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 - Initial API and implementation
*
* </copyright>
*
* $Id: AbstractExampleInstallerWizard.java,v 1.8 2008/12/01 21:47:46 emerks Exp $
*/
package net.enilink.komma.common.ui.rcp.wizards;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.jar.JarFile;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.window.IShellProvider;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
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.Text;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.actions.RenameResourceAction;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.dialogs.IOverwriteQuery;
import org.eclipse.ui.ide.undo.DeleteResourcesOperation;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
import org.eclipse.ui.wizards.datatransfer.ImportOperation;
import org.eclipse.ui.wizards.datatransfer.ZipFileStructureProvider;
import net.enilink.komma.common.CommonPlugin;
import net.enilink.komma.common.ui.CommonUIPlugin;
import net.enilink.komma.common.ui.dialogs.DiagnosticDialog;
import net.enilink.komma.common.util.BasicDiagnostic;
import net.enilink.komma.common.util.Diagnostic;
import net.enilink.komma.common.util.DiagnosticException;
import net.enilink.komma.core.URI;
/**
* <p>
* This abstract example installer wizard simply copies or unzips a number of
* files and directories into the workspace, creating the projects to hold them.
* This wizard can be added as a new wizard to the new wizards dialog through
* the <tt>org.eclipse.ui.newWizards</tt> extension point.
* </p>
*
* <p>
* Clients should subclass this class and override the
* {@link #getProjectDescriptors()} method to provide the location and name of
* the project content that should be added to the workspace. Note that any
* projects that are already in the workspace will <i>not</i> be overwritten
* because the user could have made changes to them that would be lost.
* </p>
*
* <p>
* It is highly recommended when registering subclasses to the new wizards
* extension point that the wizard declaration should have canFinishEarly =
* true. Any label and icon can be freely given to the wizard to suit the needs
* of the client.
* </p>
*
* @since 2.2.0
*/
public abstract class AbstractExampleInstallerWizard extends Wizard implements
INewWizard, IShellProvider {
public static class ProjectDescriptor {
protected String name;
protected URI contentURI;
protected String description;
protected IProject project;
public URI getContentURI() {
return contentURI;
}
public void setContentURI(URI contentURI) {
this.contentURI = contentURI;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public IProject getProject() {
if (project == null) {
project = ResourcesPlugin.getWorkspace().getRoot()
.getProject(getName());
}
return project;
}
}
public static class FileToOpen {
protected String location;
protected String editorID;
protected IFile workspaceFile;
public String getEditorID() {
return editorID;
}
public void setEditorID(String editorID) {
this.editorID = editorID;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public IFile getWorkspaceFile() {
if (workspaceFile == null) {
workspaceFile = ResourcesPlugin.getWorkspace().getRoot()
.getFile(new Path(getLocation()));
}
return workspaceFile;
}
}
public class ProjectPage extends WizardPage {
protected org.eclipse.swt.widgets.List projectList;
protected Text descriptionText;
protected Button renameButton;
public ProjectPage(String pageName, String title,
ImageDescriptor titleImage) {
super(pageName, title, titleImage);
}
public void createControl(Composite parent) {
SashForm sashForm = new SashForm(parent, SWT.VERTICAL);
sashForm.setLayoutData(new GridData(GridData.FILL_BOTH
| GridData.GRAB_VERTICAL));
projectList = new org.eclipse.swt.widgets.List(sashForm, SWT.SINGLE
| SWT.BORDER);
projectList.setLayoutData(new GridData(GridData.FILL_BOTH));
projectList.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
itemSelected();
}
});
projectList.setFocus();
Composite composite = new Composite(sashForm, SWT.NONE);
{
GridLayout layout = new GridLayout(2, false);
int margin = -5;
int spacing = 3;
layout.marginTop = margin;
layout.marginLeft = margin;
layout.marginRight = margin;
layout.marginBottom = margin;
layout.horizontalSpacing = spacing;
layout.verticalSpacing = spacing;
composite.setLayout(layout);
}
descriptionText = new Text(composite, SWT.READ_ONLY | SWT.MULTI
| SWT.WRAP | SWT.V_SCROLL | SWT.BORDER);
{
GridData gridData = new GridData(GridData.FILL_BOTH);
gridData.heightHint = convertHeightInCharsToPixels(2);
gridData.grabExcessVerticalSpace = true;
descriptionText.setLayoutData(gridData);
}
Composite buttonComposite = new Composite(composite, SWT.NONE);
buttonComposite.setLayoutData(new GridData(
GridData.VERTICAL_ALIGN_BEGINNING
| GridData.HORIZONTAL_ALIGN_END));
buttonComposite.setLayout(new GridLayout());
{
GridLayout layout = new GridLayout();
int margin = -5;
int spacing = 3;
layout.marginTop = margin;
layout.marginLeft = margin;
layout.marginRight = margin;
layout.marginBottom = margin;
layout.horizontalSpacing = spacing;
layout.verticalSpacing = spacing;
buttonComposite.setLayout(layout);
}
renameButton = new Button(buttonComposite, SWT.PUSH);
renameButton.setLayoutData(new GridData(
GridData.HORIZONTAL_ALIGN_BEGINNING
| GridData.FILL_HORIZONTAL));
renameButton.setText(CommonUIPlugin.INSTANCE
.getString("_UI_Rename_label"));
renameButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
renameExistingProject();
}
});
renameButton.setEnabled(false);
refresh();
sashForm.setWeights(new int[] { 70, 30 });
setControl(sashForm);
}
public void refresh() {
if (getProjectDescriptors().isEmpty()) {
setErrorMessage(CommonUIPlugin.INSTANCE
.getString("_UI_NoProjectError_message"));
setPageComplete(false);
} else {
setErrorMessage(null);
int selectionIndex = projectList.getSelectionIndex();
if (selectionIndex < 0) {
selectionIndex = 0;
}
projectList.removeAll();
for (ProjectDescriptor projectDescriptor : getProjectDescriptors()) {
String name = projectDescriptor.getName();
boolean exists = projectDescriptor.getProject().exists();
String item = exists ? CommonUIPlugin.INSTANCE.getString(
"_UI_ExistingProjectName_message",
new String[] { name }) : name;
projectList.add(item);
projectList.setData(item, projectDescriptor);
}
if (getControl() != null) {
projectList.setSelection(selectionIndex);
itemSelected();
}
setPageComplete(true);
}
}
@Override
public void setVisible(boolean visible) {
if (visible && projectList.getItemCount() > 0
&& projectList != null
&& projectList.getSelectionCount() == 0) {
int index = 0;
int count = 0;
for (ProjectDescriptor projectDescriptor : getProjectDescriptors()) {
if (projectDescriptor.getProject().exists()) {
index = count;
break;
}
count++;
}
projectList.select(index);
refresh();
}
super.setVisible(visible);
}
protected ProjectDescriptor getSelectedProjectDescriptor() {
return projectList.getSelectionCount() == 0 ? null
: (ProjectDescriptor) projectList.getData(projectList
.getSelection()[0]);
}
protected void itemSelected() {
ProjectDescriptor projectDescriptor = getSelectedProjectDescriptor();
if (projectDescriptor != null) {
boolean exists = projectDescriptor.getProject().exists();
renameButton.setEnabled(exists);
String description = projectDescriptor.getDescription() != null ? projectDescriptor
.getDescription() : "";
if (exists) {
String renameMessage = CommonUIPlugin.INSTANCE
.getString("_UI_ProjectRename_message");
description = description == "" ? renameMessage
: CommonUIPlugin.INSTANCE
.getString(
"_UI_ProjectDescriptionAndRename_message",
new String[] { description,
renameMessage });
}
descriptionText.setText(description);
}
}
protected void renameExistingProject() {
ProjectDescriptor projectDescriptor = getSelectedProjectDescriptor();
if (projectDescriptor != null
&& projectDescriptor.getProject().exists()) {
RenameResourceAction renameResourceAction = new RenameResourceAction(
AbstractExampleInstallerWizard.this);
renameResourceAction.selectionChanged(new StructuredSelection(
projectDescriptor.getProject()));
renameResourceAction.run();
projectDescriptor.project = null;
refresh();
}
}
}
protected static final IOverwriteQuery OVERWRITE_ALL_QUERY = new IOverwriteQuery() {
public String queryOverwrite(String pathString) {
return IOverwriteQuery.ALL;
}
};
protected IWorkbench workbench;
protected IStructuredSelection structuredSelection;
public AbstractExampleInstallerWizard() {
setNeedsProgressMonitor(true);
setWindowTitle(CommonUIPlugin.INSTANCE
.getString("_UI_ExampleInstallerWizard_title"));
}
public void init(IWorkbench workbench, IStructuredSelection selection) {
this.workbench = workbench;
this.structuredSelection = selection;
}
/**
* Returns the project descriptors to be used by this wizard. This method is
* called multiple times, so subclasses are expected to cache this
* information if necessary.
*
* @return a list of ProjectDescriptors
*/
protected abstract List<ProjectDescriptor> getProjectDescriptors();
protected abstract List<FileToOpen> getFilesToOpen();
protected ProjectPage projectPage;
@Override
public void dispose() {
projectPage = null;
super.dispose();
}
@Override
public void addPages() {
projectPage = new ProjectPage("projectPage",
CommonUIPlugin.INSTANCE.getString("_UI_ProjectPage_title"),
null);
projectPage.setDescription(CommonUIPlugin.INSTANCE
.getString("_UI_ProjectPage_description"));
addPage(projectPage);
}
@Override
public boolean performFinish() {
final Exception exceptionWrapper = new Exception();
try {
getContainer().run(false, true, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
monitor.beginTask(CommonUIPlugin.INSTANCE
.getString("_UI_InstallingExample_message"), 3);
WorkspaceModifyOperation op = new WorkspaceModifyOperation() {
@Override
protected void execute(IProgressMonitor monitor)
throws CoreException,
InvocationTargetException, InterruptedException {
Diagnostic diagnostic = deleteExistingProjects(new SubProgressMonitor(
monitor, 1));
if (diagnostic.getSeverity() != Diagnostic.OK) {
exceptionWrapper
.initCause(new DiagnosticException(
diagnostic));
throw new InterruptedException();
}
try {
installExample(monitor);
} catch (Exception e) {
exceptionWrapper.initCause(e);
throw new InterruptedException();
}
}
};
op.run(new SubProgressMonitor(monitor, 1));
openFiles(new SubProgressMonitor(monitor, 1));
monitor.done();
}
});
return true;
} catch (InterruptedException e) {
if (exceptionWrapper.getCause() != null) {
openErrorDialog(
CommonUIPlugin.INSTANCE
.getString("_UI_InstallExampleError_message"),
exceptionWrapper.getCause());
}
} catch (InvocationTargetException e) {
CommonUIPlugin.INSTANCE.log(e);
}
if (projectPage != null && !projectPage.getControl().isDisposed()) {
projectPage.refresh();
}
return false;
}
protected Diagnostic deleteExistingProjects(IProgressMonitor monitor) {
StringBuilder projectNames = new StringBuilder();
List<IProject> projects = new ArrayList<IProject>();
for (ProjectDescriptor projectDescriptor : getProjectDescriptors()) {
IProject project = projectDescriptor.getProject();
if (project.exists()) {
projectNames.append(", '").append(project.getName())
.append("'");
projects.add(project);
}
}
if (!projects.isEmpty()) {
projectNames.delete(0, ", ".length());
String title = null;
String message = null;
if (projects.size() == 1) {
title = CommonUIPlugin.INSTANCE
.getString("_UI_ConfirmSingleDeletion_title");
message = CommonUIPlugin.INSTANCE.getString(
"_UI_ConfirmSingleDeletion_message",
new String[] { projectNames.toString() });
} else {
title = CommonUIPlugin.INSTANCE
.getString("_UI_ConfirmMultipleDeletion_title");
message = CommonUIPlugin.INSTANCE.getString(
"_UI_ConfirmMultipleDeletion_message",
new String[] { projectNames.toString() });
}
if (MessageDialog.openConfirm(getShell(), title, message)) {
DeleteResourcesOperation op = new DeleteResourcesOperation(
projects.toArray(new IProject[projects.size()]),
"deleteprojects", true);
try {
return BasicDiagnostic.toDiagnostic(op.execute(
new SubProgressMonitor(monitor, 1), null));
} catch (ExecutionException e) {
return BasicDiagnostic.toDiagnostic(e);
}
} else {
return Diagnostic.CANCEL_INSTANCE;
}
}
return Diagnostic.OK_INSTANCE;
}
protected void installExample(IProgressMonitor progressMonitor)
throws Exception {
List<ProjectDescriptor> projectDescriptors = getProjectDescriptors();
progressMonitor.beginTask(CommonUIPlugin.INSTANCE
.getString("_UI_CreatingProjects_message"),
2 * projectDescriptors.size());
for (ProjectDescriptor projectDescriptor : projectDescriptors) {
ImportOperation importOperation = createImportOperation(projectDescriptor);
createProject(projectDescriptor, new SubProgressMonitor(
progressMonitor, 1));
importOperation.setContext(getShell());
importOperation.run(new SubProgressMonitor(progressMonitor, 1));
}
progressMonitor.done();
}
protected void openFiles(IProgressMonitor progressMonitor) {
List<FileToOpen> filesToOpen = getFilesToOpen();
if (!filesToOpen.isEmpty()) {
progressMonitor.beginTask(CommonUIPlugin.INSTANCE
.getString("_UI_OpeningFiles_message"), filesToOpen.size());
for (FileToOpen fileToOpen : filesToOpen) {
IFile workspaceFile = fileToOpen.getWorkspaceFile();
if (workspaceFile != null && workspaceFile.exists()) {
try {
openEditor(workspaceFile, fileToOpen.getEditorID());
progressMonitor.worked(1);
} catch (PartInitException e) {
CommonUIPlugin.INSTANCE.log(e);
}
}
}
progressMonitor.done();
}
}
protected void openErrorDialog(String message, Throwable throwable) {
DiagnosticDialog.open(getShell(),
CommonUIPlugin.INSTANCE.getString("_UI_Error_label"), message,
BasicDiagnostic.toDiagnostic(throwable));
}
protected void createProject(ProjectDescriptor projectDescriptor,
IProgressMonitor monitor) throws CoreException {
monitor.beginTask(CommonUIPlugin.INSTANCE.getString(
"_UI_CreateProject_message",
new String[] { projectDescriptor.getName() }), 3);
IProject project = projectDescriptor.getProject();
project.create(new SubProgressMonitor(monitor, 1));
project.open(new SubProgressMonitor(monitor, 1));
monitor.done();
}
protected ImportOperation createImportOperation(
ProjectDescriptor projectDescriptor) throws Exception {
URI contentURI = projectDescriptor.getContentURI();
if (contentURI.hasTrailingPathSeparator()) {
return createDirectoryImportOperation(projectDescriptor);
} else {
return createFileImportOperation(projectDescriptor);
}
}
protected ImportOperation createDirectoryImportOperation(
ProjectDescriptor projectDescriptor) throws Exception {
URI contentURI = projectDescriptor.getContentURI();
if (contentURI.isPlatform()) {
contentURI = CommonPlugin.asLocalURI(contentURI);
}
String location = contentURI.toFileString();
if (location != null) {
File directory = new File(location);
if (directory.isDirectory() && directory.canRead()) {
List<File> filesToImport = new ArrayList<File>();
filesToImport.addAll(Arrays.asList(directory.listFiles()));
ImportOperation importOperation = new ImportOperation(
projectDescriptor.getProject().getFullPath(),
directory, FileSystemStructureProvider.INSTANCE,
OVERWRITE_ALL_QUERY, filesToImport);
importOperation.setCreateContainerStructure(false);
return importOperation;
}
}
throw new Exception(CommonUIPlugin.INSTANCE.getString(
"_UI_DirectoryError_message", contentURI.toString()));
}
protected ImportOperation createFileImportOperation(
ProjectDescriptor projectDescriptor) throws Exception {
URI contentURI = projectDescriptor.getContentURI();
if (contentURI.isPlatform()) {
contentURI = CommonPlugin.asLocalURI(contentURI);
}
String location = contentURI.toFileString();
if (location != null) {
File file = new File(location);
if (file.isFile() && file.canRead()) {
if (isZipFile(file)) {
return createZipImportOperation(projectDescriptor, file);
}
}
}
throw new Exception(
CommonUIPlugin.INSTANCE.getString("_UI_FileError_message",
new String[] { contentURI.toString() }));
}
protected boolean isZipFile(File file) {
try {
ZipFile zipFile = new ZipFile(file);
zipFile.close();
return true;
} catch (ZipException e) {
// Ignore
} catch (IOException e) {
// Ignore
}
return false;
}
protected ImportOperation createZipImportOperation(
ProjectDescriptor projectDescriptor, File file) throws Exception {
final ZipFile zipFile = file.getName().endsWith(".jar") ? new JarFile(
file) : new ZipFile(file);
ZipFileStructureProvider zipFileStructureProvider = new ZipFileStructureProvider(
zipFile);
return new ImportOperation(
projectDescriptor.getProject().getFullPath(),
zipFileStructureProvider.getRoot(), zipFileStructureProvider,
OVERWRITE_ALL_QUERY) {
@Override
protected void execute(IProgressMonitor progressMonitor) {
try {
super.execute(progressMonitor);
} finally {
try {
zipFile.close();
} catch (IOException exception) {
// Ignore.
}
}
}
};
}
protected IWorkbench getWorkbench() {
return workbench;
}
protected IStructuredSelection getSelection() {
return structuredSelection;
}
protected void openEditor(IFile file, String editorID)
throws PartInitException {
IEditorRegistry editorRegistry = getWorkbench().getEditorRegistry();
if (editorID == null || editorRegistry.findEditor(editorID) == null) {
editorID = getWorkbench().getEditorRegistry()
.getDefaultEditor(file.getFullPath().toString()).getId();
}
IWorkbenchPage page = getWorkbench().getActiveWorkbenchWindow()
.getActivePage();
page.openEditor(new FileEditorInput(file), editorID, true,
IWorkbenchPage.MATCH_ID);
}
}