de.hu_berlin.german.korpling.saltnpepper.debugger.MainFrame.java Source code

Java tutorial

Introduction

Here is the source code for de.hu_berlin.german.korpling.saltnpepper.debugger.MainFrame.java

Source

/*
 * Copyright 2013 Thomas Krause <krauseto@hu-berlin.de>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.hu_berlin.german.korpling.saltnpepper.debugger;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.AppenderBase;
import ch.qos.logback.core.encoder.EchoEncoder;
import ch.qos.logback.core.encoder.Encoder;
import com.google.common.io.PatternFilenameFilter;
import java.awt.Rectangle;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import javax.swing.DefaultListModel;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;

/**
 *
 * @author Thomas Krause <krauseto@hu-berlin.de>
 */
public class MainFrame extends javax.swing.JFrame {

    public static final String PARAMETER_FILE = "parameter-file";
    public static final String LAST_MODULE_PATH = "last-module-path";
    public static final String JAR_PREFIX = "jar-";
    public static final String WINDOW_WIDTH = "window-width";
    public static final String WINDOW_HEIGHT = "window-height";
    public static final String WINDOW_X = "window-x";
    public static final String WINDOW_Y = "window-y";
    public static final String WINDOW_STATE = "window-state";
    public static final String WINDOW_SPLIT = "window-split";

    private static final Logger log = LoggerFactory.getLogger(MainFrame.class);
    private Properties props;
    private File configFile;
    private DefaultListModel<File> modules = new DefaultListModel<File>();
    private DefaultListSelectionModel selectedModules = new DefaultListSelectionModel();

    private LoggerContext lc;

    /**
     * Creates new form MainFrame
     */
    public MainFrame() {
        SLF4JBridgeHandler.install();

        // load use configuration
        props = new Properties();
        File configDir = new File(System.getProperty("user.home"), ".saltnpepper");
        if (configDir.isDirectory() || configDir.mkdir()) {
            configFile = new File(configDir, "debugger.properties");
            if (configFile.isFile()) {
                try {
                    props.load(new FileReader(configFile));
                } catch (IOException ex) {
                    log.error(null, ex);
                }
            }
        }

        initComponents();

        setWindowSateFromProps();

        lc = (LoggerContext) LoggerFactory.getILoggerFactory();
        JoranConfigurator jc = new JoranConfigurator();
        jc.setContext(lc);
        addAppender(null);

        lstModuleJars.setModel(modules);
        selectedModules.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        lstModuleJars.setSelectionModel(selectedModules);
        addWindowListener(new WindowListener());

        // init file filters
        FileNameExtensionFilter paramsFilter = new FileNameExtensionFilter(
                "Parameter files (*.pepperParams, *.pepperparams)", "pepperParams", "pepperparams");
        paramFileChooser.addChoosableFileFilter(paramsFilter);
        paramFileChooser.setFileFilter(paramsFilter);

        FileNameExtensionFilter jarFilter = new FileNameExtensionFilter("Jar files (*.jar)", "jar");
        moduleJarFileChooser.addChoosableFileFilter(jarFilter);
        moduleJarFileChooser.setFileFilter(jarFilter);
        moduleJarFileChooser.setMultiSelectionEnabled(true);

        loadModulesFromProps();

        txtPepperParams.setText("");
        String oldParamPath = props.getProperty(PARAMETER_FILE);
        if (oldParamPath != null) {
            File oldParamFile = new File(oldParamPath);
            if (oldParamFile.isFile()) {
                txtPepperParams.setText(oldParamPath);
            }
        }
        String lastModulePath = props.getProperty(LAST_MODULE_PATH);
        if (lastModulePath != null) {
            File lastModuleFile = new File(lastModulePath);
            if (lastModuleFile.isFile()) {
                moduleJarFileChooser.setSelectedFile(lastModuleFile);
            }
        }

    }

    public class ConversionAppender extends AppenderBase<ILoggingEvent> {
        private Encoder<ILoggingEvent> encoder = new EchoEncoder<ILoggingEvent>();
        private ByteArrayOutputStream out = new ByteArrayOutputStream();

        @Override
        public void start() {
            try {
                encoder.init(out);
            } catch (IOException ex) {
            }
            super.start();
        }

        @Override
        protected void append(final ILoggingEvent event) {
            if (event.getLevel().isGreaterOrEqual(Level.DEBUG)) {
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {

                        try {
                            encoder.doEncode(event);
                            out.flush();
                            txtOutput.append(out.toString());
                            out.reset();
                        } catch (IOException ex) {
                        }
                    }
                });
            }
        }
    }

    private void addAppender(String name) {
        if (name == null) {
            name = Logger.ROOT_LOGGER_NAME;
        }
        ch.qos.logback.classic.Logger realLogger = lc.getLogger(name);

        ConversionAppender appender = new ConversionAppender();

        realLogger.addAppender(appender);
        appender.start();
    }

    private File getRoot() {
        try {
            File jarFile = new File(MainFrame.class.getProtectionDomain().getCodeSource().getLocation().toURI());

            File root = jarFile.getParentFile();
            if (jarFile.isDirectory()) {
                // this is not a jar file, but we are debugging
                // use the working directory instead
                root = new File(System.getProperty("user.dir"));
            }
            return root;
        } catch (URISyntaxException ex) {
            log.error(null, ex);
        }
        return new File(System.getProperty("user.dir"));
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        paramFileChooser = new javax.swing.JFileChooser();
        moduleJarFileChooser = new javax.swing.JFileChooser();
        splitOutput = new javax.swing.JSplitPane();
        panelOutput = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        jScrollPane2 = new javax.swing.JScrollPane();
        txtOutput = new javax.swing.JTextArea();
        panelControl = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        txtPepperParams = new javax.swing.JTextField();
        btBrowseParams = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        lstModuleJars = new javax.swing.JList();
        btAddModuleJar = new javax.swing.JButton();
        btRemoveModuleJar = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        btStart = new javax.swing.JButton();

        paramFileChooser.setDialogTitle("Open Pepper conversion parameter file");

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);

        splitOutput.setDividerLocation(300);
        splitOutput.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);

        jLabel3.setText("Output:");

        txtOutput.setEditable(false);
        txtOutput.setColumns(20);
        txtOutput.setRows(5);
        jScrollPane2.setViewportView(txtOutput);

        javax.swing.GroupLayout panelOutputLayout = new javax.swing.GroupLayout(panelOutput);
        panelOutput.setLayout(panelOutputLayout);
        panelOutputLayout
                .setHorizontalGroup(panelOutputLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, 580, Short.MAX_VALUE)
                        .addComponent(jScrollPane2));
        panelOutputLayout.setVerticalGroup(panelOutputLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(panelOutputLayout.createSequentialGroup().addContainerGap().addComponent(jLabel3)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 129, Short.MAX_VALUE)));

        splitOutput.setBottomComponent(panelOutput);

        jLabel1.setText("Parameter File:");

        btBrowseParams.setText("Browse");
        btBrowseParams.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btBrowseParamsActionPerformed(evt);
            }
        });

        jScrollPane1.setViewportView(lstModuleJars);

        btAddModuleJar.setText("Add module jar");
        btAddModuleJar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btAddModuleJarActionPerformed(evt);
            }
        });

        btRemoveModuleJar.setText("Remove module jar");
        btRemoveModuleJar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btRemoveModuleJarActionPerformed(evt);
            }
        });

        jLabel2.setText("module jars:");

        btStart.setText("Start conversion");
        btStart.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btStartActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout panelControlLayout = new javax.swing.GroupLayout(panelControl);
        panelControl.setLayout(panelControlLayout);
        panelControlLayout
                .setHorizontalGroup(
                        panelControlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelControlLayout
                                        .createSequentialGroup().addComponent(btAddModuleJar).addPreferredGap(
                                                javax.swing.LayoutStyle.ComponentPlacement.RELATED,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addComponent(btRemoveModuleJar).addContainerGap())
                                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, panelControlLayout
                                        .createSequentialGroup().addGroup(panelControlLayout
                                                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                                .addGroup(panelControlLayout.createSequentialGroup()
                                                        .addContainerGap()
                                                        .addComponent(
                                                                jLabel2, javax.swing.GroupLayout.DEFAULT_SIZE, 226,
                                                                Short.MAX_VALUE)
                                                        .addGap(275, 275, 275))
                                                .addGroup(panelControlLayout.createSequentialGroup()
                                                        .addComponent(jLabel1,
                                                                javax.swing.GroupLayout.PREFERRED_SIZE, 107,
                                                                javax.swing.GroupLayout.PREFERRED_SIZE)
                                                        .addPreferredGap(
                                                                javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                                        .addComponent(txtPepperParams).addPreferredGap(
                                                                javax.swing.LayoutStyle.ComponentPlacement.RELATED)))
                                        .addComponent(btBrowseParams))
                                .addComponent(jScrollPane1).addComponent(btStart,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        Short.MAX_VALUE));
        panelControlLayout.setVerticalGroup(panelControlLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(panelControlLayout.createSequentialGroup().addContainerGap()
                        .addGroup(panelControlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(btBrowseParams)
                                .addComponent(txtPepperParams, javax.swing.GroupLayout.PREFERRED_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(jLabel1))
                        .addGap(11, 11, 11)
                        .addGroup(panelControlLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(btAddModuleJar).addComponent(btRemoveModuleJar))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(jLabel2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 168, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(btStart)));

        splitOutput.setLeftComponent(panelControl);

        getContentPane().add(splitOutput, java.awt.BorderLayout.CENTER);

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void btStartActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btStartActionPerformed
    {//GEN-HEADEREND:event_btStartActionPerformed

        // sync and write out configuration (in case we are disrupted)
        storeConfiguration();

        // clear
        txtOutput.setText("");

        File[] modulesAsArray = new File[modules.size()];
        modules.copyInto(modulesAsArray);

        File root = getRoot();

        File[] pepperInstallationMatch = root.listFiles(
                new PatternFilenameFilter("^de.hu_berlin.german.korpling.saltnpepper.pepper-starter_.*$"));

        if (pepperInstallationMatch.length > 0 && pepperInstallationMatch[0].isDirectory()) {
            File pepperRoot = pepperInstallationMatch[0];

            PepperConversionWorker worker = new PepperConversionWorker(modulesAsArray,
                    new File(txtPepperParams.getText()), pepperRoot, btStart);
            worker.execute();
            btStart.setEnabled(false);

        } else {
            JOptionPane.showMessageDialog(this, "Could not find the \"pepper-install\" folder", "ERROR",
                    JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_btStartActionPerformed

    private void btRemoveModuleJarActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btRemoveModuleJarActionPerformed
    {//GEN-HEADEREND:event_btRemoveModuleJarActionPerformed

        if (selectedModules.isSelectionEmpty()) {
            JOptionPane.showMessageDialog(this, "You need to select an entry for removal");
            return;
        }

        int i;
        while ((i = selectedModules.getMaxSelectionIndex()) >= 0) {
            modules.remove(i);
        }

    }//GEN-LAST:event_btRemoveModuleJarActionPerformed

    private void btAddModuleJarActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btAddModuleJarActionPerformed
    {//GEN-HEADEREND:event_btAddModuleJarActionPerformed

        int returnStatus = moduleJarFileChooser.showOpenDialog(this);
        if (returnStatus == JFileChooser.APPROVE_OPTION) {

            File[] allSelected = moduleJarFileChooser.getSelectedFiles();
            for (File nonCanonical : allSelected) {
                try {
                    File selected = nonCanonical.getCanonicalFile();
                    props.put(LAST_MODULE_PATH, selected.getPath());
                    // check if already existing
                    if (modules.contains(selected)) {
                        JOptionPane.showMessageDialog(this, "This file is already in the module list", "ERROR",
                                JOptionPane.ERROR_MESSAGE);
                    } else {
                        // add
                        modules.addElement(selected);
                    }
                } catch (IOException ex) {
                    log.error(null, ex);
                }
            }
        }

    }//GEN-LAST:event_btAddModuleJarActionPerformed

    private void btBrowseParamsActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_btBrowseParamsActionPerformed
    {//GEN-HEADEREND:event_btBrowseParamsActionPerformed

        // Open param search dialog
        if (!txtPepperParams.getText().isEmpty()) {
            File selectedFile = new File(txtPepperParams.getText());
            paramFileChooser.setSelectedFile(selectedFile);
        }
        int returnState = paramFileChooser.showOpenDialog(this);
        if (returnState == JFileChooser.APPROVE_OPTION) {
            try {
                // save new path
                txtPepperParams.setText(paramFileChooser.getSelectedFile().getCanonicalPath());
                // save new path
                props.put(PARAMETER_FILE, txtPepperParams.getText());
            } catch (IOException ex) {
                log.error(null, ex);
            }
        }

    }//GEN-LAST:event_btBrowseParamsActionPerformed

    private void storeConfiguration() {
        if (props != null && configFile != null) {
            syncPropsFromModuleList();
            storeWindowState();
            try {
                props.store(new FileWriter(configFile), "Pepper debugger configuration");
            } catch (IOException ex) {
                log.error(null, ex);
            }
        }
    }

    private void setWindowSateFromProps() {

        if (props.containsKey(WINDOW_STATE)) {
            setExtendedState(Integer.parseInt(props.getProperty(WINDOW_STATE)));
        }
        if (getExtendedState() == JFrame.NORMAL) {
            setLocationByPlatform(false);
            if (props.containsKey(WINDOW_X) && props.containsKey(WINDOW_Y) && props.containsKey(WINDOW_HEIGHT)
                    && props.containsKey(WINDOW_WIDTH)) {
                setBounds((int) Double.parseDouble(props.getProperty(WINDOW_X)),
                        (int) Double.parseDouble(props.getProperty(WINDOW_Y)),
                        (int) Double.parseDouble(props.getProperty(WINDOW_WIDTH)),
                        (int) Double.parseDouble(props.getProperty(WINDOW_HEIGHT)));
            }
        }

        if (props.containsKey(WINDOW_SPLIT)) {
            splitOutput.setDividerLocation(Integer.parseInt(props.getProperty(WINDOW_SPLIT)));
        }
    }

    private void loadModulesFromProps() {
        TreeMap<Integer, File> orderedFiles = new TreeMap<Integer, File>();
        Set<Object> keys = new HashSet<Object>(props.keySet());
        for (Object o : keys) {
            if (o instanceof String) {
                String k = (String) o;
                if (k.startsWith(JAR_PREFIX)) {
                    int i = Integer.parseInt(k.substring(JAR_PREFIX.length()));
                    orderedFiles.put(i, new File(props.getProperty(k)));
                }
            }
        }
        for (File f : orderedFiles.values()) {
            modules.addElement(f);
        }
    }

    private void syncPropsFromModuleList() {
        // clear old entries
        Set<Object> keys = new HashSet<Object>(props.keySet());
        for (Object o : keys) {
            if (o instanceof String) {
                String k = (String) o;
                if (k.startsWith(JAR_PREFIX)) {
                    props.remove(k);
                }
            }
        }
        // add all from list
        for (int i = 0; i < modules.getSize(); i++) {
            props.put(JAR_PREFIX + i, modules.getElementAt(i).getPath());
        }
    }

    private void storeWindowState() {
        props.put(WINDOW_STATE, "" + getExtendedState());
        Rectangle bounds = getBounds();
        props.put(WINDOW_WIDTH, "" + bounds.getWidth());
        props.put(WINDOW_HEIGHT, "" + bounds.getHeight());
        props.put(WINDOW_X, "" + bounds.getX());
        props.put(WINDOW_Y, "" + bounds.getY());
        props.put(WINDOW_SPLIT, "" + splitOutput.getDividerLocation());
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
        * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
        */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            log.error(null, ex);
        } catch (InstantiationException ex) {
            log.error(null, ex);
        } catch (IllegalAccessException ex) {
            log.error(null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            log.error(null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new MainFrame().setVisible(true);
            }
        });
    }

    public class WindowListener extends WindowAdapter {

        @Override
        public void windowClosing(WindowEvent e) {
            storeConfiguration();
            System.exit(0);
        }

    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton btAddModuleJar;
    private javax.swing.JButton btBrowseParams;
    private javax.swing.JButton btRemoveModuleJar;
    private javax.swing.JButton btStart;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JList lstModuleJars;
    private javax.swing.JFileChooser moduleJarFileChooser;
    private javax.swing.JPanel panelControl;
    private javax.swing.JPanel panelOutput;
    private javax.swing.JFileChooser paramFileChooser;
    private javax.swing.JSplitPane splitOutput;
    private javax.swing.JTextArea txtOutput;
    private javax.swing.JTextField txtPepperParams;
    // End of variables declaration//GEN-END:variables
}