11package io .jenkins .plugins .casc .impl .configurators ;
22
3+ import edu .umd .cs .findbugs .annotations .CheckForNull ;
34import edu .umd .cs .findbugs .annotations .NonNull ;
45import hudson .model .Descriptor ;
56import hudson .util .Secret ;
1112import io .jenkins .plugins .casc .impl .attributes .DescribableAttribute ;
1213import io .jenkins .plugins .casc .model .CNode ;
1314import io .jenkins .plugins .casc .model .Mapping ;
15+ import java .lang .annotation .Annotation ;
16+ import java .lang .reflect .AnnotatedElement ;
1417import java .lang .reflect .Constructor ;
1518import java .lang .reflect .InvocationTargetException ;
1619import java .lang .reflect .Method ;
2528import java .util .Set ;
2629import java .util .logging .Level ;
2730import java .util .logging .Logger ;
28- import javax .annotation .CheckForNull ;
29- import javax .annotation .Nonnull ;
30- import javax .annotation .ParametersAreNonnullByDefault ;
31- import javax .annotation .PostConstruct ;
3231import jenkins .model .Jenkins ;
3332import org .kohsuke .stapler .ClassDescriptor ;
3433import org .kohsuke .stapler .DataBoundConstructor ;
3534import org .kohsuke .stapler .Stapler ;
3635
3736/**
3837 * A generic {@link Configurator} to configure components with a {@link org.kohsuke.stapler.DataBoundConstructor}.
39- * Intended to replicate Stapler's request-to-instance lifecycle, including {@link PostConstruct} init methods.
38+ * Intended to replicate Stapler's request-to-instance lifecycle, including PostConstruct init methods.
4039 * Will rely on <a href="https://github.com/jenkinsci/jep/tree/master/jep/205">JEP-205</a> once implemented
4140 *
4241 * @author <a href="mailto:[email protected] ">Nicolas De Loof</a> @@ -45,6 +44,25 @@ public class DataBoundConfigurator<T> extends BaseConfigurator<T> {
4544
4645 private static final Logger LOGGER = Logger .getLogger (DataBoundConfigurator .class .getName ());
4746
47+ // Avoid compile-time dependencies
48+ private static final Set <String > NONNULL_ANNOTATIONS =
49+ Set .of ("jakarta.annotation.Nonnull" , "javax.annotation.Nonnull" );
50+ private static final Set <String > NULLABLE_ANNOTATIONS =
51+ Set .of ("jakarta.annotation.Nullable" , "javax.annotation.CheckForNull" );
52+ private static final Set <String > PARAMETERS_ARE_NONNULL_ANNOTATIONS =
53+ Set .of ("javax.annotation.ParametersAreNonnullByDefault" );
54+ private static final Set <String > POST_CONSTRUCT_ANNOTATIONS =
55+ Set .of ("jakarta.annotation.PostConstruct" , "javax.annotation.PostConstruct" );
56+
57+ private static boolean hasAnnotation (AnnotatedElement element , Set <String > annotationNames ) {
58+ for (Annotation ann : element .getAnnotations ()) {
59+ if (annotationNames .contains (ann .annotationType ().getName ())) {
60+ return true ;
61+ }
62+ }
63+ return false ;
64+ }
65+
4866 private final Class <T > target ;
4967
5068 public DataBoundConfigurator (Class <T > clazz ) {
@@ -81,7 +99,7 @@ public T configure(CNode c, ConfigurationContext context) throws ConfiguratorExc
8199 T object = super .configure (c , context );
82100
83101 for (Method method : target .getMethods ()) {
84- if (method .getParameterCount () == 0 && method . getAnnotation ( PostConstruct . class ) != null ) {
102+ if (method .getParameterCount () == 0 && hasAnnotation ( method , POST_CONSTRUCT_ANNOTATIONS ) ) {
85103 try {
86104 method .invoke (object , null );
87105 } catch (IllegalAccessException | InvocationTargetException e ) {
@@ -115,11 +133,11 @@ private T tryConstructor(Constructor<T> constructor, Mapping config, Configurati
115133
116134 Class <?> clazz = constructor .getDeclaringClass ();
117135 if (value == null
118- && (parameters [i ]. isAnnotationPresent ( Nonnull . class )
119- || constructor . isAnnotationPresent ( ParametersAreNonnullByDefault . class )
120- || clazz . isAnnotationPresent ( ParametersAreNonnullByDefault . class )
121- || clazz .getPackage (). isAnnotationPresent ( ParametersAreNonnullByDefault . class )
122- && !parameters [i ]. isAnnotationPresent ( CheckForNull . class ))) {
136+ && (hasAnnotation ( parameters [i ], NONNULL_ANNOTATIONS )
137+ || hasAnnotation ( constructor , PARAMETERS_ARE_NONNULL_ANNOTATIONS )
138+ || hasAnnotation ( clazz , PARAMETERS_ARE_NONNULL_ANNOTATIONS )
139+ || hasAnnotation ( clazz .getPackage (), PARAMETERS_ARE_NONNULL_ANNOTATIONS )
140+ && !hasAnnotation ( parameters [i ], NULLABLE_ANNOTATIONS ))) {
123141
124142 if (Set .class .isAssignableFrom (t )) {
125143 LOGGER .log (
0 commit comments