org.ut.biolab.medsavant.MedSavantClient.java Source code

Java tutorial

Introduction

Here is the source code for org.ut.biolab.medsavant.MedSavantClient.java

Source

/**
 * See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This software 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 Lesser General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this software; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF
 * site: http://www.fsf.org.
 */
package org.ut.biolab.medsavant;

import com.apple.eawt.AboutHandler;
import com.apple.eawt.AppEvent;
import com.apple.eawt.Application;
import com.apple.eawt.PreferencesHandler;
import com.apple.eawt.QuitHandler;
import com.apple.eawt.QuitResponse;
import org.ut.biolab.medsavant.shared.serverapi.CustomTablesAdapter;
import org.ut.biolab.medsavant.shared.serverapi.OntologyManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.NetworkManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.SessionManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.UserManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.CohortManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.AnnotationManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.VariantManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.SetupAdapter;
import org.ut.biolab.medsavant.shared.serverapi.GeneSetManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.LogManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.MedSavantServerRegistry;
import org.ut.biolab.medsavant.shared.serverapi.SettingsManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.ProjectManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.NotificationManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.DBUtilsAdapter;
import org.ut.biolab.medsavant.shared.serverapi.ReferenceManagerAdapter;
import org.ut.biolab.medsavant.shared.serverapi.PatientManagerAdapter;
import java.rmi.*;
import java.rmi.registry.*;
import java.awt.Insets;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.plaf.ColorUIResource;

import com.jidesoft.plaf.LookAndFeelFactory;
import gnu.getopt.Getopt;
import java.awt.Color;
import java.io.File;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.net.NoRouteToHostException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.net.ssl.SSLHandshakeException;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.swing.JOptionPane;
import javax.swing.UIDefaults;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.plaf.InsetsUIResource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.ut.biolab.medsavant.client.controller.SettingsController;
import org.ut.biolab.medsavant.client.util.ClientMiscUtils;
import org.ut.biolab.medsavant.client.util.MedSavantExceptionHandler;
import org.ut.biolab.medsavant.client.util.MedSavantWorker;
import org.ut.biolab.medsavant.client.util.ServerModificationInvocationHandler;
import org.ut.biolab.medsavant.shared.util.MiscUtils;
import org.ut.biolab.medsavant.client.view.MedSavantFrame;
import org.ut.biolab.medsavant.client.view.font.FontFactory;
import org.ut.biolab.medsavant.client.view.login.SplashFrame;
import org.ut.biolab.medsavant.client.view.util.DialogUtils;
import org.ut.biolab.medsavant.shared.model.exception.LockException;
import org.ut.biolab.medsavant.shared.model.SessionExpiredException;
import org.ut.biolab.medsavant.shared.serverapi.RegionSetManagerAdapter;
import org.ut.biolab.medsavant.shared.util.DirectorySettings;
import org.ut.biolab.medsavant.shared.util.VersionSettings;
import org.ut.biolab.savant.analytics.savantanalytics.AnalyticsAgent;

public class MedSavantClient implements MedSavantServerRegistry {

    private static final Log LOG = LogFactory.getLog(MedSavantClient.class);
    public static CustomTablesAdapter CustomTablesManager;
    public static AnnotationManagerAdapter AnnotationManagerAdapter;
    public static CohortManagerAdapter CohortManager;
    public static GeneSetManagerAdapter GeneSetManager;
    public static LogManagerAdapter LogManager;
    public static NetworkManagerAdapter NetworkManager;
    public static OntologyManagerAdapter OntologyManager;
    public static PatientManagerAdapter PatientManager;
    public static ProjectManagerAdapter ProjectManager;
    public static UserManagerAdapter UserManager;
    public static SessionManagerAdapter SessionManager;
    public static SettingsManagerAdapter SettingsManager;
    public static RegionSetManagerAdapter RegionSetManager;
    public static ReferenceManagerAdapter ReferenceManager;
    public static DBUtilsAdapter DBUtils;
    public static SetupAdapter SetupManager;
    public static VariantManagerAdapter VariantManager; //proxy
    public static NotificationManagerAdapter NotificationManager;
    private static boolean initialized = false;
    private static String[] restartCommand;
    private static boolean restarting = false;
    private static final Object managerLock = new Object();

    //Proxy the adapters to process annotations and fire events to the cache controller.
    private static void initProxies() {
        VariantManager = (VariantManagerAdapter) Proxy.newProxyInstance(VariantManager.getClass().getClassLoader(),
                new Class[] { VariantManagerAdapter.class },
                new ServerModificationInvocationHandler<VariantManagerAdapter>(VariantManager));

        CohortManager = (CohortManagerAdapter) Proxy.newProxyInstance(CohortManager.getClass().getClassLoader(),
                new Class[] { CohortManagerAdapter.class },
                new ServerModificationInvocationHandler<CohortManagerAdapter>(CohortManager));

        PatientManager = (PatientManagerAdapter) Proxy.newProxyInstance(PatientManager.getClass().getClassLoader(),
                new Class[] { PatientManagerAdapter.class },
                new ServerModificationInvocationHandler<PatientManagerAdapter>(PatientManager));

        RegionSetManager = (RegionSetManagerAdapter) Proxy.newProxyInstance(
                RegionSetManager.getClass().getClassLoader(), new Class[] { RegionSetManagerAdapter.class },
                new ServerModificationInvocationHandler<RegionSetManagerAdapter>(RegionSetManager));

        OntologyManager = (OntologyManagerAdapter) Proxy.newProxyInstance(
                OntologyManager.getClass().getClassLoader(), new Class[] { OntologyManagerAdapter.class },
                new ServerModificationInvocationHandler<OntologyManagerAdapter>(OntologyManager));
    }

    /**
     * Restarts MedSavant (This function has NOT been tested with Web Start)
     */
    public static void restart() {
        if (!restarting) {
            restarting = true;
            try {
                /*  if (msg != null) {
                 DialogUtils.displayMessage("MedSavant needs to restart.", msg);
                 }*/
                SettingsController.getInstance().setBoolean("BootFromLogout", true);
                System.out.println("Restarting with " + restartCommand[0]);
                Runtime.getRuntime().exec(restartCommand);
                System.exit(0);
            } catch (IOException e) { //thrown by exec
                DialogUtils.displayError("Error restarting MedSavant. Please restart MedSavant manually.");
                LOG.error(e);
            } catch (Exception e) {
                LOG.error(e);
            }
        }
    }

    public static void setRestartCommand(String[] args) {
        List<String> restartCommandList = new ArrayList<String>();

        String launcher = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
        restartCommandList.add(launcher);
        for (String jvmArg : ManagementFactory.getRuntimeMXBean().getInputArguments()) {
            restartCommandList.add(jvmArg);
        }
        restartCommandList.add("-cp");
        restartCommandList.add(ManagementFactory.getRuntimeMXBean().getClassPath());
        restartCommandList.add(MedSavantClient.class.getName());
        for (String arg : args) {
            restartCommandList.add(arg);
        }

        restartCommand = restartCommandList.toArray(new String[restartCommandList.size()]);
    }

    /**
     * Ensure the user is running Java 1.7+
     */
    static public void checkJavaVersion() {
        System.out.println(System.getProperty("java.specification.version"));
        String javaVersion = System.getProperty("java.specification.version");
        if (javaVersion.equals("1.7") || javaVersion.equals("1.8")) {
            return;
        }
        DialogUtils.displayError("Incompatible Java Version",
                "Please upgrade your version of Java to 1.7 or greater.");
        System.exit(1);
    }

    static public void main(String args[]) {

        //checkJavaVersion();      
        new MedSavantWorker<Void>("Analytics Start") {

            @Override
            protected Void doInBackground() throws Exception {
                try {
                    AnalyticsAgent.onStartSession("MedSavant", VersionSettings.getVersionString());
                } catch (Exception ex) {
                    LOG.error("Couldn't connect to analytics agent.");
                }
                return null;
            }

            @Override
            protected void showSuccess(Void result) {

            }

        }.execute();

        // Avoids "Comparison method violates its general contract" bug.
        // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7075600
        System.setProperty("java.util.Arrays.useLegacyMergeSort", "true");
        setRestartCommand(args);
        setExceptionHandler();

        verifyJIDE();
        setLAF();

        // initialize settings
        SettingsController.getInstance();

        Getopt g = new Getopt("MedSavant", args, "h:p:d:u:w:");
        int c;

        while ((c = g.getopt()) != -1) {
            switch (c) {
            case 'h':
                String host = g.getOptarg();
                SettingsController.getInstance().setServerAddress(host);
                break;
            case 'p':
                int port = Integer.parseInt(g.getOptarg());
                SettingsController.getInstance().setServerPort(port + "");
                break;
            case 'd':
                String dbname = g.getOptarg();
                SettingsController.getInstance().setDBName(dbname);
                break;
            case 'u':
                String username = g.getOptarg();
                SettingsController.getInstance().setUsername(username);
                break;
            case 'w':
                String password = g.getOptarg();
                SettingsController.getInstance().setPassword(password);
                break;
            case '?':
                break; // getopt() already printed an error
            default:
                System.out.print("getopt() returned " + c + "\n");
            }
        }

        //Setup temporary directories
        String username = System.getProperty("user.name");
        DirectorySettings.setTmpDirectory(
                (new File(System.getProperty("java.io.tmpdir"), "msavant_" + username)).getAbsolutePath());
        DirectorySettings.setMedSavantDirectory(
                (new File(System.getProperty("user.home"), MiscUtils.WINDOWS ? "medsavant" : ".medsavant"))
                        .getAbsolutePath());

        LOG.info("MedSavant booted");
        System.out.println("READY.");
        SplashFrame loginFrame = new SplashFrame();
        loginFrame.setVisible(true);

    }

    public static void initializeRegistry(String serverAddress, String serverPort)
            throws RemoteException, NotBoundException, NoRouteToHostException, ConnectIOException {

        if (initialized) {
            return;
        }

        int port = (new Integer(serverPort)).intValue();

        Registry registry;

        LOG.debug("Connecting to MedSavantServerEngine @ " + serverAddress + ":" + serverPort + "...");

        try {
            registry = LocateRegistry.getRegistry(serverAddress, port, new SslRMIClientSocketFactory());
            LOG.debug("Retrieving adapters...");
            setAdaptersFromRegistry(registry);
            LOG.info("Connected with SSL/TLS Encryption");
        } catch (ConnectIOException ex) {
            if (ex.getCause() instanceof SSLHandshakeException) {
                registry = LocateRegistry.getRegistry(serverAddress, port);
                LOG.debug("Retrieving adapters...");
                setAdaptersFromRegistry(registry);
                LOG.info("Connected without SSL/TLS encryption");
            }
        }
        LOG.debug("Done");

    }

    private static void setAdaptersFromRegistry(Registry registry)
            throws RemoteException, NotBoundException, NoRouteToHostException, ConnectIOException {
        CustomTablesAdapter CustomTablesManager;
        AnnotationManagerAdapter AnnotationManagerAdapter;
        CohortManagerAdapter CohortManager;
        GeneSetManagerAdapter GeneSetManager;
        LogManagerAdapter LogManager;
        NetworkManagerAdapter NetworkManager;
        OntologyManagerAdapter OntologyManager;
        PatientManagerAdapter PatientManager;
        ProjectManagerAdapter ProjectManager;
        UserManagerAdapter UserManager;
        SessionManagerAdapter SessionManager;
        SettingsManagerAdapter SettingsManager;
        RegionSetManagerAdapter RegionSetManager;
        ReferenceManagerAdapter ReferenceManager;
        DBUtilsAdapter DBUtils;
        SetupAdapter SetupManager;
        VariantManagerAdapter VariantManager;
        NotificationManagerAdapter NotificationManager;

        //   try {
        AnnotationManagerAdapter = (AnnotationManagerAdapter) registry.lookup(ANNOTATION_MANAGER);
        CohortManager = (CohortManagerAdapter) (registry.lookup(COHORT_MANAGER));
        LogManager = (LogManagerAdapter) registry.lookup(LOG_MANAGER);
        NetworkManager = (NetworkManagerAdapter) registry.lookup(NETWORK_MANAGER);
        OntologyManager = (OntologyManagerAdapter) registry.lookup(ONTOLOGY_MANAGER);
        PatientManager = (PatientManagerAdapter) registry.lookup(PATIENT_MANAGER);
        ProjectManager = (ProjectManagerAdapter) registry.lookup(PROJECT_MANAGER);
        GeneSetManager = (GeneSetManagerAdapter) registry.lookup(GENE_SET_MANAGER);
        ReferenceManager = (ReferenceManagerAdapter) registry.lookup(REFERENCE_MANAGER);
        RegionSetManager = (RegionSetManagerAdapter) registry.lookup(REGION_SET_MANAGER);
        SessionManager = (SessionManagerAdapter) registry.lookup(SESSION_MANAGER);
        SettingsManager = (SettingsManagerAdapter) registry.lookup(SETTINGS_MANAGER);
        UserManager = (UserManagerAdapter) registry.lookup(USER_MANAGER);
        VariantManager = (VariantManagerAdapter) registry.lookup(VARIANT_MANAGER);
        DBUtils = (DBUtilsAdapter) registry.lookup(DB_UTIL_MANAGER);
        SetupManager = (SetupAdapter) registry.lookup(SETUP_MANAGER);
        CustomTablesManager = (CustomTablesAdapter) registry.lookup(CUSTOM_TABLES_MANAGER);
        NotificationManager = (NotificationManagerAdapter) registry.lookup(NOTIFICATION_MANAGER);

        if (Thread.interrupted()) {
            return;
        }

        synchronized (managerLock) {
            MedSavantClient.CustomTablesManager = CustomTablesManager;
            MedSavantClient.AnnotationManagerAdapter = AnnotationManagerAdapter;
            MedSavantClient.CohortManager = CohortManager;
            MedSavantClient.GeneSetManager = GeneSetManager;
            MedSavantClient.LogManager = LogManager;
            MedSavantClient.NetworkManager = NetworkManager;
            MedSavantClient.OntologyManager = OntologyManager;
            MedSavantClient.PatientManager = PatientManager;
            MedSavantClient.ProjectManager = ProjectManager;
            MedSavantClient.UserManager = UserManager;
            MedSavantClient.SessionManager = SessionManager;
            MedSavantClient.SettingsManager = SettingsManager;
            MedSavantClient.RegionSetManager = RegionSetManager;
            MedSavantClient.ReferenceManager = ReferenceManager;
            MedSavantClient.DBUtils = DBUtils;
            MedSavantClient.SetupManager = SetupManager;
            MedSavantClient.VariantManager = VariantManager;
            MedSavantClient.NotificationManager = NotificationManager;

            initProxies();
        }
    }

    private static void setLAF() {
        try {

            if (ClientMiscUtils.MAC) {
                customizeForMac();
            }

            // UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); //Metal works with sliders.
            //UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); //GTK doesn't work with sliders.
            //UIManager.setLookAndFeel("javax.swing.plaf.nimbus.NimbusLookAndFeel"); //Nimbus doesn't work with sliders.
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());

            for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
                LOG.debug("Installed LAF: " + info.getName() + " class: " + info.getClassName());
            }
            LOG.debug("System LAF is: " + UIManager.getSystemLookAndFeelClassName());
            LOG.debug("Cross platform LAF is: " + UIManager.getCrossPlatformLookAndFeelClassName());

            LookAndFeelFactory.addUIDefaultsInitializer(new LookAndFeelFactory.UIDefaultsInitializer() {
                public void initialize(UIDefaults defaults) {
                    Map<String, Object> defaultValues = new HashMap<String, Object>();
                    defaultValues.put("Slider.trackWidth", new Integer(7));
                    defaultValues.put("Slider.majorTickLength", new Integer(6));
                    defaultValues.put("Slider.highlight", new ColorUIResource(255, 255, 255));
                    defaultValues.put("Slider.horizontalThumbIcon",
                            javax.swing.plaf.metal.MetalIconFactory.getHorizontalSliderThumbIcon());
                    defaultValues.put("Slider.verticalThumbIcon",
                            javax.swing.plaf.metal.MetalIconFactory.getVerticalSliderThumbIcon());
                    defaultValues.put("Slider.focusInsets", new InsetsUIResource(0, 0, 0, 0));

                    for (Map.Entry<String, Object> e : defaultValues.entrySet()) {
                        if (defaults.get(e.getKey()) == null) {
                            LOG.debug("Missing key " + e.getKey() + ", using default value " + e.getValue());
                            defaults.put(e.getKey(), e.getValue());
                        } else {
                            LOG.debug("Found key " + e.getKey() + " with value " + defaults.get(e.getKey()));
                        }
                    }
                }
            });

            if (MiscUtils.WINDOWS) {
                UIManager.put("CheckBox.background", new javax.swing.plaf.ColorUIResource(Color.WHITE));
                UIManager.put("Panel.background", new javax.swing.plaf.ColorUIResource(Color.WHITE));
                LookAndFeelFactory.installJideExtension(LookAndFeelFactory.XERTO_STYLE_WITHOUT_MENU);
                /*UIManager.put("JideTabbedPane.tabAreaBackground", new javax.swing.plaf.ColorUIResource(Color.WHITE));
                UIManager.put("JideTabbedPane.background", new javax.swing.plaf.ColorUIResource(Color.WHITE));
                UIManager.put("SidePane.background", new javax.swing.plaf.ColorUIResource(Color.WHITE));*/
            } else {
                LookAndFeelFactory.installJideExtension();
            }

            LookAndFeelFactory.installDefaultLookAndFeelAndExtension();

            System.setProperty("awt.useSystemAAFontSettings", "on");
            System.setProperty("swing.aatext", "true");

            UIManager.put("TabbedPane.contentBorderInsets", new Insets(0, 0, 0, 0));

            //tooltips
            UIManager.put("ToolTip.background", new ColorUIResource(255, 255, 255));
            ToolTipManager.sharedInstance().setDismissDelay(8000);
            ToolTipManager.sharedInstance().setInitialDelay(500);
        } catch (Exception x) {
            LOG.error("Unable to install look & feel.", x);
        }

    }

    private static void customizeForMac() {

        try {

            UIManager.put("Panel.background", new Color(237, 237, 237)); // the above line makes the bg dark, setting back

            System.setProperty("apple.laf.useScreenMenuBar", "true");
            System.setProperty("com.apple.mrj.application.apple.menu.about.name", "MedSavant");

            batchApplyProperty(new String[] { "Button.font", "ToggleButton.font", "RadioButton.font",
                    "CheckBox.font", "ColorChooser.font", "ComboBox.font", "Label.font", "List.font",
                    "MenuBar.font", "MenuItem.font", "RadioButtonMenuItem.font", "CheckBoxMenuItem.font",
                    "Menu.font", "PopupMenu.font", "OptionPane.font", "Panel.font", "ProgressBar.font",
                    "ScrollPane.font", "Viewport.font", "TabbedPane.font", "Table.font", "TableHeader.font",
                    "TextField.font", "PasswordField.font", "TextArea.font", "TextPane.font", "EditorPane.font",
                    "TitledBorder.font", "ToolBar.font", "ToolTip.font", "Tree.font", "JOptionPane.font",
                    "JDialog.font" }, FontFactory.getGeneralFont());

            System.setProperty("awt.useSystemAAFontSettings", "on");
            System.setProperty("swing.aatext", "true");

            UIManager.put("TitledBorder.border", UIManager.getBorder("TitledBorder.aquaVariant"));
            //com.apple.eawt.FullScreenUtilities.setWindowCanFullScreen(this, true);
            Application macOSXApplication = Application.getApplication();
            macOSXApplication.setAboutHandler(new AboutHandler() {
                @Override
                public void handleAbout(AppEvent.AboutEvent evt) {
                    JOptionPane.showMessageDialog(MedSavantFrame.getInstance(), "MedSavant "
                            + VersionSettings.getVersionString() + "\nCreated by Biolab at University of Toronto.");
                }
            });
            macOSXApplication.setPreferencesHandler(new PreferencesHandler() {
                @Override
                public void handlePreferences(AppEvent.PreferencesEvent pe) {
                    DialogUtils.displayMessage("Preferences available for Administrators only");
                }
            });
            macOSXApplication.setQuitHandler(new QuitHandler() {
                @Override
                public void handleQuitRequestWith(AppEvent.QuitEvent evt, QuitResponse resp) {
                    MedSavantFrame.getInstance().requestClose();
                    resp.cancelQuit(); // If user accepted close request, System.exit() was called and we never get here.
                }
            });
        } catch (Throwable x) {
            System.err.println(
                    "Warning: MedSavant requires Java for Mac OS X 10.6 Update 3 (or later).\nPlease check Software Update for the latest version.");
        }
    }

    private static void batchApplyProperty(String[] propn, Object o) {
        for (String s : propn) {
            UIManager.put(s, o);
        }
    }

    private static void verifyJIDE() {
        com.jidesoft.utils.Lm.verifyLicense("Marc Fiume", "Savant Genome Browser",
                "1BimsQGmP.vjmoMbfkPdyh0gs3bl3932");
    }

    private static void setExceptionHandler() {
        Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                LOG.info("Global exception handler caught: " + t.getName() + ": " + e);

                if (e instanceof InvocationTargetException) {
                    e = ((InvocationTargetException) e).getCause();
                }

                if (e instanceof SessionExpiredException) {
                    SessionExpiredException see = (SessionExpiredException) e;
                    MedSavantExceptionHandler.handleSessionExpiredException(see);
                    return;
                }

                if (e instanceof LockException) {
                    DialogUtils.displayMessage("Cannot modify database",
                            "<html>Another process is making changes.<br/>Please try again later.</html>");
                    return;
                }

                e.printStackTrace();
                DialogUtils.displayException("Error", e.getLocalizedMessage(), e);
            }
        });
    }
}