package org.jboss.resteasy.core.interception;
import org.jboss.resteasy.annotations.interception.Precedence;
import org.jboss.resteasy.resteasy_jaxrs.i18n.Messages;
import org.jboss.resteasy.spi.ConstructorInjector;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.resteasy.spi.interception.AcceptedByMethod;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*
* @deprecated The Resteasy interceptor facility introduced in release 2.x
* is replaced by the JAX-RS 2.0 compliant interceptor facility in release 3.0.x.
*
* @see jaxrs-api (https://jcp.org/en/jsr/detail?id=339)
*/
@Deprecated
@SuppressWarnings("unchecked")
public class InterceptorRegistry<T>
{
protected static interface InterceptorFactory
{
Object preMatch();
Object postMatch(Class declaring, AccessibleObject target);
int getOrder();
}
protected abstract class AbstractInterceptorFactory implements InterceptorFactory
{
protected String precedence = "DEFAULT";
protected int order = 100000;
protected void setPrecedence(Class<?> clazz)
{
Precedence precedence = clazz.getAnnotation(Precedence.class);
if (precedence != null)
{
this.precedence = precedence.value();
Integer o = precedenceOrder.get(this.precedence);
if (o == null) throw new RuntimeException(Messages.MESSAGES.unknownInterceptorPrecedence(this.precedence));
this.order = o;
}
else
{
for (Annotation annotation : clazz.getAnnotations())
{
precedence = annotation.annotationType().getAnnotation(Precedence.class);
if (precedence != null)
{
this.precedence = precedence.value();
Integer o = precedenceOrder.get(this.precedence);
if (o == null) throw new RuntimeException(Messages.MESSAGES.unknownInterceptorPrecedence(this.precedence));
this.order = o;
break;
}
}
}
}
public String getPrecedence()
{
return precedence;
}
public int getOrder()
{
return order;
}
protected Object binding(Class declaring, AccessibleObject target, Object inter)
{
if (inter instanceof AcceptedByMethod)
{
if (target == null || !(target instanceof Method)) return null;
Method method = (Method)target;
if (((AcceptedByMethod)inter).accept(declaring, method))
{
return inter;
}
else
{
return null;
}
}
return inter;
}
}
protected class SingletonInterceptorFactory extends AbstractInterceptorFactory
{
private Object interceptor;
public SingletonInterceptorFactory(Object interceptor)
{
this.interceptor = interceptor;
setPrecedence(interceptor.getClass());
}
@Override
public Object preMatch()
{
return null;
}
@Override
public Object postMatch(Class declaring, AccessibleObject target)
{
final Object inter = interceptor;
return binding(declaring, target, inter);
}
}
protected class PerMethodInterceptorFactory extends AbstractInterceptorFactory
{
private ConstructorInjector constructorInjector;
public PerMethodInterceptorFactory(Class clazz)
{
constructorInjector = providerFactory.createConstructorInjector(clazz);
setPrecedence(clazz);
}
@Override
public Object preMatch()
{
return null;
}
@Override
public Object postMatch(Class declaring, AccessibleObject target)
{
final Object inter = constructorInjector.construct();
return binding(declaring, target, inter);
}
}
protected ResteasyProviderFactory providerFactory;
protected Class<T> intf;
protected List<InterceptorFactory> interceptors = new ArrayList<InterceptorFactory>();
protected Map<String, Integer> precedenceOrder = new HashMap<String, Integer>();
protected List<String> precedenceList = new ArrayList<String>();
protected List<InterceptorRegistryListener> listeners = new ArrayList<InterceptorRegistryListener>();
public InterceptorRegistry<T> cloneTo(ResteasyProviderFactory factory)
{
InterceptorRegistry<T> clone = new InterceptorRegistry<T>(intf, factory);
clone.interceptors.addAll(interceptors);
clone.precedenceOrder.putAll(precedenceOrder);
precedenceList.addAll(precedenceList);
return clone;
}
public class PrecedenceComparator implements Comparator<InterceptorFactory>
{
public int compare(InterceptorFactory factory, InterceptorFactory factory2)
{
return factory.getOrder() - factory2.getOrder();
}
}
public List<InterceptorRegistryListener> getListeners()
{
return listeners;
}
public Class<T> getIntf()
{
return intf;
}
public InterceptorRegistry(Class<T> intf, ResteasyProviderFactory providerFactory)
{
this.providerFactory = providerFactory;
this.intf = intf;
precedenceOrder.put("DEFAULT", 100000);
}
protected void recalculateOrder()
{
precedenceOrder.clear();
for (int i = 0; i < precedenceList.size(); i++)
{
precedenceOrder.put(precedenceList.get(i), i);
}
precedenceOrder.put("DEFAULT", 100000);
}
public void appendPrecedence(String precedence)
{
precedenceList.add(precedence);
recalculateOrder();
}
public void insertPrecedenceAfter(String after, String newPrecedence)
{
for (int i = 0; i < precedenceList.size(); i++)
{
if (precedenceList.get(i).equals(after))
{
precedenceList.add(i + 1, newPrecedence);
break;
}
}
recalculateOrder();
}
public void insertPrecedenceBefore(String after, String newPrecedence)
{
for (int i = 0; i < precedenceList.size(); i++)
{
if (precedenceList.get(i).equals(after))
{
precedenceList.add(i, newPrecedence);
break;
}
}
recalculateOrder();
}
public T[] bind(Class declaring, AccessibleObject target)
{
List<T> list = bindForList(declaring, target);
return list.toArray((T[]) Array.newInstance(intf, list.size()));
}
public List<T> bindForList(Class declaring, AccessibleObject target)
{
List<T> list = new ArrayList<T>();
for (InterceptorFactory factory : interceptors)
{
Object interceptor = factory.postMatch(declaring, target);
if (interceptor != null) addNewInterceptor(list, interceptor);
}
return list;
}
protected void addNewInterceptor(List<T> list, Object interceptor)
{
providerFactory.injectProperties(interceptor);
list.add((T) interceptor);
}
public void register(Class<? extends T> clazz)
{
interceptors.add(new PerMethodInterceptorFactory(clazz));
Collections.sort(interceptors, new PrecedenceComparator());
for (InterceptorRegistryListener listener : listeners)
{
listener.registryUpdated(this);
}
}
public void register(T interceptor)
{
interceptors.add(new SingletonInterceptorFactory(interceptor));
Collections.sort(interceptors, new PrecedenceComparator());
for (InterceptorRegistryListener listener : listeners)
{
listener.registryUpdated(this);
}
}
}