/******************************************************************************* * Copyright (c) 2012 Google, Inc. * 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: * Google, Inc. - initial API and implementation *******************************************************************************/ package com.windowtester.eclipse.ui.wizard; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IWorkspace; 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.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.Wizard; import org.eclipse.ui.IImportWizard; import org.eclipse.ui.INewWizard; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.actions.WorkspaceModifyOperation; import org.osgi.framework.Bundle; import com.windowtester.eclipse.ui.dialogs.ExceptionDetailsDialog; import com.windowtester.ui.util.Logger; /** * Wizard for creating a new example project in the workspace */ public class NewExampleProjectWizard extends Wizard implements INewWizard, IImportWizard, IExecutableExtension { private String bundleId; private String zipPath; private NewExampleProjectWizardPage page; public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { /* $codepro.preprocessor.if version >= 3.2 $ */ bundleId = config.getContributor().getName(); /* $codepro.preprocessor.elseif version == 3.1 $ bundleId = config.getNamespace(); $codepro.preprocessor.elseif version < 3.1 $ bundleId = config.getDeclaringExtension().getNamespace(); $codepro.preprocessor.endif $ */ if (data instanceof String) { zipPath = "examples/" + ((String) data) + "-src.zip"; } else { Logger.logStackTrace("Expected data to be name of zip file containing example projects, but found " + data); } } public void init(IWorkbench workbench, IStructuredSelection selection) { } public void addPages() { setWindowTitle("New Project(s)"); page = new NewExampleProjectWizardPage(bundleId, zipPath); addPage(page); } public boolean performFinish() { try { getContainer().run(true, true, new WorkspaceModifyOperation() { protected void execute(IProgressMonitor monitor) throws CoreException, InvocationTargetException, InterruptedException { monitor.beginTask("Extracting new example projects", 2); try { unzipProjects(new SubProgressMonitor(monitor, 1)); importProjects(new SubProgressMonitor(monitor, 1)); } catch (IOException e) { throw new InvocationTargetException(e); } monitor.done(); } }); } catch (InvocationTargetException e) { String errMsg = "Failed create example projects from " + zipPath + " in bundle " + bundleId; Logger.log(errMsg, e); new ExceptionDetailsDialog(getShell(), "Import Failed", errMsg, e).open(); return false; } catch (InterruptedException e) { // Canceled by user return false; } return true; } private void unzipProjects(IProgressMonitor monitor) throws IOException { Bundle bundle = Platform.getBundle(bundleId); URL zipUrl = bundle.getEntry(zipPath); InputStream input = zipUrl.openStream(); try { unzipProjects(input, monitor); } finally { input.close(); } } private void unzipProjects(InputStream input, IProgressMonitor monitor) throws IOException { monitor.beginTask("Unzipping projects", 100); IPath rootPath = ResourcesPlugin.getWorkspace().getRoot().getLocation(); ZipInputStream zip = new ZipInputStream(input); while (true) { if (monitor.isCanceled()) throw new OperationCanceledException(); ZipEntry entry = zip.getNextEntry(); if (entry == null) break; String relPath = entry.getName(); if (relPath.endsWith("/")) continue; File outputFile = rootPath.append(relPath).toFile(); outputFile.getParentFile().mkdirs(); OutputStream output = new BufferedOutputStream(new FileOutputStream(outputFile)); try { byte[] buf = new byte[1024]; while (true) { int count = zip.read(buf); if (count == -1) break; output.write(buf, 0, count); } monitor.worked(1); } finally { output.close(); } } monitor.done(); } private void importProjects(IProgressMonitor monitor) throws CoreException { if (monitor.isCanceled()) throw new OperationCanceledException(); String[] projectNames = page.getProjectNames(); monitor.beginTask("Import projects", projectNames.length * 2); for (int i = 0; i < projectNames.length; i++) { if (monitor.isCanceled()) throw new OperationCanceledException(); importProject(projectNames[i], monitor); } monitor.done(); } private void importProject(String projectName, IProgressMonitor monitor) throws CoreException { final IWorkspace workspace = ResourcesPlugin.getWorkspace(); final IProject project = workspace.getRoot().getProject(projectName); IProjectDescription description = workspace.newProjectDescription(projectName); description.setLocation(null); project.create(description, new SubProgressMonitor(monitor, 1)); project.open(new SubProgressMonitor(monitor, 1)); // Direct ECLIPSE_HOME references are different each Eclipse installation // so adjust the classpath accordingly IJavaProject javaProject = JavaCore.create(project); IClasspathEntry[] classpath = javaProject.getRawClasspath(); boolean modified = false; for (int i = 0; i < classpath.length; i++) { IClasspathEntry entry = classpath[i]; if (entry.getEntryKind() != IClasspathEntry.CPE_VARIABLE) continue; IPath path = entry.getPath(); if (path.segmentCount() != 3) continue; if (!path.segment(0).equals("ECLIPSE_HOME")) continue; if (!path.segment(1).equals("plugins")) continue; String jarName = path.segment(2); path = path.removeLastSegments(1); IPath pluginsPath = JavaCore.getResolvedVariablePath(path); if (pluginsPath == null) { Logger.log("Failed to resolve " + path); continue; } File pluginsDir = pluginsPath.toFile(); String jarPrefix = jarName.substring(0, jarName.indexOf('_') + 1); String[] childNames = pluginsDir.list(); if (childNames == null) { Logger.log("Failed to obtain children for " + pluginsDir.getPath()); continue; } for (int j = 0; j < childNames.length; j++) { String name = childNames[j]; if (name.startsWith(jarPrefix)) { modified = true; classpath[i] = JavaCore.newVariableEntry(path.append(name), null, null); break; } } } if (modified) javaProject.setRawClasspath(classpath, new NullProgressMonitor()); } }