/**
* <p>Copyright: Copyright (c) 2009</p>
* <p>Company: �������ӹɷ�����˾</p>
*/
package com.hundsun.ares.studio.ui.wizard;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import org.apache.commons.compress.archivers.ArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExecutableExtension;
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.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.MessageDialogWithToggle;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveRegistry;
import org.eclipse.ui.IPluginContribution;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.activities.IActivityManager;
import org.eclipse.ui.activities.IIdentifier;
import org.eclipse.ui.activities.IWorkbenchActivitySupport;
import org.eclipse.ui.activities.WorkbenchActivityHelper;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.ide.undo.CreateProjectOperation;
import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
import org.eclipse.ui.internal.IPreferenceConstants;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.internal.ide.IDEInternalPreferences;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.ide.StatusUtil;
import org.eclipse.ui.internal.registry.PerspectiveDescriptor;
import org.eclipse.ui.internal.util.PrefUtil;
import org.eclipse.ui.internal.wizards.newresource.ResourceMessages;
import org.eclipse.ui.statushandlers.StatusAdapter;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
import com.hundsun.ares.studio.core.IResPathEntry;
import com.hundsun.ares.studio.core.util.ResourcesUtil;
import com.hundsun.ares.studio.core.util.Util;
import com.hundsun.ares.studio.ui.ARESUI;
import com.hundsun.ares.studio.ui.template.Template;
/**
* �½�ģ�幤����
* @author sundl
*/
public class NewTemplateProjectWizard extends BasicNewResourceWizard implements INewWizard, IExecutableExtension{
private static Logger logger = Logger.getLogger(NewTemplateProjectWizard.class);
/**
* The wizard id for creating new projects in the workspace.
* @since 3.4
*/
public static final String WIZARD_ID = "com.hundsun.ares.studio.ui.wizard.temmplateproject"; //$NON-NLS-1$
private WizardNewProjectCreationPage mainPage;
private TemplateSelectWizardPage templatePage;
// cache of newly-created project
private IProject newProject;
/**
* The config element which declares this wizard.
*/
private IConfigurationElement configElement;
private static String WINDOW_PROBLEMS_TITLE = ResourceMessages.NewProject_errorOpeningWindow;
/**
* Extension attribute name for final perspective.
*/
private static final String FINAL_PERSPECTIVE = "finalPerspective"; //$NON-NLS-1$
/**
* Extension attribute name for preferred perspectives.
*/
private static final String PREFERRED_PERSPECTIVES = "preferredPerspectives"; //$NON-NLS-1$
/**
* Creates a wizard for creating a new project resource in the workspace.
*/
public NewTemplateProjectWizard() {
IDialogSettings workbenchSettings = ARESUI.getDefault().getDialogSettings();
IDialogSettings section = workbenchSettings.getSection("NewTemplateProjectResourceWizard");//$NON-NLS-1$
if (section == null) {
section = workbenchSettings.addNewSection("NewTemplateProjectResourceWizard");//$NON-NLS-1$
}
setDialogSettings(section);
}
/*
* (non-Javadoc) Method declared on IWizard.
*/
public void addPages() {
super.addPages();
mainPage = new WizardNewProjectCreationPage("basicNewProjectPage") { //$NON-NLS-1$
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.dialogs.WizardNewProjectCreationPage#createControl(org.eclipse.swt.widgets.Composite)
*/
public void createControl(Composite parent) {
super.createControl(parent);
createWorkingSetGroup(
(Composite) getControl(),
getSelection(),
new String[] { "org.eclipse.ui.resourceWorkingSetPage" }); //$NON-NLS-1$
Dialog.applyDialogFont(getControl());
}
};
mainPage.setTitle(ResourceMessages.NewProject_title);
mainPage.setDescription(ResourceMessages.NewProject_description);
this.addPage(mainPage);
templatePage = new TemplateSelectWizardPage();
this.addPage(templatePage);
}
/**
* Creates a new project resource with the selected name.
* <p>
* In normal usage, this method is invoked after the user has pressed Finish
* on the wizard; the enablement of the Finish button implies that all
* controls on the pages currently contain valid values.
* </p>
* <p>
* Note that this wizard caches the new project once it has been
* successfully created; subsequent invocations of this method will answer
* the same project resource without attempting to create it again.
* </p>
*
* @return the created project resource, or <code>null</code> if the
* project was not created
*/
private IProject createNewProject() {
if (newProject != null) {
return newProject;
}
// get a project handle
final IProject newProjectHandle = mainPage.getProjectHandle();
// get a project descriptor
URI location = null;
if (!mainPage.useDefaults()) {
location = mainPage.getLocationURI();
}
IWorkspace workspace = ResourcesPlugin.getWorkspace();
final IProjectDescription description = workspace
.newProjectDescription(newProjectHandle.getName());
description.setLocationURI(location);
// create the new project operation
IRunnableWithProgress op = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException {
CreateProjectOperation op = new CreateProjectOperation(
description, ResourceMessages.NewProject_windowTitle) {
@Override
protected void doExecute(IProgressMonitor monitor, IAdaptable uiInfo) throws CoreException {
super.doExecute(monitor, uiInfo);
String projectName = description.getName();
Template template = templatePage.getSelectedTemplate();
InputStream is = null;
try {
if (template.isLocal()) {
is = new FileInputStream(new File(template.getPath()));
} else {
URL url = new URL(template.getPath());
is = url.openStream();
}
Unzip(is, newProjectHandle, true, monitor);
} catch (IOException e) {
e.printStackTrace();
}
// IProjectDescription desc = newProjectHandle.getDescription();
// desc.setName(projectName);
// newProjectHandle.setDescription(desc, monitor);
}
};
try {
// see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=219901
// directly execute the operation so that the undo state is
// not preserved. Making this undoable resulted in too many
// accidental file deletions.
op.execute(monitor, WorkspaceUndoUtil
.getUIInfoAdapter(getShell()));
} catch (ExecutionException e) {
throw new InvocationTargetException(e);
}
}
};
// run the new project creation operation
try {
getContainer().run(true, true, op);
} catch (InterruptedException e) {
return null;
} catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
if (t instanceof ExecutionException
&& t.getCause() instanceof CoreException) {
CoreException cause = (CoreException) t.getCause();
StatusAdapter status;
if (cause.getStatus().getCode() == IResourceStatus.CASE_VARIANT_EXISTS) {
status = new StatusAdapter(
StatusUtil
.newStatus(
IStatus.WARNING,
NLS
.bind(
ResourceMessages.NewProject_caseVariantExistsError,
newProjectHandle
.getName()),
cause));
} else {
status = new StatusAdapter(StatusUtil.newStatus(cause
.getStatus().getSeverity(),
ResourceMessages.NewProject_errorMessage, cause));
}
status.setProperty(StatusAdapter.TITLE_PROPERTY,
ResourceMessages.NewProject_errorMessage);
StatusManager.getManager().handle(status, StatusManager.BLOCK);
} else {
StatusAdapter status = new StatusAdapter(new Status(
IStatus.WARNING, IDEWorkbenchPlugin.IDE_WORKBENCH, 0,
NLS.bind(ResourceMessages.NewProject_internalError, t
.getMessage()), t));
status.setProperty(StatusAdapter.TITLE_PROPERTY,
ResourceMessages.NewProject_errorMessage);
StatusManager.getManager().handle(status,
StatusManager.LOG | StatusManager.BLOCK);
}
return null;
}
newProject = newProjectHandle;
return newProject;
}
/**
* ��ѹ������Ӧ��ѹ���ļ�����ָ����λ�á�
* @param is
* @param target
* @param filePattern �ļ�����·����ƥ��������ʽ������null����ȫ����ѹ
* @param overwrite �����Ѿ����ڵ��ļ��Ƿ�
* @param pm
*/
public static void Unzip(InputStream is, IContainer target, boolean overwrite, IProgressMonitor monitor) throws CoreException, IOException{
ZipArchiveInputStream zip = new ZipArchiveInputStream(is, null, true);
ArchiveEntry entry;
monitor = Util.monitorFor(monitor);
monitor.beginTask("", IProgressMonitor.UNKNOWN);
entry = zip.getNextEntry();
while (entry != null) {
boolean canProcess = true;
if (StringUtils.equals(entry.getName(), "template.xml")
|| StringUtils.endsWith(entry.getName(), ".svn")) {
canProcess = false;
}
if (canProcess) {
if (entry.isDirectory()) {
IFolder folder = target.getFolder(new Path(entry.getName()));
ResourcesUtil.safelyCreateFolder(folder);
} else {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = zip.read(buffer)) > 0) {
bos.write(buffer, 0, len);
}
// �滻ģ���е���Ŀ��Ϊ�û����������
if (StringUtils.equals(entry.getName(), ".project")) {
InputStream inputStream = new ByteArrayInputStream(bos.toByteArray());
SAXReader reader = new SAXReader();
try {
Document document = reader.read(inputStream);
Element root = document.getRootElement();
Element element = root.element("name");
element.setText(target.getName());
OutputFormat format = OutputFormat.createPrettyPrint();
format.setIndent(true);
format.setEncoding("utf-8");
bos.close();
bos = new ByteArrayOutputStream();
XMLWriter writer = new XMLWriter(bos, format);
writer.write(document);
} catch (Exception exception) {
logger.error(exception);
}
}
bos.close();
IFile file = target.getFile(new Path(entry.getName()));
ResourcesUtil.safelyCreateFile(file, new ByteArrayInputStream(bos.toByteArray()), overwrite, null);
}
}
monitor.worked(1);
entry = zip.getNextEntry();
}
zip.close();
monitor.done();
}
/**
* Returns the newly created project.
*
* @return the created project, or <code>null</code> if project not
* created
*/
public IProject getNewProject() {
return newProject;
}
/*
* (non-Javadoc) Method declared on IWorkbenchWizard.
*/
public void init(IWorkbench workbench, IStructuredSelection currentSelection) {
super.init(workbench, currentSelection);
setNeedsProgressMonitor(true);
setWindowTitle(ResourceMessages.NewProject_windowTitle);
}
/*
* (non-Javadoc) Method declared on BasicNewResourceWizard.
*/
protected void initializeDefaultPageImageDescriptor() {
ImageDescriptor desc = IDEWorkbenchPlugin
.getIDEImageDescriptor("wizban/newprj_wiz.png");//$NON-NLS-1$
setDefaultPageImageDescriptor(desc);
}
/*
* (non-Javadoc) Opens a new window with a particular perspective and input.
*/
private static void openInNewWindow(IPerspectiveDescriptor desc) {
// Open the page.
try {
PlatformUI.getWorkbench().openWorkbenchWindow(desc.getId(),
ResourcesPlugin.getWorkspace().getRoot());
} catch (WorkbenchException e) {
IWorkbenchWindow window = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow();
if (window != null) {
ErrorDialog.openError(window.getShell(), WINDOW_PROBLEMS_TITLE,
e.getMessage(), e.getStatus());
}
}
}
/*
* (non-Javadoc) Method declared on IWizard.
*/
public boolean performFinish() {
createNewProject();
if (newProject == null) {
return false;
}
IWorkingSet[] workingSets = mainPage.getSelectedWorkingSets();
getWorkbench().getWorkingSetManager().addToWorkingSets(newProject,
workingSets);
updatePerspective();
selectAndReveal(newProject);
return true;
}
/*
* (non-Javadoc) Replaces the current perspective with the new one.
*/
private static void replaceCurrentPerspective(IPerspectiveDescriptor persp) {
// Get the active page.
IWorkbenchWindow window = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow();
if (window == null) {
return;
}
IWorkbenchPage page = window.getActivePage();
if (page == null) {
return;
}
// Set the perspective.
page.setPerspective(persp);
}
/**
* Stores the configuration element for the wizard. The config element will
* be used in <code>performFinish</code> to set the result perspective.
*/
public void setInitializationData(IConfigurationElement cfig,
String propertyName, Object data) {
configElement = cfig;
}
/**
* Updates the perspective for the active page within the window.
*/
protected void updatePerspective() {
updatePerspective(configElement);
}
/**
* Updates the perspective based on the current settings in the
* Workbench/Perspectives preference page.
*
* Use the setting for the new perspective opening if we are set to open in
* a new perspective.
* <p>
* A new project wizard class will need to implement the
* <code>IExecutableExtension</code> interface so as to gain access to the
* wizard's <code>IConfigurationElement</code>. That is the configuration
* element to pass into this method.
* </p>
*
* @param configElement -
* the element we are updating with
*
* @see IPreferenceConstants#OPM_NEW_WINDOW
* @see IPreferenceConstants#OPM_ACTIVE_PAGE
* @see IWorkbenchPreferenceConstants#NO_NEW_PERSPECTIVE
*/
public static void updatePerspective(IConfigurationElement configElement) {
// Do not change perspective if the configuration element is
// not specified.
if (configElement == null) {
return;
}
// Retrieve the new project open perspective preference setting
String perspSetting = PrefUtil.getAPIPreferenceStore().getString(
IDE.Preferences.PROJECT_OPEN_NEW_PERSPECTIVE);
String promptSetting = IDEWorkbenchPlugin.getDefault()
.getPreferenceStore().getString(
IDEInternalPreferences.PROJECT_SWITCH_PERSP_MODE);
// Return if do not switch perspective setting and are not prompting
if (!(promptSetting.equals(MessageDialogWithToggle.PROMPT))
&& perspSetting
.equals(IWorkbenchPreferenceConstants.NO_NEW_PERSPECTIVE)) {
return;
}
// Read the requested perspective id to be opened.
String finalPerspId = configElement.getAttribute(FINAL_PERSPECTIVE);
if (finalPerspId == null) {
return;
}
// Map perspective id to descriptor.
IPerspectiveRegistry reg = PlatformUI.getWorkbench()
.getPerspectiveRegistry();
// leave this code in - the perspective of a given project may map to
// activities other than those that the wizard itself maps to.
IPerspectiveDescriptor finalPersp = reg
.findPerspectiveWithId(finalPerspId);
if (finalPersp != null && finalPersp instanceof IPluginContribution) {
IPluginContribution contribution = (IPluginContribution) finalPersp;
if (contribution.getPluginId() != null) {
IWorkbenchActivitySupport workbenchActivitySupport = PlatformUI
.getWorkbench().getActivitySupport();
IActivityManager activityManager = workbenchActivitySupport
.getActivityManager();
IIdentifier identifier = activityManager
.getIdentifier(WorkbenchActivityHelper
.createUnifiedId(contribution));
Set idActivities = identifier.getActivityIds();
if (!idActivities.isEmpty()) {
Set enabledIds = new HashSet(activityManager
.getEnabledActivityIds());
if (enabledIds.addAll(idActivities)) {
workbenchActivitySupport
.setEnabledActivityIds(enabledIds);
}
}
}
} else {
IDEWorkbenchPlugin.log("Unable to find persective " //$NON-NLS-1$
+ finalPerspId
+ " in BasicNewProjectResourceWizard.updatePerspective"); //$NON-NLS-1$
return;
}
// gather the preferred perspectives
// always consider the final perspective (and those derived from it)
// to be preferred
ArrayList preferredPerspIds = new ArrayList();
addPerspectiveAndDescendants(preferredPerspIds, finalPerspId);
String preferred = configElement.getAttribute(PREFERRED_PERSPECTIVES);
if (preferred != null) {
StringTokenizer tok = new StringTokenizer(preferred, " \t\n\r\f,"); //$NON-NLS-1$
while (tok.hasMoreTokens()) {
addPerspectiveAndDescendants(preferredPerspIds, tok.nextToken());
}
}
IWorkbenchWindow window = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow();
if (window != null) {
IWorkbenchPage page = window.getActivePage();
if (page != null) {
IPerspectiveDescriptor currentPersp = page.getPerspective();
// don't switch if the current perspective is a preferred
// perspective
if (currentPersp != null
&& preferredPerspIds.contains(currentPersp.getId())) {
return;
}
}
// prompt the user to switch
if (!confirmPerspectiveSwitch(window, finalPersp)) {
return;
}
}
int workbenchPerspectiveSetting = WorkbenchPlugin.getDefault()
.getPreferenceStore().getInt(
IPreferenceConstants.OPEN_PERSP_MODE);
// open perspective in new window setting
if (workbenchPerspectiveSetting == IPreferenceConstants.OPM_NEW_WINDOW) {
openInNewWindow(finalPersp);
return;
}
// replace active perspective setting otherwise
replaceCurrentPerspective(finalPersp);
}
/**
* Adds to the list all perspective IDs in the Workbench who's original ID
* matches the given ID.
*
* @param perspectiveIds
* the list of perspective IDs to supplement.
* @param id
* the id to query.
* @since 3.0
*/
private static void addPerspectiveAndDescendants(List perspectiveIds,
String id) {
IPerspectiveRegistry registry = PlatformUI.getWorkbench()
.getPerspectiveRegistry();
IPerspectiveDescriptor[] perspectives = registry.getPerspectives();
for (int i = 0; i < perspectives.length; i++) {
// @issue illegal ref to workbench internal class;
// consider adding getOriginalId() as API on IPerspectiveDescriptor
PerspectiveDescriptor descriptor = ((PerspectiveDescriptor) perspectives[i]);
if (descriptor.getOriginalId().equals(id)) {
perspectiveIds.add(descriptor.getId());
}
}
}
public boolean canFinish() {
if (!(getContainer().getCurrentPage() instanceof TemplateSelectWizardPage))
return false;
return super.canFinish();
}
/**
* Prompts the user for whether to switch perspectives.
*
* @param window
* The workbench window in which to switch perspectives; must not
* be <code>null</code>
* @param finalPersp
* The perspective to switch to; must not be <code>null</code>.
*
* @return <code>true</code> if it's OK to switch, <code>false</code>
* otherwise
*/
private static boolean confirmPerspectiveSwitch(IWorkbenchWindow window,
IPerspectiveDescriptor finalPersp) {
IPreferenceStore store = IDEWorkbenchPlugin.getDefault()
.getPreferenceStore();
String pspm = store
.getString(IDEInternalPreferences.PROJECT_SWITCH_PERSP_MODE);
if (!IDEInternalPreferences.PSPM_PROMPT.equals(pspm)) {
// Return whether or not we should always switch
return IDEInternalPreferences.PSPM_ALWAYS.equals(pspm);
}
String desc = finalPersp.getDescription();
String message;
if (desc == null || desc.length() == 0)
message = NLS.bind(ResourceMessages.NewProject_perspSwitchMessage,
finalPersp.getLabel());
else
message = NLS.bind(
ResourceMessages.NewProject_perspSwitchMessageWithDesc,
new String[] { finalPersp.getLabel(), desc });
MessageDialogWithToggle dialog = MessageDialogWithToggle
.openYesNoQuestion(window.getShell(),
ResourceMessages.NewProject_perspSwitchTitle, message,
null /* use the default message for the toggle */,
false /* toggle is initially unchecked */, store,
IDEInternalPreferences.PROJECT_SWITCH_PERSP_MODE);
int result = dialog.getReturnCode();
// If we are not going to prompt anymore propogate the choice.
if (dialog.getToggleState()) {
String preferenceValue;
if (result == IDialogConstants.YES_ID) {
// Doesn't matter if it is replace or new window
// as we are going to use the open perspective setting
preferenceValue = IWorkbenchPreferenceConstants.OPEN_PERSPECTIVE_REPLACE;
} else {
preferenceValue = IWorkbenchPreferenceConstants.NO_NEW_PERSPECTIVE;
}
// update PROJECT_OPEN_NEW_PERSPECTIVE to correspond
PrefUtil.getAPIPreferenceStore().setValue(
IDE.Preferences.PROJECT_OPEN_NEW_PERSPECTIVE,
preferenceValue);
}
return result == IDialogConstants.YES_ID;
}
}