/* * 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.template; import java.io.File; import java.io.IOException; import java.io.StringWriter; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import org.eclipse.core.runtime.FileLocator; import org.osgi.framework.Bundle; import com.amazonaws.eclipse.lambda.LambdaPlugin; import com.amazonaws.eclipse.lambda.blueprint.LambdaBlueprint; import com.amazonaws.eclipse.lambda.blueprint.ServerlessBlueprint; import freemarker.template.Configuration; import freemarker.template.Template; import freemarker.template.TemplateException; import freemarker.template.TemplateExceptionHandler; /** * Class that manages Freemarker code template and Json configuration files. * Use a get*Template method to get a certain Freemarker template. * Use a get*File method to get a certain File. */ public class CodeTemplateManager { private static final String CODE_TEMPLATE_BASE_DIR = "code-template"; private static final String LAMBDA_BLUEPRINTS_BASE_DIR = "lambda"; private static final String SERVERLESS_BLUEPRINTS_BASE_DIR = "serverless"; private static final String LAMBDA_BLUEPRINTS_CONFIG_PATH = String.format("%s/%s", LAMBDA_BLUEPRINTS_BASE_DIR, "blueprints.json"); private static final String SERVERLESS_BLUEPRINTS_CONFIG_PATH = String.format("%s/%s", SERVERLESS_BLUEPRINTS_BASE_DIR, "blueprints.json"); private static final String LAMBDA_BLUEPRINT_HANDLER_NAME = "handler.java.ftl"; private static final String LAMBDA_BLUEPRINT_HANDLER_TEST_NAME = "handler-test.java.ftl"; private static final String LAMBDA_BLUEPRINT_POM_NAME = "pom.xml.ftl"; private static final String LAMBDA_README_FILE_PATH = String.format("%s/%s", LAMBDA_BLUEPRINTS_BASE_DIR, "README.ftl"); private static final String SERVERLESS_README_FILE_PATH = String.format("%s/%s", SERVERLESS_BLUEPRINTS_BASE_DIR, "README.html"); private static final String SERVERLESS_INPUT_MODEL_PATH = String.format("%s/%s", SERVERLESS_BLUEPRINTS_BASE_DIR, "serverless-input.ftl"); private static final String SERVERLESS_OUTPUT_MODEL_PATH = String.format("%s/%s", SERVERLESS_BLUEPRINTS_BASE_DIR, "serverless-output.ftl"); private static final String SERVERLESS_HANDLER_CLASS_PATH = String.format("%s/%s", SERVERLESS_BLUEPRINTS_BASE_DIR, "serverless-handler.ftl"); public static final String SERVERLESS_BLUEPRINT_SAM_NAME = "serverless.template"; private static final String SERVERLESS_BLUEPRINT_POM_NAME = "pom.xml.ftl"; private static final String TEST_RESOURCES_BASE_DIR = "test-resource"; private static final String TEST_CLASSES_BASE_DIR = "test-class"; private static final String TEST_CONTEXT_FILE_PATH = String.format("%s/%s", TEST_CLASSES_BASE_DIR, "test-context.ftl"); private static final String TEST_UTILS_FILE_PATH = String.format("%s/%s", TEST_CLASSES_BASE_DIR, "test-utils.ftl"); private final Configuration freemarkerCfg; private static final CodeTemplateManager INSTANCE = new CodeTemplateManager(); private CodeTemplateManager() { freemarkerCfg = setupFreemarker(); } public static CodeTemplateManager getInstance() { return INSTANCE; } /** * Helper method to return the populated content rendered by Freemarker to the given * template and template data. */ public static String processTemplateWithData(Template template, Object templateData) throws TemplateException, IOException { try (StringWriter stringWriter = new StringWriter()) { template.process(templateData, stringWriter); stringWriter.flush(); return stringWriter.toString(); } } /** * Template data model {@link #com.amazonaws.eclipse.lambda.project.template.data.LambdaBlueprintTemplateData} */ public Template getLambdaHandlerTemplate(LambdaBlueprint blueprint) { return blueprint == null ? null : getTemplate(String.format("%s/%s/%s", LAMBDA_BLUEPRINTS_BASE_DIR, blueprint.getBaseDir(), LAMBDA_BLUEPRINT_HANDLER_NAME)); } /** * Template data model {@link #com.amazonaws.eclipse.lambda.project.template.data.LambdaBlueprintTemplateData} */ public Template getLambdaHandlerTestTemplate(LambdaBlueprint blueprint) { return blueprint == null ? null : getTemplate(String.format("%s/%s/%s", LAMBDA_BLUEPRINTS_BASE_DIR, blueprint.getBaseDir(), LAMBDA_BLUEPRINT_HANDLER_TEST_NAME)); } /** * Template data model {@link #com.amazonaws.eclipse.lambda.project.template.data.PomFileTemplateData} */ public Template getLambdaBlueprintPomTemplate(LambdaBlueprint blueprint) { return blueprint == null ? null : getTemplate(String.format("%s/%s/%s", LAMBDA_BLUEPRINTS_BASE_DIR, blueprint.getBaseDir(), LAMBDA_BLUEPRINT_POM_NAME)); } // Test JSON file could be null for some blueprints public File getLambdaTestJsonFile(LambdaBlueprint blueprint) { return blueprint == null || blueprint.getTestJsonFile() == null ? null : getFile(String.format("%s/%s", TEST_RESOURCES_BASE_DIR, blueprint.getTestJsonFile())); } /** * Template data model {@link #com.amazonaws.eclipse.lambda.project.template.data.LambdaBlueprintTemplateData} */ public Template getTestContextTemplate() { return getTemplate(TEST_CONTEXT_FILE_PATH); } /** * Template data model {@link #com.amazonaws.eclipse.lambda.project.template.data.LambdaBlueprintTemplateData} */ public Template getTestUtilsTemplate() { return getTemplate(TEST_UTILS_FILE_PATH); } /** * Template data model {@link #com.amazonaws.eclipse.lambda.project.template.data.LambdaBlueprintTemplateData} */ public Template getlambdaProjectReadmeTemplate() { return getTemplate(LAMBDA_README_FILE_PATH); } /** * Template data model {@link #com.amazonaws.eclipse.lambda.serverless.template.ServerlessDataModelTemplateData} */ public Template getServerlessInputClassTemplate() { return getTemplate(SERVERLESS_INPUT_MODEL_PATH); } /** * Template data model {@link #com.amazonaws.eclipse.lambda.serverless.template.ServerlessDataModelTemplateData} */ public Template getServerlessOutputClassTemplate() { return getTemplate(SERVERLESS_OUTPUT_MODEL_PATH); } /** * Template data model {@link #com.amazonaws.eclipse.lambda.serverless.template.ServerlessHandlerTemplateData} */ public Template getServerlessHandlerClassTemplate() { return getTemplate(SERVERLESS_HANDLER_CLASS_PATH); } /** * Template data model {@link #com.amazonaws.eclipse.lambda.serverless.template.ServerlessHandlerTemplateData} */ public Template getServerlessHandlerClassTemplate(ServerlessBlueprint blueprint, String handlerName) { String templatePath = blueprint.getHandlerTemplatePaths().get(handlerName); return getTemplate(String.format("%s/%s/%s", SERVERLESS_BLUEPRINTS_BASE_DIR, blueprint.getBaseDir(), templatePath)); } public File getServerlessSamFile(ServerlessBlueprint blueprint) { return getFile(String.format("%s/%s/%s", SERVERLESS_BLUEPRINTS_BASE_DIR, blueprint.getBaseDir(), SERVERLESS_BLUEPRINT_SAM_NAME)); } /** * Template data model {@link #com.amazonaws.eclipse.lambda.project.template.data.PomFileTemplateData} */ public Template getServerlessPomFile(ServerlessBlueprint blueprint) { return getTemplate(String.format("%s/%s/%s", SERVERLESS_BLUEPRINTS_BASE_DIR, blueprint.getBaseDir(), SERVERLESS_BLUEPRINT_POM_NAME)); } public File getServerlessBlueprintsConfigFile() { return getFile(SERVERLESS_BLUEPRINTS_CONFIG_PATH); } public File getLambdaBlueprintsConfigFile() { return getFile(LAMBDA_BLUEPRINTS_CONFIG_PATH); } public File getServerlessReadmeFile() { return getFile(SERVERLESS_README_FILE_PATH); } private Configuration setupFreemarker() { Configuration cfg = new Configuration(Configuration.VERSION_2_3_21); try { cfg.setDirectoryForTemplateLoading(getCodeTemplateBasedir()); } catch (IOException e) { throw new RuntimeException( "Failed to setup freemarker template directory.", e); } cfg.setDefaultEncoding("UTF-8"); cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER); return cfg; } private File getCodeTemplateBasedir() { Bundle bundle = LambdaPlugin.getDefault().getBundle(); File file = null; try { URL bundleBaseUrl = FileLocator.toFileURL(bundle.getEntry(CODE_TEMPLATE_BASE_DIR)); URI bundleBaseUri = new URI(bundleBaseUrl.getProtocol(), bundleBaseUrl.getPath(), null); file = new File(bundleBaseUri); } catch (IOException e) { throw new RuntimeException("Failed to find plugin bundle root.", e); } catch (URISyntaxException e) { throw new RuntimeException("Failed to find plugin bundle root.", e); } return file; } private File getFile(String path) { return new File(getCodeTemplateBasedir(), path); } private Template getTemplate(String templatePath) { try { return freemarkerCfg.getTemplate(templatePath); } catch (IOException e) { throw new RuntimeException( "Failed to load Freemarker template from " + templatePath, e); } } }