package org.jboss.resteasy.client.core.extractors;
import org.jboss.resteasy.annotations.ClientResponseType;
import org.jboss.resteasy.annotations.ResponseObject;
import org.jboss.resteasy.client.ClientResponse;
import org.jboss.resteasy.client.EntityTypeFactory;
import org.jboss.resteasy.client.core.BaseClientResponse;
import org.jboss.resteasy.util.Types;
import javax.ws.rs.core.Response;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* @author Solomon.Duskis
*/
@SuppressWarnings("unchecked")
public class DefaultEntityExtractorFactory implements EntityExtractorFactory
{
public static final EntityExtractor clientResponseExtractor = new EntityExtractor<ClientResponse>()
{
public ClientResponse extractEntity(ClientRequestContext context, Object... args)
{
return context.getClientResponse();
}
};
public static EntityExtractor<Response.Status> createStatusExtractor(final boolean release)
{
return new EntityExtractor<Response.Status>()
{
public Response.Status extractEntity(ClientRequestContext context, Object... args)
{
if (release)
context.getClientResponse().releaseConnection();
return context.getClientResponse().getResponseStatus();
}
};
}
public static final EntityExtractor createVoidExtractor(final boolean release)
{
return new EntityExtractor()
{
public Object extractEntity(ClientRequestContext context, Object... args)
{
try
{
context.getClientResponse().checkFailureStatus();
}
catch (RuntimeException e)
{
context.getErrorHandler().clientErrorHandling(context.getClientResponse(), e);
}
if (release)
context.getClientResponse().releaseConnection();
return null;
}
};
}
public EntityExtractor createExtractor(final Method method)
{
final Class returnType = method.getReturnType();
if (isVoidReturnType(returnType))
return createVoidExtractor(true);
if (returnType.equals(Response.Status.class))
return createStatusExtractor(true);
if (Response.class.isAssignableFrom(returnType))
return createResponseTypeEntityExtractor(method);
if (returnType.isInterface() && returnType.isAnnotationPresent(ResponseObject.class))
return new ResponseObjectProxy(method, new ResponseObjectEntityExtractorFactory());
// We are not a ClientResponse type so we need to unmarshall and narrow it
// to right type. If we are unable to unmarshall, or encounter any kind of
// Exception, give the ClientErrorHandlers a chance to handle the
// ClientResponse manually.
return new BodyEntityExtractor(method);
}
protected EntityExtractor createResponseTypeEntityExtractor(final Method method)
{
final ClientResponseType responseHint = method.getAnnotation(ClientResponseType.class);
if (responseHint != null)
{
final Class responseHintReturnType = responseHint.entityType();
if (isVoidReturnType(responseHintReturnType))
{
final Class<? extends EntityTypeFactory> entityTypeFactory = responseHint.entityTypeFactory();
return new EntityExtractor()
{
public Object extractEntity(ClientRequestContext context, Object... args)
{
EntityTypeFactory factory = null;
try
{
factory = entityTypeFactory.newInstance();
}
catch (InstantiationException e)
{
throw (context.getClientResponse())
.createResponseFailure("Could not create a default entity type factory of type "
+ entityTypeFactory.getClass().getName());
}
catch (IllegalAccessException e)
{
throw ((BaseClientResponse<?>) context.getClientResponse())
.createResponseFailure("Could not create a default entity type factory of type "
+ entityTypeFactory.getClass().getName() + ". " + e.getMessage());
}
context.getClientResponse().setReturnType(
factory.getEntityType(((BaseClientResponse<?>) context.getClientResponse()).getStatus(),
((BaseClientResponse<?>) context.getClientResponse()).getMetadata()));
return context.getClientResponse();
}
};
}
else
{
return new EntityExtractor()
{
public Object extractEntity(ClientRequestContext context, Object... args)
{
context.getClientResponse().setReturnType(responseHintReturnType);
return context.getClientResponse();
}
};
}
}
else
{
final Type methodGenericReturnType = method.getGenericReturnType();
if (methodGenericReturnType instanceof ParameterizedType)
{
final ParameterizedType zType = (ParameterizedType) methodGenericReturnType;
final Type genericReturnType = zType.getActualTypeArguments()[0];
final Class<?> responseReturnType = Types.getRawType(genericReturnType);
return new EntityExtractor()
{
public Object extractEntity(ClientRequestContext context, Object... args)
{
context.getClientResponse().setReturnType(responseReturnType);
context.getClientResponse().setGenericReturnType(genericReturnType);
return context.getClientResponse();
}
};
}
else
return clientResponseExtractor;
}
}
public static final boolean isVoidReturnType(Class<?> returnType)
{
return returnType == null || void.class.equals(returnType) || Void.class.equals(returnType);
}
}