diff options
author | Jiri Vanek <[email protected]> | 2013-12-20 15:23:08 +0100 |
---|---|---|
committer | Jiri Vanek <[email protected]> | 2013-12-20 15:23:08 +0100 |
commit | b498f0bd16cb77a6082e2bb797d8f4daec07c345 (patch) | |
tree | 466eb30b20e7a5a685bb535c95723ae8726e0eac /netx/net | |
parent | b616acb51f3bb0217cd24f6018650504dbc40727 (diff) |
Rewritten java console
Diffstat (limited to 'netx/net')
7 files changed, 1462 insertions, 74 deletions
diff --git a/netx/net/sourceforge/jnlp/Launcher.java b/netx/net/sourceforge/jnlp/Launcher.java index 2982b45..6e07b22 100644 --- a/netx/net/sourceforge/jnlp/Launcher.java +++ b/netx/net/sourceforge/jnlp/Launcher.java @@ -915,6 +915,9 @@ public class Launcher { if (exitOnFailure) { JNLPRuntime.exit(1); } + } catch (Throwable ex) { + OutputController.getLogger().log(OutputController.Level.ERROR_ALL, ex); + throw new RuntimeException(ex); } } diff --git a/netx/net/sourceforge/jnlp/util/logging/ConsoleOutputPane.java b/netx/net/sourceforge/jnlp/util/logging/ConsoleOutputPane.java new file mode 100644 index 0000000..fe55d8e --- /dev/null +++ b/netx/net/sourceforge/jnlp/util/logging/ConsoleOutputPane.java @@ -0,0 +1,887 @@ +package net.sourceforge.jnlp.util.logging; + +import java.awt.Color; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.IOException; +import java.util.Observable; +import java.util.Observer; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.regex.Pattern; +import javax.swing.ButtonGroup; +import javax.swing.JFrame; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultHighlighter; +import javax.swing.text.Document; +import javax.swing.text.PlainDocument; +import javax.swing.text.html.HTMLDocument; +import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.util.logging.headers.ObservableMessagesProvider; + +public class ConsoleOutputPane extends javax.swing.JPanel implements Observer { + + @Override + public synchronized void update(Observable o, Object arg) { + if (!autorefresh.isSelected()) { + statistics.setText(model.createStatisticHint()); + return; + } + boolean passed = model.shouldUpdate(); + + if (!passed) { + statistics.setText(model.createStatisticHint()); + return; + } + if (sortBy.getSelectedIndex() == 0) { + //no sort, we can just update + updatePane(false); + } else { + refreshPane(); + } + + } + private ConsoleOutputPaneModel model; + private int lastPostion; //index of search + private DefaultHighlighter.DefaultHighlightPainter searchHighligh = new DefaultHighlighter.DefaultHighlightPainter(Color.blue); + private Object lastSearchTag; + + public ConsoleOutputPane(ObservableMessagesProvider dataProvider) { + model = new ConsoleOutputPaneModel(dataProvider); + initComponents(); + regExFilter.setText(ConsoleOutputPaneModel.defaultPattern.pattern()); + if (!LogConfig.getLogConfig().isEnableHeaders()) { + showHeaders.setSelected(false); + } + if (JNLPRuntime.isWebstartApplication()) { + showPlugin.setSelected(false); + showPreInit.setSelected(false); + showPostInit.setSelected(false); + showIncomplete.setSelected(false); + showComplete.setSelected(false); + + showPlugin.setEnabled(false); + showPreInit.setEnabled(false); + showPostInit.setEnabled(false); + showIncomplete.setEnabled(false); + showComplete.setEnabled(false); + } + regExFilter.getDocument().addDocumentListener(new DocumentListener() { + + @Override + public void insertUpdate(DocumentEvent e) { + colorize(); + } + + @Override + public void removeUpdate(DocumentEvent e) { + colorize(); + } + + @Override + public void changedUpdate(DocumentEvent e) { + colorize(); + } + + private void colorize() { + try { + String s = regExFilter.getText(); + Pattern p = Pattern.compile(s); + model.lastValidPattern = p; + regExLabel.setForeground(Color.green); + } catch (Exception ex) { + regExLabel.setForeground(Color.red); + } + } + }); + regExFilter.addMouseListener(new MouseAdapter() { + + @Override + public void mouseClicked(final MouseEvent e) { + java.awt.EventQueue.invokeLater(new Runnable() { + + @Override + public void run() { + try { + if (e.getButton() != MouseEvent.BUTTON3) { + insertChars.setVisible(false); + return; + } + insertChars.setLocation(e.getXOnScreen(), e.getYOnScreen()); + insertChars.setVisible(!insertChars.isVisible()); + } catch (Exception ex) { + OutputController.getLogger().log(ex); + } + } + }); + } + }); + regExFilter.addKeyListener(new KeyAdapter() { + + @Override + public void keyPressed(final KeyEvent e) { + if (e.getKeyCode() != KeyEvent.VK_CONTEXT_MENU) { + return; + } + java.awt.EventQueue.invokeLater(new Runnable() { + + @Override + public void run() { + try{ + insertChars.setLocation(regExFilter.getLocationOnScreen()); + insertChars.setVisible(!insertChars.isVisible()); + } catch (Exception ex) { + OutputController.getLogger().log(ex); + } + } + }); + } + }); + + ButtonGroup matches = new ButtonGroup(); + matches.add(match); + matches.add(notMatch); + showHideActionPerformed(null); + updateModel(); + refreshPane(); + + } + + private ActionListener createDefaultAction() { + return new ActionListener() { + + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + refreshAction(evt); + } + }; + } + ActionListener defaultActionSingleton = createDefaultAction(); + + private ActionListener getDefaultActionSingleton() { + return defaultActionSingleton; + } + + private synchronized void refreshPane() { + if (highLight.isSelected()) { + jEditorPane1.setContentType("text/html"); + } else { + jEditorPane1.setContentType("text/plain"); + } + model.lastUpdateIndex = 0; + updatePane(true); + } + /** + * when various threads update (and it can be)underlying jeditorpane + * simultanouskly, then it can lead to unpredictible issues synchroisation + * is doen in invoe later + */ + private AtomicBoolean done = new AtomicBoolean(true); + + private synchronized void updatePane(final boolean reset) { + if (!done.get()) { + return; + } + done.set(false); + java.awt.EventQueue.invokeLater(new Runnable() { + + @Override + public void run() { + try { + refreshPaneBody(reset); + } catch (Exception ex) { + OutputController.getLogger().log(ex); + } finally { + done.set(true); + } + } + }); + } + + private synchronized void refreshPaneBody(final boolean reset) throws BadLocationException, IOException { + if (reset) { + jEditorPane1.setText(model.importList(0)); + } else { + String s = model.importList(); + if (highLight.isSelected()) { + HTMLDocument orig = (HTMLDocument) jEditorPane1.getDocument(); + if (revertSort.isSelected()) { + orig.insertAfterEnd(orig.getRootElements()[0].getElement(0)/*body*/, s); + } else { + orig.insertBeforeEnd(orig.getRootElements()[0], s); + } + } else { + if (revertSort.isSelected()) { + jEditorPane1.setText(s + jEditorPane1.getText()); + } else { + jEditorPane1.setText(jEditorPane1.getText() + s); + } + } + } + jEditorPane1.setCaretPosition(0); + //jEditorPane1.repaint(); + if (mark.isSelected()) { + markActionPerformed(null); + } + statistics.setText(model.createStatisticHint()); + } + + @SuppressWarnings("unchecked") + private void initComponents() { + + jPanel2 = new javax.swing.JPanel(); + showHeaders = new javax.swing.JCheckBox(); + showUser = new javax.swing.JCheckBox(); + showOrigin = new javax.swing.JCheckBox(); + showLevel = new javax.swing.JCheckBox(); + showDate = new javax.swing.JCheckBox(); + showThread1 = new javax.swing.JCheckBox(); + showThread2 = new javax.swing.JCheckBox(); + showMessage = new javax.swing.JCheckBox(); + showOut = new javax.swing.JCheckBox(); + showErr = new javax.swing.JCheckBox(); + showJava = new javax.swing.JCheckBox(); + showPlugin = new javax.swing.JCheckBox(); + showPreInit = new javax.swing.JCheckBox(); + sortByLabel = new javax.swing.JLabel(); + regExLabel = new javax.swing.JCheckBox(); + sortBy = new javax.swing.JComboBox(); + searchLabel = new javax.swing.JLabel(); + autorefresh = new javax.swing.JCheckBox(); + refresh = new javax.swing.JButton(); + apply = new javax.swing.JButton(); + regExFilter = new javax.swing.JTextField(); + //this is crucial, otherwie PalinDocument implementatin is repalcing all \n by space + ((PlainDocument) regExFilter.getDocument()).getDocumentProperties().remove("filterNewlines"); + copyPlain = new javax.swing.JButton(); + copyRich = new javax.swing.JButton(); + next = new javax.swing.JButton(); + previous = new javax.swing.JButton(); + search = new javax.swing.JTextField(); + caseSensitive = new javax.swing.JCheckBox(); + showIncomplete = new javax.swing.JCheckBox(); + highLight = new javax.swing.JCheckBox(); + wordWrap = new javax.swing.JCheckBox(); + showDebug = new javax.swing.JCheckBox(); + showInfo = new javax.swing.JCheckBox(); + showCode = new javax.swing.JCheckBox(); + statistics = new javax.swing.JLabel(); + showPostInit = new javax.swing.JCheckBox(); + showComplete = new javax.swing.JCheckBox(); + match = new javax.swing.JRadioButton(); + notMatch = new javax.swing.JRadioButton(); + revertSort = new javax.swing.JCheckBox(); + mark = new javax.swing.JCheckBox(); + jScrollPane1 = new javax.swing.JScrollPane(); + jEditorPane1 = new javax.swing.JTextPane(); + showHide = new javax.swing.JButton(); + + showHeaders.setSelected(true); + showHeaders.setText("Show headers:"); + showHeaders.addActionListener(getDefaultActionSingleton()); + + showUser.setSelected(true); + showUser.setText("user"); + showUser.addActionListener(getDefaultActionSingleton()); + + showOrigin.setSelected(true); + showOrigin.setText("origin"); + showOrigin.addActionListener(getDefaultActionSingleton()); + + showLevel.setSelected(true); + showLevel.setText("level"); + showLevel.addActionListener(getDefaultActionSingleton()); + + showDate.setSelected(true); + showDate.setText("date"); + showDate.addActionListener(getDefaultActionSingleton()); + + showThread1.setSelected(true); + showThread1.setText("thread 1"); + showThread1.addActionListener(getDefaultActionSingleton()); + + showThread2.setSelected(true); + showThread2.setText("thread 2"); + showThread2.addActionListener(getDefaultActionSingleton()); + + showMessage.setSelected(true); + showMessage.setText("Show messages"); + showMessage.addActionListener(getDefaultActionSingleton()); + + showOut.setSelected(true); + showOut.setText("std. Out"); + showOut.addActionListener(getDefaultActionSingleton()); + + showErr.setSelected(true); + showErr.setText("std. Err"); + showErr.addActionListener(getDefaultActionSingleton()); + + showJava.setSelected(true); + showJava.setText("java"); + showJava.addActionListener(getDefaultActionSingleton()); + + showPlugin.setSelected(true); + showPlugin.setText("plugin"); + showPlugin.addActionListener(getDefaultActionSingleton()); + + showPreInit.setSelected(true); + showPreInit.setText("pre-init"); + showPreInit.setToolTipText("plugin only"); + showPreInit.addActionListener(getDefaultActionSingleton()); + + sortByLabel.setText("Sort by:"); + + regExLabel.setText("Regular expression filter:"); + regExLabel.addActionListener(getDefaultActionSingleton()); + + sortBy.setModel(new javax.swing.DefaultComboBoxModel(new String[]{"As arrived (no sort)", "user", "origin", "level", "date", "code", "thread1", "thread2", "message"})); + sortBy.addActionListener(getDefaultActionSingleton()); + + searchLabel.setText("Search:"); + + autorefresh.setSelected(true); + autorefresh.setText("auto refresh"); + + refresh.setText("refresh"); + refresh.addActionListener(getDefaultActionSingleton()); + + apply.setText("Apply"); + apply.addActionListener(new java.awt.event.ActionListener() { + + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + model.usedPattern = model.lastValidPattern; + refreshAction(evt); + } + }); + + regExFilter.setText(".*"); + + copyPlain.setText("Copy all (plain)"); + copyPlain.addActionListener(new java.awt.event.ActionListener() { + + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + copyPlainActionPerformed(evt); + } + }); + + copyRich.setText("Copy all (rich)"); + copyRich.addActionListener(new java.awt.event.ActionListener() { + + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + copyRichActionPerformed(evt); + } + }); + + next.setText("next>>>"); + next.addActionListener(new java.awt.event.ActionListener() { + + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + nextActionPerformed(evt); + } + }); + + previous.setText("<<<previous"); + previous.addActionListener(new java.awt.event.ActionListener() { + + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + previousActionPerformed(evt); + } + }); + + caseSensitive.setText("case sensitive"); + + showIncomplete.setSelected(true); + showIncomplete.setText("incomplete"); + showIncomplete.setToolTipText("plugin only"); + showIncomplete.addActionListener(getDefaultActionSingleton()); + + highLight.setSelected(true); + highLight.setText("highlight"); + highLight.addActionListener(getDefaultActionSingleton()); + + wordWrap.setText("word wrap"); + wordWrap.addActionListener(getDefaultActionSingleton()); + + showDebug.setSelected(true); + showDebug.setText("debug"); + showDebug.addActionListener(getDefaultActionSingleton()); + + showInfo.setSelected(true); + showInfo.setText("info"); + showInfo.addActionListener(getDefaultActionSingleton()); + + showCode.setSelected(true); + showCode.setText("code"); + showCode.addActionListener(getDefaultActionSingleton()); + + statistics.setText("x/y"); + + showPostInit.setSelected(true); + showPostInit.setText("post-init"); + showPostInit.setToolTipText("plugin only"); + showPostInit.addActionListener(getDefaultActionSingleton()); + + showComplete.setSelected(true); + showComplete.setText("complete"); + showComplete.setToolTipText("plugin only"); + showComplete.addActionListener(getDefaultActionSingleton()); + + match.setSelected(true); + match.setText("match"); + match.addActionListener(getDefaultActionSingleton()); + + notMatch.setText("not"); + notMatch.addActionListener(getDefaultActionSingleton()); + + revertSort.setSelected(true); + revertSort.setText("revert"); + revertSort.addActionListener(getDefaultActionSingleton()); + + mark.setText("mark"); + mark.addActionListener(new java.awt.event.ActionListener() { + + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + markActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING). + addGroup( + jPanel2Layout.createSequentialGroup().addContainerGap().addGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING). + addGroup( + jPanel2Layout.createSequentialGroup(). + addComponent(showHeaders).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(showUser).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED). + addComponent(showOrigin).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(showLevel).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED). + addComponent(showDate).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(showCode).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(showThread1).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(showThread2)). + addGroup(jPanel2Layout.createSequentialGroup().addGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING).addGroup( + javax.swing.GroupLayout.Alignment.LEADING, jPanel2Layout.createSequentialGroup() + .addComponent(previous).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(mark).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(next).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 15, Short.MAX_VALUE). + addComponent(wordWrap).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(highLight).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(copyRich).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(copyPlain)).addGroup(javax.swing.GroupLayout.Alignment.LEADING, jPanel2Layout.createSequentialGroup(). + addComponent(searchLabel).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(search, javax.swing.GroupLayout.DEFAULT_SIZE, 438, Short.MAX_VALUE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(caseSensitive)).addGroup( + javax.swing.GroupLayout.Alignment.LEADING, jPanel2Layout.createSequentialGroup(). + addComponent(showMessage).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(showOut).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(showErr).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(showJava).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(showPlugin).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(showDebug).addGap(6, 6, 6). + addComponent(showInfo))).addGap(2, 2, 2). + addComponent(statistics)).addGroup( + javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup(). + addComponent(showPreInit).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(showPostInit).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(showIncomplete).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(showComplete)). + addGroup(jPanel2Layout.createSequentialGroup(). + addComponent(autorefresh).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(refresh).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(sortByLabel).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(revertSort).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED). + addComponent(sortBy, 0, 327, Short.MAX_VALUE)). + addGroup(jPanel2Layout.createSequentialGroup(). + addComponent(regExLabel).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(match).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(notMatch).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(regExFilter, javax.swing.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(apply, javax.swing.GroupLayout.PREFERRED_SIZE, 106, javax.swing.GroupLayout.PREFERRED_SIZE))).addContainerGap())); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup( + javax.swing.GroupLayout.Alignment.LEADING). + addGroup( + jPanel2Layout.createSequentialGroup().addContainerGap().addGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE). + addComponent(showHeaders). + addComponent(showUser). + addComponent(showLevel). + addComponent(showDate). + addComponent(showOrigin). + addComponent(showCode). + addComponent(showThread1). + addComponent(showThread2)).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE). + addComponent(showMessage). + addComponent(showOut). + addComponent(showErr). + addComponent(showJava). + addComponent(showPlugin). + addComponent(showDebug). + addComponent(showInfo). + addComponent(statistics)).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE). + addComponent(showPreInit). + addComponent(showIncomplete). + addComponent(showPostInit). + addComponent(showComplete)).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED).addGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING). + addGroup( + jPanel2Layout.createSequentialGroup().addGap(32, 32, 32).addGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE). + addComponent(regExLabel).addComponent(regExFilter, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE). + addComponent(apply). + addComponent(match). + addComponent(notMatch))). + addGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE). + addComponent(autorefresh). + addComponent(refresh). + addComponent(sortByLabel).addComponent(sortBy, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE). + addComponent(revertSort))).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED).addGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING). + addGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE). + addComponent(searchLabel).addComponent(search, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)). + addComponent(caseSensitive)).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED).addGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING). + addComponent(previous). + addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE). + addComponent(copyPlain). + addComponent(copyRich). + addComponent(highLight). + addComponent(wordWrap)). + addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE). + addComponent(mark). + addComponent(next))).addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); + + jEditorPane1.setEditable(false); + jScrollPane1.setViewportView(jEditorPane1); + + showHide.setText("Hide"); + showHide.addActionListener(new java.awt.event.ActionListener() { + + @Override + public void actionPerformed(java.awt.event.ActionEvent evt) { + showHideActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(this); + this.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING). + addGroup(jPanel1Layout.createSequentialGroup().addContainerGap(). + addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING). + addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 684, Short.MAX_VALUE). + addGroup(jPanel1Layout.createSequentialGroup().addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING). + addComponent(showHide, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 672, Short.MAX_VALUE). + addComponent(jPanel2, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)).addContainerGap())))); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING). + addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup().addContainerGap(). + addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 329, Short.MAX_VALUE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED). + addComponent(showHide).addContainerGap())); + + insertChars = new JPopupMenu(); + JMenuItem tab = new JMenuItem("insert \\t"); + tab.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + java.awt.EventQueue.invokeLater(new Runnable() { + + @Override + public void run() { + try{ + int i = regExFilter.getCaretPosition(); + StringBuilder s = new StringBuilder(regExFilter.getText()); + s.insert(i, "\t"); + regExFilter.setText(s.toString()); + regExFilter.setCaretPosition(i + 1); + insertChars.setVisible(false); + } catch (Exception ex) { + OutputController.getLogger().log(ex); + } + } + }); + } + }); + JMenuItem newLine = new JMenuItem("insert \\n"); + newLine.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + java.awt.EventQueue.invokeLater(new Runnable() { + + @Override + public void run() { + try{ + int i = regExFilter.getCaretPosition(); + StringBuilder s = new StringBuilder(regExFilter.getText()); + s.insert(i, "\n"); + regExFilter.setText(s.toString()); + regExFilter.setCaretPosition(i + 1); + insertChars.setVisible(false); + } catch (Exception ex) { + OutputController.getLogger().log(ex); + } + } + }); + } + }); + + JMenuItem resetRegex = new JMenuItem("reset default"); + resetRegex.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + java.awt.EventQueue.invokeLater(new Runnable() { + + @Override + public void run() { + try{ + regExFilter.setText(ConsoleOutputPaneModel.defaultPattern.pattern()); + model.lastValidPattern = ConsoleOutputPaneModel.defaultPattern; + model.usedPattern = model.lastValidPattern; + insertChars.setVisible(false); + } catch (Exception ex) { + OutputController.getLogger().log(ex); + } + } + }); + } + }); + + insertChars.add(newLine); + insertChars.add(tab); + insertChars.add(resetRegex); + + + validate(); + } + + private void refreshAction(java.awt.event.ActionEvent evt) { + updateModel(); + refreshPane(); + } + + private void markActionPerformed(java.awt.event.ActionEvent evt) { + int matches = 0; + if (!mark.isSelected()) { + jEditorPane1.getHighlighter().removeAllHighlights(); + return; + } + try { + Document document = jEditorPane1.getDocument(); + String find = search.getText(); + if (find.length() == 0) { + jEditorPane1.getHighlighter().removeAllHighlights(); + return; + } + for (int index = 0; index + find.length() < document.getLength(); index++) { + String subMatch = document.getText(index, find.length()); + if ((caseSensitive.isSelected() && find.equals(subMatch)) || (!caseSensitive.isSelected() && find.equalsIgnoreCase(subMatch))) { + matches++; + javax.swing.text.DefaultHighlighter.DefaultHighlightPainter highlightPainter = + new javax.swing.text.DefaultHighlighter.DefaultHighlightPainter(Color.orange); + jEditorPane1.getHighlighter().addHighlight(index, index + find.length(), + highlightPainter); + } + } + mark.setText("mark (" + matches + ")"); + } catch (BadLocationException ex) { + OutputController.getLogger().log(ex); + } + } + + private void previousActionPerformed(java.awt.event.ActionEvent evt) { + try { + Document document = jEditorPane1.getDocument(); + String find = search.getText(); + if (find.length() == 0) { + lastPostion = document.getLength() - find.length() - 1; + return; + } + for (int index = lastPostion; index >= 0; index--) { + String subMatch = document.getText(index, find.length()); + if ((caseSensitive.isSelected() && find.equals(subMatch)) || (!caseSensitive.isSelected() && find.equalsIgnoreCase(subMatch))) { + if (lastSearchTag != null) { + jEditorPane1.getHighlighter().removeHighlight(lastSearchTag); + } + lastSearchTag = jEditorPane1.getHighlighter().addHighlight(index, index + find.length(), searchHighligh); + jEditorPane1.setCaretPosition(index); + + lastPostion = index - find.length() - 1; + return; + } + } + lastPostion = document.getLength() - find.length() - 1; + } catch (BadLocationException ex) { + OutputController.getLogger().log(ex); + } + } + + private void nextActionPerformed(java.awt.event.ActionEvent evt) { + try { + Document document = jEditorPane1.getDocument(); + String find = search.getText(); + if (find.length() == 0) { + lastPostion = 0; + return; + } + for (int index = lastPostion; index + find.length() < document.getLength(); index++) { + String subMatch = document.getText(index, find.length()); + if ((caseSensitive.isSelected() && find.equals(subMatch)) || (!caseSensitive.isSelected() && find.equalsIgnoreCase(subMatch))) { + if (lastSearchTag != null) { + jEditorPane1.getHighlighter().removeHighlight(lastSearchTag); + } + lastSearchTag = jEditorPane1.getHighlighter().addHighlight(index, index + find.length(), searchHighligh); + jEditorPane1.setCaretPosition(index); + + lastPostion = index + 1; + return; + } + } + lastPostion = 0; + } catch (BadLocationException ex) { + OutputController.getLogger().log(ex); + } + } + + private void showHideActionPerformed(java.awt.event.ActionEvent evt) { + if (jPanel2.isVisible()) { + jPanel2.setVisible(false); + showHide.setText("Show controls"); + } else { + jPanel2.setVisible(true); + showHide.setText("Hide"); + } + } + + private void copyPlainActionPerformed(java.awt.event.ActionEvent evt) { + StringSelection stringSelection = new StringSelection(model.importList(false, 0)); + Clipboard clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard(); + clpbrd.setContents(stringSelection, null); + } + + private void copyRichActionPerformed(java.awt.event.ActionEvent evt) { + StringSelection stringSelection = new StringSelection(model.importList(true, 0)); + Clipboard clpbrd = Toolkit.getDefaultToolkit().getSystemClipboard(); + clpbrd.setContents(stringSelection, null); + } + + public static void main(String args[]) { + java.awt.EventQueue.invokeLater(new Runnable() { + + @Override + public void run() { + JFrame dialog = new JFrame(); + dialog.setSize(800, 600); + dialog.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + ObservableMessagesProvider producer = new ConsoleOutputPaneModel.TestMessagesProvider(); + ConsoleOutputPane jPanel1 = new ConsoleOutputPane(producer); + producer.getObservable().addObserver(jPanel1); + dialog.getContentPane().add(jPanel1, java.awt.BorderLayout.CENTER); + dialog.pack(); + dialog.setVisible(true); + } + }); + } + + private void updateModel() { + model.highLight = highLight.isSelected(); + model.matchPattern = match.isSelected(); + model.regExLabel = regExLabel.isSelected(); + model.revertSort = revertSort.isSelected(); + model.showCode = showCode.isSelected(); + model.showComplete = showComplete.isSelected(); + model.showDate = showDate.isSelected(); + model.showDebug = showDebug.isSelected(); + model.showErr = showErr.isSelected(); + model.showHeaders = showHeaders.isSelected(); + model.showIncomplete = showIncomplete.isSelected(); + model.showInfo = showInfo.isSelected(); + model.showJava = showJava.isSelected(); + model.showLevel = showLevel.isSelected(); + model.showMessage = showMessage.isSelected(); + model.showOrigin = showOrigin.isSelected(); + model.showOut = showOut.isSelected(); + model.showPlugin = showPlugin.isSelected(); + model.showPostInit = showPostInit.isSelected(); + model.showPreInit = showPreInit.isSelected(); + model.showThread1 = showThread1.isSelected(); + model.showThread2 = showThread2.isSelected(); + model.showUser = showUser.isSelected(); + model.sortBy = sortBy.getSelectedIndex(); + model.wordWrap = wordWrap.isSelected(); + + } + private javax.swing.JButton apply; + private javax.swing.JCheckBox autorefresh; + private javax.swing.JCheckBox caseSensitive; + private javax.swing.JButton copyPlain; + private javax.swing.JButton copyRich; + private javax.swing.JCheckBox highLight; + private javax.swing.JEditorPane jEditorPane1; + private javax.swing.JPanel jPanel2; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JCheckBox mark; + private javax.swing.JRadioButton match; + private javax.swing.JButton next; + private javax.swing.JRadioButton notMatch; + private javax.swing.JButton previous; + private javax.swing.JButton refresh; + private javax.swing.JTextField regExFilter; + private javax.swing.JCheckBox regExLabel; + private javax.swing.JCheckBox revertSort; + private javax.swing.JTextField search; + private javax.swing.JLabel searchLabel; + private javax.swing.JCheckBox showCode; + private javax.swing.JCheckBox showComplete; + private javax.swing.JCheckBox showDate; + private javax.swing.JCheckBox showDebug; + private javax.swing.JCheckBox showErr; + private javax.swing.JCheckBox showHeaders; + private javax.swing.JButton showHide; + private javax.swing.JCheckBox showIncomplete; + private javax.swing.JCheckBox showInfo; + private javax.swing.JCheckBox showJava; + private javax.swing.JCheckBox showLevel; + private javax.swing.JCheckBox showMessage; + private javax.swing.JCheckBox showOrigin; + private javax.swing.JCheckBox showOut; + private javax.swing.JCheckBox showPlugin; + private javax.swing.JCheckBox showPostInit; + private javax.swing.JCheckBox showPreInit; + private javax.swing.JCheckBox showThread1; + private javax.swing.JCheckBox showThread2; + private javax.swing.JCheckBox showUser; + private javax.swing.JComboBox sortBy; + private javax.swing.JLabel sortByLabel; + private javax.swing.JLabel statistics; + private javax.swing.JCheckBox wordWrap; + private javax.swing.JPopupMenu insertChars; +} diff --git a/netx/net/sourceforge/jnlp/util/logging/ConsoleOutputPaneModel.java b/netx/net/sourceforge/jnlp/util/logging/ConsoleOutputPaneModel.java new file mode 100644 index 0000000..79b132b --- /dev/null +++ b/netx/net/sourceforge/jnlp/util/logging/ConsoleOutputPaneModel.java @@ -0,0 +1,386 @@ +package net.sourceforge.jnlp.util.logging; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Observable; +import java.util.Random; +import java.util.regex.Pattern; +import net.sourceforge.jnlp.util.logging.OutputController.Level; +import net.sourceforge.jnlp.util.logging.headers.Header; +import net.sourceforge.jnlp.util.logging.headers.JavaMessage; +import net.sourceforge.jnlp.util.logging.headers.MessageWithHeader; +import net.sourceforge.jnlp.util.logging.headers.ObservableMessagesProvider; +import net.sourceforge.jnlp.util.logging.headers.PluginHeader; +import net.sourceforge.jnlp.util.logging.headers.PluginMessage; + +public class ConsoleOutputPaneModel { + + ConsoleOutputPaneModel(ObservableMessagesProvider dataProvider) { + this.dataProvider = dataProvider; + } + + boolean shouldUpdate() { + for (int i = lastUpdateIndex; i < dataProvider.getData().size(); i++) { + if (!filtered(dataProvider.getData().get(i))) { + return true; + } + } + return false; + } + + private abstract class CatchedMessageWithHeaderComparator implements Comparator<MessageWithHeader> { + + @Override + public int compare(MessageWithHeader o1, MessageWithHeader o2) { + try { + final int order = revertSort ? 1 : -1; + return order * body(o1, o2); + } catch (NullPointerException npe) { + //caused by corrupted c messages + return 0; + } + } + + abstract int body(MessageWithHeader o1, MessageWithHeader o2); + } + + //testign data provider + static class TestMessagesProvider extends Observable implements ObservableMessagesProvider { + + List<MessageWithHeader> data = new ArrayList<MessageWithHeader>(); + List<MessageWithHeader> origData = new ArrayList<MessageWithHeader>(); + + public List<MessageWithHeader> getData() { + return data; + } + + @Override + public Observable getObservable() { + return this; + } + + public TestMessagesProvider() { + createData(); + new Thread(new Runnable() { + @Override + public void run() { + while (true) { + try { + Thread.sleep(new Random().nextInt(2000)); + data.add(origData.get(new Random().nextInt(origData.size()))); + TestMessagesProvider.this.setChanged(); + TestMessagesProvider.this.notifyObservers(); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } + }).start(); + } + + void createData() { + String[] plugin = { + "plugindebug 1384850630162925 [jvanek][ITW-C-PLUGIN][MESSAGE_DEBUG][Tue Nov 19 09:43:50 CET 2013][/home/jvanek/Desktop/icedtea-web/plugin/icedteanp/IcedTeaNPPlugin.cc:1204] ITNPP Thread# 140513434003264, gthread 0x7fcbd531f8c0: PIPE: plugin read: plugin PluginProxyInfo reference 1 http://www.walter-fendt.de:80", + "preinit_plugindebug 1384850630162920 [jvanek][ITW-C-PLUGIN][MESSAGE_DEBUG][Tue Nov 19 09:43:50 CET 2013][/home/jvanek/Desktop/icedtea-web/plugin/icedteanp/IcedTeaNPPlugin.cc:1204] ITNPP Thread# 140513434003264, gthread 0x7fcbd531f8c0: PIPE: plugin read: plugin PluginProxyInfo reference 1 http://www.walter-fendt.de:80", + "plugindebugX 1384850630162954 [jvanek][ITW-Cplugindebug 1384850630163008 [jvanek][ITW-C-PLUGIN][MESSAGE_DEBUG][Tue Nov 19 09:43:50 CET 2013][/home/jvanek/Desktop/icedtea-web/plugin/icedteanp/IcedTeaNPPlugin.cc:1124] ITNPP Thread# 140513434003264, gthread 0x7fcbd531f8c0: parts[0]=plugin, parts[1]=PluginProxyInfo, reference, parts[3]=1, parts[4]=http://www.walter-fendt.de:80 -- decoded_url=http://www.walter-fendt.de:80", + "preinit_pluginerror 1384850630163294 [jvanek][ITW-C-PLUGIN][MESSAGE_ERROR][Tue Nov 19 09:43:50 CET 2013][/home/jvanek/Desktop/icedtea-web/plugin/icedteanp/IcedTeaNPPlugin.cc:1134] ITNPP Thread# 140513434003264, gthread 0x7fcbd531f8c0: Proxy info: plugin PluginProxyInfo reference 1 DIRECT", + "pluginerror 1384850630163291 [jvanek][ITW-C-PLUGIN][MESSAGE_ERROR][Tue Nov 19 09:43:50 CET 2013][/home/jvanek/Desktop/icedtea-web/plugin/icedteanp/IcedTeaNPPlugin.cc:1134] ITNPP Thread# 140513434003264, gthread 0x7fcbd531f8c0: Proxy info: plugin PluginProxyInfo reference 1 DIRECT" + }; + for (String string : plugin) { + origData.add(new PluginMessage(string)); + } + origData.add(new JavaMessage(new Header(Level.ERROR_ALL, Thread.currentThread().getStackTrace(), Thread.currentThread(), false), "message 1")); + origData.add(new JavaMessage(new Header(Level.ERROR_DEBUG, Thread.currentThread().getStackTrace(), Thread.currentThread(), false), "message 3")); + origData.add(new JavaMessage(new Header(Level.WARNING_ALL, Thread.currentThread().getStackTrace(), Thread.currentThread(), false), "message 2")); + origData.add(new JavaMessage(new Header(Level.WARNING_DEBUG, Thread.currentThread().getStackTrace(), Thread.currentThread(), false), "message 4")); + origData.add(new JavaMessage(new Header(Level.MESSAGE_DEBUG, Thread.currentThread().getStackTrace(), Thread.currentThread(), false), "message 9")); + origData.add(new JavaMessage(new Header(Level.MESSAGE_ALL, Thread.currentThread().getStackTrace(), Thread.currentThread(), false), "message 0 - multilined \n" + + "since beggining\n" + + " later\n" + + "again from beggingin\n" + + " even later")); + data.addAll(origData); + } + } + static final Pattern defaultPattern = Pattern.compile("(m?)(.*\n*)*"); + ObservableMessagesProvider dataProvider; + Pattern lastValidPattern = defaultPattern; + Pattern usedPattern = lastValidPattern; + int lastUpdateIndex; //to add just what was added newly + int statisticsShown; + private static final String HTMLCOLOR_DIMRED = "FF6666"; + private static final String HTMLCOLOR_MIDGRAY = "666666"; + private static final String HTMLCOLOR_SPARKRED = "FF0000"; + private static final String HTMLCOLOR_LIGHTGRAY = "AAAAAA"; + private static final String HTMLCOLOR_GREENYELLOW = "AAAA00"; + private static final String HTMLCOLOR_PINKYREAD = "FF0055"; + private static final String HTMLCOLOR_BLACK = "000000"; + + String importList() { + return importList(lastUpdateIndex); + } + + String importList(int start) { + return importList(highLight, start); + } + + String importList(boolean mark, int start) { + int added = start; + StringBuilder sb = new StringBuilder(); + if (mark) { + sb.append("<div style='"); + if (!wordWrap) { + sb.append("white-space:nowrap;"); + } + sb.append("font-family:\"Monospaced\"'>"); + } + + List<MessageWithHeader> sortedList; + if (start == 0) { + sortedList = preSort(dataProvider.getData()); + } else { + sortedList = preSort(Collections.synchronizedList(dataProvider.getData().subList(start, dataProvider.getData().size()))); + } + lastUpdateIndex = dataProvider.getData().size(); + + for (MessageWithHeader messageWithHeader : sortedList) { + if (filtered(messageWithHeader)) { + continue; + } + + + if (mark) { + sb.append("<div style='color:#"); + if (messageWithHeader.getHeader().isC && messageWithHeader.getHeader() instanceof PluginHeader) { + if (!((PluginHeader) (messageWithHeader.getHeader())).preinit) { + if (messageWithHeader.getHeader().level.isError()) { + sb.append(HTMLCOLOR_DIMRED); + } else { + sb.append(HTMLCOLOR_MIDGRAY); + } + } else { + if (messageWithHeader.getHeader().level.isError()) { + sb.append(HTMLCOLOR_SPARKRED); + } else { + sb.append(HTMLCOLOR_LIGHTGRAY); + } + } + } else { + if (messageWithHeader.getHeader().level.isWarning()) { + sb.append(HTMLCOLOR_GREENYELLOW); + } else if (messageWithHeader.getHeader().level.isError()) { + sb.append(HTMLCOLOR_PINKYREAD); + } else { + sb.append(HTMLCOLOR_BLACK); + } + } + sb.append("'>"); + //sb.append("<![CDATA["); + } + if (messageWithHeader instanceof PluginMessage && ((PluginMessage) (messageWithHeader)).wasError) { + sb.append("{corrupted}"); + } + String line = (createLine(messageWithHeader)); + if (mark) { + line = line.replaceAll("\n", "<br>\n"); + line = line.replaceAll(" ", " ");//small trick, html is reducting row of sapces to single space. This handles it and stimm allow line wrap + line = line.replaceAll("\t", " "); + } + sb.append(line); + if (mark) { + //sb.append("]]>"); + sb.append("</div>"); + } + //always wrap, looks better, works smoother + sb.append("\n"); + added++; + + } + if (mark) { + sb.append("</div>"); + } + statisticsShown = added; + return sb.toString(); + + } + + String createLine(MessageWithHeader m) { + StringBuilder sb = new StringBuilder(); + if (showHeaders) { + sb.append(m.getHeader().toString(showUser, + showOrigin, + showLevel, + showDate, + showCode, + showThread1, + showThread2)); + } + if (showMessage && showHeaders) { + sb.append(": "); + } + if (showMessage) { + sb.append(m.getMessage().toString()); + } + return sb.toString(); + } + + List<MessageWithHeader> preSort(List<MessageWithHeader> data) { + List<MessageWithHeader> sortedData; + if (sortBy == 0) { + if (revertSort) { + sortedData = Collections.synchronizedList(new ArrayList<MessageWithHeader>(data)); + Collections.reverse(sortedData); + } else { + sortedData = data; + } + } else { + sortedData = Collections.synchronizedList(new ArrayList<MessageWithHeader>(data)); + switch (sortBy) { + case 1: + Collections.sort(sortedData, new CatchedMessageWithHeaderComparator() { + @Override + public int body(MessageWithHeader o1, MessageWithHeader o2) { + return o1.getHeader().user.compareTo(o2.getHeader().user); + + } + }); + break; + case 2: + Collections.sort(sortedData, new CatchedMessageWithHeaderComparator() { + @Override + public int body(MessageWithHeader o1, MessageWithHeader o2) { + return o1.getHeader().getOrigin().compareTo(o2.getHeader().getOrigin()); + } + }); + break; + case 3: + Collections.sort(sortedData, new CatchedMessageWithHeaderComparator() { + @Override + public int body(MessageWithHeader o1, MessageWithHeader o2) { + return o1.getHeader().level.toString().compareTo(o2.getHeader().level.toString()); + } + }); + break; + case 4: + Collections.sort(sortedData, new CatchedMessageWithHeaderComparator() { + @Override + public int body(MessageWithHeader o1, MessageWithHeader o2) { + return o1.getHeader().date.compareTo(o2.getHeader().date); + } + }); + break; + case 5: + Collections.sort(sortedData, new CatchedMessageWithHeaderComparator() { + @Override + public int body(MessageWithHeader o1, MessageWithHeader o2) { + return o1.getHeader().caller.compareTo(o2.getHeader().caller); + } + }); + break; + case 6: + Collections.sort(sortedData, new CatchedMessageWithHeaderComparator() { + @Override + public int body(MessageWithHeader o1, MessageWithHeader o2) { + return o1.getHeader().thread1.compareTo(o2.getHeader().thread1); + } + }); + break; + case 7: + Collections.sort(sortedData, new CatchedMessageWithHeaderComparator() { + @Override + public int body(MessageWithHeader o1, MessageWithHeader o2) { + return o1.getMessage().compareTo(o2.getMessage()); + } + }); + break; + case 8: + Collections.sort(sortedData, new CatchedMessageWithHeaderComparator() { + @Override + public int body(MessageWithHeader o1, MessageWithHeader o2) { + return o1.getHeader().thread2.compareTo(o2.getHeader().thread2); + } + }); + break; + } + + } + return sortedData; + } + + boolean filtered(MessageWithHeader m) { + if (!showOut && m.getHeader().level.isOutput() && !m.getHeader().level.isWarning()) { + return true; + } + if (!showErr && m.getHeader().level.isError() && !m.getHeader().level.isWarning()) { + return true; + } + if (!showDebug && m.getHeader().level.isDebug()) { + return true; + } + if (!showInfo && m.getHeader().level.isInfo()) { + return true; + } + if (!showJava && !m.getHeader().isC) { + return true; + } + if (!showPlugin && m.getHeader().isC) { + return true; + } + if (m.getHeader() instanceof PluginHeader) { + PluginHeader mm = (PluginHeader) m.getHeader(); + if (!showPreInit && mm.preinit) { + return true; + } + if (!showPostInit && !mm.preinit) { + return true; + } + if (!showIncomplete && m instanceof PluginMessage && ((PluginMessage) (m)).wasError) { + return true; + } + if (!showComplete && m instanceof PluginMessage && !((PluginMessage) (m)).wasError) { + return true; + } + } + if (regExLabel) { + String s = createLine(m); + if (matchPattern && !usedPattern.matcher(s).matches()) { + return true; + } + if (!matchPattern && usedPattern.matcher(s).matches()) { + return true; + } + } + return false; + } + + String createStatisticHint() { + return statisticsShown + "/" + dataProvider.getData().size(); + } + boolean highLight; + boolean matchPattern; + boolean regExLabel; + boolean revertSort; + boolean showCode; + boolean showComplete; + boolean showDate; + boolean showDebug; + boolean showErr; + boolean showHeaders; + boolean showIncomplete; + boolean showInfo; + boolean showJava; + boolean showLevel; + boolean showMessage; + boolean showOrigin; + boolean showOut; + boolean showPlugin; + boolean showPostInit; + boolean showPreInit; + boolean showThread1; + boolean showThread2; + boolean showUser; + int sortBy; + boolean wordWrap; +} diff --git a/netx/net/sourceforge/jnlp/util/logging/JavaConsole.java b/netx/net/sourceforge/jnlp/util/logging/JavaConsole.java index 3b7d438..8671732 100644 --- a/netx/net/sourceforge/jnlp/util/logging/JavaConsole.java +++ b/netx/net/sourceforge/jnlp/util/logging/JavaConsole.java @@ -38,10 +38,11 @@ package net.sourceforge.jnlp.util.logging; import static net.sourceforge.jnlp.runtime.Translator.R; +import java.awt.BorderLayout; import java.awt.Dimension; -import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; +import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; @@ -51,37 +52,104 @@ import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.Map; +import java.util.Observable; import java.util.Properties; import java.util.Set; import javax.swing.JButton; +import javax.swing.JComponent; import javax.swing.JDialog; +import javax.swing.JFormattedTextField; import javax.swing.JFrame; +import javax.swing.JLabel; import javax.swing.JPanel; -import javax.swing.JScrollPane; +import javax.swing.JSpinner; import javax.swing.JSplitPane; -import javax.swing.JTextArea; +import javax.swing.SpinnerNumberModel; import javax.swing.SwingUtilities; -import javax.swing.border.EmptyBorder; -import javax.swing.border.TitledBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import javax.swing.text.DefaultFormatter; import net.sourceforge.jnlp.config.DeploymentConfiguration; import net.sourceforge.jnlp.runtime.JNLPRuntime; import net.sourceforge.jnlp.util.ImageResources; import net.sourceforge.jnlp.util.logging.headers.Header; +import net.sourceforge.jnlp.util.logging.headers.JavaMessage; +import net.sourceforge.jnlp.util.logging.headers.MessageWithHeader; +import net.sourceforge.jnlp.util.logging.headers.ObservableMessagesProvider; import net.sourceforge.jnlp.util.logging.headers.PluginMessage; /** * A simple Java console for IcedTeaPlugin and JavaWS * */ -public class JavaConsole { +public class JavaConsole implements ObservableMessagesProvider { + + private List<MessageWithHeader> rawData = Collections.synchronizedList(new ArrayList<MessageWithHeader>()); + private List<ConsoleOutputPane> outputs = new ArrayList<ConsoleOutputPane>(); + + private void refreshOutputs() { + refreshOutputs(outputsPanel, (Integer)numberOfOutputs.getValue()); + } + + private void refreshOutputs(JPanel pane, int count) { + pane.removeAll(); + while(outputs.size()>count){ + getObservable().deleteObserver(outputs.get(outputs.size()-1)); + outputs.remove(outputs.size()-1); + } + while(outputs.size()<count){ + ConsoleOutputPane c1 = new ConsoleOutputPane(this); + observable.addObserver(c1); + outputs.add(c1); + } + if (count == 0){ + pane.add(new JPanel()); + } else if (outputs.size() == 1){ + pane.add(outputs.get(0)); + } else { + JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,outputs.get(outputs.size()-2), outputs.get(outputs.size()-1)); + splitPane.setDividerLocation(0.5); + splitPane.setResizeWeight(0.5); + + for (int i = outputs.size()-3; i>=0; i--){ + JSplitPane outerPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, outputs.get(i), splitPane); + outerPane.setDividerLocation(0.5); + outerPane.setResizeWeight(0.5); + splitPane = outerPane; + } + pane.add(splitPane); + + } + pane.validate(); + } + + private static class PublicObservable extends Observable { + + @Override + public synchronized void setChanged() { + super.setChanged(); + } + } public static interface ClassLoaderInfoProvider { public Map<String, String> getLoaderInfo(); } + private static JavaConsole console; - private static Dimension lastSize; + + private Dimension lastSize; + private JDialog consoleWindow; + private JPanel contentPanel; + private JPanel outputsPanel; + private ClassLoaderInfoProvider classLoaderInfoProvider; + private JSpinner numberOfOutputs; + private PublicObservable observable = new PublicObservable(); + private boolean initialized = false; private static class JavaConsoleHolder { @@ -116,21 +184,7 @@ public class JavaConsole { || (DeploymentConfiguration.CONSOLE_SHOW_JAVAWS.equals(config.getProperty(DeploymentConfiguration.KEY_CONSOLE_STARTUP_MODE)) && isApplication); } - private JDialog consoleWindow; - private JTextArea stdErrText; - private JTextArea stdOutText; - private JPanel contentPanel; - private ClassLoaderInfoProvider classLoaderInfoProvider; - private boolean initialized = false; - - private String stdErrTextSrc = ""; - private String stdOutTextSrc = ""; - - public JavaConsole() { - - } - - + private void initializeWindow() { if (!initialized){ initialize(); @@ -149,7 +203,8 @@ public class JavaConsole { }); consoleWindow.setIconImages(ImageResources.INSTANCE.getApplicationImages()); - + //view is added after console is made visible so no performance impact when hidden/ + refreshOutputs(); consoleWindow.add(content); consoleWindow.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); //HIDE_ON_CLOSE can cause shut down deadlock consoleWindow.pack(); @@ -158,7 +213,7 @@ public class JavaConsole { } else { consoleWindow.setSize(new Dimension(900, 600)); } - consoleWindow.setMinimumSize(new Dimension(900, 300)); + consoleWindow.setMinimumSize(new Dimension(300, 300)); } @@ -168,36 +223,18 @@ public class JavaConsole { private void initialize() { contentPanel = new JPanel(); + outputsPanel = new JPanel(); + + outputsPanel.setLayout(new BorderLayout()); contentPanel.setLayout(new GridBagLayout()); GridBagConstraints c; - - Font monoSpace = new Font("Monospaced", Font.PLAIN, 12); - - - stdOutText = new JTextArea(); - JScrollPane stdOutScrollPane = new JScrollPane(stdOutText); - stdOutScrollPane.setBorder(new TitledBorder( - new EmptyBorder(5, 5, 5, 5), "System.out")); - stdOutText.setEditable(false); - stdOutText.setFont(monoSpace); - - stdErrText = new JTextArea(); - JScrollPane stdErrScrollPane = new JScrollPane(stdErrText); - stdErrScrollPane.setBorder(new TitledBorder( - new EmptyBorder(5, 5, 5, 5), "System.err")); - stdErrText.setEditable(false); - stdErrText.setFont(monoSpace); - - JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, - stdOutScrollPane, stdErrScrollPane); - c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.gridheight = 10; c.weighty = 1; - contentPanel.add(splitPane, c); + contentPanel.add(outputsPanel, c); /* buttons */ @@ -208,6 +245,7 @@ public class JavaConsole { c.weighty = 0; JPanel buttonPanel = new JPanel(); + buttonPanel.setLayout(new GridLayout(2, 0, 0, 0)); contentPanel.add(buttonPanel, c); JButton gcButton = new JButton(R("CONSOLErungc")); @@ -221,6 +259,7 @@ public class JavaConsole { System.gc(); OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("ButDone")); printMemoryInfo(); + updateModel(); } }); @@ -235,6 +274,7 @@ public class JavaConsole { Runtime.getRuntime().runFinalization(); OutputController.getLogger().log(OutputController.Level.MESSAGE_ALL, R("ButDone")); printMemoryInfo(); + updateModel(); } }); @@ -245,6 +285,7 @@ public class JavaConsole { @Override public void actionPerformed(ActionEvent e) { printMemoryInfo(); + updateModel(); } }); @@ -255,6 +296,7 @@ public class JavaConsole { @Override public void actionPerformed(ActionEvent e) { printSystemProperties(); + updateModel(); } }); @@ -265,6 +307,7 @@ public class JavaConsole { @Override public void actionPerformed(ActionEvent e) { printClassLoaders(); + updateModel(); } }); @@ -275,9 +318,26 @@ public class JavaConsole { @Override public void actionPerformed(ActionEvent e) { printThreadInfo(); + updateModel(); } }); + JLabel numberOfOutputsL = new JLabel(" Number of outputs: "); + buttonPanel.add(numberOfOutputsL); + numberOfOutputs = new JSpinner(new SpinnerNumberModel(1, 0, 10, 1)); + JComponent comp = numberOfOutputs.getEditor(); + JFormattedTextField field = (JFormattedTextField) comp.getComponent(0); + DefaultFormatter formatter = (DefaultFormatter) field.getFormatter(); + formatter.setCommitsOnValidEdit(true); + numberOfOutputs.addChangeListener(new ChangeListener() { + + @Override + public void stateChanged(ChangeEvent e) { + refreshOutputs(); + } + }); + buttonPanel.add(numberOfOutputs); + JButton closeButton = new JButton(R("ButClose")); buttonPanel.add(closeButton); closeButton.addActionListener(new ActionListener() { @@ -294,8 +354,6 @@ public class JavaConsole { } }); - splitPane.setDividerLocation(0.5); - splitPane.setResizeWeight(0.5); initialized = true; } @@ -304,12 +362,17 @@ public class JavaConsole { } public void showConsole(boolean modal) { - initializeWindow(); - consoleWindow.setModal(modal); - consoleWindow.setVisible(true); + if (consoleWindow == null || !consoleWindow.isVisible()){ + initializeWindow(); + consoleWindow.setModal(modal); + consoleWindow.setVisible(true); + } } public void hideConsole() { + //no need to update when hidden + outputsPanel.removeAll();//?? + getObservable().deleteObservers(); consoleWindow.setModal(false); consoleWindow.setVisible(false); consoleWindow.dispose(); @@ -417,23 +480,17 @@ public class JavaConsole { } - synchronized void addMessage(Header header, String message) { - String headerString = ""; - if (LogConfig.getLogConfig().isEnableHeaders()){ - headerString = header.toString(); - } - if (header.level.isError()){ - stdErrTextSrc += headerString + message +"\n"; - } - if (header.level.isOutput()){ - stdOutTextSrc += headerString + message + "\n"; - } - if (initialized){ - stdErrText.setText(stdErrTextSrc); - stdOutText.setText(stdOutTextSrc); - } + synchronized void addMessage(MessageWithHeader m) { + rawData.add(m); + updateModel(); + } + + private synchronized void updateModel() { + observable.setChanged(); + observable.notifyObservers(); } + /** * parse plugin message and add it as header+message to data * @param s string to be parsed @@ -443,7 +500,16 @@ public class JavaConsole { OutputController.getLogger().log(pm); } - + @Override + public List<MessageWithHeader> getData() { + return rawData; + } + + @Override + public Observable getObservable() { + return observable; + } + public void createPluginReader(final File file) { OutputController.getLogger().log("Starting processing of plugin-debug-to-console " + file.getAbsolutePath()); Thread t = new Thread(new Runnable() { diff --git a/netx/net/sourceforge/jnlp/util/logging/OutputController.java b/netx/net/sourceforge/jnlp/util/logging/OutputController.java index 996eebb..3bec9f0 100644 --- a/netx/net/sourceforge/jnlp/util/logging/OutputController.java +++ b/netx/net/sourceforge/jnlp/util/logging/OutputController.java @@ -146,7 +146,7 @@ public class OutputController { messageQue.remove(0); //filtering is done in console during runtime if (LogConfig.getLogConfig().isLogToConsole()) { - JavaConsole.getConsole().addMessage(s.getHeader(), s.getMessage()); + JavaConsole.getConsole().addMessage(s); } if (!JNLPRuntime.isDebug() && (s.getHeader().level == Level.MESSAGE_DEBUG || s.getHeader().level == Level.WARNING_DEBUG diff --git a/netx/net/sourceforge/jnlp/util/logging/headers/Header.java b/netx/net/sourceforge/jnlp/util/logging/headers/Header.java index bb09f89..c2a91bb 100644 --- a/netx/net/sourceforge/jnlp/util/logging/headers/Header.java +++ b/netx/net/sourceforge/jnlp/util/logging/headers/Header.java @@ -45,13 +45,13 @@ public class Header { public static String default_user = System.getProperty("user.name"); public String user = default_user; - public boolean application; - public Level level; + public boolean application = true; + public Level level = Level.WARNING_ALL; public Date date = new Date(); - public boolean isC;//false=> java - public String caller; - public String thread1; - public String thread2; + public boolean isC = false;//false=> java + public String caller = "unknown"; + public String thread1 = "unknown"; + public String thread2 = "unknown"; //to alow simple inheritance public Header() { diff --git a/netx/net/sourceforge/jnlp/util/logging/headers/ObservableMessagesProvider.java b/netx/net/sourceforge/jnlp/util/logging/headers/ObservableMessagesProvider.java new file mode 100644 index 0000000..a8b8bea --- /dev/null +++ b/netx/net/sourceforge/jnlp/util/logging/headers/ObservableMessagesProvider.java @@ -0,0 +1,46 @@ +/* +Copyright (C) 2009, 2013 Red Hat + +This file is part of IcedTea. + +IcedTea 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, or (at your option) +any later version. + +IcedTea 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 IcedTea; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ +package net.sourceforge.jnlp.util.logging.headers; + +import java.util.List; +import java.util.Observable; + +public interface ObservableMessagesProvider { + + public List<MessageWithHeader> getData(); + public Observable getObservable(); +} |