/******************************************************************************* * Copyright (c) 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.net.URI; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.swt.widgets.Shell; import org.springframework.ide.eclipse.wizard.WizardPlugin; import org.springframework.ide.eclipse.wizard.template.infrastructure.Template; import org.springframework.ide.eclipse.wizard.template.infrastructure.processor.ProcessingInfo; import org.springframework.ide.eclipse.wizard.template.infrastructure.processor.Processor; import org.springframework.ide.eclipse.wizard.template.infrastructure.ui.WizardUIInfoElement; import org.springframework.ide.eclipse.wizard.template.newproject.NewProjectProcessingInfo; import org.springsource.ide.eclipse.commons.core.SpringCoreUtils; /** * Creates and configures a project based on a selected template. In some cases, * the template data is downloaded when the project is being created. For * example, this would be the case of templates that do not contribute any UI to * the New Spring Wizard, and are therefore downloaded and processed only when a * user clicks "Finish" in the wizard * */ public class TemplateProjectConfiguration extends ProjectConfiguration { private final Shell shell; private final Map<String, Object> collectedInput; private final Map<String, String> inputKinds; private final TemplateProjectConfigurationDescriptor configurationDescriptor; public TemplateProjectConfiguration(TemplateProjectConfigurationDescriptor configurationDescriptor, Shell shell) { this.configurationDescriptor = configurationDescriptor; this.shell = shell; collectedInput = new HashMap<String, Object>(); inputKinds = new HashMap<String, String>(); } /** * User this constructor if no descriptor is available at the time that a * request is made for a project configuration. * @param shell required to display errors or prompt user while creating a * project. */ public TemplateProjectConfiguration(Shell shell) { this(null, shell); } protected Shell getShell() { return shell; } protected void handleError(String errorMessage) throws CoreException { throw new CoreException(new Status(IStatus.ERROR, WizardPlugin.PLUGIN_ID, errorMessage)); } protected void handleError(String errorMessage, Exception error) throws CoreException { throw new CoreException(new Status(IStatus.ERROR, WizardPlugin.PLUGIN_ID, errorMessage, error)); } @Override public void configureProject(IProgressMonitor monitor) throws CoreException { Template template = configurationDescriptor.getTemplate(); IProject project = getProject(); if (template == null) { handleError("No project template selected to configure the project: " + getProject().getName()); return; } if (project == null) { handleError("Failed to create a project. No project available to configure."); return; } // Now collect all the template variable inputs IStatus status = collectInput(); if (status == null || status.getSeverity() != IStatus.ERROR) { if (status != null && status.getSeverity() == IStatus.WARNING) { WizardPlugin.getDefault().getLog().log(status); } URI newPath = configurationDescriptor.getProjectLocationPath(); String[] topLevelPackageTokens = configurationDescriptor.getTopLevelPackageTokens(); String projectName = project.getName(); try { ProcessingInfo processingInfo = new NewProjectProcessingInfo(template.getZippedLocation(), getProject() .getName(), configurationDescriptor.getSpringVersion()); Processor processor = new Processor(processingInfo); IProject processedProject = processor.process(project, newPath, topLevelPackageTokens, configurationDescriptor.getProjectNameToken(), collectedInput, inputKinds, shell, monitor); if (processedProject != null) { processedProject.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); SpringCoreUtils.buildFullProject(processedProject); } } catch (Exception e) { handleError("Failure while processing template for project: " + projectName, e); } } else { throw new CoreException(status); } } @Override protected IProject create(IProgressMonitor monitor) throws CoreException { String projectName = configurationDescriptor.getActualProjectName(); return ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); } /** * Collect user input and input kinds, and return status that indicates * whether there were clashes or error when collecting input. Note that * exceptions are not throw as the if there are issues which are just * warnings, the template processing should still occur with the collected * input. Error status will halt the template processing * @return OK status, or warning if template processing should continue, or * error if template processing should stop */ protected IStatus collectInput() { List<TemplateInputCollector> inputHandlers = configurationDescriptor.getInputHandlers(); IStatus status = Status.OK_STATUS; for (TemplateInputCollector handler : inputHandlers) { Map<String, String> desInputKinds = handler.getInputKinds(); if (desInputKinds != null) { inputKinds.putAll(desInputKinds); } Map<String, Object> desCollectedInput = handler.getCollectedInput(); if (desCollectedInput != null) { collectedInput.putAll(desCollectedInput); } } // Also handle the Spring version replacement Template template = configurationDescriptor.getTemplate(); String templateSpringVersion = template != null && template.getTemplateData() != null && template.getTemplateData().getDescriptor() != null ? template.getTemplateData().getDescriptor() .getSpringVersion() : null; SpringVersion userDefinedSpringVersion = configurationDescriptor.getSpringVersion(); // Check if there is another token that is also using the same value as // the template-defined Spring version. // If so, log a warning that Spring version cannot be replaced as the // token is used by some other token definition if (inputKinds.containsKey(templateSpringVersion)) { status = new Status( IStatus.WARNING, WizardPlugin.PLUGIN_ID, "Unable to replace Spring version: " + templateSpringVersion + " with " + userDefinedSpringVersion + " as the original Spring version token value is already used by another token definition. Check the token definitions in the template's wizard input definition file."); } else if (templateSpringVersion != null && userDefinedSpringVersion != null) { inputKinds.put(templateSpringVersion, WizardUIInfoElement.FIXED_TOKEN_KIND); collectedInput.put(templateSpringVersion, userDefinedSpringVersion.getVersion()); } return status; } }