Java tutorial
/* * 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 }