11# pylint: disable=useless-super-delegation,too-many-locals
22# pylint doesn't recognize abstract methods
33import logging
4+ import os
45import shutil
56import xml .etree .ElementTree as ET # nosec
67from collections import namedtuple
@@ -44,6 +45,7 @@ def wrapper(*args, **kwargs):
4445DEFAULT_SETTINGS = {PROTOCOL_VERSION_SETTING : DEFAULT_PROTOCOL_VERSION }
4546
4647MINIMUM_JAVA_DEPENDENCY_VERSION = "2.0.0"
48+ MINIMUM_JAVA_DEPENDENCY_VERSION_EXECUTABLE_HANDLER_WRAPPER = "2.0.3"
4749
4850
4951class JavaArchiveNotFoundError (SysExitRecommendedError ):
@@ -67,6 +69,7 @@ class JavaLanguagePlugin(LanguagePlugin):
6769 RUNTIME = "java8"
6870 ENTRY_POINT = "{}.HandlerWrapper::handleRequest"
6971 TEST_ENTRY_POINT = "{}.HandlerWrapper::testEntrypoint"
72+ EXECUTABLE_ENTRY_POINT = "{}.HandlerWrapperExecutable"
7073 CODE_URI = "./target/{}-1.0-SNAPSHOT.jar"
7174
7275 def __init__ (self ):
@@ -166,19 +169,22 @@ def init(self, project):
166169 src = (project .root / "src" / "main" / "java" ).joinpath (* self .namespace )
167170 LOG .debug ("Making source folder structure: %s" , src )
168171 src .mkdir (parents = True , exist_ok = True )
172+ resources = project .root / "src" / "resources"
173+ LOG .debug ("Making resources folder structure: %s" , resources )
174+ resources .mkdir (parents = True , exist_ok = True )
169175 tst = (project .root / "src" / "test" / "java" ).joinpath (* self .namespace )
170176 LOG .debug ("Making test folder structure: %s" , tst )
171177 tst .mkdir (parents = True , exist_ok = True )
172178
173179 # initialize shared files
174- self .init_shared (project , src , tst )
180+ self .init_shared (project , src , tst , resources )
175181
176182 # write specialized generated files
177183 if self ._is_aws_guided (project ):
178184 self .init_guided_aws (project , src , tst )
179185
180186 @logdebug
181- def init_shared (self , project , src , tst ):
187+ def init_shared (self , project , src , tst , resources ):
182188 """Writing project configuration"""
183189 # .gitignore
184190 path = project .root / ".gitignore"
@@ -257,6 +263,12 @@ def init_shared(self, project, src, tst):
257263 )
258264 project .safewrite (path , contents )
259265
266+ # log4j2
267+ path = resources / "log4j2.xml"
268+ LOG .debug ("Writing log4j2: %s" , path )
269+ contents = resource_stream (__name__ , "data/log4j2.xml" ).read ()
270+ project .safewrite (path , contents )
271+
260272 self .init_handlers (project , src , tst )
261273
262274 @logdebug
@@ -304,6 +316,9 @@ def _init_settings(self, project):
304316 project .runtime = self .RUNTIME
305317 project .entrypoint = self .ENTRY_POINT .format (self .package_name )
306318 project .test_entrypoint = self .TEST_ENTRY_POINT .format (self .package_name )
319+ project .executable_entrypoint = self .EXECUTABLE_ENTRY_POINT .format (
320+ self .package_name
321+ )
307322 project .settings .update (DEFAULT_SETTINGS )
308323
309324 @staticmethod
@@ -345,9 +360,13 @@ def generate(self, project):
345360 package_name = self .package_name ,
346361 operations = project .schema .get ("handlers" , {}).keys (),
347362 pojo_name = "ResourceModel" ,
363+ wrapper_parent = "LambdaWrapper" ,
348364 )
349365 project .overwrite (path , contents )
350366
367+ # write generated handler integration with ExecutableWrapper
368+ self ._write_executable_wrapper_class (src , project )
369+
351370 path = src / "BaseConfiguration.java"
352371 LOG .debug ("Writing base configuration: %s" , path )
353372 template = self .env .get_template ("generate/BaseConfiguration.java" )
@@ -403,6 +422,39 @@ def generate(self, project):
403422
404423 LOG .debug ("Generate complete" )
405424
425+ def _write_executable_wrapper_class (self , src , project ):
426+ try :
427+ java_plugin_dependency_version = self ._get_java_plugin_dependency_version (
428+ project
429+ )
430+ if (
431+ java_plugin_dependency_version
432+ >= MINIMUM_JAVA_DEPENDENCY_VERSION_EXECUTABLE_HANDLER_WRAPPER
433+ ):
434+ path = src / "HandlerWrapperExecutable.java"
435+ LOG .debug ("Writing handler wrapper: %s" , path )
436+ template = self .env .get_template ("generate/HandlerWrapper.java" )
437+ contents = template .render (
438+ package_name = self .package_name ,
439+ operations = project .schema .get ("handlers" , {}).keys (),
440+ pojo_name = "ResourceModel" ,
441+ wrapper_parent = "ExecutableWrapper" ,
442+ )
443+ project .overwrite (path , contents )
444+ else :
445+ LOG .info (
446+ "Please update your java plugin dependency to version "
447+ "%s or above in order to use "
448+ "the Executable Handler Wrapper feature." ,
449+ MINIMUM_JAVA_DEPENDENCY_VERSION_EXECUTABLE_HANDLER_WRAPPER ,
450+ )
451+ except JavaPluginNotFoundError :
452+ LOG .info (
453+ "Please make sure to have 'aws-cloudformation-rpdk-java-plugin' "
454+ "to version %s or above." ,
455+ MINIMUM_JAVA_DEPENDENCY_VERSION ,
456+ )
457+
406458 def _update_settings (self , project ):
407459 try :
408460 java_plugin_dependency_version = self ._get_java_plugin_dependency_version (
@@ -427,6 +479,15 @@ def _update_settings(self, project):
427479 project .settings [PROTOCOL_VERSION_SETTING ] = DEFAULT_PROTOCOL_VERSION
428480 project .write_settings ()
429481
482+ if (
483+ hasattr (project , "executable_entrypoint" )
484+ and not project .executable_entrypoint
485+ ):
486+ project .executable_entrypoint = self .EXECUTABLE_ENTRY_POINT .format (
487+ self .package_name
488+ )
489+ project .write_settings ()
490+
430491 @staticmethod
431492 def _find_jar (project ):
432493 jar_glob = list (
@@ -490,3 +551,23 @@ def write_with_relative_path(path):
490551 for path in (project .root / "target" / "generated-sources" ).rglob ("*" ):
491552 if path .is_file ():
492553 write_with_relative_path (path )
554+
555+ @logdebug
556+ def generate_image_build_config (self , project ):
557+ """Generating image build config"""
558+
559+ jar_path = self ._find_jar (project )
560+
561+ dockerfile_path = (
562+ os .path .dirname (os .path .realpath (__file__ ))
563+ + "/data/build-image-src/Dockerfile-"
564+ + project .runtime
565+ )
566+
567+ project_path = project .root
568+
569+ return {
570+ "executable_name" : str (jar_path .relative_to (project .root )),
571+ "dockerfile_path" : dockerfile_path ,
572+ "project_path" : str (project_path ),
573+ }
0 commit comments