/*
* Copyright 2016 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.lambda.project.wizard.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import com.amazonaws.eclipse.core.maven.MavenFactory;
import com.amazonaws.eclipse.core.validator.JavaPackageName;
import com.amazonaws.eclipse.lambda.LambdaPlugin;
import com.amazonaws.eclipse.lambda.blueprint.ServerlessBlueprint;
import com.amazonaws.eclipse.lambda.model.LambdaFunctionDataModel;
import com.amazonaws.eclipse.lambda.project.template.CodeTemplateManager;
import com.amazonaws.eclipse.lambda.project.template.data.LambdaBlueprintTemplateData;
import com.amazonaws.eclipse.lambda.project.template.data.PomFileTemplateData;
import com.amazonaws.eclipse.lambda.project.wizard.model.LambdaFunctionWizardDataModel;
import com.amazonaws.eclipse.lambda.project.wizard.model.NewServerlessProjectDataModel;
import com.amazonaws.eclipse.lambda.serverless.template.ServerlessDataModelTemplateData;
import com.amazonaws.eclipse.lambda.serverless.template.ServerlessHandlerTemplateData;
import com.amazonaws.util.IOUtils;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* Class that manages adding files (Java files, resource files, or configuration files) to project.
*/
public class FunctionProjectUtil {
public static void createLambdaBlueprintProject(IProject project, LambdaFunctionWizardDataModel dataModel)
throws TemplateException, IOException, CoreException {
LambdaFunctionDataModel lambdaFunctionDataModel = dataModel.getLambdaFunctionDataModel();
emitLambdaHandler(project, lambdaFunctionDataModel);
emitLambdaTestUtils(project, lambdaFunctionDataModel);
emitLambdaTestContext(project, lambdaFunctionDataModel);
emitLambdaHandlerTest(project, lambdaFunctionDataModel);
emitLambdaTestJson(project, lambdaFunctionDataModel);
emitLambdaPom(project, dataModel);
}
/**
* TODO consider to add Lambda function to any project, not only to Lambda project.
*/
public static void createLambdaHandler(IProject project, LambdaFunctionDataModel dataModel)
throws TemplateException, IOException, CoreException {
emitLambdaHandler(project, dataModel);
emitLambdaTestUtils(project, dataModel);
emitLambdaTestContext(project, dataModel);
emitLambdaHandlerTest(project, dataModel);
emitLambdaTestJson(project, dataModel);
}
public static File emitLambdaProjectReadme(IProject project, LambdaFunctionDataModel dataModel)
throws TemplateException, IOException, CoreException {
Template readmeTemplate = CodeTemplateManager.getInstance().getlambdaProjectReadmeTemplate();
LambdaBlueprintTemplateData templateData = dataModel.collectLambdaBlueprintTemplateData();
String readmeContent = CodeTemplateManager.processTemplateWithData(readmeTemplate, templateData);
return addFileToProject(project, "README.html", readmeContent);
}
public static void createServerlessBlueprintProject(IProject project, NewServerlessProjectDataModel dataModel)
throws JsonParseException, JsonMappingException, IOException, CoreException, TemplateException {
emitServerlessModels(project, dataModel);
emitServerlessHandlers(project, dataModel);
emitServerlessSam(project, dataModel);
emitServerlessPom(project, dataModel);
}
private static void emitLambdaHandler(IProject project, LambdaFunctionDataModel dataModel)
throws TemplateException, IOException, CoreException {
Template handlerTemplate = CodeTemplateManager.getInstance().getLambdaHandlerTemplate(
dataModel.getSelectedBlueprint());
LambdaBlueprintTemplateData freeMarkerDataModel = dataModel.collectLambdaBlueprintTemplateData();
String handlerContent = CodeTemplateManager.processTemplateWithData(handlerTemplate, freeMarkerDataModel);
addSourceClassToProject(
project,
JavaPackageName.parse(freeMarkerDataModel.getPackageName()),
freeMarkerDataModel.getHandlerClassName(),
handlerContent);
}
private static void emitLambdaTestUtils(IProject project, LambdaFunctionDataModel dataModel)
throws TemplateException, IOException, CoreException {
Template testUtilTemplate = CodeTemplateManager.getInstance().getTestUtilsTemplate();
LambdaBlueprintTemplateData freeMarkerDataModel = dataModel.collectLambdaBlueprintTemplateData();
String testUtilContent = CodeTemplateManager.processTemplateWithData(testUtilTemplate, freeMarkerDataModel);
addTestClassToProject(
project,
JavaPackageName.parse(freeMarkerDataModel.getPackageName()),
"TestUtils",
testUtilContent);
}
private static void emitLambdaTestContext(IProject project, LambdaFunctionDataModel dataModel)
throws TemplateException, IOException, CoreException {
Template testContextTemplate = CodeTemplateManager.getInstance().getTestContextTemplate();
LambdaBlueprintTemplateData freeMarkerDataModel = dataModel.collectLambdaBlueprintTemplateData();
String testContextContent = CodeTemplateManager.processTemplateWithData(testContextTemplate, freeMarkerDataModel);
addTestClassToProject(
project,
JavaPackageName.parse(freeMarkerDataModel.getPackageName()),
"TestContext",
testContextContent);
}
private static void emitLambdaHandlerTest(IProject project, LambdaFunctionDataModel dataModel)
throws TemplateException, IOException, CoreException {
Template handlerTestTemplate = CodeTemplateManager.getInstance().getLambdaHandlerTestTemplate(
dataModel.getSelectedBlueprint());
LambdaBlueprintTemplateData freeMarkerDataModel = dataModel.collectLambdaBlueprintTemplateData();
String handlerTestContent = CodeTemplateManager.processTemplateWithData(handlerTestTemplate, freeMarkerDataModel);
addTestClassToProject(
project,
JavaPackageName.parse(freeMarkerDataModel.getPackageName()),
freeMarkerDataModel.getHandlerTestClassName(),
handlerTestContent);
}
private static void emitLambdaTestJson(IProject project, LambdaFunctionDataModel dataModel)
throws FileNotFoundException, IOException, CoreException {
File testJsonFile = CodeTemplateManager.getInstance().getLambdaTestJsonFile(
dataModel.getSelectedBlueprint());
if (testJsonFile != null) {
addTestResourceToProject(project, testJsonFile.getName(), testJsonFile);
}
}
private static void emitLambdaPom(IProject project, LambdaFunctionWizardDataModel dataModel)
throws CoreException, TemplateException, IOException {
LambdaFunctionDataModel lambdaFunctionDataModel = dataModel.getLambdaFunctionDataModel();
Template pomTemplate = CodeTemplateManager.getInstance().getLambdaBlueprintPomTemplate(
lambdaFunctionDataModel.getSelectedBlueprint());
PomFileTemplateData pomTemplateData = dataModel.collectPomTemplateData();
String pomContent = CodeTemplateManager.processTemplateWithData(pomTemplate, pomTemplateData);
addFileToProject(project, "pom.xml", pomContent);
}
private static void emitServerlessModels(IProject project, NewServerlessProjectDataModel dataModel)
throws TemplateException, IOException, CoreException {
if (dataModel.getSelectedBlueprint().isNeedLambdaProxyIntegrationModel()) {
ServerlessDataModelTemplateData templateData = dataModel.getServerlessDataModelTemplateData();
addSourceClassToProject(
project,
JavaPackageName.parse(templateData.getPackageName()),
templateData.getServerlessInputClassName(),
CodeTemplateManager.processTemplateWithData(
CodeTemplateManager.getInstance().getServerlessInputClassTemplate(),
templateData));
addSourceClassToProject(
project,
JavaPackageName.parse(templateData.getPackageName()),
templateData.getServerlessOutputClassName(),
CodeTemplateManager.processTemplateWithData(
CodeTemplateManager.getInstance().getServerlessOutputClassTemplate(),
templateData));
}
}
private static void emitServerlessHandlers(IProject project, NewServerlessProjectDataModel dataModel)
throws IOException, CoreException, TemplateException {
ServerlessBlueprint blueprint = dataModel.getSelectedBlueprint();
for (ServerlessHandlerTemplateData templateData : dataModel.getServerlessHandlerTemplateData()) {
if (dataModel.isUseBlueprint()) {
addSourceClassToProject(
project,
JavaPackageName.parse(templateData.getPackageName()),
templateData.getClassName(),
CodeTemplateManager.processTemplateWithData(
CodeTemplateManager.getInstance().getServerlessHandlerClassTemplate(blueprint, templateData.getClassName()),
templateData));
} else {
addSourceClassToProject(
project,
JavaPackageName.parse(templateData.getPackageName()),
templateData.getClassName(),
CodeTemplateManager.processTemplateWithData(
CodeTemplateManager.getInstance().getServerlessHandlerClassTemplate(),
templateData));
}
}
}
private static void emitServerlessSam(IProject project, NewServerlessProjectDataModel dataModel)
throws FileNotFoundException, IOException, CoreException {
File samFile = CodeTemplateManager.getInstance().getServerlessSamFile(dataModel.getSelectedBlueprint());
addFileToProject(project, samFile.getName(), samFile);
}
private static void emitServerlessPom(IProject project, NewServerlessProjectDataModel dataModel)
throws CoreException, TemplateException, IOException {
addFileToProject(project, "pom.xml",
CodeTemplateManager.processTemplateWithData(
CodeTemplateManager.getInstance().getServerlessPomFile(dataModel.getSelectedBlueprint()),
dataModel.getServerlessPomTemplateData()));
}
public static File emitServerlessReadme(IProject project, NewServerlessProjectDataModel dataModel)
throws FileNotFoundException, IOException, CoreException {
return addFileToProject(
project,
"README.html",
CodeTemplateManager.getInstance().getServerlessReadmeFile());
}
public static File getServerlessTemplateFile(IProject project) {
return getProjectDirectory(project, CodeTemplateManager.SERVERLESS_BLUEPRINT_SAM_NAME).toFile();
}
private static void addSourceClassToProject(IProject project,
JavaPackageName packageName, String className, String classContent)
throws CoreException, FileNotFoundException {
IPath srcRoot = getProjectDirectory(project, MavenFactory.getMavenSourceFolder());
String fileName = className + ".java";
addClassToProject(srcRoot, packageName, fileName, classContent);
}
private static void addTestClassToProject(IProject project,
JavaPackageName packageName, String className, String classContent)
throws CoreException, FileNotFoundException {
IPath tstRoot = getProjectDirectory(project, MavenFactory.getMavenTestFolder());
String fileName = className + ".java";
addClassToProject(tstRoot, packageName, fileName, classContent);
}
private static void addTestResourceToProject(IProject project, String fileName, File file)
throws FileNotFoundException, IOException, CoreException {
IPath testResourcePath = getProjectDirectory(project, MavenFactory.getMavenTestResourceFolder());
addFileToProject(testResourcePath, fileName, file);
}
/**
* Add a Java class to project.
*
* @param root - The package root path for the Java class.
* @param packageName - The package name model
* @param fileName - The Java class file name
* @param classContent - The Java class file content.
*/
private static void addClassToProject(IPath root,
JavaPackageName packageName, String fileName, String classContent)
throws CoreException, FileNotFoundException {
IPath targetPath = root;
for (String component : packageName.getComponents()) {
targetPath = targetPath.append(component);
}
addFileToProject(targetPath, fileName, classContent);
}
/*
* Add file to the root of the specified project.
*/
private static File addFileToProject(IProject project, String fileName, File file)
throws FileNotFoundException, IOException, CoreException {
IPath targetPath = getProjectDirectory(project, null);
String fileContent = IOUtils.toString(new FileInputStream(file));
return addFileToProject(targetPath, fileName, fileContent);
}
/*
* Add a file to the root of the specified project.
*/
private static File addFileToProject(IProject project, String fileName, String fileContent)
throws FileNotFoundException, CoreException {
IPath targetPath = getProjectDirectory(project, null);
return addFileToProject(targetPath, fileName, fileContent);
}
private static File addFileToProject(IPath targetPath, String fileName, File file)
throws FileNotFoundException, IOException, CoreException {
String fileContent = IOUtils.toString(new FileInputStream(file));
return addFileToProject(targetPath, fileName, fileContent);
}
/**
* Add a file with the specified content to the target path.
*
* @param targetPath - The target location for the file to be added in.
* @param fileName - The file name
* @param fileContent - The file content
* @return The file in the target location.
*/
private static File addFileToProject(IPath targetPath, String fileName, String fileContent)
throws CoreException, FileNotFoundException {
IFileStore targetFileStore = EFS.getLocalFileSystem().fromLocalFile(
targetPath.append(fileName).toFile());
File targetFile = targetFileStore.toLocalFile(EFS.NONE, null);
targetFile.getParentFile().mkdirs();
PrintStream ps = new PrintStream(new FileOutputStream(targetFile));
ps.print(fileContent);
ps.close();
return targetFile;
}
/*
* Return the absolute path of the specified location relative to the project.
*/
public static IPath getProjectDirectory(IProject project, String path) {
IPath workspaceRoot = project.getWorkspace().getRoot().getRawLocation();
IPath projectRoot = workspaceRoot.append(project.getFullPath());
if (path == null) {
return projectRoot;
} else {
return projectRoot.append(path);
}
}
public static void refreshProject(IProject project) {
// Finally, refresh the project so that the new files show up
try {
project.refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
LambdaPlugin.getDefault().logWarning(
"Failed to refresh project " + project.getName(), e);
}
}
}