1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.jmx.gui;
18
19 import java.awt.BorderLayout;
20 import java.awt.Color;
21 import java.awt.Font;
22 import java.awt.event.ActionEvent;
23 import java.io.IOException;
24 import java.io.PrintWriter;
25 import java.io.StringWriter;
26 import java.util.HashMap;
27 import java.util.Map;
28
29 import javax.management.InstanceNotFoundException;
30 import javax.management.MalformedObjectNameException;
31 import javax.management.Notification;
32 import javax.management.NotificationFilterSupport;
33 import javax.management.NotificationListener;
34 import javax.management.ObjectName;
35 import javax.management.remote.JMXConnector;
36 import javax.management.remote.JMXConnectorFactory;
37 import javax.management.remote.JMXServiceURL;
38 import javax.swing.AbstractAction;
39 import javax.swing.JFrame;
40 import javax.swing.JOptionPane;
41 import javax.swing.JPanel;
42 import javax.swing.JScrollPane;
43 import javax.swing.JTabbedPane;
44 import javax.swing.JTextArea;
45 import javax.swing.JToggleButton;
46 import javax.swing.SwingUtilities;
47 import javax.swing.UIManager;
48 import javax.swing.UIManager.LookAndFeelInfo;
49
50 import org.apache.logging.log4j.core.helpers.Assert;
51 import org.apache.logging.log4j.core.jmx.LoggerContextAdminMBean;
52 import org.apache.logging.log4j.core.jmx.StatusLoggerAdminMBean;
53
54
55
56
57
58
59
60
61
62 public class ClientGUI extends JPanel implements NotificationListener {
63 private static final long serialVersionUID = -253621277232291174L;
64 private final Client client;
65 private JTextArea statusLogTextArea;
66 private JTabbedPane tabbedPane;
67 private JToggleButton wrapLinesToggleButton;
68
69 private final AbstractAction toggleWrapAction = new AbstractAction() {
70 private static final long serialVersionUID = -4214143754637722322L;
71
72 @Override
73 public void actionPerformed(final ActionEvent e) {
74 final boolean wrap = wrapLinesToggleButton.isSelected();
75 statusLogTextArea.setLineWrap(wrap);
76 }
77 };
78
79 public ClientGUI(final Client client) throws InstanceNotFoundException,
80 MalformedObjectNameException, IOException {
81 this.client = Assert.isNotNull(client, "client");
82 createWidgets();
83 populateWidgets();
84 registerListeners();
85 }
86
87 private void createWidgets() {
88 statusLogTextArea = new JTextArea();
89 statusLogTextArea.setEditable(false);
90 statusLogTextArea.setBackground(this.getBackground());
91 statusLogTextArea.setForeground(Color.black);
92 statusLogTextArea.setFont(new Font("Monospaced", Font.PLAIN,
93 statusLogTextArea.getFont().getSize()));
94 statusLogTextArea.setWrapStyleWord(true);
95
96 wrapLinesToggleButton = new JToggleButton(toggleWrapAction);
97 wrapLinesToggleButton.setToolTipText("Toggle line wrapping");
98 final JScrollPane scrollStatusLog = new JScrollPane(statusLogTextArea,
99 JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
100 JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
101 scrollStatusLog.setCorner(JScrollPane.LOWER_RIGHT_CORNER, wrapLinesToggleButton);
102
103 tabbedPane = new JTabbedPane();
104 tabbedPane.addTab("StatusLogger", scrollStatusLog);
105
106 this.setLayout(new BorderLayout());
107 this.add(tabbedPane, BorderLayout.CENTER);
108 }
109
110 private void populateWidgets() {
111
112 final StatusLoggerAdminMBean statusAdmin = client.getStatusLoggerAdmin();
113 final String[] messages = statusAdmin.getStatusDataHistory();
114 for (final String message : messages) {
115 statusLogTextArea.append(message + "\n");
116 }
117
118 for (final LoggerContextAdminMBean ctx : client.getLoggerContextAdmins()) {
119 final ClientEditConfigPanel editor = new ClientEditConfigPanel(ctx);
120 tabbedPane.addTab("LoggerContext: " + ctx.getName(), editor);
121 }
122 }
123
124 private void registerListeners() throws InstanceNotFoundException,
125 MalformedObjectNameException, IOException {
126 final NotificationFilterSupport filter = new NotificationFilterSupport();
127 filter.enableType(StatusLoggerAdminMBean.NOTIF_TYPE_MESSAGE);
128 final ObjectName objName = new ObjectName(StatusLoggerAdminMBean.NAME);
129 client.getConnection().addNotificationListener(objName, this, filter,
130 null);
131 }
132
133 @Override
134 public void handleNotification(final Notification notif, final Object paramObject) {
135 if (StatusLoggerAdminMBean.NOTIF_TYPE_MESSAGE.equals(notif.getType())) {
136 statusLogTextArea.append(notif.getMessage() + "\n");
137 }
138 }
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 public static void main(final String[] args) throws Exception {
155 if (args.length < 1) {
156 usage();
157 return;
158 }
159 String serviceUrl = args[0];
160 if (!serviceUrl.startsWith("service:jmx")) {
161 serviceUrl = "service:jmx:rmi:///jndi/rmi://" + args[0] + "/jmxrmi";
162 }
163 final JMXServiceURL url = new JMXServiceURL(serviceUrl);
164 final Map<String, String> paramMap = new HashMap<String, String>();
165 for (final Object objKey : System.getProperties().keySet()) {
166 final String key = (String) objKey;
167 paramMap.put(key, System.getProperties().getProperty(key));
168 }
169 final JMXConnector connector = JMXConnectorFactory.connect(url, paramMap);
170 final Client client = new Client(connector);
171 final String title = "Log4j JMX Client - " + url;
172
173 SwingUtilities.invokeLater(new Runnable() {
174 @Override
175 public void run() {
176 installLookAndFeel();
177 try {
178 final ClientGUI gui = new ClientGUI(client);
179 final JFrame frame = new JFrame(title);
180 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
181 frame.getContentPane().add(gui, BorderLayout.CENTER);
182 frame.pack();
183 frame.setVisible(true);
184 } catch (final Exception ex) {
185
186
187
188 ex.printStackTrace();
189
190
191
192 final StringWriter sr = new StringWriter();
193 ex.printStackTrace(new PrintWriter(sr));
194 JOptionPane.showMessageDialog(null, sr.toString(), "Error",
195 JOptionPane.ERROR_MESSAGE);
196 }
197 }
198 });
199 }
200
201 private static void usage() {
202 final String me = ClientGUI.class.getName();
203 System.err.println("Usage: java " + me + " <host>:<port>");
204 System.err.println(" or: java " + me
205 + " service:jmx:rmi:///jndi/rmi://<host>:<port>/jmxrmi");
206 final String longAdr = " service:jmx:rmi://<host>:<port>/jndi/rmi://<host>:<port>/jmxrmi";
207 System.err.println(" or: java " + me + longAdr);
208 }
209
210 private static void installLookAndFeel() {
211 try {
212 for (final LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
213 if ("Nimbus".equals(info.getName())) {
214 UIManager.setLookAndFeel(info.getClassName());
215 return;
216 }
217 }
218 } catch (final Exception ex) {
219 ex.printStackTrace();
220 }
221 try {
222 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
223 } catch (final Exception e) {
224 e.printStackTrace();
225 }
226 }
227 }