com.biomeris.i2b2.export.ws.ExportService.java Source code

Java tutorial

Introduction

Here is the source code for com.biomeris.i2b2.export.ws.ExportService.java

Source

/*
 * Copyright (c) 2015 Biomeris s.r.l. 
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the i2b2 Software License v2.1 
 * which accompanies this distribution. 
 * 
 * Contributors: 
 *     Matteo Gabetta
 */
package com.biomeris.i2b2.export.ws;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.xml.bind.JAXB;
import javax.xml.bind.JAXBException;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.axiom.om.OMElement;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.description.AxisService;
import org.apache.axis2.engine.ServiceLifeCycle;
import org.apache.axis2.service.Lifecycle;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.HttpHostConnectException;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.xerces.dom.ElementNSImpl;
import org.springframework.util.Assert;
import org.w3c.dom.Document;

import com.biomeris.i2b2.export.datavo.i2b2message.BodyType;
import com.biomeris.i2b2.export.datavo.i2b2message.MessageHeaderType;
import com.biomeris.i2b2.export.datavo.i2b2message.ResponseHeaderType;
import com.biomeris.i2b2.export.datavo.i2b2message.ResponseMessageType;
import com.biomeris.i2b2.export.datavo.i2b2message.ResultStatusType;
import com.biomeris.i2b2.export.datavo.pdo.BlobType;
import com.biomeris.i2b2.export.datavo.pdo.ObservationSet;
import com.biomeris.i2b2.export.datavo.pdo.ObservationType;
import com.biomeris.i2b2.export.datavo.pm.ConfigureType;
import com.biomeris.i2b2.export.datavo.pm.ProjectType;
import com.biomeris.i2b2.export.datavo.pm.UserType;
import com.biomeris.i2b2.export.engine.ExportCellException;
import com.biomeris.i2b2.export.engine.io.input.ExportListRequest;
import com.biomeris.i2b2.export.engine.io.input.ExportRequest;
import com.biomeris.i2b2.export.engine.io.input.OpenNewSessionRequest;
import com.biomeris.i2b2.export.engine.io.input.TestSessionRequest;
import com.biomeris.i2b2.export.engine.io.misc.Export;
import com.biomeris.i2b2.export.engine.io.misc.Network;
import com.biomeris.i2b2.export.engine.io.misc.Session;
import com.biomeris.i2b2.export.engine.io.output.ExportListResponse;
import com.biomeris.i2b2.export.engine.io.output.ExportResponse;
import com.biomeris.i2b2.export.engine.io.output.OpenNewSessionResponse;
import com.biomeris.i2b2.export.engine.io.output.TestSessionResponse;
import com.biomeris.i2b2.export.engine.session.WExport;
import com.biomeris.i2b2.export.engine.session.WSession;
import com.biomeris.i2b2.export.engine.session.WSessionManager;
import com.biomeris.i2b2.export.ws.messages.MessageBuilder;
import com.biomeris.i2b2.export.ws.messages.MessageFactory;
import com.biomeris.i2b2.export.ws.messages.MessageManager;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;

import edu.harvard.i2b2.common.exception.I2B2Exception;

public class ExportService implements ServiceLifeCycle, Lifecycle {
    private static WSessionManager sessionManager;
    private static Log log = LogFactory.getLog(ExportService.class);
    private static int authStrategy = -1;
    private static int authLevel = -1;
    private static int sessionLifespan;

    private final static int MAX_AUTH_STRATEGY = 2;
    private final static int MAX_AUTH_LEVEL = 5;

    public OMElement testSession(OMElement inputElement) throws I2B2Exception, JsonSyntaxException {
        Assert.notNull(inputElement, "Export Cell: Incoming request is null");

        MessageHeaderType messageHeaderType = MessageManager.extractReqMess(inputElement).getMessageHeader();
        String requestJsonStr = MessageManager.extractObsBlob(inputElement);

        Gson gson = new Gson();
        TestSessionRequest request = gson.fromJson(requestJsonStr, TestSessionRequest.class);

        TestSessionResponse response = new TestSessionResponse();

        WSession wSession = sessionManager.getSession(request.getSessionId());
        if (wSession != null) {
            response.setValid(true);
        } else {
            response.setValid(false);
        }
        response.setLifeSpan(sessionLifespan);

        String tsrString = new GsonBuilder().create().toJson(response);

        ObservationSet observationSet = new ObservationSet();
        ObservationType observationType = new ObservationType();
        BlobType blobType = new BlobType();
        blobType.getContent().add(tsrString);
        observationType.setObservationBlob(blobType);
        observationSet.getObservation().add(observationType);

        ResponseMessageType responseMessageType = MessageFactory.createBuildResponse(messageHeaderType,
                observationSet);
        String rmtString = MessageFactory.convertToXMLString(responseMessageType);

        OMElement out = null;
        try {
            out = MessageFactory.createResponseOMElementFromString(rmtString);
        } catch (XMLStreamException e) {
            e.printStackTrace();
        }

        log.debug(rmtString);

        return out;
    }

    public OMElement openNewSession(OMElement inputElement) throws I2B2Exception, JsonSyntaxException {
        Assert.notNull(inputElement, "Export Cell: Incoming request is null");

        MessageHeaderType messageHeaderType = MessageManager.extractReqMess(inputElement).getMessageHeader();
        String requestJsonStr = MessageManager.extractObsBlob(inputElement);

        Gson gson = new Gson();
        OpenNewSessionRequest request = gson.fromJson(requestJsonStr, OpenNewSessionRequest.class);

        boolean validUser = false;
        if (authStrategy > 0) {
            try {
                validUser = validateUser(request.getNetwork());
            } catch (JAXBException | IOException | TransformerException e1) {
                // do nothing
            }
        } else {
            validUser = true;
        }

        OpenNewSessionResponse response = new OpenNewSessionResponse();
        if (!validUser) {
            String error = "You are not allowed to use export functions";
            response.setError(error);
        } else {
            WSession wSession = sessionManager.createNewSession();
            wSession.setNetwork(request.getNetwork());
            Session session = new Session();
            session.setId(wSession.getId());
            response.setSession(session);
        }

        String onsrString = new GsonBuilder().create().toJson(response);

        ObservationSet observationSet = new ObservationSet();
        ObservationType observationType = new ObservationType();
        BlobType blobType = new BlobType();
        blobType.getContent().add(onsrString);
        observationType.setObservationBlob(blobType);
        observationSet.getObservation().add(observationType);

        ResponseMessageType responseMessageType = MessageFactory.createBuildResponse(messageHeaderType,
                observationSet);
        String rmtString = MessageFactory.convertToXMLString(responseMessageType);

        OMElement out = null;
        try {
            out = MessageFactory.createResponseOMElementFromString(rmtString);
        } catch (XMLStreamException e) {
            e.printStackTrace();
        }

        log.debug(rmtString);

        return out;
    }

    public OMElement export(OMElement inputElement) throws I2B2Exception, JsonSyntaxException, ExportCellException {
        Assert.notNull(inputElement, "Export Cell: Incoming request is null");

        OMElement returnElement = null;
        MessageHeaderType messageHeaderType = MessageManager.extractReqMess(inputElement).getMessageHeader();
        String requestJsonStr = MessageManager.extractObsBlob(inputElement);

        Gson gson = new Gson();
        ExportRequest request = gson.fromJson(requestJsonStr, ExportRequest.class);

        String sessionId = request.getSessionId();
        WSession wSession = sessionManager.getSession(sessionId);

        if (wSession == null) {
            throw new ExportCellException("Session does not exist");
        }

        if (request.getNewPassword() != null) {
            wSession.getNetwork().setPassword(request.getNewPassword());
        } else {
            if (authStrategy > 1) {
                throw new ExportCellException("Password not provided.");
            }
        }

        boolean validUser = false;
        if (authStrategy > 1) {
            try {
                validUser = validateUser(wSession.getNetwork());
            } catch (JAXBException | IOException | TransformerException e1) {
                // do nothing
            }
        } else {
            validUser = true;
        }

        ExportResponse response = new ExportResponse();

        if (validUser) {
            response.setSessionId(sessionId);

            WExport wExport = null;
            wExport = wSession.addNewExport(request.getName());
            wExport.setExportParams(request.getExportParams());
            wExport.setConcepts(request.getConcepts());
            wExport.setPatSetId(request.getPatientSetId());
            wExport.setPatSetName(request.getPatientSetName());

            response.setExportId(wExport.getId());

            ExportRunnable erun = new ExportRunnable(wSession, wExport);
            Thread t = new Thread(erun);
            t.start();
        } else {
            String error = "You're not allowed to use export functions";
            response.setError(error);
        }

        String jsonRespStr = new GsonBuilder().create().toJson(response);

        ObservationSet observationSet = new ObservationSet();
        ObservationType observationType = new ObservationType();
        BlobType blobType = new BlobType();
        blobType.getContent().add(jsonRespStr);
        observationType.setObservationBlob(blobType);
        observationSet.getObservation().add(observationType);
        ResponseMessageType responseMessageType = MessageFactory.createBuildResponse(messageHeaderType,
                observationSet);
        String rmtStr = MessageFactory.convertToXMLString(responseMessageType);

        try {
            returnElement = MessageFactory.createResponseOMElementFromString(rmtStr);
        } catch (XMLStreamException e) {
            e.printStackTrace();
        }

        log.debug(rmtStr);

        return returnElement;
    }

    public OMElement exportList(OMElement inputElement) throws I2B2Exception, ExportCellException {
        Assert.notNull(inputElement, "Export Cell: Incoming request is null");

        OMElement returnElement = null;
        MessageHeaderType messageHeaderType = MessageManager.extractReqMess(inputElement).getMessageHeader();
        String requestJsonStr = MessageManager.extractObsBlob(inputElement);

        Gson gson = new Gson();
        ExportListRequest request = gson.fromJson(requestJsonStr, ExportListRequest.class);

        String sessionId = request.getSessionId();
        WSession wSession = sessionManager.getSession(sessionId);

        if (wSession == null) {
            throw new ExportCellException("Session does not exist");
        }

        if (request.getNewPassword() != null) {
            wSession.getNetwork().setPassword(request.getNewPassword());
        }

        boolean validUser = false;
        if (authStrategy > 1) {
            try {
                validUser = validateUser(wSession.getNetwork());
            } catch (JAXBException | IOException | TransformerException e1) {
                // do nothing
            }
        } else {
            validUser = true;
        }

        ExportListResponse response = new ExportListResponse();

        if (validUser) {
            response.setSessionId(sessionId);

            List<Export> exports = new ArrayList<>();
            for (WExport we : wSession.getExports()) {
                Export e = we.makeIOExport();
                exports.add(e);
            }
            response.setExports(exports);
        } else {
            String error = "You're not allowed to use export functions";
            response.setError(error);
        }

        String jsonRespStr = new GsonBuilder().create().toJson(response);

        ObservationSet observationSet = new ObservationSet();
        ObservationType observationType = new ObservationType();
        BlobType blobType = new BlobType();
        blobType.getContent().add(jsonRespStr);
        observationType.setObservationBlob(blobType);
        observationSet.getObservation().add(observationType);
        ResponseMessageType responseMessageType = MessageFactory.createBuildResponse(messageHeaderType,
                observationSet);
        String rmtStr = MessageFactory.convertToXMLString(responseMessageType);

        try {
            returnElement = MessageFactory.createResponseOMElementFromString(rmtStr);
        } catch (XMLStreamException e) {
            e.printStackTrace();
        }

        log.debug(rmtStr);

        return returnElement;
    }

    private boolean validateUser(Network network) throws JAXBException, IOException, TransformerException {
        boolean output = false;

        String pmRequest = MessageBuilder.buildPMGetServiceRequest(network);
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost(network.getProxyAddress());
        StringEntity entity1A = new StringEntity(pmRequest, Consts.UTF_8);

        entity1A.setContentType("text/xml");
        entity1A.setChunked(true);
        httpPost.setEntity(entity1A);

        CloseableHttpResponse response = null;
        try {
            response = httpclient.execute(httpPost);
            log.debug("Proxy: " + network.getProxyAddress());
        } catch (HttpHostConnectException hhce) {
            try {
                if (network.getStaticProxyAddress() != null) {
                    httpPost = new HttpPost(network.getStaticProxyAddress());
                    httpPost.setEntity(entity1A);

                    response = httpclient.execute(httpPost);
                    log.debug("Proxy: " + network.getStaticProxyAddress());
                }
            } catch (HttpHostConnectException e) {
                throw e;
            }
        }

        try {
            HttpEntity entity1R = response.getEntity();

            String responseString = EntityUtils.toString(entity1R);

            ResponseMessageType rmt = JAXB.unmarshal(new StringReader(responseString), ResponseMessageType.class);

            ResponseHeaderType responseHeader = rmt.getResponseHeader();
            ResultStatusType responseStatus = responseHeader.getResultStatus();
            if (responseStatus.getStatus().getType().equals("ERROR")) {
                return false;
            }

            BodyType body = rmt.getMessageBody();

            ElementNSImpl bodyEl = (ElementNSImpl) body.getAny().get(0);
            String bodyStr = elementToString(bodyEl);

            ConfigureType configureType = JAXB.unmarshal(new StringReader(bodyStr), ConfigureType.class);
            UserType userType = configureType.getUser();

            if (userType.isIsAdmin()) {
                output = true;
            } else {
                List<ProjectType> userProjects = userType.getProject();
                for (ProjectType pt : userProjects) {
                    if (pt.getId().equals(network.getProject())) {
                        if (userAccessLevel(pt.getRole()) >= authLevel) {
                            output = true;
                        }
                    }
                }
            }

            EntityUtils.consume(entity1R);
        } finally {
            response.close();
        }

        return output;
    }

    private int userAccessLevel(List<String> roles) {
        int output = 0;
        for (String role : roles) {
            int roleLevel = dataAccessLevel(role);
            if (roleLevel > output) {
                output = roleLevel;
            }
        }
        return output;
    }

    private int dataAccessLevel(String dataAccess) {
        switch (dataAccess.toUpperCase()) {
        case "DATA_OBFSC":
            return 1;
        case "DATA_AGG":
            return 2;
        case "DATA_LDS":
            return 3;
        case "DATA_DEID":
            return 4;
        case "DATA_PROT":
            return 5;
        default:
            return 0;
        }
    }

    private String elementToString(ElementNSImpl element) throws TransformerException {

        Document doc = element.getOwnerDocument();
        DOMSource domSource = new DOMSource(doc);
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        transformer.transform(domSource, result);

        return writer.toString();
    }

    private void authStrategy() {
        Properties exportCellProperties;
        InputStream is_i2b2 = ExportService.class.getClassLoader()
                .getResourceAsStream("conf/exportcell.properties");
        exportCellProperties = new Properties();
        try {
            exportCellProperties.load(is_i2b2);
        } catch (IOException e) {
            e.printStackTrace();
        }

        switch (exportCellProperties.getProperty("exportcell.auth.strategy").toUpperCase()) {
        case "NONE":
            authStrategy = 0;
            break;
        case "SINGLE":
            authStrategy = 1;
            break;
        case "MULTI":
            authStrategy = 2;
            break;
        default:
            authStrategy = MAX_AUTH_STRATEGY;
        }
    }

    private void authLevel() {
        Properties exportCellProperties;
        InputStream is_i2b2 = ExportService.class.getClassLoader()
                .getResourceAsStream("conf/exportcell.properties");
        exportCellProperties = new Properties();
        try {
            exportCellProperties.load(is_i2b2);
        } catch (IOException e) {
            e.printStackTrace();
        }

        authLevel = dataAccessLevel(exportCellProperties.getProperty("exportcell.auth.level"));
        if (authLevel == 0) {
            authLevel = MAX_AUTH_LEVEL;
        }
    }

    private void sessionLifespan() {
        Properties exportCellProperties;
        InputStream is_i2b2 = ExportService.class.getClassLoader()
                .getResourceAsStream("conf/exportcell.properties");
        exportCellProperties = new Properties();
        try {
            exportCellProperties.load(is_i2b2);
        } catch (IOException e) {
            e.printStackTrace();
        }

        sessionLifespan = Integer.parseInt(exportCellProperties.getProperty("exportcell.session.timeout.minutes"));
    }

    // This method will be called before each call
    public synchronized void init(ServiceContext serviceContext) {
    }

    // This method will be called after each call
    public synchronized void destroy(ServiceContext serviceContext) {
    }

    //Called at startup
    public void startUp(ConfigurationContext configctx, AxisService service) {
        authStrategy();
        authLevel();
        sessionLifespan();

        sessionManager = new WSessionManager();

        CleanerRunnable cleanRun = new CleanerRunnable(sessionManager);
        Thread t = new Thread(cleanRun);
        t.start();
    }

    //Should be called at shutdown
    public void shutDown(ConfigurationContext configctx, AxisService service) {
    }
}