oscar.oscarLab.ca.all.pageUtil.LabUploadAction.java Source code

Java tutorial

Introduction

Here is the source code for oscar.oscarLab.ca.all.pageUtil.LabUploadAction.java

Source

/**
 * Copyright (c) 2001-2002. Department of Family Medicine, McMaster University. All Rights Reserved.
 * This software is published under the GPL GNU General Public License.
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version. 
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * This software was written for the
 * Department of Family Medicine
 * McMaster University
 * Hamilton
 * Ontario, Canada
 */

/*
 * LabUploadAction.java
 *
 * Created on June 12, 2007, 2:31 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package oscar.oscarLab.ca.all.pageUtil;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.upload.FormFile;
import org.oscarehr.common.OtherIdManager;
import org.oscarehr.common.dao.OscarKeyDao;
import org.oscarehr.common.dao.PublicKeyDao;
import org.oscarehr.common.model.OscarKey;
import org.oscarehr.common.model.OtherId;
import org.oscarehr.util.MiscUtils;
import org.oscarehr.util.SpringUtils;

import oscar.OscarProperties;
import oscar.oscarLab.FileUploadCheck;
import oscar.oscarLab.ca.all.parsers.HHSEmrDownloadHandler;
import oscar.oscarLab.ca.all.upload.HandlerClassFactory;
import oscar.oscarLab.ca.all.upload.handlers.MessageHandler;
import oscar.oscarLab.ca.all.util.Utilities;

public class LabUploadAction extends Action {
    protected static Logger logger = Logger.getLogger(LabUploadAction.class);

    @Override
    public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
            HttpServletResponse response) {
        LabUploadForm frm = (LabUploadForm) form;
        FormFile importFile = frm.getImportFile();

        String signature = request.getParameter("signature");
        String key = request.getParameter("key");
        String service = request.getParameter("service");
        String outcome = "";
        String audit = "";
        Integer httpCode = 200;

        ArrayList<Object> clientInfo = getClientInfo(service);
        PublicKey clientKey = (PublicKey) clientInfo.get(0);
        String type = (String) clientInfo.get(1);

        try {

            InputStream is = decryptMessage(importFile.getInputStream(), key, clientKey);
            String fileName = importFile.getFileName();
            String filePath = Utilities.saveFile(is, fileName);
            importFile.getInputStream().close();
            File file = new File(filePath);

            if (validateSignature(clientKey, signature, file)) {
                logger.debug("Validated Successfully");
                MessageHandler msgHandler = HandlerClassFactory.getHandler(type);

                if (type.equals("HHSEMR") && OscarProperties.getInstance()
                        .getProperty("lab.hhsemr.filter_ordering_provider", "false").equals("true")) {
                    logger.info("Applying filter to HHS EMR lab");
                    String hl7Data = FileUtils.readFileToString(file, "UTF-8");
                    HHSEmrDownloadHandler filterHandler = new HHSEmrDownloadHandler();
                    filterHandler.init(hl7Data);
                    OtherId providerOtherId = OtherIdManager.searchTable(OtherIdManager.PROVIDER, "STAR",
                            filterHandler.getClientRef());
                    if (providerOtherId == null) {
                        logger.info("Filtering out this message, as we don't have client ref "
                                + filterHandler.getClientRef() + " in our database (" + file + ")");
                        outcome = "uploaded";
                        request.setAttribute("outcome", outcome);
                        return mapping.findForward("success");
                    }
                }

                is = new FileInputStream(file);
                try {
                    int check = FileUploadCheck.addFile(file.getName(), is, "0");
                    if (check != FileUploadCheck.UNSUCCESSFUL_SAVE) {
                        if ((audit = msgHandler.parse(service, filePath, check)) != null) {
                            outcome = "uploaded";
                            httpCode = HttpServletResponse.SC_OK;
                        } else {
                            outcome = "upload failed";
                            httpCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
                        }
                    } else {
                        outcome = "uploaded previously";
                        httpCode = HttpServletResponse.SC_CONFLICT;
                    }
                } finally {
                    is.close();
                }
            } else {
                logger.info("failed to validate");
                outcome = "validation failed";
                httpCode = HttpServletResponse.SC_NOT_ACCEPTABLE;
            }
        } catch (Exception e) {
            MiscUtils.getLogger().error("Error", e);
            outcome = "exception";
            httpCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
        }
        request.setAttribute("outcome", outcome);
        request.setAttribute("audit", audit);

        if (request.getParameter("use_http_response_code") != null) {
            try {
                response.sendError(httpCode, outcome);
            } catch (IOException e) {
                logger.error("Error", e);
            }
            return (null);
        } else
            return mapping.findForward("success");
    }

    public LabUploadAction() {
    }

    /*
     * Decrypt the encrypted message and return the original version of the message as an InputStream
     */
    public static InputStream decryptMessage(InputStream is, String skey, PublicKey pkey) {

        Base64 base64 = new Base64(0);

        // Decrypt the secret key and the message
        try {

            // retrieve the servers private key
            PrivateKey key = getServerPrivate();

            // Decrypt the secret key using the servers private key
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] newSecretKey = cipher.doFinal(base64.decode(skey.getBytes(MiscUtils.ENCODING)));

            // Decrypt the message using the secret key
            SecretKeySpec skeySpec = new SecretKeySpec(newSecretKey, "AES");
            Cipher msgCipher = Cipher.getInstance("AES");
            msgCipher.init(Cipher.DECRYPT_MODE, skeySpec);

            is = new CipherInputStream(is, msgCipher);

            // Return the decrypted message
            return (new BufferedInputStream(is));

        } catch (Exception e) {
            logger.error("Could not decrypt the message", e);
            return (null);
        }
    }

    /*
     * Check that the signature 'sigString' matches the message InputStream 'msgIS' thus verifying that the message has not been altered.
     */
    public static boolean validateSignature(PublicKey key, String sigString, File input) {
        Base64 base64 = new Base64(0);
        byte[] buf = new byte[1024];

        try {

            InputStream msgIs = new FileInputStream(input);
            Signature sig = Signature.getInstance("MD5WithRSA");
            sig.initVerify(key);

            // Read in the message bytes and update the signature
            int numRead = 0;
            while ((numRead = msgIs.read(buf)) >= 0) {
                sig.update(buf, 0, numRead);
            }
            msgIs.close();

            return (sig.verify(base64.decode(sigString.getBytes(MiscUtils.ENCODING))));

        } catch (Exception e) {
            logger.debug("Could not validate signature: " + e);
            MiscUtils.getLogger().error("Error", e);
            return (false);
        }
    }

    /*
     * Retrieve the clients public key from the database
     */
    public static ArrayList<Object> getClientInfo(String service) {

        PublicKey Key = null;
        Base64 base64 = new Base64(0);
        String keyString = "";
        String type = "";
        byte[] publicKey;
        ArrayList<Object> info = new ArrayList<Object>();

        try {
            PublicKeyDao publicKeyDao = (PublicKeyDao) SpringUtils.getBean("publicKeyDao");
            org.oscarehr.common.model.PublicKey publicKeyObject = publicKeyDao.find(service);

            if (publicKeyObject != null) {
                keyString = publicKeyObject.getBase64EncodedPublicKey();
                type = publicKeyObject.getType();
            }

            publicKey = base64.decode(keyString.getBytes(MiscUtils.ENCODING));
            X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(publicKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            Key = keyFactory.generatePublic(pubKeySpec);

            info.add(Key);
            info.add(type);

        } catch (Exception e) {
            logger.error("Could not retrieve private key: ", e);
        }
        return (info);
    }

    /*
     * Retrieve the servers private key from the database
     */
    private static PrivateKey getServerPrivate() {

        PrivateKey Key = null;
        Base64 base64 = new Base64(0);
        byte[] privateKey;

        try {
            OscarKeyDao oscarKeyDao = (OscarKeyDao) SpringUtils.getBean("oscarKeyDao");
            OscarKey oscarKey = oscarKeyDao.find("oscar");
            logger.info("oscar key: " + oscarKey);

            privateKey = base64.decode(oscarKey.getPrivateKey().getBytes(MiscUtils.ENCODING));
            PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(privateKey);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            Key = keyFactory.generatePrivate(privKeySpec);
        } catch (Exception e) {
            logger.error("Could not retrieve private key: ", e);
        }
        return (Key);
    }

}