package com.revolsys.swing.logging; import java.awt.BorderLayout; import java.awt.Component; import java.awt.Dialog.ModalityType; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Font; import java.awt.Window; import java.io.PrintWriter; import java.sql.Timestamp; import javax.swing.BorderFactory; import javax.swing.JDialog; import javax.swing.JEditorPane; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.ScrollPaneConstants; import javax.swing.SwingUtilities; import javax.swing.border.Border; import org.apache.commons.io.output.StringBuilderWriter; import org.apache.log4j.Level; import org.apache.log4j.spi.LoggingEvent; import org.jdesktop.swingx.plaf.basic.core.BasicTransferable; import com.revolsys.datatype.DataTypes; import com.revolsys.swing.SwingUtil; import com.revolsys.swing.action.RunnableAction; import com.revolsys.swing.dnd.ClipboardUtil; import com.revolsys.swing.layout.GroupLayouts; import com.revolsys.swing.parallel.Invoke; import com.revolsys.util.CaseConverter; import com.revolsys.util.Property; public class LoggingEventPanel extends JPanel { private static final long serialVersionUID = 1L; private static void addField(final JPanel panel, final String fieldName, final Object value, final boolean useScrollPane) { if (Property.hasValue(value)) { addLabel(panel, fieldName); String stringValue = DataTypes.toString(value); if (!Property.hasValue(stringValue)) { stringValue = "-"; } final JTextPane label = new JTextPane(); label.setContentType("text/html"); label.setEditable(false); label.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, true); label.setFont(new JLabel().getFont()); label.setText(stringValue); if (useScrollPane) { final JScrollPane scrollPane = new JScrollPane(label); scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); scrollPane.setBorder(BorderFactory.createEtchedBorder()); panel.add(scrollPane); } else { final Border border = BorderFactory.createCompoundBorder(BorderFactory.createEtchedBorder(), BorderFactory.createEmptyBorder(1, 2, 1, 2)); label.setBorder(border); panel.add(label); } } } private static void addLabel(final JPanel panel, final String fieldName) { final JLabel label = new JLabel(CaseConverter.toCapitalizedWords(fieldName)); label.setFont(label.getFont().deriveFont(Font.BOLD)); panel.add(label); } public static String getStackTrace(final LoggingEvent event) { final StringBuilder stackTrace = new StringBuilder(); final String[] stack = event.getThrowableStrRep(); if (stack != null) { for (final String trace : stack) { stackTrace.append(trace); stackTrace.append("\n"); } } return stackTrace.toString(); } public static void showDialog(final Component parent, final LoggingEvent event) { Invoke.later(() -> { final long time = event.getTimeStamp(); final Timestamp timestamp = new Timestamp(time); final String stackTraceBuilder = getStackTrace(event); final Level level = event.getLevel(); final String loggerName = event.getLoggerName(); final String threadName = event.getThreadName(); final Object message = event.getMessage(); final LoggingEventPanel panel = new LoggingEventPanel(timestamp, level, loggerName, threadName, message, stackTraceBuilder); panel.showDialog(parent, "Application Log Details"); }); } public static void showDialog(final Component parent, final String title, final String message, final Throwable e) { Invoke.later(() -> { final StringBuilderWriter stackTrace = new StringBuilderWriter(); try ( PrintWriter printWriter = new PrintWriter(stackTrace)) { e.printStackTrace(printWriter); } final LoggingEventPanel panel = new LoggingEventPanel(null, null, null, null, message, stackTrace); panel.showDialog(parent, title); }); } public static void showDialog(final Component parent, final String message, final Throwable e) { showDialog(parent, "Error", message, e); } private final StringBuilder copyText = new StringBuilder(); public LoggingEventPanel(final Timestamp time, final Object level, final String loggerName, final String threadName, final Object message, final Object stackTrace) { setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); addField(this, "Timestamp", time, false); addField(this, "level", level, false); addField(this, "loggerName", loggerName, false); addField(this, "message", message, false); addField(this, "threadName", threadName, false); if (message != null) { this.copyText.append(message); } if (Property.hasValue(stackTrace)) { addField(this, "Stack Trace", "<pre>" + stackTrace + "</pre>", true); if (this.copyText.length() > 0) { this.copyText.append("\n"); } this.copyText.append(stackTrace); } GroupLayouts.makeColumns(this, 2, true); setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); } private void showDialog(final Component parent, final String title) { final Window window; if (parent == null) { window = SwingUtil.getActiveWindow(); } else { window = SwingUtilities.getWindowAncestor(parent); } final JDialog dialog = new JDialog(window, title, ModalityType.APPLICATION_MODAL); dialog.setLayout(new BorderLayout()); dialog.add(this, BorderLayout.CENTER); final JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT)); buttons.add(RunnableAction.newButton("Copy Error", () -> { final BasicTransferable transferable = new BasicTransferable(this.copyText.toString(), "<pre>" + this.copyText + "</pre>"); ClipboardUtil.setContents(transferable); })); buttons.add(RunnableAction.newButton("OK", () -> dialog.setVisible(false))); dialog.add(buttons, BorderLayout.SOUTH); dialog.setMaximumSize(new Dimension(1000, 700)); dialog.pack(); dialog.setVisible(true); } }