/******************************************************************************* * Copyright (c) 2012, 2013 VMware, 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: * VMware, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.wizard.template; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.mylyn.commons.core.CoreUtil; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.springframework.ide.eclipse.wizard.WizardPlugin; import org.springframework.ide.eclipse.wizard.template.infrastructure.ITemplateProjectData; import org.springframework.ide.eclipse.wizard.template.infrastructure.Template; import org.springframework.ide.eclipse.wizard.template.infrastructure.TemplateProjectData; import org.springsource.ide.eclipse.commons.content.core.ContentItem; import org.springsource.ide.eclipse.commons.content.core.ContentManager; import org.springsource.ide.eclipse.commons.content.core.ContentPlugin; import org.springsource.ide.eclipse.commons.content.core.TemplateDownloader; import org.springsource.ide.eclipse.commons.content.core.util.IContentConstants; import org.springsource.ide.eclipse.commons.ui.UiStatusHandler; /** * @author Terry Denney * @author Kaitlin Duck Sherwood */ public class TemplateUtils { public static File importDirectory(ContentItem item, final Shell shell, boolean promptForDownload, SubMonitor monitor) throws CoreException, InterruptedException { Assert.isNotNull(item); String id = item.getId(); ContentManager manager = ContentPlugin.getDefault().getManager(); if (item.needsDownload()) { final ContentItem finalItem = item; final boolean[] response = { true }; if (promptForDownload) { Display.getDefault().syncExec(new Runnable() { public void run() { response[0] = promptForDownload(shell, finalItem); } }); } if (response[0]) { TemplateDownloader downloader = getTemplateDownloader(finalItem); IStatus status = downloader.downloadTemplate(monitor); if (!status.isOK()) { String message = NLS.bind("Download of template ''{0}'' failed: {1}", id, status.getMessage()); throw new CoreException(new Status(IStatus.ERROR, WizardPlugin.PLUGIN_ID, message)); } // re-get template project since it may changed item = manager.getItem(id); if (item == null) { return null; } } else if (!item.isLocal()) { return null; } } File baseDir = manager.getInstallDirectory(); if (item.isRuntimeDefined()) { File directory = new File(baseDir, item.getPath()); String projectName = item.getLocalDescriptor().getUrl(); IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); File templateFolder = project.getLocation().toFile(); copyFolder(templateFolder, directory); } if (!item.isLocal()) { String message = NLS.bind("Download of template ''{0}'' failed", id); throw new CoreException(new Status(IStatus.ERROR, WizardPlugin.PLUGIN_ID, message)); } File projectDir = new File(baseDir, item.getPath()); return projectDir; } /** * Determines if the given template has been downloaded. * @param template * @return true if downloaded, false otherwise */ public static boolean hasBeenDownloaded(Template template) { return template != null && template.getTemplateData() != null; } private static TemplateDownloader getTemplateDownloader(ContentItem item) { ContentManager manager = ContentPlugin.getDefault().getManager(); // Templates for simple projects are located in the bundle return manager.createDownloader(item); } private static void copyFolder(File source, File destination) { File[] sourceFiles = source.listFiles(); for (File sourceFile : sourceFiles) { File destinationFile = new File(destination, sourceFile.getName()); if (sourceFile.isDirectory()) { copyFolder(sourceFile, destinationFile); } else { FileOutputStream toStream = null; FileInputStream fromStream = null; try { fromStream = new FileInputStream(sourceFile); toStream = new FileOutputStream(destinationFile); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = fromStream.read(buffer)) != -1) { toStream.write(buffer, 0, bytesRead); // write } } catch (FileNotFoundException e) { WizardPlugin .getDefault() .getLog() .log(new Status(IStatus.ERROR, WizardPlugin.PLUGIN_ID, "Failed to copy folder due to: " + e.getMessage(), e)); } catch (IOException e) { WizardPlugin .getDefault() .getLog() .log(new Status(IStatus.ERROR, WizardPlugin.PLUGIN_ID, "I/O error when copying folder: " + e.getMessage(), e)); } finally { if (fromStream != null) { try { fromStream.close(); } catch (IOException e) { } } if (toStream != null) { try { toStream.close(); } catch (IOException e) { } } } } } } public static ITemplateProjectData importTemplate(Template template, final Shell shell, final IProgressMonitor monitor) throws CoreException, InterruptedException { SubMonitor progress = SubMonitor.convert(monitor, 100); // Do not prompt for download for Simple Templates, as they are bundled // in the plugin and // do not require download boolean shouldPromptForDownload = !(template instanceof SimpleProject); File templateDir = importDirectory(template.getItem(), shell, shouldPromptForDownload, progress); if (templateDir == null) { return null; } if (!wasDownloadedViaDescriptor(templateDir)) { File[] childrenFiles = templateDir.listFiles(); if (childrenFiles.length != 1) { String message = NLS .bind("There are more files the template download directory {0} than expected; using first directory", templateDir); IStatus status = new Status(IStatus.WARNING, WizardPlugin.PLUGIN_ID, message); UiStatusHandler.logAndDisplay(shell, status); } File subdir = null; for (File childFile : childrenFiles) { if (childFile.isDirectory()) { subdir = childFile; break; } } if (subdir != null) { File[] grandchildren = subdir.listFiles(); for (File grandchild : grandchildren) { grandchild.renameTo(new File(templateDir, grandchild.getName())); } subdir.delete(); } else { // There is another error thrown later on String message = NLS.bind( "There wasn't either {0} or a directory in the template download directory {1}", IContentConstants.TEMPLATE_DATA_FILE_NAME, templateDir); IStatus status = new Status(IStatus.WARNING, WizardPlugin.PLUGIN_ID, message); UiStatusHandler.logAndDisplay(shell, status); } } TemplateProjectData data = new TemplateProjectData(templateDir); data.read(); progress.setWorkRemaining(10); return data; } // The layout of templates downloaded via descriptors.xml must // have template.xml in the root directory. private static boolean wasDownloadedViaDescriptor(File templateDir) { File templateXml = new File(templateDir, IContentConstants.TEMPLATE_DATA_FILE_NAME); return templateXml.exists(); } protected static boolean promptForDownload(Shell shell, ContentItem item) { if (CoreUtil.TEST_MODE) { return true; } try { List<ContentItem> dependencies = ContentPlugin.getDefault().getManager().getDependencies(item); long size = 0; for (ContentItem dependency : dependencies) { size += dependency.getDownloadSize(); } String formattedSize; if (size > 0) { formattedSize = NLS.bind("{0} bytes", size); } else { formattedSize = NLS.bind("unknown size", null); } String message; String requiredBundle = null; if (item.getLocalDescriptor() != null) { requiredBundle = item.getLocalDescriptor().getRequiresBundle(); } else if (item.getRemoteDescriptor() != null) { requiredBundle = item.getRemoteDescriptor().getRequiresBundle(); } if (requiredBundle != null && !hasBundle(requiredBundle)) { message = NLS .bind("Warning: this project requires the bundle \n\t{0}\nwhich is not installed. You can download this template, but it will probably get build errors.\n\n", requiredBundle); } else { message = ""; } if (!item.isLocal()) { message = message + NLS.bind("{0} requires a download of {1}.\n\nProceed?", item.getName(), formattedSize); return MessageDialog.openQuestion(shell, "Import", message); } else if (item.isNewerVersionAvailable()) { message = NLS.bind("An update for {0} is available which requires a download of {1}.\n\n" + message + "Update?", item.getName(), formattedSize); return MessageDialog.openQuestion(shell, "Import", message); } } catch (CoreException e) { UiStatusHandler.logAndDisplay(shell, e.getStatus()); return false; } return true; } private static boolean hasBundle(String requiredBundle) { return (Platform.getBundle(requiredBundle) != null); } }