Commit 129a7c39 authored by Skylot's avatar Skylot

gui: add log viewer

parent ac3f3e83
...@@ -116,7 +116,8 @@ public class JadxCLIArgs implements IJadxArgs { ...@@ -116,7 +116,8 @@ public class JadxCLIArgs implements IJadxArgs {
if (isVerbose()) { if (isVerbose()) {
ch.qos.logback.classic.Logger rootLogger = ch.qos.logback.classic.Logger rootLogger =
(ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME); (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
rootLogger.setLevel(ch.qos.logback.classic.Level.DEBUG); // remove INFO ThresholdFilter
rootLogger.getAppender("STDOUT").clearAllFilters();
} }
} catch (JadxException e) { } catch (JadxException e) {
System.err.println("ERROR: " + e.getMessage()); System.err.println("ERROR: " + e.getMessage());
......
<configuration> <configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder> <encoder>
<pattern>%-5level - %msg%n</pattern> <pattern>%-5level - %msg%n</pattern>
</encoder> </encoder>
</appender> </appender>
<root level="INFO"> <root level="DEBUG">
<appender-ref ref="STDOUT"/> <appender-ref ref="STDOUT"/>
</root> </root>
......
...@@ -3,6 +3,7 @@ package jadx.gui; ...@@ -3,6 +3,7 @@ package jadx.gui;
import jadx.gui.settings.JadxSettings; import jadx.gui.settings.JadxSettings;
import jadx.gui.settings.JadxSettingsAdapter; import jadx.gui.settings.JadxSettingsAdapter;
import jadx.gui.ui.MainWindow; import jadx.gui.ui.MainWindow;
import jadx.gui.utils.LogCollector;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import javax.swing.UIManager; import javax.swing.UIManager;
...@@ -15,6 +16,7 @@ public class JadxGUI { ...@@ -15,6 +16,7 @@ public class JadxGUI {
public static void main(String[] args) { public static void main(String[] args) {
try { try {
LogCollector.register();
final JadxSettings jadxArgs = JadxSettingsAdapter.load(); final JadxSettings jadxArgs = JadxSettingsAdapter.load();
// overwrite loaded settings by command line arguments // overwrite loaded settings by command line arguments
if (!jadxArgs.processArgs(args)) { if (!jadxArgs.processArgs(args)) {
......
package jadx.gui.ui;
import ch.qos.logback.classic.Level;
import jadx.gui.utils.LogCollector;
import jadx.gui.utils.NLS;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
class LogViewer extends JDialog {
private static final long serialVersionUID = -2188700277429054641L;
private static final Level[] LEVEL_ITEMS = {Level.DEBUG, Level.INFO, Level.WARN, Level.ERROR};
private static Level level = Level.WARN;
private RSyntaxTextArea textPane;
public LogViewer() {
initUI();
registerLogListener();
}
public final void initUI() {
textPane = new RSyntaxTextArea();
textPane.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
JPanel controlPane = new JPanel();
controlPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
final JComboBox cb = new JComboBox(LEVEL_ITEMS);
cb.setSelectedItem(level);
cb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int i = cb.getSelectedIndex();
level = LEVEL_ITEMS[i];
registerLogListener();
}
});
JLabel levelLabel = new JLabel(NLS.str("log.level"));
levelLabel.setLabelFor(cb);
controlPane.add(levelLabel);
controlPane.add(cb);
JScrollPane scrollPane = new JScrollPane(textPane);
JButton close = new JButton(NLS.str("tabs.close"));
close.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
close();
}
});
close.setAlignmentX(0.5f);
Container contentPane = getContentPane();
contentPane.add(controlPane, BorderLayout.PAGE_START);
contentPane.add(scrollPane, BorderLayout.CENTER);
contentPane.add(close, BorderLayout.PAGE_END);
setTitle("Log Viewer");
pack();
setSize(800, 600);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setModalityType(ModalityType.MODELESS);
setLocationRelativeTo(null);
}
private void registerLogListener() {
LogCollector logCollector = LogCollector.getInstance();
logCollector.resetListener();
textPane.setText("");
logCollector.registerListener(new LogCollector.ILogListener() {
@Override
public Level getFilterLevel() {
return level;
}
@Override
public void onAppend(final String logStr) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
textPane.append(logStr);
textPane.updateUI();
}
});
}
});
}
private void close() {
LogCollector.getInstance().resetListener();
dispose();
}
public static void main(String[] args) {
new LogViewer().setVisible(true);
}
}
...@@ -84,6 +84,7 @@ public class MainWindow extends JFrame { ...@@ -84,6 +84,7 @@ public class MainWindow extends JFrame {
private static final ImageIcon ICON_FORWARD = Utils.openIcon("icon_forward"); private static final ImageIcon ICON_FORWARD = Utils.openIcon("icon_forward");
private static final ImageIcon ICON_PREF = Utils.openIcon("wrench"); private static final ImageIcon ICON_PREF = Utils.openIcon("wrench");
private static final ImageIcon ICON_DEOBF = Utils.openIcon("lock_edit"); private static final ImageIcon ICON_DEOBF = Utils.openIcon("lock_edit");
private static final ImageIcon ICON_LOG = Utils.openIcon("report");
private final JadxWrapper wrapper; private final JadxWrapper wrapper;
private final JadxSettings settings; private final JadxSettings settings;
...@@ -375,6 +376,19 @@ public class MainWindow extends JFrame { ...@@ -375,6 +376,19 @@ public class MainWindow extends JFrame {
}; };
find.addActionListener(findAction); find.addActionListener(findAction);
JMenu tools = new JMenu(NLS.str("menu.tools"));
tools.setMnemonic(KeyEvent.VK_T);
JMenuItem logItem = new JMenuItem(NLS.str("menu.log"), ICON_LOG);
ActionListener logAction = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new LogViewer().setVisible(true);
}
};
logItem.addActionListener(logAction);
tools.add(logItem);
JMenu help = new JMenu(NLS.str("menu.help")); JMenu help = new JMenu(NLS.str("menu.help"));
help.setMnemonic(KeyEvent.VK_H); help.setMnemonic(KeyEvent.VK_H);
...@@ -390,6 +404,7 @@ public class MainWindow extends JFrame { ...@@ -390,6 +404,7 @@ public class MainWindow extends JFrame {
menuBar.add(file); menuBar.add(file);
menuBar.add(view); menuBar.add(view);
menuBar.add(nav); menuBar.add(nav);
menuBar.add(tools);
menuBar.add(help); menuBar.add(help);
setJMenuBar(menuBar); setJMenuBar(menuBar);
...@@ -470,6 +485,10 @@ public class MainWindow extends JFrame { ...@@ -470,6 +485,10 @@ public class MainWindow extends JFrame {
} }
}); });
JButton logBtn = new JButton(ICON_LOG);
logBtn.setToolTipText(NLS.str("menu.log"));
logBtn.addActionListener(logAction);
updateLink = new Link("", JadxUpdate.JADX_RELEASES_URL); updateLink = new Link("", JadxUpdate.JADX_RELEASES_URL);
updateLink.setVisible(false); updateLink.setVisible(false);
...@@ -495,6 +514,9 @@ public class MainWindow extends JFrame { ...@@ -495,6 +514,9 @@ public class MainWindow extends JFrame {
toolbar.add(deobfToggleBtn); toolbar.add(deobfToggleBtn);
toolbar.addSeparator(); toolbar.addSeparator();
toolbar.add(logBtn);
toolbar.addSeparator();
toolbar.add(prefButton); toolbar.add(prefButton);
toolbar.addSeparator(); toolbar.addSeparator();
......
...@@ -9,6 +9,7 @@ import jadx.gui.treemodel.JNode; ...@@ -9,6 +9,7 @@ import jadx.gui.treemodel.JNode;
import jadx.gui.utils.NLS; import jadx.gui.utils.NLS;
import jadx.gui.utils.NameIndex; import jadx.gui.utils.NameIndex;
import jadx.gui.utils.Position; import jadx.gui.utils.Position;
import jadx.gui.utils.TextStandardActions;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.Box; import javax.swing.Box;
...@@ -198,7 +199,7 @@ public class SearchDialog extends JDialog { ...@@ -198,7 +199,7 @@ public class SearchDialog extends JDialog {
@Override @Override
public Component getListCellRendererComponent(JList list, public Component getListCellRendererComponent(JList list,
Object obj, int index, boolean isSelected, boolean cellHasFocus) { Object obj, int index, boolean isSelected, boolean cellHasFocus) {
if (!(obj instanceof JNode)) { if (!(obj instanceof JNode)) {
return null; return null;
} }
...@@ -317,7 +318,7 @@ public class SearchDialog extends JDialog { ...@@ -317,7 +318,7 @@ public class SearchDialog extends JDialog {
setSize(700, 500); setSize(700, 500);
setLocationRelativeTo(null); setLocationRelativeTo(null);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setModalityType(ModalityType.APPLICATION_MODAL); setModalityType(ModalityType.MODELESS);
} }
private JCheckBox makeOptionsCheckBox(String name, final SearchOptions opt) { private JCheckBox makeOptionsCheckBox(String name, final SearchOptions opt) {
......
package jadx.gui.utils;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Layout;
import ch.qos.logback.core.read.CyclicBufferAppender;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.LoggerFactory;
public class LogCollector extends CyclicBufferAppender<ILoggingEvent> {
private static LogCollector instance = new LogCollector();
public static LogCollector getInstance() {
return instance;
}
public static void register() {
Logger rootLogger = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
LoggerContext loggerContext = rootLogger.getLoggerContext();
PatternLayout layout = new PatternLayout();
layout.setContext(loggerContext);
layout.setPattern("%-5level: %msg%n");
layout.start();
instance.setContext(loggerContext);
instance.setLayout(layout);
instance.start();
rootLogger.addAppender(instance);
}
public interface ILogListener {
Level getFilterLevel();
void onAppend(String logStr);
}
private Layout<ILoggingEvent> layout;
@Nullable
private ILogListener listener;
public LogCollector() {
setName("LogCollector");
setMaxSize(50000);
}
@Override
protected void append(ILoggingEvent event) {
super.append(event);
if (listener != null
&& event.getLevel().isGreaterOrEqual(listener.getFilterLevel())) {
synchronized (this) {
listener.onAppend(layout.doLayout(event));
}
}
}
public void setLayout(Layout<ILoggingEvent> layout) {
this.layout = layout;
}
public void registerListener(@NotNull ILogListener listener) {
this.listener = listener;
synchronized (this) {
listener.onAppend(init(listener.getFilterLevel()));
}
}
public void resetListener() {
this.listener = null;
}
private String init(Level filterLevel) {
StringBuilder sb = new StringBuilder();
int length = getLength();
for (int i = 0; i < length; i++) {
ILoggingEvent event = get(i);
if (event.getLevel().isGreaterOrEqual(filterLevel)) {
sb.append(layout.doLayout(event));
}
}
return sb.toString();
}
}
...@@ -8,6 +8,8 @@ menu.flatten=Show flatten packages ...@@ -8,6 +8,8 @@ menu.flatten=Show flatten packages
menu.navigation=Navigation menu.navigation=Navigation
menu.search=Search ... menu.search=Search ...
menu.find_in_file=Find in ... menu.find_in_file=Find in ...
menu.tools=Tools
menu.log=Log Viewer
menu.help=Help menu.help=Help
menu.about=About menu.about=About
menu.update_label=New version %s available! menu.update_label=New version %s available!
...@@ -69,6 +71,8 @@ preferences.cancel=Cancel ...@@ -69,6 +71,8 @@ preferences.cancel=Cancel
msg.open_file=Please open file msg.open_file=Please open file
msg.saving_sources=Saving sources msg.saving_sources=Saving sources
log.level=Log level:
popup.undo=Undo popup.undo=Undo
popup.redo=Redo popup.redo=Redo
popup.cut=Cut popup.cut=Cut
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment