package edu.gatech.i3l.fhir.smart.servlet; import java.io.BufferedReader; import java.io.IOException; import java.io.PrintWriter; import java.sql.Timestamp; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.Enumeration; import java.util.Iterator; import java.util.List; import java.util.TimeZone; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import javax.servlet.ServletException; //import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.oltu.oauth2.common.exception.OAuthProblemException; import org.apache.oltu.oauth2.common.exception.OAuthSystemException; import org.apache.oltu.oauth2.common.message.types.ParameterStyle; import org.apache.oltu.oauth2.rs.request.OAuthAccessResourceRequest; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.WebApplicationContext; import com.google.gson.Gson; import edu.gatech.i3l.fhir.jpa.provider.JpaSystemProviderDstu2; import edu.gatech.i3l.fhir.security.Authorization; /** * Servlet implementation class SmartServices @WebServlet(description = "SMART on FHIR internal services", urlPatterns = { "/_services/smart/Launch" }) */ public class SmartServices extends HttpServlet { private static final long serialVersionUID = 1L; private WebApplicationContext myAppCtx; private SmartOnFhirLaunchContextProvider launchContextProvider; private String url; private String client_id; private String client_secret; /** * @see HttpServlet#HttpServlet() */ public SmartServices() { super(); } public void init() throws ServletException { // According to SMART on FHIR folks in Harvard. They want to support both // basic AUTH and bearer AUTH for the internal communication for this. url = getServletConfig().getInitParameter("introspectUrl"); client_id = getServletConfig().getInitParameter("client_id"); client_secret = getServletConfig().getInitParameter("client_secret"); myAppCtx = ContextLoaderListener.getCurrentWebApplicationContext(); launchContextProvider = myAppCtx.getBean("mySmartService", SmartOnFhirLaunchContextProvider.class); // bookDB = (BookDBAO)getServletContext(). // getAttribute("bookDB"); // if (bookDB == null) throw new // UnavailableException("Couldn’t get database."); } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub String launchId = new String(request.getPathInfo().substring(1)); if (launchId == null || launchId.isEmpty()) { System.out.println("LaunchID is invalid"); return; } System.out.println("Get LaunchID = "+launchId); Authorization smartAuth = new Authorization(url, client_id, client_secret); if (smartAuth.asBasicAuth(request) == true || smartAuth.asBearerAuth(request) == true) { SmartLaunchContext smartLaunchContext = launchContextProvider.getContext(Long.valueOf(launchId)); if (smartLaunchContext != null) { JSONObject jsonResp = smartLaunchContext.getJSONObject(); if (jsonResp == null) { System.out.println("Launch ID "+launchId+" does not exist."); return; } String respString = jsonResp.toString(); response.setContentType("application/json; charset=UTF-8;"); response.getWriter().append(respString); System.out.println(respString); } } } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // We have received a request to create Launch context StringBuilder buffer = new StringBuilder(); BufferedReader reader = request.getReader(); // String url = getServletConfig().getInitParameter("introspectUrl"); // String client_id = getServletConfig().getInitParameter("client_id"); // String client_secret = getServletConfig().getInitParameter("client_secret"); Authorization smartAuth = new Authorization(url, client_id, client_secret); if (smartAuth.asBasicAuth(request) == true || smartAuth.asBearerAuth(request) == true) { if (smartAuth.assertScope("smart/orchestrate_launch") == false) { // This is internal communication for SMART orchestration. Other request is not // allowed. return; } String line; while ((line=reader.readLine())!=null) { buffer.append(line); } System.out.println("LaunchContext: "+buffer.toString()); // Convert the body content to JSON and create launch context in database. // JSONObject servReq = new JSONObject(buffer.toString()); String launchContextClientId = servReq.getString("client_id"); String launchContextCreatedBy = smartAuth.getClientId(); String launchContextUsername = smartAuth.getUserId(); java.util.Date date= new java.util.Date(); Timestamp ts = new Timestamp(date.getTime()); SmartLaunchContext smartLaunchContext = new SmartLaunchContext(); smartLaunchContext.setClientId(launchContextClientId); smartLaunchContext.setCreatedBy(launchContextCreatedBy); smartLaunchContext.setCreatedAt(ts); smartLaunchContext.setUsername(launchContextUsername); List<SmartLaunchContextParam> smartLaunchContextParams = new ArrayList<SmartLaunchContextParam>(); smartLaunchContext.setSmartLaunchContextParams(smartLaunchContextParams); JSONObject paramsJSON = servReq.getJSONObject("parameters"); Iterator<?> paramsIter = paramsJSON.keys(); String jsonParams=""; while (paramsIter.hasNext()) { String key = (String) paramsIter.next(); String val = paramsJSON.getString(key); System.out.println ("Parameters: key: "+key+" val:"+val); SmartLaunchContextParam smartLaunchContextParam = new SmartLaunchContextParam(); smartLaunchContextParam.setParamName(key); smartLaunchContextParam.setParamValue(val); smartLaunchContext.addSmartLaunchContextParam(smartLaunchContextParam); // if (key.equalsIgnoreCase("patient")) { // // We supposed to have only patient. // jsonParams="\"patient\":\""+val+"\"," // +"\"smart_style_url\":"+"\"https://fhir.smarthealthit.org/stylesheets/smart_v1.json\""+"," // +"\"need_patient_banner\":true"; // } } launchContextProvider.setContext(smartLaunchContext); /* Response with JSON object with the following information. * { * "created_by": “[CLIENTID]", * "username": “[USERNAME]", * "launch_id": “[LAUNCHID]", * "created_at": “[ISO8601TIMESTAMP]", * "parameters": { * "patient": “[PATIENTID]", * "smart_style_url": "https://fhir.smarthealthit.org/stylesheets/smart_v1.json", * "need_patient_banner": true * } * } */ response.setContentType("application/json; charset=UTF-8;"); // TimeZone tz = TimeZone.getTimeZone("UTC"); // DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm"); // df.setTimeZone(tz); // date = new Date(ts.getTime()); // String createdAt = df.format(date); // PrintWriter out = response.getWriter(); // String jsonData = "{\"created_by\":\""+launchContextClientId+"\"," // +"\"username\":\""+launchContextUsername+"\"," // +"\"launch_id\":\""+smartLaunchContext.getLaunchId()+"\"," // +"\"created_at\":\""+createdAt+"\""; // // // Parameters // if (jsonParams.isEmpty() == false) { // jsonData = jsonData.concat(",\"parameters\": {"+jsonParams+"}"); // } // // jsonData = jsonData.concat("}"); String jsonData = smartLaunchContext.getJSONObject().toString(); out.println(jsonData) ; out.close(); System.out.println("SMARTonFHIR service response: "+jsonData); } // Enumeration<String> headerNames = request.getHeaderNames(); // while (headerNames.hasMoreElements()) { // String headerName = headerNames.nextElement(); // System.out.println(headerName); // Enumeration<String> headers = request.getHeaders(headerName); // while (headers.hasMoreElements()) { // String headerValue = headers.nextElement(); // System.out.println(" "+headerValue); // } // } } }