imageviewer.system.ImageViewerClient.java Source code

Java tutorial

Introduction

Here is the source code for imageviewer.system.ImageViewerClient.java

Source

/*******************************************************************************
 * Copyright (c) 2011 UCLA Medical Imaging Informatics Group
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl.html
 ******************************************************************************/
package imageviewer.system;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Toolkit;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import java.io.File;
import java.lang.reflect.Field;
import java.net.InetAddress;

import java.util.ArrayList;
import java.util.Map;
import java.util.Timer;

import javax.imageio.ImageIO;

import javax.media.jai.JAI;
import javax.media.jai.TileCache;
import javax.media.jai.TileScheduler;

import javax.media.j3d.VirtualUniverse;

import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;

import org.apache.log4j.Logger;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.UnrecognizedOptionException;

import org.jdesktop.swingx.plaf.LookAndFeelAddons;

import org.jvnet.flamingo.ribbon.JRibbon;

import imageviewer.rendering.wl.DefaultWindowLevelManager;
import imageviewer.tools.plugins.PluginLoader;

import imageviewer.ui.ApplicationPanel;
import imageviewer.ui.ApplicationContext;
import imageviewer.ui.layout.LayoutFactory;

import imageviewer.ui.swing.ImageViewerLookAndFeel;
import imageviewer.ui.swing.ImageViewerLookAndFeelAddons;
import imageviewer.ui.swing.MenuReader;
import imageviewer.ui.swing.flamingo.RibbonReader;

// =======================================================================
/* Main client program for ImageViewer. 
 * 
 */

public class ImageViewerClient {

    private static Logger LOG = Logger.getLogger("imageviewer.client");

    // =======================================================================

    JFrame mainFrame = null;
    boolean fullScreen = true;
    Timer timer = null;

    /**
     * ImageViewerClient constructor.  Sets up JAI, the frame, menu, look and feel, 
     * window level manager, memory management, etc.  
     * 
     * @param dir - directory or file path of images to open on startup 
     * @param fullScreen - open in full screen mode?
     */

    public ImageViewerClient(CommandLine args) {
        initialize(args);
    }

    // =======================================================================

    private void initialize(CommandLine args) {

        // First, process all the different command line arguments that we
        // need to override and/or send onwards for initialization.

        boolean fullScreen = (args.hasOption("fullscreen")) ? true : false;
        String dir = (args.hasOption("dir")) ? args.getOptionValue("dir") : null;
        String type = (args.hasOption("type")) ? args.getOptionValue("type") : "DICOM";
        String prefix = (args.hasOption("client")) ? args.getOptionValue("client") : null;

        LOG.info("Java home environment: " + System.getProperty("java.home"));

        // Logging system taken care of through properties file.  Check
        // for JAI.  Set up JAI accordingly with the size of the cache
        // tile and to recycle cached tiles as needed.

        verifyJAI();
        TileCache tc = JAI.getDefaultInstance().getTileCache();
        tc.setMemoryCapacity(32 * 1024 * 1024);
        TileScheduler ts = JAI.createTileScheduler();
        ts.setPriority(Thread.MAX_PRIORITY);
        JAI.getDefaultInstance().setTileScheduler(ts);
        JAI.getDefaultInstance().setRenderingHint(JAI.KEY_CACHED_TILE_RECYCLING_ENABLED, Boolean.TRUE);

        // Set up the frame and everything else.  First, try and set the
        // UI manager to use our look and feel because it's groovy and
        // lets us control the GUI components much better.

        try {
            UIManager.setLookAndFeel(new ImageViewerLookAndFeel());
            LookAndFeelAddons.setAddon(ImageViewerLookAndFeelAddons.class);
        } catch (Exception exc) {
            LOG.error("Could not set imageViewer L&F.");
        }

        // Load up the ApplicationContext information...

        ApplicationContext ac = ApplicationContext.getContext();
        if (ac == null) {
            LOG.error("Could not load configuration, exiting.");
            System.exit(1);
        }

        // Override the client node information based on command line
        // arguments...Make sure that the files are there, otherwise just
        // default to a local configuration.

        String hostname = new String("localhost");
        try {
            hostname = InetAddress.getLocalHost().getHostName();
        } catch (Exception exc) {
        }

        String[] gatewayConfigs = (prefix != null)
                ? (new String[] { "resources/server/" + prefix + "GatewayConfig.xml",
                        (String) ac.getProperty(ApplicationContext.IMAGESERVER_GATEWAY_CONFIG),
                        "resources/server/" + hostname + "GatewayConfig.xml",
                        "resources/server/localGatewayConfig.xml" })
                : (new String[] { (String) ac.getProperty(ApplicationContext.IMAGESERVER_GATEWAY_CONFIG),
                        "resources/server/" + hostname + "GatewayConfig.xml",
                        "resources/server/localGatewayConfig.xml" });
        String[] nodeConfigs = (prefix != null)
                ? (new String[] { "resources/server/" + prefix + "NodeConfig.xml",
                        (String) ac.getProperty(ApplicationContext.IMAGESERVER_CLIENT_NODE),
                        "resources/server/" + hostname + "NodeConfig.xml", "resources/server/localNodeConfig.xml" })
                : (new String[] { (String) ac.getProperty(ApplicationContext.IMAGESERVER_CLIENT_NODE),
                        "resources/server/" + hostname + "NodeConfig.xml",
                        "resources/server/localNodeConfig.xml" });

        for (int loop = 0; loop < gatewayConfigs.length; loop++) {
            String s = gatewayConfigs[loop];
            if ((s != null) && (s.length() != 0) && (!"null".equals(s))) {
                File f = new File(s);
                if (f.exists()) {
                    ac.setProperty(ApplicationContext.IMAGESERVER_GATEWAY_CONFIG, s);
                    break;
                }
            }
        }

        LOG.info("Using gateway config: " + ac.getProperty(ApplicationContext.IMAGESERVER_GATEWAY_CONFIG));

        for (int loop = 0; loop < nodeConfigs.length; loop++) {
            String s = nodeConfigs[loop];
            if ((s != null) && (s.length() != 0) && (!"null".equals(s))) {
                File f = new File(s);
                if (f.exists()) {
                    ac.setProperty(ApplicationContext.IMAGESERVER_CLIENT_NODE, s);
                    break;
                }
            }
        }
        LOG.info("Using client config: " + ac.getProperty(ApplicationContext.IMAGESERVER_CLIENT_NODE));

        // Load the layouts and set the default window/level manager...

        LayoutFactory.initialize();
        DefaultWindowLevelManager dwlm = new DefaultWindowLevelManager();

        // Create the main JFrame, set its behavior, and let the
        // ApplicationPanel know the glassPane and layeredPane.  Set the
        // menubar based on reading in the configuration menus.

        mainFrame = new JFrame("imageviewer");
        try {
            ArrayList<Image> iconList = new ArrayList<Image>();
            iconList.add(ImageIO.read(new File("resources/icons/mii.png")));
            iconList.add(ImageIO.read(new File("resources/icons/mii32.png")));
            mainFrame.setIconImages(iconList);
        } catch (Exception exc) {
        }

        mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        mainFrame.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent we) {
                int confirm = ApplicationPanel.getInstance().showDialog(
                        "Are you sure you want to quit imageViewer?", null, JOptionPane.QUESTION_MESSAGE,
                        JOptionPane.OK_CANCEL_OPTION, UIManager.getIcon("Dialog.shutdownIcon"));
                if (confirm == JOptionPane.OK_OPTION) {
                    boolean hasUnsaved = SaveStack.getInstance().hasUnsavedItems();
                    if (hasUnsaved) {
                        int saveResult = ApplicationPanel.getInstance().showDialog(
                                "There is still unsaved data.  Do you want to save this data in the local archive?",
                                null, JOptionPane.QUESTION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION);
                        if (saveResult == JOptionPane.CANCEL_OPTION)
                            return;
                        if (saveResult == JOptionPane.YES_OPTION)
                            SaveStack.getInstance().saveAll();
                    }
                    LOG.info("Shutting down imageServer local archive...");
                    try {
                        ImageViewerClientNode.getInstance().shutdown();
                    } catch (Exception exc) {
                        LOG.error("Problem shutting down imageServer local archive...");
                    } finally {
                        System.exit(0);
                    }
                }
            }
        });

        String menuFile = (String) ApplicationContext.getContext().getProperty(ac.CONFIG_MENUS);
        String ribbonFile = (String) ApplicationContext.getContext().getProperty(ac.CONFIG_RIBBON);
        if (menuFile != null) {
            JMenuBar mb = new JMenuBar();
            mb.setBackground(Color.black);
            MenuReader.parseFile(menuFile, mb);
            mainFrame.setJMenuBar(mb);
            ApplicationContext.getContext().setApplicationMenuBar(mb);
        } else if (ribbonFile != null) {
            RibbonReader rr = new RibbonReader();
            JRibbon jr = rr.parseFile(ribbonFile);
            mainFrame.getContentPane().add(jr, BorderLayout.NORTH);
            ApplicationContext.getContext().setApplicationRibbon(jr);
        }
        mainFrame.getContentPane().add(ApplicationPanel.getInstance(), BorderLayout.CENTER);
        ApplicationPanel.getInstance().setGlassPane((JPanel) (mainFrame.getGlassPane()));
        ApplicationPanel.getInstance().setLayeredPane(mainFrame.getLayeredPane());

        // Load specified plugins...has to occur after the menus are
        // created, btw.

        PluginLoader.initialize("config/plugins.xml");

        // Detect operating system...

        String osName = System.getProperty("os.name");
        ApplicationContext.getContext().setProperty(ApplicationContext.OS_NAME, osName);
        LOG.info("Detected operating system: " + osName);

        // Try and hack the searched library paths if it's windows so we
        // can add a local dll path...

        try {
            if (osName.contains("Windows")) {
                Field f = ClassLoader.class.getDeclaredField("usr_paths");
                f.setAccessible(true);
                String[] paths = (String[]) f.get(null);
                String[] tmp = new String[paths.length + 1];
                System.arraycopy(paths, 0, tmp, 0, paths.length);
                File currentPath = new File(".");
                tmp[paths.length] = currentPath.getCanonicalPath() + "/lib/dll/";
                f.set(null, tmp);
                f.setAccessible(false);
            }
        } catch (Exception exc) {
            LOG.error("Error attempting to dynamically set library paths.");
        }

        // Get screen resolution...

        GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
                .getDefaultConfiguration();
        Rectangle r = gc.getBounds();
        LOG.info("Detected screen resolution: " + (int) r.getWidth() + "x" + (int) r.getHeight());

        // Try and see if Java3D is installed, and if so, what version...

        try {
            VirtualUniverse vu = new VirtualUniverse();
            Map m = vu.getProperties();
            String s = (String) m.get("j3d.version");
            LOG.info("Detected Java3D version: " + s);
        } catch (Throwable t) {
            LOG.info("Unable to detect Java3D installation");
        }

        // Try and see if native JOGL is installed...

        try {
            System.loadLibrary("jogl");
            ac.setProperty(ApplicationContext.JOGL_DETECTED, Boolean.TRUE);
            LOG.info("Detected native libraries for JOGL");
        } catch (Throwable t) {
            LOG.info("Unable to detect native JOGL installation");
            ac.setProperty(ApplicationContext.JOGL_DETECTED, Boolean.FALSE);
        }

        // Start the local client node to connect to the network and the
        // local archive running on this machine...Thread the connection
        // process so it doesn't block the imageViewerClient creating this
        // instance.  We may not be connected to the given gateway, so the
        // socketServer may go blah...

        final boolean useNetwork = (args.hasOption("nonet")) ? false : true;
        ApplicationPanel.getInstance().addStatusMessage("ImageViewer is starting up, please wait...");
        if (useNetwork)
            LOG.info("Starting imageServer client to join network - please wait...");
        Thread t = new Thread(new Runnable() {
            public void run() {
                try {
                    ImageViewerClientNode.getInstance(
                            (String) ApplicationContext.getContext()
                                    .getProperty(ApplicationContext.IMAGESERVER_GATEWAY_CONFIG),
                            (String) ApplicationContext.getContext()
                                    .getProperty(ApplicationContext.IMAGESERVER_CLIENT_NODE),
                            useNetwork);
                    ApplicationPanel.getInstance().addStatusMessage("Ready");
                } catch (Exception exc) {
                    exc.printStackTrace();
                }
            }
        });
        t.setPriority(9);
        t.start();

        this.fullScreen = fullScreen;
        mainFrame.setUndecorated(fullScreen);

        // Set the view to encompass the default screen.

        if (fullScreen) {
            Insets i = Toolkit.getDefaultToolkit().getScreenInsets(gc);
            mainFrame.setLocation(r.x + i.left, r.y + i.top);
            mainFrame.setSize(r.width - i.left - i.right, r.height - i.top - i.bottom);
        } else {
            mainFrame.setSize(1100, 800);
            mainFrame.setLocation(r.x + 200, r.y + 100);
        }

        if (dir != null)
            ApplicationPanel.getInstance().load(dir, type);

        timer = new Timer();
        timer.schedule(new GarbageCollectionTimer(), 5000, 2500);
        mainFrame.setVisible(true);
    }

    // =======================================================================

    public boolean isFullScreen() {
        return fullScreen;
    }

    public void setFullScreen(boolean x) {
        fullScreen = x;
    }

    public JFrame getMainFrame() {
        return mainFrame;
    }

    // =======================================================================

    private void verifyJAI() {

        // JAI Detection

        boolean dllPassFlag = false;
        try {
            Class.forName("javax.media.jai.JAI");
        } catch (ClassNotFoundException exc) {
            JFrame frame = new JFrame("mii imageviewer");
            JOptionPane.showMessageDialog(frame, "JAI is not installed on this machine. Please install.");
            exc.printStackTrace();
            System.exit(1);
        }

        // JAI DLL Detection

        try {
            System.load(System.getProperty("java.home") + "/bin/mlib_jai.dll");
            dllPassFlag = true;
        } catch (Exception exc) {
            dllPassFlag = false;
        } catch (UnsatisfiedLinkError exc22) {
            dllPassFlag = false;
        }

        // Don't ever check for *.so objects!  Breaks things on Linux! -gsw

        if (dllPassFlag == false) {
            LOG.error("Missing JAI DLL or system libraries.");
        } else {
            LOG.info("Java Advanced Imaging (JAI) version: " + JAI.getBuildVersion());
        }
    }

    // =======================================================================

    public static void main(String[] args) {

        // Use Apache command-line interface (CLI) to set up the argument
        // handling, etc. 

        Option help = new Option("help", "Print this message");
        Option fullScreen = new Option("fullscreen", "Run imageViewer in full screen mode");
        Option noNetwork = new Option("nonet", "No network connectivity");
        Option client = OptionBuilder.withArgName("prefix").hasArg()
                .withDescription("Specify client node (prefix) for imageServer").create("client");
        Option imageType = OptionBuilder.withArgName("image type").hasArg().withDescription("Open as image type")
                .create("type");
        Option imageDir = OptionBuilder.withArgName("image directory").hasArg()
                .withDescription("Open images in directory").create("dir");
        Option property = OptionBuilder.withArgName("property=value").hasArg().withValueSeparator()
                .withDescription("use value for given property").create("D");

        Options o = new Options();
        o.addOption(help);
        o.addOption(client);
        o.addOption(imageDir);
        o.addOption(fullScreen);
        o.addOption(noNetwork);
        o.addOption(property);

        try {
            CommandLineParser parser = new GnuParser();
            CommandLine line = parser.parse(o, args);
            String jaasConfig = System.getProperty("java.security.auth.login.config");
            if (jaasConfig == null)
                System.setProperty("java.security.auth.login.config", "config/jaas.config");
            String antialising = new String("swing.aatext");
            if (System.getProperty(antialising) == null)
                System.setProperty(antialising, "true");
            @SuppressWarnings("unused")
            ImageViewerClient ivc = new ImageViewerClient(line);
        } catch (UnrecognizedOptionException uoe) {
            System.err.println("Unknown argument: " + uoe.getMessage());
            HelpFormatter hf = new HelpFormatter();
            hf.printHelp("ImageViewerClient", o);
            System.exit(1);
        } catch (Exception exc) {
            exc.printStackTrace();
        }
    }
}