package org.jboss.resteasy.core;
import org.jboss.resteasy.spi.ApplicationException;
import org.jboss.resteasy.spi.Failure;
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.HttpResponse;
import org.jboss.resteasy.spi.InternalServerErrorException;
import org.jboss.resteasy.spi.PropertyInjector;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.resteasy.spi.ValueInjector;
import org.jboss.resteasy.spi.metadata.FieldParameter;
import org.jboss.resteasy.spi.metadata.ResourceClass;
import org.jboss.resteasy.spi.metadata.SetterParameter;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
public class ResourcePropertyInjector implements PropertyInjector
{
private static class FieldInjector
{
public FieldParameter param;
public ValueInjector injector;
private FieldInjector(final FieldParameter param, final ValueInjector injector)
{
this.param = param;
this.injector = injector;
}
}
private static class SetterInjector
{
public SetterParameter param;
public ValueInjector injector;
private SetterInjector(final SetterParameter param, final ValueInjector injector)
{
this.param = param;
this.injector = injector;
}
}
protected List<FieldInjector> fields = new ArrayList<FieldInjector>();
protected List<SetterInjector> setters = new ArrayList<SetterInjector>();
protected ResourceClass resourceClass;
protected ResteasyProviderFactory factory;
public ResourcePropertyInjector(final ResourceClass resourceClass, final ResteasyProviderFactory factory)
{
this.resourceClass = resourceClass;
this.factory = factory;
for (FieldParameter param : resourceClass.getFields())
{
ValueInjector injector = factory.getInjectorFactory().createParameterExtractor(param, factory);
if (injector == null) continue;
fields.add(new FieldInjector(param, injector));
}
for (SetterParameter param : resourceClass.getSetters())
{
ValueInjector injector = factory.getInjectorFactory().createParameterExtractor(param, factory);
if (injector == null) continue;
setters.add(new SetterInjector(param, injector));
}
}
@SuppressWarnings("unchecked")
@Override
public CompletionStage<Void> inject(HttpRequest request, HttpResponse response, Object target, boolean unwrapAsync) throws Failure
{
CompletionStage<Void> ret = null;
for (FieldInjector injector : fields)
{
Object injectedObject = injector.injector.inject(request, response, unwrapAsync);
if (injectedObject != null && injectedObject instanceof CompletionStage) {
if (ret == null) ret = CompletableFuture.completedFuture(null);
ret = ret.thenCompose(v ->
((CompletionStage<Object>)injectedObject)
.thenAccept(value -> {
try
{
injector.param.getField().set(target, value);
}
catch (IllegalAccessException e)
{
throw new InternalServerErrorException(e);
}
}));
} else {
try {
injector.param.getField().set(target, CompletionStageHolder.resolve(injectedObject));
} catch (IllegalAccessException e) {
throw new InternalServerErrorException(e);
}
}
}
for (SetterInjector injector : setters)
{
Object injectedObject = injector.injector.inject(request, response, unwrapAsync);
if (injectedObject != null && injectedObject instanceof CompletionStage) {
if (ret == null) ret = CompletableFuture.completedFuture(null);
ret = ret.thenCompose(v ->
((CompletionStage<Object>)injectedObject)
.thenAccept(value -> {
try
{
injector.param.getSetter().invoke(target, value);
}
catch (IllegalAccessException e)
{
throw new InternalServerErrorException(e);
}
catch (InvocationTargetException e)
{
throw new ApplicationException(e.getCause());
}
}));
} else {
try
{
injector.param.getSetter().invoke(target, CompletionStageHolder.resolve(injectedObject));
}
catch (IllegalAccessException e)
{
throw new InternalServerErrorException(e);
}
catch (InvocationTargetException e)
{
throw new ApplicationException(e.getCause());
}
}
}
return ret;
}
@SuppressWarnings("unchecked")
@Override
public CompletionStage<Void> inject(Object target, boolean unwrapAsync)
{
CompletionStage<Void> ret = null;
for (FieldInjector injector : fields)
{
Object injectedObject = injector.injector.inject(unwrapAsync);
if (injectedObject != null && injectedObject instanceof CompletionStage) {
if (ret == null) ret = CompletableFuture.completedFuture(null);
ret = ret.thenCompose(v ->
((CompletionStage<Object>)injectedObject)
.thenAccept(value -> {
try
{
injector.param.getField().set(target, value);
}
catch (IllegalAccessException e)
{
throw new InternalServerErrorException(e);
}
}));
} else {
try
{
injector.param.getField().set(target, CompletionStageHolder.resolve(injectedObject));
}
catch (IllegalAccessException e)
{
throw new InternalServerErrorException(e);
}
}
}
for (SetterInjector injector : setters)
{
Object injectedObject = injector.injector.inject(unwrapAsync);
if (injectedObject != null && injectedObject instanceof CompletionStage) {
if (ret == null) ret = CompletableFuture.completedFuture(null);
ret = ret.thenCompose(v ->
((CompletionStage<Object>)injectedObject)
.thenAccept(value -> {
try
{
injector.param.getSetter().invoke(target, value);
}
catch (IllegalAccessException e)
{
throw new InternalServerErrorException(e);
}
catch (InvocationTargetException e)
{
throw new ApplicationException(e.getCause());
}
}));
} else {
try
{
injector.param.getSetter().invoke(target, CompletionStageHolder.resolve(injectedObject));
}
catch (IllegalAccessException e)
{
throw new InternalServerErrorException(e);
}
catch (InvocationTargetException e)
{
throw new ApplicationException(e.getCause());
}
}
}
return ret;
}
}