org.symbian.tools.wrttools/src/org/symbian/tools/wrttools/wizards/WrtWidgetWizard.java
author Eugene Ostroukhov <eostroukhov@symbian.org>
Wed, 13 Jan 2010 15:13:10 -0800
changeset 33 71a6ac16b759
parent 22 6297dfe3bd9d
child 54 5a2cfa9bc743
permissions -rw-r--r--
WRT wizards will switch to JS perspective on completion

/**
 * Copyright (c) 2009 Symbian Foundation and/or its subsidiary(-ies).
 * All rights reserved.
 * This component and the accompanying materials are made available
 * under the terms of the License "Eclipse Public License v1.0"
 * which accompanies this distribution, and is available
 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
 *
 * Initial Contributors:
 * Symbian Foundation - initial contribution.
 * Contributors:
 * Description:
 * Overview:
 * Details:
 * Platforms/Drives/Compatibility:
 * Assumptions/Requirement/Pre-requisites:
 * Failures and causes:
 */
package org.symbian.tools.wrttools.wizards;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExecutableExtension;
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.core.runtime.SubProgressMonitor;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.dialogs.WizardNewProjectCreationPage;
import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard;
import org.symbian.tools.wrttools.Activator;
import org.symbian.tools.wrttools.core.ProjectTemplate;
import org.symbian.tools.wrttools.util.NonClosingStream;
import org.symbian.tools.wrttools.util.ProjectUtils;

public class WrtWidgetWizard extends Wizard implements INewWizard, IExecutableExtension {
	private WizardNewProjectCreationPage resourcePage;
	private WizardContext context;
	private DataBindingContext bindingContext;
	private Map<ProjectTemplate, WRTProjectDetailsWizardPage> templateDetails = new HashMap<ProjectTemplate, WRTProjectDetailsWizardPage>();
	private WRTProjectTemplateWizardPage templatesPage;
	private WRTProjectFilesWizardPage filesPage;
	private IConfigurationElement config;

	public WrtWidgetWizard() {
		setWindowTitle("New WRT Widget");
	}

	@Override
	public boolean performFinish() {
		try {
			getContainer().run(true, true, new IRunnableWithProgress() {
				@Override
				public void run(IProgressMonitor monitor)
						throws InvocationTargetException, InterruptedException {
					action(monitor);
				}
			});
		} catch (InvocationTargetException e) {
			Activator.log(e);
		} catch (InterruptedException e) {
			Activator.log(e);
		}
		BasicNewProjectResourceWizard.updatePerspective(config);
		return true;
	}

	protected void action(IProgressMonitor monitor) {
		try {
			ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
				@Override
				public void run(IProgressMonitor monitor) throws CoreException {
					createAndInitProject(monitor);
				}
			}, monitor);
		} catch (CoreException e) {
			Activator.log(e);
		}
	}

	protected void createAndInitProject(IProgressMonitor monitor)
			throws CoreException {
		monitor.beginTask("Creating project", 100);
		IProject project = ProjectUtils.createWrtProject(context.getProjectName(), context.getProjectUri(), new SubProgressMonitor(monitor, 30));
		populateProject(project, new SubProgressMonitor(monitor, 70));
		monitor.done();
	}

	private void populateProject(IProject project, IProgressMonitor monitor)
			throws CoreException {
		URL projectContents = context.getTemplate().getProjectContents();
		Map<String, String> vars = context.getTemplateVars();

		ZipInputStream stream = null;
		try {
			Velocity.init();
			VelocityContext ctx = new VelocityContext(vars);
			stream = new ZipInputStream(projectContents.openStream());
			monitor.beginTask("Generating project contents",
					IProgressMonitor.UNKNOWN);
			ZipEntry entry;
			while ((entry = stream.getNextEntry()) != null
					&& !monitor.isCanceled()) {
				String name = entry.getName();
				boolean isVelocity = name.endsWith(".velocitytemplate");
				if (isVelocity) {
					name = name.substring(0, name.length()
							- ".velocitytemplate".length());
				}
				if (name.startsWith("$")) {
					int dotLocation = name.indexOf(".");
					String template = name.substring(1,
							dotLocation > 1 ? dotLocation : name.length());
					if (vars.containsKey(template)) {
						name = vars.get(template)
								+ name.substring(dotLocation > 1 ? dotLocation
										: name.length());
					}
				}
				if (entry.isDirectory()) {
					IFolder folder = project.getFolder(entry.getName());
					folder.create(false, true, new SubProgressMonitor(monitor, 1));
				} else if (isVelocity) {
					copyTemplate(project, name, stream, (int) entry.getSize(),
							ctx, monitor);
				} else {
					ProjectUtils.copyFile(project, name, stream, entry.getSize(), monitor);
				}
				stream.closeEntry();
			}
			monitor.done();
		} catch (Exception e) {
			throw new CoreException(new Status(IStatus.ERROR,
					Activator.PLUGIN_ID, "Project creation failed", e));
		} finally {
			if (stream != null) {
				try {
					stream.close();
				} catch (IOException e) {
					// Ignore - something really bad happened
				}
			}
		}
		ProjectUtils.addPreviewer(project, new Path(context.getHtmlFileName()));
	}

	private void copyTemplate(IProject project, String name,
			ZipInputStream stream, int size, VelocityContext ctx,
			IProgressMonitor monitor) throws IOException, CoreException {
		// Templates will not be more then a few megs - we can afford the memory
		ByteArrayOutputStream file = new ByteArrayOutputStream();

		Reader reader = new InputStreamReader(new NonClosingStream(stream));
		Writer writer = new OutputStreamWriter(file);

		Velocity.evaluate(ctx, writer, name, reader);

		reader.close();
		writer.close();

		ByteArrayInputStream contents = new ByteArrayInputStream(file
				.toByteArray());
		IFile f = project.getFile(name);
		f.create(contents, true, new SubProgressMonitor(monitor, 1));
	}

	@Override
	public void init(IWorkbench workbench, IStructuredSelection selection) {
		context = new WizardContext();
		bindingContext = new DataBindingContext();
	}

	@Override
	public void addPages() {
		resourcePage = new WizardNewProjectCreationPage("Resource");
		resourcePage
				.setDescription("Create a WRT widget project in the workspace or other location");
		resourcePage.setTitle("Create a New WRT Widget Project");
		addPage(resourcePage);

		templatesPage = new WRTProjectTemplateWizardPage(context,
				bindingContext);
		addPage(templatesPage);

		ProjectTemplate[] templates = ProjectTemplate.getAllTemplates();
		for (ProjectTemplate projectTemplate : templates) {
			WRTProjectDetailsWizardPage page = projectTemplate
					.createWizardPage(context, bindingContext);
			addPage(page);
			templateDetails.put(projectTemplate, page);
		}

		filesPage = new WRTProjectFilesWizardPage(context, bindingContext);
		addPage(filesPage);
	}

	@Override
	public boolean canFinish() {
		return super.canFinish()
				&& getContainer().getCurrentPage() == filesPage;
	}

	@Override
	public IWizardPage getNextPage(IWizardPage page) {
		if (page == resourcePage) {
			context.setProjectName(resourcePage.getProjectName());
			context.setProjectUri(isDefaultProjectLocation() ? null
					: resourcePage.getLocationURI());
		}
		if (page == templatesPage) {
			ProjectTemplate template = context.getTemplate();
			if (template != null) {
				WRTProjectDetailsWizardPage activePage = templateDetails
						.get(template);
				for (WRTProjectDetailsWizardPage wizardPage : templateDetails
						.values()) {
					wizardPage.setActive(wizardPage == activePage);
				}
				bindingContext.updateModels();
				return activePage;
			}
		}
		if (page instanceof WRTProjectDetailsWizardPage) {
			return filesPage;
		}
		return super.getNextPage(page);
	}

	private boolean isDefaultProjectLocation() {
		IPath project = resourcePage.getLocationPath();
		IPath workspace = ResourcesPlugin.getWorkspace().getRoot()
				.getLocation();
		return workspace.isPrefixOf(project);
	}
	
	@Override
	public void setInitializationData(IConfigurationElement config,
			String propertyName, Object data) throws CoreException {
		this.config = config;
	}
}