org.oscarehr.integration.excelleris.com.colcamex.www.core.Connect.java Source code

Java tutorial

Introduction

Here is the source code for org.oscarehr.integration.excelleris.com.colcamex.www.core.Connect.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
 */
package org.oscarehr.integration.excelleris.com.colcamex.www.core;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.CookieHandler;
import java.net.CookieManager;
import java.net.CookiePolicy;
import java.net.MalformedURLException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.io.IOUtils;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

/**
 * @author Dennis Warren Colcamex Resources
 * 
 * Major Contributors: 
 *  OSCARprn
 *  NERD
 *   
 * This community edition of Expedius is for use at your own risk, without warranty, and 
 * support. 
 * 
 */
public class Connect {

    private static Connect instance = null;

    // all connection logging is handled by java.util.logging in a custom log formatter.
    private static Logger logger = Logger.getLogger("ExpediusConnect"); //ExpediusLog.getLog();

    private HttpsURLConnection sconn;
    private SSLSocketFactory socketFactory;
    private W3CDocumentHandler documentHandler;
    private DocumentBuilder documentBuilder;
    private boolean hasResponse;
    private Document response;
    private InputStream in;
    private boolean loggedIn;
    private int responseCode;

    private Connect() {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        try {
            documentBuilder = documentBuilderFactory.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            logger.log(Level.SEVERE, "Expedius connect failed to initialize document factory.");
        }
        _init();
    }

    private Connect(W3CDocumentHandler documentBuilder) {
        setDocumentHandler(documentBuilder);
        _init();
    }

    private void _init() {
        CookieManager cookieManager = new CookieManager();
        cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
        CookieHandler.setDefault(cookieManager);
    }

    /**
     * Static constructor. Returns an instance of Connect.
     * Set with Expedius Document Handler or null for default generic dom parser.
     * 
     * @return ExpediusConnect connection class.
     */
    public static Connect getInstance(W3CDocumentHandler documentBuilder) {

        if (instance == null) {

            if (documentBuilder == null) {
                instance = new Connect();
            } else {
                instance = new Connect(documentBuilder);
            }

        }

        return instance;
    }

    public void connect(URL httpsUri) throws SocketTimeoutException, IOException {

        if ((httpsUri != null) && (getSocketFactory() != null)) {
            connect(httpsUri, getSocketFactory());
        } else {
            logger.log(Level.WARNING, "The connection link or SSL socket is missing. Unable to connect.");
        }
    }

    public void connect(String httpsUri) throws SocketTimeoutException, IOException {

        if ((httpsUri != null) && (getSocketFactory() != null)) {
            connect(httpsUri, getSocketFactory());
        } else {
            logger.log(Level.WARNING, "The connection link or SSL socket is missing. Unable to connect.");
        }

    }

    public void connect(String httpsUri, SSLSocketFactory sf) throws SocketTimeoutException, IOException {

        URL path = null;
        if (httpsUri != null) {
            try {
                path = new URL(httpsUri);
            } catch (MalformedURLException e) {
                logger.log(Level.SEVERE, "The URI for connect is not correctly formed.", e);
                setResponseCode(HttpsURLConnection.HTTP_INTERNAL_ERROR);
            } finally {
                if (path != null) {
                    connect(path, sf);
                }
            }
        }

    }

    /**
     * Connection method. Confirms connection to server and sets up
     * any security certificates required.
     * 
     * @param excellerisUri
     * @param protocol
     * @return
     * @throws SocketTimeoutException 
     * @throws HttpException
     * @throws IOException
     * @throws SAXException 
     * @throws ParserConfigurationException 
     */
    public void connect(URL httpsUri, SSLSocketFactory sf) throws SocketTimeoutException, IOException {

        setHasResponse(Boolean.FALSE);
        setSocketFactory(sf);

        in = execute(httpsUri);

        if (in != null) {

            if (in.available() > 0) {

                try {
                    if (documentHandler != null) {
                        setResponse(documentHandler.parse(in));
                    } else if (documentBuilder != null) {
                        setResponse(documentBuilder.parse(in));
                    }
                    setHasResponse(Boolean.TRUE);
                } catch (SAXException e) {
                    logger.log(Level.SEVERE,
                            "Expedius connection manager failed to parse a server response during Connect.", e);
                } finally {
                    close();
                    logger.info("Expedius connection status is HttpsURLConnection [" + responseCode + "]");
                }
            }
        }
    }

    /**
     * Overloaded for String input with place holders @password and @username.
     * @param username
     * @param password
     * @param httpsUri
     * @return
     * @throws IOException
     * @throws SAXException
     * @throws ParserConfigurationException
     */
    public void login(String username, String password, String httpsUri)
            throws SocketTimeoutException, IOException {

        if ((username != null) && (password != null)) {

            if (httpsUri.contains("@username") && httpsUri.contains("@password")) {
                httpsUri = httpsUri.replaceAll("@username", username).replaceAll("@password", password);
            }

            login(httpsUri);
        }

    }

    public void login(String query) throws SocketTimeoutException, IOException {

        URL path = null;
        try {
            path = new URL(query);
        } catch (MalformedURLException e) {
            logger.log(Level.SEVERE, "The URI for login is not correctly formed.", e);
            setResponseCode(HttpsURLConnection.HTTP_INTERNAL_ERROR);
        } finally {
            if (path != null) {
                login(path);
            }
        }
    }

    /**
     * Login method parses the login script with a login username and password.
     * 
     * @param username
     * @param password
     * @param query
     * @return
     * @throws IOException 
     * @throws MalformedURLException 
     * @throws SocketTimeoutException 
     * @throws SAXException 
     * @throws ParserConfigurationException 
     * @throws Exception
     */
    public void login(URL query) throws SocketTimeoutException, IOException {

        setHasResponse(Boolean.FALSE);

        if (query != null) {

            in = execute(query);

            if (in != null) {

                if (in.available() > 0) {
                    try {
                        if (documentHandler != null) {
                            setResponse(documentHandler.parse(in));
                        } else if (documentBuilder != null) {
                            setResponse(documentBuilder.parse(in));
                        }
                        setHasResponse(Boolean.TRUE);
                    } catch (SAXException e) {
                        logger.log(Level.WARNING,
                                "Expedius connection manager failed to parse a server response during Login.", e);
                    } finally {
                        if (getResponseCode() == HttpsURLConnection.HTTP_OK) {
                            setLoggedIn(Boolean.TRUE);
                        }

                        close();
                    }
                }

            }
        }
    }

    /**
     * Overload for string input.
     * @param httpsUri
     * @return
     * @throws MalformedURLException 
     * @throws SocketTimeoutException 
     * @throws IOException
     * @throws SAXException
     * @throws ParserConfigurationException
     */
    public void fetch(String httpsUri) throws SocketTimeoutException, IOException {
        URL path = null;
        try {
            path = new URL(httpsUri);
        } catch (MalformedURLException e) {
            logger.log(Level.SEVERE, "The URI for fetch is not correctly formed.", e);
            setResponseCode(HttpsURLConnection.HTTP_INTERNAL_ERROR);
        } finally {
            if (path != null) {
                fetch(path);
            }
        }
    }

    /**
     * Fetch the xml file. (HL7)
     * @param query
     * @return HTTP response code
     * @throws SocketTimeoutException 
     * @throws IOException
     * @throws SAXException
     */
    public void fetch(URL httpsUri) throws SocketTimeoutException, IOException {

        setHasResponse(Boolean.FALSE);
        in = execute(httpsUri);

        if (in != null) {

            StringWriter writer = new StringWriter();
            try {
                IOUtils.copy(in, writer, "UTF-8");
            } catch (IOException e) {
                logger.log(Level.SEVERE, "", e);

            }

            if (in.available() > 0) {

                try {
                    if (documentHandler != null) {
                        setResponse(documentHandler.parse(in));
                    } else if (documentBuilder != null) {
                        setResponse(documentBuilder.parse(in));
                    }
                    setHasResponse(Boolean.TRUE);
                } catch (SAXException e) {
                    logger.log(Level.WARNING,
                            "Expedius connection manager failed to parse a server response during Fetch.", e);
                } finally {
                    close();
                }
            } else {
                setResponseCode(HttpsURLConnection.HTTP_NO_CONTENT);
            }
        }

    }

    /**
     * Option to acknowledge batches of labs. As for the IHA POI.
     * @param httpsUriList
     * @return
     * @throws SocketTimeoutException
     * @throws MalformedURLException
     * @throws IOException
     */
    public void acknowledge(ArrayList<String> httpsUriList) throws SocketTimeoutException, IOException {

        if (httpsUriList.size() > 0) {
            Iterator<String> httpsList = httpsUriList.iterator();
            while ((getResponseCode() == HttpsURLConnection.HTTP_OK) && (httpsList.hasNext())) {
                acknowledge(httpsList.next());
            }
        }

        setResponseCode(sconn.getResponseCode());

    }

    public void acknowledge(String httpsUri) throws SocketTimeoutException, IOException {
        URL path = null;
        try {
            path = new URL(httpsUri);
        } catch (MalformedURLException e) {
            logger.log(Level.SEVERE, "The URI for acknowledge is not correctly formed.", e);
            setResponseCode(HttpsURLConnection.HTTP_INTERNAL_ERROR);
        } finally {
            if (path != null) {
                acknowledge(path);
            }
        }
    }

    /**
     * Send an acknowledge signal that the labs were 
     * retrieved.  This way the same labs will not get down loaded again
     * 
     * @return HTTP response code.
     * @param query
     * @throws IOException
     * @throws SAXException 
     */
    public void acknowledge(URL httpsUri) throws SocketTimeoutException, IOException {

        setHasResponse(Boolean.FALSE);
        in = execute(httpsUri);

        if (in != null) {

            if (in.available() > 0) {
                try {
                    if (documentHandler != null) {
                        setResponse(documentHandler.parse(in));
                    } else if (documentBuilder != null) {
                        setResponse(documentBuilder.parse(in));
                    }
                    setHasResponse(Boolean.TRUE);
                } catch (SAXException e) {
                    logger.log(Level.WARNING,
                            "Expedius connection manager failed to parse a server response during Acknowledge.", e);
                } finally {
                    close();
                }
            }

        }

    }

    /**
     * 
     * @param httpsUri
     * @return
     * @throws SocketTimeoutException
     * @throws MalformedURLException
     * @throws IOException
     * @throws SAXException
     */
    public void logout(String httpsUri) throws SocketTimeoutException, IOException {
        URL path = null;
        try {
            path = new URL(httpsUri);
        } catch (MalformedURLException e) {
            logger.log(Level.SEVERE, "The URI for logout is not correctly formed.", e);
            setResponseCode(HttpsURLConnection.HTTP_INTERNAL_ERROR);
        } finally {
            if (path != null) {
                logout(path);
            }
        }
    }

    /**
     * Logout and close the connection.
     * Is is important to logout to maintain security.
     * 
     * @param query
     * @throws MalformedURLException
     * @throws IOException
     * @throws SAXException 
     */
    public void logout(URL httpsUri) throws SocketTimeoutException, IOException {

        setHasResponse(Boolean.FALSE);

        if (isLoggedIn()) {
            in = execute(httpsUri);
        }

        if (in != null) {

            // this needs to be worked around because Excelleris 
            // returns an invalid response.
            if (in.available() > 0) {
                try {
                    if (documentHandler != null) {
                        setResponse(documentHandler.parse(in));
                    } else if (documentBuilder != null) {
                        setResponse(documentBuilder.parse(in));
                    }
                    setHasResponse(Boolean.TRUE);
                } catch (SAXException e) {
                    logger.log(Level.WARNING, "Expedius connection manager failed to parse a server response.", e);
                } finally {
                    close();
                    setLoggedIn(Boolean.FALSE);
                    logger.info("Disconnected");
                }

            }
        }
    }

    /**
     * Close all statement. 
     * @throws IOException 
     */
    public void close() throws SocketTimeoutException, IOException {

        if (in != null) {
            in.close();
        }

        if (sconn != null) {
            sconn.disconnect();
        }
    }

    public SSLSocketFactory getSocketFactory() {
        return socketFactory;
    }

    public void setSocketFactory(SSLSocketFactory socketFactory) {
        this.socketFactory = socketFactory;
    }

    /**
     * A Switch for when there are lab results to retrieve.
     * @return
     */

    public boolean hasResponse() {
        return hasResponse;
    }

    private void setHasResponse(boolean response) {
        this.hasResponse = response;
    }

    private void setResponse(Document response) {
        this.response = response;
    }

    public Document getResponse() {
        return this.response;
    }

    public int getResponseCode() {
        return responseCode;
    }

    private void setResponseCode(int responseCode) {
        this.responseCode = responseCode;
    }

    /**
     * Current logged in status 
     * @return boolean
     */
    public boolean isLoggedIn() {
        return loggedIn;
    }

    public void setLoggedIn(boolean loggedIn) {
        this.loggedIn = loggedIn;
    }

    /**
     * Execute get and post commands to the server
     * Returns an input stream.
     * @param query
     * @return
     * @throws IOException
     */
    private InputStream execute(URL httpsUri) throws IOException {

        if (httpsUri != null) {

            sconn = (HttpsURLConnection) httpsUri.openConnection();
            sconn.setConnectTimeout(5000);
            sconn.setReadTimeout(10000);
            sconn.setRequestMethod("GET");
            //sconn.setDoOutput(false);
            sconn.setDoInput(true);

            if (getSocketFactory() != null) {
                sconn.setSSLSocketFactory(this.getSocketFactory());
            }

            sconn.connect();

            setResponseCode(sconn.getResponseCode());

            if (getResponseCode() == HttpsURLConnection.HTTP_OK) {
                return sconn.getInputStream();
            }
        }

        return null;
    }

    public W3CDocumentHandler getDocumentHandler() {
        return documentHandler;
    }

    public void setDocumentHandler(W3CDocumentHandler documentHandler) {
        this.documentHandler = documentHandler;
    }

}