/* * Copyright 2010-2012 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). * You may not use this file except in compliance with the License. * A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. This file is distributed * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing * permissions and limitations under the License. */ package com.amazonaws.eclipse.elasticbeanstalk.webproject; import static com.amazonaws.eclipse.core.util.JavaProjectUtils.setDefaultJreToProjectClasspath; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.util.List; import org.apache.commons.io.FileUtils; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.FileLocator; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.browser.IWebBrowser; import org.eclipse.ui.browser.IWorkbenchBrowserSupport; import org.eclipse.wst.common.componentcore.ComponentCore; import org.eclipse.wst.common.componentcore.resources.IVirtualComponent; import org.eclipse.wst.common.componentcore.resources.IVirtualFolder; import org.osgi.framework.Bundle; import com.amazonaws.eclipse.core.AccountInfo; import com.amazonaws.eclipse.core.AwsToolkitCore; import com.amazonaws.eclipse.core.maven.MavenFactory; import com.amazonaws.eclipse.core.model.MavenConfigurationDataModel; import com.amazonaws.eclipse.core.validator.JavaPackageName; import com.amazonaws.eclipse.elasticbeanstalk.ElasticBeanstalkPlugin; /** * Runnable (with progress) that creates a new AWS Java web project, based on * the configured data model. This class is responsible for creating the WTP * dynamic web project, adding and configuring the AWS SDK for Java, creating * the security credential configuration file and eventually configuring the WTP * runtime targeted by the new project. */ final class CreateNewAwsJavaWebProjectRunnable implements IRunnableWithProgress { private final NewAwsJavaWebProjectDataModel dataModel; private static final IWorkbenchBrowserSupport BROWSER_SUPPORT = PlatformUI.getWorkbench().getBrowserSupport(); public CreateNewAwsJavaWebProjectRunnable(NewAwsJavaWebProjectDataModel dataModel) { this.dataModel = dataModel; } /* (non-Javadoc) * @see org.eclipse.jface.operation.IRunnableWithProgress#run(org.eclipse.core.runtime.IProgressMonitor) */ public void run(IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException { SubMonitor monitor = SubMonitor.convert(progressMonitor, "Creating new AWS Java web project", 100); try { IProject project = createBeanstalkProject( dataModel.getMavenConfigurationDataModel(), monitor); IJavaProject javaProject = JavaCore.create(project); setDefaultJreToProjectClasspath(javaProject, monitor); monitor.worked(20); addTemplateFiles(project); monitor.worked(10); // Configure the Tomcat session manager if (dataModel.getUseDynamoDBSessionManagement()) { addSessionManagerConfigurationFiles(project); } monitor.worked(10); if (dataModel.getProjectTemplate() == JavaWebProjectTemplate.DEFAULT) { // Open the readme.html in an editor browser window. File root = project.getLocation().toFile(); final File indexHtml = new File(root, "src/main/webapp/index.html"); // Internal browser must be opened within UI thread Display.getDefault().syncExec(new Runnable() { public void run() { try { IWebBrowser browser = BROWSER_SUPPORT.createBrowser( IWorkbenchBrowserSupport.AS_EDITOR, null, null, null); browser.openURL(indexHtml.toURI().toURL()); } catch (Exception e) { ElasticBeanstalkPlugin .getDefault() .logError( "Failed to open project index page in Eclipse editor.", e); } } }); } } catch (Exception e) { throw new InvocationTargetException(e); } finally { progressMonitor.done(); } } private void addSessionManagerConfigurationFiles(IProject project) throws IOException, CoreException { Bundle bundle = ElasticBeanstalkPlugin.getDefault().getBundle(); URL url = FileLocator.resolve(bundle.getEntry("/")); IPath templateRoot = new Path(url.getFile(), "templates"); FileUtils.copyDirectory( templateRoot.append("dynamodb-session-manager").toFile(), project.getLocation().toFile()); // Add the user's credentials to context.xml File localContextXml = project.getLocation() .append(".ebextensions") .append("context.xml").toFile(); AccountInfo accountInfo = AwsToolkitCore.getDefault().getAccountManager().getAccountInfo(dataModel.getAccountId()); String contextContents = FileUtils.readFileToString(localContextXml); contextContents = contextContents.replace("{ACCESS_KEY}", accountInfo.getAccessKey()); contextContents = contextContents.replace("{SECRET_KEY}", accountInfo.getSecretKey()); FileUtils.writeStringToFile(localContextXml, contextContents); project.refreshLocal(IResource.DEPTH_INFINITE, null); // Update the J2EE Deployment Assembly by creating a link from the '/.ebextensions' // folder to the '/WEB-INF/.ebextensions' folder in the web assembly mapping for WTP IVirtualComponent rootComponent = ComponentCore.createComponent(project); IVirtualFolder rootFolder = rootComponent.getRootFolder(); try { Path source = new Path("/.ebextensions"); Path target = new Path("/WEB-INF/.ebextensions"); IVirtualFolder subFolder = rootFolder.getFolder(target); subFolder.createLink(source, 0, null); } catch( CoreException ce ) { String message = "Unable to configure deployment assembly to map .ebextension directory"; ElasticBeanstalkPlugin.getDefault().logError(message, ce); } } private IProject createBeanstalkProject(MavenConfigurationDataModel mavenConfig, IProgressMonitor monitor) throws CoreException, IOException { List<IProject> projects = MavenFactory.createArchetypeProject( "org.apache.maven.archetypes", "maven-archetype-webapp", "1.0", mavenConfig.getGroupId(), mavenConfig.getArtifactId(), mavenConfig.getVersion(), mavenConfig.getPackageName(), monitor); // This archetype only has one project return projects.get(0); } private void addTemplateFiles(IProject project) throws IOException, CoreException { final String CREDENTIAL_PROFILE_PLACEHOLDER = "{CREDENTIAL_PROFILE}"; final String PACKAGE_NAME_PLACEHOLDER = "{PACKAGE_NAME}"; Bundle bundle = ElasticBeanstalkPlugin.getDefault().getBundle(); URL url = FileLocator.resolve(bundle.getEntry("/")); IPath templateRoot = new Path(url.getFile(), "templates"); AccountInfo currentAccountInfo = AwsToolkitCore.getDefault().getAccountManager().getAccountInfo(dataModel.getAccountId()); File pomFile = project.getFile("pom.xml").getLocation().toFile(); MavenConfigurationDataModel mavenConfig = dataModel.getMavenConfigurationDataModel(); switch (dataModel.getProjectTemplate()) { case WORKER: replacePomFile(templateRoot.append("worker/pom.xml").toFile(), mavenConfig.getGroupId(), mavenConfig.getArtifactId(), mavenConfig.getVersion(), pomFile); String packageName = dataModel.getMavenConfigurationDataModel().getPackageName(); JavaPackageName javaPackageName = JavaPackageName.parse(packageName); IPath location = project.getFile(MavenFactory.getMavenSourceFolder()).getLocation(); for (String component : javaPackageName.getComponents()) { location = location.append(component); } FileUtils.copyDirectory(templateRoot.append("worker/src").toFile(), location.toFile()); File workerServlet = location.append("WorkerServlet.java").toFile(); replaceStringInFile(workerServlet, CREDENTIAL_PROFILE_PLACEHOLDER, currentAccountInfo.getAccountName()); replaceStringInFile(workerServlet, PACKAGE_NAME_PLACEHOLDER, packageName); File workerRequest = location.append("WorkRequest.java").toFile(); replaceStringInFile(workerRequest, PACKAGE_NAME_PLACEHOLDER, packageName); location = project.getFile("src/main/webapp").getLocation(); FileUtils.copyDirectory( templateRoot.append("worker/WebContent/").toFile(), location.toFile()); File webXml = location.append("WEB-INF/web.xml").toFile(); replaceStringInFile(webXml, PACKAGE_NAME_PLACEHOLDER, packageName); break; case DEFAULT: replacePomFile(templateRoot.append("basic/pom.xml").toFile(), mavenConfig.getGroupId(), mavenConfig.getArtifactId(), mavenConfig.getVersion(), pomFile); location = project.getFile("src/main/webapp").getLocation(); FileUtils.copyDirectory( templateRoot.append("basic/WebContent").toFile(), location.toFile()); File indexJsp = location.append("index.jsp").toFile(); replaceStringInFile(indexJsp, CREDENTIAL_PROFILE_PLACEHOLDER, currentAccountInfo.getAccountName()); break; default: throw new IllegalStateException("Unknown project template: " + dataModel.getProjectTemplate()); } project.refreshLocal(IResource.DEPTH_INFINITE, null); } private String replacePomFile(File pomTemplate, String groupId, String artifactId, String version, File targetFile) throws IOException { final String GROUP_ID_PLACEHOLDER = "{GROUP_ID}"; final String ARTIFACT_ID_PLACEHOLDER = "{ARTIFACT_ID}"; final String VERSION_PLACEHOLDER = "{VERSION}"; String content = FileUtils.readFileToString(pomTemplate); content = content.replace(GROUP_ID_PLACEHOLDER, groupId) .replace(ARTIFACT_ID_PLACEHOLDER, artifactId) .replace(VERSION_PLACEHOLDER, version); FileUtils.writeStringToFile(targetFile, content); return content; } /** Replace source strings with target string and return the original content of the file. */ private String replaceStringInFile(File file, String source, String target) throws IOException { String originalContent = FileUtils.readFileToString(file); String replacedContent = originalContent.replace(source, target); FileUtils.writeStringToFile(file, replacedContent); return originalContent; } }