package com.sap.hana.cloud.samples.benefits.connectivity.http;
import java.io.IOException;
import java.net.*;
import java.util.*;
import javax.naming.*;
import javax.ws.rs.core.MediaType;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.helpers.IOUtils;
import org.slf4j.*;
import com.sap.core.connectivity.api.authentication.*;
import com.sap.core.connectivity.api.configuration.*;
import com.sap.hana.cloud.samples.benefits.connectivity.http.headers.*;
@SuppressWarnings("nls")
public class HTTPConnector {
private static final String PATH_SUFFIX = "/";
private static final String ACCEPT_HEADER = "Accept";
private static final String GET_METHOD = "GET";
private static final String DESTINATION_URL = "URL";
private static final Logger logger = LoggerFactory.getLogger(HTTPConnector.class);
private final ProxyUserHeaderProvider proxyUserHeaderProvider = new ProxyUserHeaderProvider();
private final String destinationName;
private AuthenticationHeaderProvider localAuthenticationHeaderProvider;
private ConnectivityConfiguration localConnectivityConfiguration;
private HTTPResponseValidator responseValidator;
public HTTPConnector(String destinationName) {
this.destinationName = destinationName;
this.responseValidator = new DefaultHTTPResponseValidator();
}
public SimpleHttpResponse executeGET(String path) throws InvalidResponseException, IOException {
DestinationConfiguration destinationConfiguration = lookupDestinationConfiguration();
URL requestURL = getRequestURL(destinationConfiguration, path);
logger.info("HTTP GET request to URL {}", requestURL.toString());
HttpURLConnection urlConnection = (HttpURLConnection) requestURL.openConnection();
injectAuthenticationHeaders(urlConnection, destinationConfiguration);
SimpleHttpResponse httpResponse = executeGET(urlConnection);
return httpResponse;
}
private SimpleHttpResponse executeGET(HttpURLConnection connection) throws IOException,
com.sap.hana.cloud.samples.benefits.connectivity.http.InvalidResponseException {
connection.setRequestMethod(GET_METHOD);
int responseCode = connection.getResponseCode();
SimpleHttpResponse httpResponse = new SimpleHttpResponse(connection.getURL().toString(), responseCode, connection.getResponseMessage());
httpResponse.setContentType(connection.getContentType());
httpResponse.setContent(IOUtils.toString(connection.getInputStream()));
logResponse(httpResponse);
validateResponse(httpResponse);
return httpResponse;
}
private void logResponse(SimpleHttpResponse httpResponse) {
logger.debug("Response from requesting {} is {} {}", httpResponse.getRequestPath(), httpResponse.getResponseCode(),
httpResponse.getResponseMessage());
logger.debug("Response content type from requesting {} is {}", httpResponse.getRequestPath(), httpResponse.getContentType());
logger.debug("Response content from requesting {} is {}", httpResponse.getRequestPath(), httpResponse.getContent());
}
private void validateResponse(SimpleHttpResponse httpResponse)
throws com.sap.hana.cloud.samples.benefits.connectivity.http.InvalidResponseException {
if (this.responseValidator != null) {
this.responseValidator.validateHTTPResponse(httpResponse);
}
}
private void injectAuthenticationHeaders(HttpURLConnection urlConnection, DestinationConfiguration destinationConfiguration) throws IOException {
urlConnection.addRequestProperty(ACCEPT_HEADER, MediaType.APPLICATION_JSON);
List<AuthenticationHeader> authenticationHeaders = getAuthenticationHeaders(destinationConfiguration);
authenticationHeaders.add(this.proxyUserHeaderProvider.createMappingHeader()); // User Mapping Header required for Mock API Endpoint
for (AuthenticationHeader authenticationHeader : authenticationHeaders) {
urlConnection.addRequestProperty(authenticationHeader.getName(), authenticationHeader.getValue());
}
}
private URL getRequestURL(DestinationConfiguration destinationConfiguration, String path) throws IOException {
String requestBaseURL = destinationConfiguration.getProperty(DESTINATION_URL);
if (StringUtils.isEmpty(requestBaseURL)) {
String errorMessage = String.format("Request URL in Destination %s is not configured. Make sure to have the destination configured.",
this.destinationName);
throwConfigurationError(errorMessage);
}
if (!requestBaseURL.endsWith(PATH_SUFFIX)) {
requestBaseURL += PATH_SUFFIX;
}
logger.info("HTTP Request from destination {} with base URL {} and relative path {}", this.destinationName, requestBaseURL, path);
URL baseURL = new URL(requestBaseURL);
URL fullURL = new URL(baseURL, path);
return fullURL;
}
private void throwConfigurationError(String errorMessage) throws IOException {
logger.error(errorMessage);
throw new IOException(errorMessage);
}
private synchronized AuthenticationHeaderProvider lookupAuthenticationHeaderProvider() throws IOException {
try {
if (this.localAuthenticationHeaderProvider == null) {
Context ctx = new InitialContext();
this.localAuthenticationHeaderProvider = (AuthenticationHeaderProvider) ctx.lookup("java:comp/env/authenticationHeaderProvider");
}
return this.localAuthenticationHeaderProvider;
} catch (NamingException e) {
throw new IOException(e.getMessage(), e);
}
}
private List<AuthenticationHeader> getAuthenticationHeaders(DestinationConfiguration destinationConfiguration) throws IOException {
String authenticationType = destinationConfiguration.getProperty("Authentication");
List<AuthenticationHeader> authenticationHeaders = new ArrayList<>();
if ("OAuth2SAMLBearerAssertion".equals(authenticationType)) {
AuthenticationHeaderProvider headerProvider = lookupAuthenticationHeaderProvider();
authenticationHeaders.addAll(headerProvider.getOAuth2SAMLBearerAssertionHeaders(destinationConfiguration));
} else if ("BasicAuthentication".equals(authenticationType)) {
BasicAuthenticationHeaderProvider headerProvider = new BasicAuthenticationHeaderProvider();
authenticationHeaders.add(headerProvider.getAuthenticationHeader(destinationConfiguration));
}
return authenticationHeaders;
}
private DestinationConfiguration lookupDestinationConfiguration() throws IOException {
ConnectivityConfiguration configuration = lookupConnectivityConfiguration();
DestinationConfiguration destinationConfiguration = configuration.getConfiguration(this.destinationName);
if (destinationConfiguration == null) {
String errorMessage = String.format("Destination %s is not found. Make sure to have the destination configured.", this.destinationName);
logger.error(errorMessage);
throw new IOException(errorMessage);
}
return destinationConfiguration;
}
private synchronized ConnectivityConfiguration lookupConnectivityConfiguration() throws IOException {
try {
if (this.localConnectivityConfiguration == null) {
Context ctx = new InitialContext();
this.localConnectivityConfiguration = (ConnectivityConfiguration) ctx.lookup("java:comp/env/connectivityConfiguration");
}
return this.localConnectivityConfiguration;
} catch (NamingException e) {
throw new IOException(e.getMessage(), e);
}
}
}