22
33import com .google .common .base .CaseFormat ;
44import com .google .common .collect .ImmutableSet ;
5+ import com .hubspot .jinjava .JinjavaConfig ;
56import com .hubspot .jinjava .interpret .DeferredValueException ;
7+ import com .hubspot .jinjava .interpret .JinjavaInterpreter ;
68import com .hubspot .jinjava .util .EagerReconstructionUtils ;
9+ import java .beans .IntrospectionException ;
10+ import java .beans .Introspector ;
11+ import java .beans .MethodDescriptor ;
712import java .lang .invoke .MethodType ;
813import java .lang .reflect .Method ;
14+ import java .util .HashMap ;
915import java .util .LinkedList ;
1016import java .util .List ;
17+ import java .util .Map ;
18+ import java .util .Objects ;
1119import java .util .Set ;
20+ import java .util .concurrent .ConcurrentHashMap ;
1221import javax .el .ELContext ;
22+ import javax .el .ELException ;
1323import javax .el .MethodNotFoundException ;
1424
1525/**
@@ -39,35 +49,18 @@ public class JinjavaBeanELResolver extends BeanELResolver {
3949 .add ("merge" )
4050 .build ();
4151
42- private final AllowlistMethodValidator allowlistMethodValidator ;
43- private final AllowlistReturnTypeValidator allowlistReturnTypeValidator ;
52+ private final ConcurrentHashMap <Class <?>, BeanMethods > beanMethodsCache ;
4453
4554 public JinjavaBeanELResolver () {
46- this (
47- true ,
48- AllowlistMethodValidator .create (MethodValidatorConfig .of ()),
49- AllowlistReturnTypeValidator .create (ReturnTypeValidatorConfig .of ())
50- );
51- }
52-
53- public JinjavaBeanELResolver (
54- AllowlistMethodValidator allowlistMethodValidator ,
55- AllowlistReturnTypeValidator allowlistReturnTypeValidator
56- ) {
57- this (true , allowlistMethodValidator , allowlistReturnTypeValidator );
55+ this (true );
5856 }
5957
6058 /**
6159 * Creates a new read/write {@link JinjavaBeanELResolver}.
6260 */
63- public JinjavaBeanELResolver (
64- boolean readOnly ,
65- AllowlistMethodValidator allowlistMethodValidator ,
66- AllowlistReturnTypeValidator allowlistReturnTypeValidator
67- ) {
61+ public JinjavaBeanELResolver (boolean readOnly ) {
6862 super (readOnly );
69- this .allowlistMethodValidator = allowlistMethodValidator ;
70- this .allowlistReturnTypeValidator = allowlistReturnTypeValidator ;
63+ this .beanMethodsCache = new ConcurrentHashMap <Class <?>, BeanMethods >();
7164 }
7265
7366 @ Override
@@ -77,9 +70,9 @@ public Class<?> getType(ELContext context, Object base, Object property) {
7770
7871 @ Override
7972 public Object getValue (ELContext context , Object base , Object property ) {
80- return allowlistReturnTypeValidator . validateReturnType (
81- super . getValue ( context , base , transformPropertyName ( property ) )
82- );
73+ return getJinjavaConfig ()
74+ . getReturnTypeValidator ( )
75+ . validateReturnType ( super . getValue ( context , base , transformPropertyName ( property )) );
8376 }
8477
8578 @ Override
@@ -118,9 +111,9 @@ public Object invoke(
118111 );
119112 }
120113
121- return allowlistReturnTypeValidator . validateReturnType (
122- super . invoke ( context , base , method , paramTypes , params )
123- );
114+ return getJinjavaConfig ()
115+ . getReturnTypeValidator ( )
116+ . validateReturnType ( super . invoke ( context , base , method , paramTypes , params ) );
124117 }
125118
126119 @ Override
@@ -167,17 +160,30 @@ protected Method findMethod(
167160 )
168161 );
169162 }
170- return allowlistMethodValidator .validateMethod (method );
163+ return getJinjavaConfig (). getMethodValidator () .validateMethod (method );
171164 }
172165
173166 @ Override
174167 protected Method getWriteMethod (Object base , Object property ) {
175- return allowlistMethodValidator .validateMethod (super .getWriteMethod (base , property ));
168+ return getJinjavaConfig ()
169+ .getMethodValidator ()
170+ .validateMethod (super .getWriteMethod (base , property ));
176171 }
177172
178173 @ Override
179174 protected Method getReadMethod (Object base , Object property ) {
180- return allowlistMethodValidator .validateMethod (super .getReadMethod (base , property ));
175+ return getJinjavaConfig ()
176+ .getMethodValidator ()
177+ .validateMethod (super .getReadMethod (base , property ));
178+ }
179+
180+ private static JinjavaConfig getJinjavaConfig () {
181+ return Objects
182+ .requireNonNull (
183+ JinjavaInterpreter .getCurrent (),
184+ "JinjavaInterpreter.closeablePushCurrent must be used if using a JinjavaInterpreter directly"
185+ )
186+ .getConfig ();
181187 }
182188
183189 private static boolean checkAssignableParameterTypes (Object [] params , Method method ) {
@@ -221,4 +227,52 @@ private String transformPropertyName(Object property) {
221227 }
222228 return CaseFormat .LOWER_UNDERSCORE .to (CaseFormat .LOWER_CAMEL , propertyStr );
223229 }
230+
231+ protected final class BeanMethods {
232+
233+ private final Map <String , List <BeanMethod >> map = new HashMap <>();
234+
235+ public BeanMethods (Class <?> baseClass ) {
236+ MethodDescriptor [] descriptors ;
237+ try {
238+ descriptors = Introspector .getBeanInfo (baseClass ).getMethodDescriptors ();
239+ } catch (IntrospectionException e ) {
240+ throw new ELException (e );
241+ }
242+ for (MethodDescriptor descriptor : descriptors ) {
243+ map .compute (
244+ descriptor .getName (),
245+ (k , v ) -> {
246+ if (v == null ) {
247+ v = new LinkedList <>();
248+ }
249+ v .add (new BeanMethod (descriptor ));
250+ return v ;
251+ }
252+ );
253+ }
254+ }
255+
256+ public List <BeanMethod > getBeanMethods (String methodName ) {
257+ return map .get (methodName );
258+ }
259+ }
260+
261+ protected final class BeanMethod {
262+
263+ private final MethodDescriptor descriptor ;
264+
265+ private Method method ;
266+
267+ public BeanMethod (MethodDescriptor descriptor ) {
268+ this .descriptor = descriptor ;
269+ }
270+
271+ public Method getMethod () {
272+ if (method == null ) {
273+ method = findAccessibleMethod (descriptor .getMethod ());
274+ }
275+ return method ;
276+ }
277+ }
224278}
0 commit comments