package io.oasp.gastronomy.restaurant.general.common;
import java.util.Arrays;
import java.util.HashMap;
import org.apache.cxf.common.util.Base64Utility;
import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import io.oasp.gastronomy.restaurant.general.common.api.RestService;
/**
* This class contains a method to aid simulating a REST client.
*
*/
public class RestTestClientBuilder {
/**
* The port to which the server is bound during testing.
*/
private int localServerPort;
private JacksonJsonProvider jacksonJsonProvider;
/*
* The user used for authentication during testing.
*/
private String login;
/**
* This method creates a proxy for the specified {@code RestService} interface. Use {@code #setLogin(String)} to set
* login ID which will be used as both user name and pasword for authentication.
*
* @param <T> The generic type for which a proxy must be created.
* @param clazz The interface specifying the generic type.
* @return a proxy of the specified type.
*/
public <T extends RestService> T build(Class<T> clazz) {
if (this.login == null) {
throw new IllegalStateException("RestTestClientBuilder not properly initialized. No login provided.");
}
return this.build(clazz, this.login, this.login, createRestServiceUrl());
}
/**
* This method creates a proxy for the specified {@code RestService} interface. The provided {@code String login} is
* used as both user name and password for authentication. The method {@code setLocalServerPort} MUST be called in
* advance. The method {@code setLocalServerPort} MUST be called in advance.
*
* @param <T> The generic type for which a proxy must be created.
* @param clazz The interface specifying the generic type.
* @param login the {@code String} used as for authentcation.
* @return a proxy of the specified type.
*/
public <T extends RestService> T build(Class<T> clazz, String login) {
return this.build(clazz, login, login, createRestServiceUrl());
}
/**
* This method returns an instance of an implementation the specified {@code clazz} (which should be a REST service
* interface, e.g. TablemanagementRestService.class). <br/>
* The caller must take care that no parameter value is equal to {@code NULL}. <br/>
* The caller will be authenticated using basic authentication with the provided credentials. The method
* {@code setLocalServerPort} MUST be called in advance.
*
* @param <T> The return type.
* @param clazz This must be an interface type.
* @param userName The userName for basic authentication.
* @param tmpPassword The password for basic authentication.
* @param tmpUrl The URL through which the server is reached.
* @return A REST proxy of type {@code T}
*/
public <T extends RestService> T build(Class<T> clazz, String userName, String tmpPassword, String tmpUrl) {
JAXRSClientFactoryBean factoryBean = new JAXRSClientFactoryBean();
factoryBean.setAddress(tmpUrl);
factoryBean.setHeaders(new HashMap<String, String>());
// example for basic auth
String payload = userName + ":" + tmpPassword;
String authorizationHeader = "Basic " + Base64Utility.encode(payload.getBytes());
factoryBean.getHeaders().put("Authorization", Arrays.asList(authorizationHeader));
factoryBean.setProviders(Arrays.asList(this.jacksonJsonProvider));
factoryBean.setServiceClass(clazz);
return factoryBean.create(clazz);
}
/*
* @return the URL of the REST service.
*/
private String createRestServiceUrl() {
return "http://localhost:" + this.localServerPort + "/services/rest";
}
/**
* Sets the {@code jacksonJsonProvider}.
*
* @param jacksonJsonProvider An instance of {@link JacksonJsonProvider}
*/
public void setJacksonJsonProvider(JacksonJsonProvider jacksonJsonProvider) {
this.jacksonJsonProvider = jacksonJsonProvider;
}
/**
* Sets the {@code localServerPort}.
*
* @param localServerPort The port through which the server is available during testing
*/
public void setLocalServerPort(int localServerPort) {
this.localServerPort = localServerPort;
}
/**
* Sets the {@code login}.
*
* @param login Used for authentication.
*/
public void setLogin(String login) {
this.login = login;
}
}