Skip to content

Commit dcb5830

Browse files
committed
SLING-11917 Evaluate constructor parameter names via reflection
This is available if compiled accordingly (with javac flag -parameters, https://docs.oracle.com/en/java/javase/17/docs/specs/man/javac.html#option-parameters)
1 parent 0b4f64e commit dcb5830

4 files changed

Lines changed: 29 additions & 25 deletions

File tree

src/main/java/org/apache/sling/models/impl/ModelAdapterFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ private RuntimeException setMethod(InjectableMethod injectableMethod, Map<Method
10171017

10181018
private RuntimeException setConstructorParameter(ConstructorParameter constructorParameter, List<Object> parameterValues, Object value) {
10191019
if (constructorParameter.getParameterType() instanceof Class<?>) {
1020-
Result<Object> result = adaptIfNecessary(value, (Class<?>) constructorParameter.getParameterType(), constructorParameter.getGenericType());
1020+
Result<Object> result = adaptIfNecessary(value, (Class<?>) constructorParameter.getParameterType(), constructorParameter.getType());
10211021
if (result.wasSuccessful() ) {
10221022
parameterValues.set(constructorParameter.getParameterIndex(), result.getValue());
10231023
return null;

src/main/java/org/apache/sling/models/impl/model/ConstructorParameter.java

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@
2020

2121
import java.lang.annotation.Annotation;
2222
import java.lang.reflect.AnnotatedElement;
23+
import java.lang.reflect.Parameter;
2324
import java.lang.reflect.Type;
2425
import java.util.Arrays;
2526

2627
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
28+
import org.apache.sling.models.impl.ReflectionUtil;
2729
import org.apache.sling.models.spi.injectorspecific.StaticInjectAnnotationProcessorFactory;
2830

2931
/**
@@ -34,23 +36,30 @@
3436
public class ConstructorParameter extends AbstractInjectableElement {
3537

3638
private final Type parameterType;
37-
private final Type genericType;
3839
private final boolean isPrimitive;
3940
private final int parameterIndex;
4041

42+
/**
43+
* Try to extract parameter names according to https://openjdk.org/jeps/118 (requires javac flag -parameters)
44+
* @param parameter
45+
* @param parameterIndex
46+
* @param processorFactories
47+
* @param defaultInjectionStrategy
48+
*/
49+
public static ConstructorParameter of(Parameter parameter, int parameterIndex, StaticInjectAnnotationProcessorFactory[] processorFactories, DefaultInjectionStrategy defaultInjectionStrategy) {
50+
Type genericType = ReflectionUtil.mapPrimitiveClasses(parameter.getParameterizedType());
51+
boolean isPrimitive = (parameter.getParameterizedType() != genericType);
52+
return new ConstructorParameter(parameter.getAnnotations(), parameter.getType(), genericType, isPrimitive, parameterIndex, parameter.getName(), processorFactories, defaultInjectionStrategy);
53+
}
54+
4155
public ConstructorParameter(Annotation[] annotations, Type parameterType, Type genericType, boolean isPrimitive,
42-
int parameterIndex, StaticInjectAnnotationProcessorFactory[] processorFactories, DefaultInjectionStrategy defaultInjectionStrategy) {
43-
super(new FakeAnnotatedElement(annotations, parameterIndex), genericType, null, processorFactories, defaultInjectionStrategy);
56+
int parameterIndex, String name, StaticInjectAnnotationProcessorFactory[] processorFactories, DefaultInjectionStrategy defaultInjectionStrategy) {
57+
super(new FakeAnnotatedElement(annotations, parameterIndex), genericType, name, processorFactories, defaultInjectionStrategy);
4458
this.parameterType = parameterType;
45-
this.genericType = genericType;
4659
this.isPrimitive = isPrimitive;
4760
this.parameterIndex = parameterIndex;
4861
}
4962

50-
public Type getGenericType() {
51-
return this.genericType;
52-
}
53-
5463
public Type getParameterType() {
5564
return this.parameterType;
5665
}
@@ -65,7 +74,7 @@ public int getParameterIndex() {
6574

6675
@Override
6776
public String toString() {
68-
return "Parameter" + this.parameterIndex + "[" + this.genericType.toString() + "]";
77+
return "Parameter" + this.parameterIndex + "[" + getType().toString() + "]";
6978
}
7079

7180
public static class FakeAnnotatedElement implements AnnotatedElement {

src/main/java/org/apache/sling/models/impl/model/ModelClassConstructor.java

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,12 @@
2020

2121
import java.lang.reflect.Constructor;
2222
import java.lang.reflect.InvocationTargetException;
23-
import java.lang.reflect.Type;
23+
import java.lang.reflect.Parameter;
24+
import java.util.stream.IntStream;
2425

2526
import javax.inject.Inject;
2627

2728
import org.apache.sling.models.annotations.DefaultInjectionStrategy;
28-
import org.apache.sling.models.impl.ReflectionUtil;
2929
import org.apache.sling.models.spi.injectorspecific.StaticInjectAnnotationProcessorFactory;
3030

3131
public class ModelClassConstructor<M> {
@@ -38,20 +38,15 @@ public ModelClassConstructor(Constructor<M> constructor, StaticInjectAnnotationP
3838
this.constructor = constructor;
3939
this.hasInjectAnnotation = constructor.isAnnotationPresent(Inject.class);
4040

41-
Type[] parameterTypes = constructor.getGenericParameterTypes();
42-
this.constructorParametersArray = new ConstructorParameter[parameterTypes.length];
43-
44-
for (int i = 0; i < parameterTypes.length; i++) {
45-
Type genericType = ReflectionUtil.mapPrimitiveClasses(parameterTypes[i]);
46-
boolean isPrimitive = (parameterTypes[i] != genericType);
47-
this.constructorParametersArray[i] = new ConstructorParameter(
48-
constructor.getParameterAnnotations()[i], constructor.getParameterTypes()[i], genericType, isPrimitive, i,
49-
processorFactories, defaultInjectionStrategy);
50-
}
41+
Parameter[] parameters = constructor.getParameters();
42+
this.constructorParametersArray = IntStream
43+
.range(0, parameters.length)
44+
.mapToObj(i -> ConstructorParameter.of(parameters[i], i, processorFactories, defaultInjectionStrategy))
45+
.toArray(ConstructorParameter[]::new);
5146
}
5247

5348
/**
54-
* Proxies the call to {@link Constructor#newInstance(Object...)}, checking (and
49+
* Proxies the call to {@link Constructor#newInsztance(Object...)}, checking (and
5550
* setting) accessibility first.
5651
*
5752
* @param parameters

src/test/java/org/apache/sling/models/impl/injectors/SelfInjectorTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ public class SelfInjectorTest {
6565
@Before
6666
public void setup() {
6767
lenient().when(modelAnnotation.defaultInjectionStrategy()).thenReturn(DefaultInjectionStrategy.REQUIRED);
68-
firstConstructorParameter = new ConstructorParameter(new Annotation[0], Object.class, Object.class, true, 0,
68+
firstConstructorParameter = new ConstructorParameter(new Annotation[0], Object.class, Object.class, true, 0, null,
6969
new StaticInjectAnnotationProcessorFactory[0], null);
70-
secondConstructorParameter = new ConstructorParameter(new Annotation[0], Object.class, Object.class, true, 1,
70+
secondConstructorParameter = new ConstructorParameter(new Annotation[0], Object.class, Object.class, true, 1, null,
7171
new StaticInjectAnnotationProcessorFactory[0], null);
7272
}
7373

0 commit comments

Comments
 (0)