6161import java .util .logging .Logger ;
6262
6363import javax .ws .rs .core .Application ;
64+ import javax .ws .rs .core .Context ;
6465
6566import javax .annotation .ManagedBean ;
6667import javax .annotation .Priority ;
6768import javax .enterprise .context .ApplicationScoped ;
6869import javax .enterprise .context .Dependent ;
6970import javax .enterprise .context .spi .CreationalContext ;
7071import javax .enterprise .event .Observes ;
71- import javax .enterprise .inject .AmbiguousResolutionException ;
7272import javax .enterprise .inject .Default ;
7373import javax .enterprise .inject .spi .AfterBeanDiscovery ;
7474import javax .enterprise .inject .spi .AfterTypeDiscovery ;
@@ -141,6 +141,18 @@ public class CdiComponentProvider implements ComponentProvider, Extension {
141141 private volatile Map <Class <?>, Set <Method >> methodsToSkip = new HashMap <>();
142142 private volatile Map <Class <?>, Set <Field >> fieldsToSkip = new HashMap <>();
143143
144+ /** set of non JAX-RS components containing JAX-RS injection points */
145+ private final Set <Type > typesInjectableByJaxRs = new HashSet <>();
146+
147+ /** annotation types that distinguish the classes to be added to {@link #typesInjectableByJaxRs} */
148+ private static final Set <Class <? extends Annotation >> JAX_RS_INJECT_ANNOTATIONS =
149+ new HashSet <Class <? extends Annotation >>() {
150+ {
151+ addAll (JaxRsParamProducer .JAX_RS_STRING_PARAM_ANNOTATIONS );
152+ add (Context .class );
153+ }
154+ };
155+
144156 private final Hk2CustomBoundTypesProvider customHk2TypesProvider = lookupHk2CustomBoundTypesProvider ();
145157
146158 @ Override
@@ -180,13 +192,14 @@ public Class<? extends Annotation> annotationType() {
180192 }
181193 };
182194
183- static final Set <Class <? extends Annotation >> JaxRsParamAnnotationTYPES = new HashSet <Class <? extends Annotation >>() {
195+ static final Set <Class <? extends Annotation >> JAX_RS_STRING_PARAM_ANNOTATIONS = new HashSet <Class <? extends Annotation >>() {
184196 {
185197 add (javax .ws .rs .PathParam .class );
186198 add (javax .ws .rs .QueryParam .class );
187199 add (javax .ws .rs .CookieParam .class );
188200 add (javax .ws .rs .HeaderParam .class );
189201 add (javax .ws .rs .MatrixParam .class );
202+ add (javax .ws .rs .FormParam .class );
190203 }
191204 };
192205
@@ -347,9 +360,9 @@ public Set<Type> getTypeClosure() {
347360 }
348361
349362 @ Override
350- public <T extends Annotation > T getAnnotation (Class <T > annotationType ) {
363+ public <T extends Annotation > T getAnnotation (final Class <T > annotationType ) {
351364 if (annotationType == JaxRsParamProducer .JaxRsParamQualifier .class ) {
352- return isJaxRsParamAnnotationPresent ( ) ? (T )JaxRsParamProducer .JaxRsParamQUALIFIER : null ;
365+ return hasAnnotation ( ap , JaxRsParamProducer . JAX_RS_STRING_PARAM_ANNOTATIONS ) ? (T )JaxRsParamProducer .JaxRsParamQUALIFIER : null ;
353366 } else {
354367 return ap .getAnnotation (annotationType );
355368 }
@@ -358,30 +371,22 @@ public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
358371 @ Override
359372 public Set <Annotation > getAnnotations () {
360373 final Set <Annotation > result = new HashSet <>();
361- for (Annotation a : ap .getAnnotations ()) {
374+ for (final Annotation a : ap .getAnnotations ()) {
362375 result .add (a );
363376 final Class <? extends Annotation > annotationType = a .annotationType ();
364- if (JaxRsParamProducer .JaxRsParamAnnotationTYPES .contains (annotationType )) {
377+ if (JaxRsParamProducer .JAX_RS_STRING_PARAM_ANNOTATIONS .contains (annotationType )) {
365378 result .add (JaxRsParamProducer .JaxRsParamQUALIFIER );
366379 }
367380 }
368381 return result ;
369382 }
370383
371384 @ Override
372- public boolean isAnnotationPresent (Class <? extends Annotation > annotationType ) {
373- return (annotationType == JaxRsParamProducer .JaxRsParamQualifier .class && isJaxRsParamAnnotationPresent ())
385+ public boolean isAnnotationPresent (final Class <? extends Annotation > annotationType ) {
386+ return (annotationType == JaxRsParamProducer .JaxRsParamQualifier .class
387+ && hasAnnotation (ap , JaxRsParamProducer .JAX_RS_STRING_PARAM_ANNOTATIONS ))
374388 || ap .isAnnotationPresent (annotationType );
375389 }
376-
377- private boolean isJaxRsParamAnnotationPresent () {
378- for (Class <? extends Annotation > a : JaxRsParamProducer .JaxRsParamAnnotationTYPES ) {
379- if (ap .isAnnotationPresent (a )) {
380- return true ;
381- }
382- }
383- return false ;
384- }
385390 });
386391 }
387392 return parameters ;
@@ -408,7 +413,7 @@ public Set<Type> getTypeClosure() {
408413 }
409414
410415 @ Override
411- public <T extends Annotation > T getAnnotation (Class <T > annotationType ) {
416+ public <T extends Annotation > T getAnnotation (final Class <T > annotationType ) {
412417 return ctor .getAnnotation (annotationType );
413418 }
414419
@@ -418,15 +423,21 @@ public Set<Annotation> getAnnotations() {
418423 }
419424
420425 @ Override
421- public boolean isAnnotationPresent (Class <? extends Annotation > annotationType ) {
426+ public boolean isAnnotationPresent (final Class <? extends Annotation > annotationType ) {
422427 return ctor .isAnnotationPresent (annotationType );
423428 }
424429 };
425430 }
426431
427432 @ SuppressWarnings ("unused" )
428433 private void processAnnotatedType (@ Observes final ProcessAnnotatedType processAnnotatedType ) {
429- final AnnotatedType annotatedType = processAnnotatedType .getAnnotatedType ();
434+ final AnnotatedType <?> annotatedType = processAnnotatedType .getAnnotatedType ();
435+
436+ // if one of the JAX-RS annotations is present in the currently seen class, add it to the "whitelist"
437+ if (containsJaxRsConstructorInjection (annotatedType ) || containsJaxRsFieldInjection (annotatedType ) || containsJaxRsMethodInjection (annotatedType )) {
438+ typesInjectableByJaxRs .add (annotatedType .getBaseType ());
439+ }
440+
430441 if (customHk2TypesProvider != null ) {
431442 final Type baseType = annotatedType .getBaseType ();
432443 if (customHk2TypesProvider .getHk2Types ().contains (baseType )) {
@@ -446,8 +457,8 @@ public Class getJavaClass() {
446457
447458 @ Override
448459 public Set <AnnotatedConstructor > getConstructors () {
449- Set <AnnotatedConstructor > result = new HashSet <>();
450- for (AnnotatedConstructor c : ( Set < AnnotatedConstructor >) annotatedType .getConstructors ()) {
460+ final Set <AnnotatedConstructor > result = new HashSet <>();
461+ for (final AnnotatedConstructor c : annotatedType .getConstructors ()) {
451462 result .add (enrichedConstructor (c ));
452463 }
453464 return result ;
@@ -474,7 +485,7 @@ public Set<Type> getTypeClosure() {
474485 }
475486
476487 @ Override
477- public <T extends Annotation > T getAnnotation (Class <T > annotationType ) {
488+ public <T extends Annotation > T getAnnotation (final Class <T > annotationType ) {
478489 return annotatedType .getAnnotation (annotationType );
479490 }
480491
@@ -484,21 +495,53 @@ public Set<Annotation> getAnnotations() {
484495 }
485496
486497 @ Override
487- public boolean isAnnotationPresent (Class <? extends Annotation > annotationType ) {
498+ public boolean isAnnotationPresent (final Class <? extends Annotation > annotationType ) {
488499 return annotatedType .isAnnotationPresent (annotationType );
489500 }
490501 });
491502 }
492503 }
493504
494- private boolean containsJaxRsParameterizedCtor (AnnotatedType annotatedType ) {
495- for (AnnotatedConstructor <?> c : (Set <AnnotatedConstructor >) annotatedType .getConstructors ()) {
496- for (AnnotatedParameter <?> p : c .getParameters ()) {
497- for (Class <? extends Annotation > a : JaxRsParamProducer .JaxRsParamAnnotationTYPES ) {
498- if (p .isAnnotationPresent (a )) {
499- return true ;
500- }
501- }
505+ private boolean containsJaxRsParameterizedCtor (final AnnotatedType annotatedType ) {
506+ return containAnnotatedParameters (annotatedType .getConstructors (), JaxRsParamProducer .JAX_RS_STRING_PARAM_ANNOTATIONS );
507+ }
508+
509+ private boolean containsJaxRsConstructorInjection (final AnnotatedType annotatedType ) {
510+ return containAnnotatedParameters (annotatedType .getConstructors (), JAX_RS_INJECT_ANNOTATIONS );
511+ }
512+
513+ private boolean containsJaxRsMethodInjection (final AnnotatedType annotatedType ) {
514+ return containAnnotatedParameters (annotatedType .getMethods (), JAX_RS_INJECT_ANNOTATIONS );
515+ }
516+
517+ private boolean containsJaxRsFieldInjection (final AnnotatedType annotatedType ) {
518+ return containAnnotation (annotatedType .getFields (), JAX_RS_INJECT_ANNOTATIONS );
519+ }
520+
521+ private boolean containAnnotatedParameters (final Collection <AnnotatedCallable > annotatedCallables ,
522+ final Set <Class <? extends Annotation >> annotationSet ) {
523+ for (final AnnotatedCallable c : annotatedCallables ) {
524+ if (containAnnotation (c .getParameters (), annotationSet )) {
525+ return true ;
526+ }
527+ }
528+ return false ;
529+ }
530+
531+ private boolean containAnnotation (final Collection <Annotated > elements ,
532+ final Set <Class <? extends Annotation >> annotationSet ) {
533+ for (Annotated e : elements ) {
534+ if (hasAnnotation (e , annotationSet )) {
535+ return true ;
536+ }
537+ }
538+ return false ;
539+ }
540+
541+ private static boolean hasAnnotation (final Annotated element , final Set <Class <? extends Annotation >> annotations ) {
542+ for (final Class <? extends Annotation > a : annotations ) {
543+ if (element .isAnnotationPresent (a )) {
544+ return true ;
502545 }
503546 }
504547 return false ;
@@ -543,7 +586,8 @@ public Set getInjectionPoints() {
543586 return Collections .emptySet ();
544587 }
545588 });
546- } else if (isJaxRsComponentType (componentClass )) {
589+ } else if (isJaxRsComponentType (componentClass )
590+ || typesInjectableByJaxRs .contains (event .getAnnotatedType ().getBaseType ())) {
547591 event .setInjectionTarget (new CdiInjectionTarget (it ) {
548592
549593 @ Override
@@ -557,7 +601,7 @@ public Set getInjectionPoints() {
557601
558602 private Set <InjectionPoint > filterHk2InjectionPointsOut (final Set <InjectionPoint > originalInjectionPoints ) {
559603 final Set <InjectionPoint > filteredInjectionPoints = new HashSet <>();
560- for (InjectionPoint ip : originalInjectionPoints ) {
604+ for (final InjectionPoint ip : originalInjectionPoints ) {
561605 final Type injectedType = ip .getType ();
562606 if (customHk2TypesProvider != null && customHk2TypesProvider .getHk2Types ().contains (injectedType )) {
563607 //remember the type, we would need to mock it's CDI binding at runtime
@@ -617,7 +661,7 @@ public static class CdiDefaultAnnotation extends AnnotationLiteral<Default> impl
617661 }
618662
619663 @ SuppressWarnings ({ "unused" , "unchecked" , "rawtypes" })
620- private void afterDiscoveryObserver (@ Observes AfterBeanDiscovery abd ) {
664+ private void afterDiscoveryObserver (@ Observes final AfterBeanDiscovery abd ) {
621665
622666 if (customHk2TypesProvider != null ) {
623667 hk2ProvidedTypes .addAll (customHk2TypesProvider .getHk2Types ());
@@ -668,7 +712,7 @@ private Hk2CustomBoundTypesProvider lookupHk2CustomBoundTypesProvider() throws S
668712
669713 private final Cache <Class <?>, Boolean > jaxRsComponentCache = new Cache <>(new Computable <Class <?>, Boolean >() {
670714 @ Override
671- public Boolean compute (Class <?> clazz ) {
715+ public Boolean compute (final Class <?> clazz ) {
672716 return Application .class .isAssignableFrom (clazz ) ||
673717 Providers .isJaxRsProvider (clazz ) ||
674718 Resource .from (clazz ) != null ;
@@ -739,7 +783,7 @@ private void bindHk2ClassAnalyzer() {
739783 }
740784
741785 private StringBuilder listTypes (final StringBuilder logMsgBuilder , final Collection <Type > types ) {
742- for (Type t : types ) {
786+ for (final Type t : types ) {
743787 logMsgBuilder .append (String .format (" - %s%n" , t ));
744788 }
745789 return logMsgBuilder ;
@@ -789,7 +833,7 @@ private class Hk2Bean implements Bean {
789833
790834 private final Type t ;
791835
792- public Hk2Bean (Type t ) {
836+ public Hk2Bean (final Type t ) {
793837 this .t = t ;
794838 }
795839
@@ -809,12 +853,12 @@ public boolean isNullable() {
809853 }
810854
811855 @ Override
812- public Object create (CreationalContext creationalContext ) {
856+ public Object create (final CreationalContext creationalContext ) {
813857 return CdiComponentProvider .this .locator .getService (t );
814858 }
815859
816860 @ Override
817- public void destroy (Object instance , CreationalContext creationalContext ) {
861+ public void destroy (final Object instance , final CreationalContext creationalContext ) {
818862 }
819863
820864 @ Override
0 commit comments