/*
* JBoss, Home of Professional Open Source
* Copyright 2011 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.arquillian.extension.rest.client;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.Providers;
import org.jboss.arquillian.container.spi.client.protocol.metadata.HTTPContext;
import org.jboss.arquillian.container.spi.client.protocol.metadata.ProtocolMetaData;
import org.jboss.arquillian.container.spi.client.protocol.metadata.Servlet;
import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.InstanceProducer;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.core.api.annotation.Observes;
import org.jboss.arquillian.test.spi.annotation.TestScoped;
import org.jboss.arquillian.test.spi.event.suite.Before;
import org.jboss.resteasy.client.ClientExecutor;
import org.jboss.resteasy.client.ClientRequest;
import org.jboss.resteasy.client.core.ClientInvoker;
import org.jboss.resteasy.client.core.ClientInvokerInterceptorFactory;
import org.jboss.resteasy.client.core.extractors.DefaultEntityExtractorFactory;
import org.jboss.resteasy.client.core.extractors.EntityExtractorFactory;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.resteasy.util.IsHttpMethod;
/**
* RestInvoker
*
* @author <a href="mailto:aslak@redhat.com">Aslak Knutsen</a>
* @version $Revision: $
*/
public class RestInvoker
{
@Inject
private Instance<ProtocolMetaData> metaDataInst;
// Share the Response in the Arquillian scopes so it can be injected by the RestEnricher
@Inject @TestScoped
private InstanceProducer<Response> responseProducer;
public void call(@Observes Before event)
{
Set<String> httpMethods = IsHttpMethod.getHttpMethods(event.getTestMethod());
if (httpMethods != null && httpMethods.size() == 1)
{
Response response = doRestCall(event.getTestMethod(), httpMethods);
responseProducer.set(response);
}
}
/**
* Get the deployment URL, create the RestEasy Client Proxy Invoker for the given TestMethod and return the result.
*
* @param testMethod
* @param httpMethods
* @return
*/
private Response doRestCall(Method testMethod, Set<String> httpMethods)
{
URI baseUri = getBaseURL();
ClientExecutor executor = ClientRequest.getDefaultExecutor();
ResteasyProviderFactory providerFactory = ResteasyProviderFactory.getInstance();
EntityExtractorFactory extractorFactory = new DefaultEntityExtractorFactory();
ArqClientInvoker invoker = new ArqClientInvoker(baseUri, testMethod.getDeclaringClass(), testMethod, providerFactory, executor, extractorFactory);
invoker.getAttributes().putAll(new HashMap<String, Object>());
ClientInvokerInterceptorFactory.applyDefaultInterceptors(invoker, providerFactory, testMethod.getDeclaringClass(), testMethod);
invoker.setHttpMethod(httpMethods.iterator().next());
return invoker.request(new Object[]{null});
}
// Currently no way to share @ArquillianResource URL (URLResourceProvider) logic internally, copied logic
private URI getBaseURL()
{
HTTPContext context = metaDataInst.get().getContext(HTTPContext.class);
if(allInSameContext(context.getServlets()))
{
return context.getServlets().get(0).getBaseURI();
}
throw new IllegalStateException("No baseURL found in HTTPContext");
}
private boolean allInSameContext(List<Servlet> servlets)
{
Set<String> context = new HashSet<String>();
for (Servlet servlet : servlets)
{
context.add(servlet.getContextRoot());
}
return context.size() == 1;
}
// Need to extend ClientInvoker to call createRequest
private static class ArqClientInvoker extends ClientInvoker
{
public ArqClientInvoker(URI baseUri, Class<?> declaring, Method method, ResteasyProviderFactory providerFactory, ClientExecutor executor, EntityExtractorFactory extractorFactory)
{
super(baseUri, declaring, method, providerFactory, executor, extractorFactory);
}
// As oppose to invoke(Object[]) which will return the Response Entity, we expose the raw Response object
public Response request(Object[] args)
{
boolean isProvidersSet = ResteasyProviderFactory.getContextData(Providers.class) != null;
if (!isProvidersSet) ResteasyProviderFactory.pushContext(Providers.class, providerFactory);
try
{
if (uri == null) throw new RuntimeException("You have not set a base URI for the client proxy");
ClientRequest request = createRequest(args);
try
{
return request.httpMethod(httpMethod);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
finally
{
if (!isProvidersSet) ResteasyProviderFactory.popContextData(Providers.class);
}
}
}
}