Summary Table

Categories Total Count
PII 0
URL 0
DNS 0
EKL 0
IP 0
PORT 0
VsID 0
CF 0
AI 0
VPD 0
PL 0
Other 0

File Content

package gov.va.med.pbm.ampl.fhir.client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.rest.gclient.ICriterion;
import ca.uhn.fhir.rest.gclient.StringClientParam;
import gov.va.med.pbm.ampl.configuration.FhirConfiguration;
import gov.va.med.pbm.ampl.utility.ESAPIValidator;
import gov.va.med.pbm.ampl.utility.ESAPIValidationType;
import gov.va.med.pbm.ampl.constant.AmplConstants;

/**
* This abstract class is the template for AMPL FHIR clients.
*
* @author Ian Meinert
* @since 1.0
*/
public abstract class AbstractFhirClient {

/**
* The application logger.
*/
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractFhirClient.class);

@SuppressWarnings("unused")
private static String sessionId;
private IGenericClient client;
private FhirContext context;

private FhirConfiguration fhirConfiguration;

/**
* The AbstractFhirClient constructor which initializes the {@link IGenericClient}, {@link FhirContext}, and
* {@link FhirConfiguration}.
*
* @param context the {@link FhirContext}
* @param fhirConfiguration the {@link FhirConfiguration}
* @throws IOException thrown by the generateIscSessionId method
*/

public AbstractFhirClient(FhirContext context, FhirConfiguration fhirConfiguration) {
this.fhirConfiguration = fhirConfiguration;
this.context = context;

try {
AbstractFhirClient.sessionId = generateIscSessionId();
this.client = this.context.newRestfulGenericClient(generateFhirServerUrl());
} catch (IOException e) {
LOGGER.error("Unable to instantiate controller", e);
}
}

/**
* The getter for the client.
*
*
* @return IGenericClient
*/
public IGenericClient getClient() {
return client;
}

/**
* The setter for the client.
*
* @param client the FHIR client
*
*/
public void setClient(IGenericClient client) {
this.client = client;
}

/**
* The getter for the context.
*
*
* @return FhirContext
*/
public FhirContext getContext() {
return context;
}

/**
* The setter for the context.
*
* @param context the FHIR context
*
*/
public void setContext(FhirContext context) {
this.context = context;
}

/**
* The getter for the sessionId.
*
* @return the sessionId
*/
public String getSessionId() {
String session = new String();
try {
session = this.generateIscSessionId();
} catch (IOException e) {
LOGGER.error("Error getting the session: " + e);
}

return session;
}

/**
* The setter for the sessionId.
*
* @param sessionId the sessionId to set
*/
public void setSessionId(String sessionId) {
AbstractFhirClient.sessionId = sessionId;
}

/**
* This method generates the {@link StringClientParam} map as required by the FHIR server.
*
* @return a map of {@link StringClientParam}
*/
public ICriterion<StringClientParam> generateSessionParameterMap() {

ICriterion<StringClientParam> parameter = new StringClientParam("iscSessionId").matches().value(this.getSessionId());

return parameter;
}

/**
* This method generates a session Id by opening a connection and requesting a session from the FHIR server.
*
* @deprecated Future session Id's will be provided by the client during OAuth.
*
* @return a FHIR server generated session Id
* @throws IOException when URL is malformed or unable to connect. Also is thrown by buffered reader
*/
private String generateIscSessionId() throws IOException {

BufferedReader br = null;
URL url = new URL(fhirConfiguration.getProtocol(), fhirConfiguration.getHost(),
fhirConfiguration.getPath() + fhirConfiguration.getIscSessionPath());
LOGGER.debug("Generated the url: " + ESAPIValidator.validateLogParam(url.toString()));

HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("accept", "text/json");
Optional<InputStream> inputStream = Optional.of(conn.getInputStream());
final StringBuilder sb = new StringBuilder();

try {
br = new BufferedReader(new InputStreamReader(inputStream.get()));
int intChar;

while ((intChar = br.read()) != -1) {
char c = (char) intChar;

try {
// Check the length to mitigate Fortify denial of service vulnerability
if (sb.length() >= AmplConstants.MAX_STR_LEN) {
throw new RuntimeException("Session ID exceeded string buffer length check. "
+ "Fortify has identified this as a possible denial of service attack.");
}

sb.append(c);
} catch (RuntimeException e) {
LOGGER.error("Session ID exceeded string buffer length check. "
+ "Fortify has identified this as a possible denial of service attack.");
}
}

LOGGER.info("Generated the IscSessionId: " + sb.toString());
} finally {
try {
if (inputStream.isPresent()) {
inputStream.get().close();
}
} catch (IOException e) {
LOGGER.error("Error closing Input Stream: " + e);
}
}

ObjectMapper objectMapper = new ObjectMapper();

JsonNode rootNode = objectMapper.readTree(sb.toString());
JsonNode parameterNode = rootNode.path("parameter");
JsonNode idNode = parameterNode.get(0).path("valueString");

String iscSessionId = idNode.asText();

LOGGER.debug("The id of this session is: " + iscSessionId);

return iscSessionId;

}

/**
* This method generates the URL for FHIR server.
*
* @return generated URL string
* @throws MalformedURLException when the required params are not valid
*/
private String generateFhirServerUrl() throws MalformedURLException {
String url = new URL(fhirConfiguration.getProtocol(), fhirConfiguration.getHost(), fhirConfiguration.getPath())
.toString();
return ESAPIValidator.validateStringInput(url, ESAPIValidationType.URL);
}
}