/*
 * Copyright (c) 2012, 2019 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.server.internal.inject;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.function.Function;
import java.util.function.Supplier;

import javax.ws.rs.Encoded;

import javax.inject.Provider;

import org.glassfish.jersey.internal.inject.Injectee;
import org.glassfish.jersey.internal.inject.InjectionResolver;
import org.glassfish.jersey.internal.util.ReflectionHelper;
import org.glassfish.jersey.server.ContainerRequest;
import org.glassfish.jersey.server.model.Parameter;
import org.glassfish.jersey.server.spi.internal.ValueParamProvider;

Abstract base class for resolving JAX-RS @XxxParam injection.
Author:Marek Potociar
Type parameters:
  • <A> – supported parameter injection annotation.
/** * Abstract base class for resolving JAX-RS {@code &#64;XxxParam} injection. * * @param <A> supported parameter injection annotation. * @author Marek Potociar */
public class ParamInjectionResolver<A extends Annotation> implements InjectionResolver<A> { private final ValueParamProvider valueParamProvider; private final Class<A> annotation; private final Provider<ContainerRequest> request;
Initialize the base parameter injection resolver.
Params:
  • valueParamProvider – parameter value supplier provider.
/** * Initialize the base parameter injection resolver. * * @param valueParamProvider parameter value supplier provider. */
public ParamInjectionResolver(ValueParamProvider valueParamProvider, Class<A> annotation, Provider<ContainerRequest> request) { this.valueParamProvider = valueParamProvider; this.annotation = annotation; this.request = request; } @Override @SuppressWarnings("unchecked") public Object resolve(Injectee injectee) { AnnotatedElement annotated = injectee.getParent(); Annotation[] annotations; if (annotated.getClass().equals(Constructor.class)) { annotations = ((Constructor) annotated).getParameterAnnotations()[injectee.getPosition()]; } else { annotations = annotated.getDeclaredAnnotations(); } Class componentClass = injectee.getInjecteeClass(); Type genericType = injectee.getRequiredType(); final Type targetGenericType; if (injectee.isFactory()) { targetGenericType = ReflectionHelper.getTypeArgument(genericType, 0); } else { targetGenericType = genericType; } final Class<?> targetType = ReflectionHelper.erasure(targetGenericType); final Parameter parameter = Parameter.create( componentClass, componentClass, hasEncodedAnnotation(injectee), targetType, targetGenericType, annotations); final Function<ContainerRequest, ?> valueProvider = valueParamProvider.getValueProvider(parameter); if (valueProvider != null) { if (injectee.isFactory()) { return (Supplier<Object>) () -> valueProvider.apply(request.get()); } else { return valueProvider.apply(request.get()); } } return null; } private boolean hasEncodedAnnotation(Injectee injectee) { AnnotatedElement element = injectee.getParent(); final boolean isConstructor = element instanceof Constructor; final boolean isMethod = element instanceof Method; // if injectee is method or constructor, check its parameters if (isConstructor || isMethod) { Annotation[] annotations; if (isMethod) { annotations = ((Method) element).getParameterAnnotations()[injectee.getPosition()]; } else { annotations = ((Constructor) element).getParameterAnnotations()[injectee.getPosition()]; } for (Annotation annotation : annotations) { if (annotation.annotationType().equals(Encoded.class)) { return true; } } } // check injectee itself (method, constructor or field) if (element.isAnnotationPresent(Encoded.class)) { return true; } // check class which contains injectee Class<?> clazz = injectee.getInjecteeClass(); return clazz.isAnnotationPresent(Encoded.class); } @Override public boolean isConstructorParameterIndicator() { return true; } @Override public boolean isMethodParameterIndicator() { return false; } @Override public Class<A> getAnnotation() { return annotation; } }