1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.log4j.chainsaw.receivers;
18
19 import org.apache.log4j.Level;
20 import org.apache.log4j.LogManager;
21 import org.apache.log4j.Logger;
22 import org.apache.log4j.chainsaw.ChainsawConstants;
23 import org.apache.log4j.chainsaw.Generator;
24 import org.apache.log4j.chainsaw.helper.TableCellEditorFactory;
25 import org.apache.log4j.plugins.Plugin;
26
27 import javax.swing.*;
28 import javax.swing.table.AbstractTableModel;
29 import javax.swing.table.DefaultTableModel;
30 import javax.swing.table.TableCellEditor;
31 import javax.swing.table.TableModel;
32 import java.awt.*;
33 import java.awt.event.WindowAdapter;
34 import java.awt.event.WindowEvent;
35 import java.beans.BeanInfo;
36 import java.beans.IntrospectionException;
37 import java.beans.Introspector;
38 import java.beans.PropertyDescriptor;
39 import java.util.*;
40 import java.util.List;
41 import javax.swing.event.CellEditorListener;
42 import javax.swing.table.TableCellRenderer;
43
44
45
46
47
48
49
50
51 public class PluginPropertyEditorPanel extends JPanel {
52
53 private final JScrollPane scrollPane = new JScrollPane();
54 private final JTable propertyTable = new JTable();
55
56 private Plugin plugin;
57 private TableModel defaultModel = new DefaultTableModel(
58 new String[]{"Property", "Value"}, 1);
59
60 private static final Logger logger = LogManager.getLogger(PluginPropertyEditorPanel.class);
61
62
63
64
65 public PluginPropertyEditorPanel() {
66 super();
67 initComponents();
68 setupListeners();
69 }
70
71
72
73
74 private void initComponents() {
75 propertyTable.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
76 setLayout(new BorderLayout());
77 scrollPane.setViewportView(propertyTable);
78
79 add(scrollPane, BorderLayout.CENTER);
80
81 propertyTable.setModel(
82 defaultModel = new DefaultTableModel(
83 new String[]{"Property", "Value"}, 1));
84
85 }
86
87
88
89
90 private void setupListeners() {
91 addPropertyChangeListener("plugin", evt -> {
92
93 final Plugin p = (Plugin) evt.getNewValue();
94
95 if (p != null) {
96
97 try {
98
99 PluginPropertyTableModel model =
100 new PluginPropertyTableModel(p);
101 propertyTable.setModel(model);
102 propertyTable.getColumnModel().getColumn(1)
103 .setCellEditor(new PluginTableCellEditor());
104 propertyTable.setEnabled(true);
105 } catch (Throwable e) {
106 logger.error("Failed to introspect the Plugin", e);
107 }
108 } else {
109 propertyTable.setModel(defaultModel);
110 propertyTable.setEnabled(false);
111 }
112
113 });
114 }
115
116
117
118
119 public final Plugin getPlugin() {
120
121 return plugin;
122 }
123
124
125
126
127 public final void setPlugin(Plugin plugin) {
128
129 Plugin oldValue = this.plugin;
130 this.plugin = plugin;
131 firePropertyChange("plugin", oldValue, this.plugin);
132 }
133
134
135
136
137 private class PluginTableCellEditor extends AbstractCellEditor
138 implements TableCellEditor {
139
140 private Map editorMap = new HashMap();
141 private DefaultCellEditor defaultEditor = new DefaultCellEditor(
142 new JTextField());
143 private DefaultCellEditor currentEditor = defaultEditor;
144
145 private PluginTableCellEditor() {
146
147 editorMap.put(Boolean.class,
148 TableCellEditorFactory.createBooleanTableCellEditor());
149 editorMap.put(Level.class,
150 TableCellEditorFactory.createLevelTableCellEditor());
151
152 editorMap.put(boolean.class, TableCellEditorFactory.createBooleanTableCellEditor());
153 }
154
155
156
157
158 public Component getTableCellEditorComponent(JTable table, Object value,
159 boolean isSelected, int row, int column) {
160
161 PluginPropertyTableModel model = (PluginPropertyTableModel) table.getModel();
162 PropertyDescriptor descriptor = model.getDescriptors()[row];
163 Class valueClass = descriptor.getPropertyType();
164
165 if (editorMap.containsKey(valueClass)) {
166
167 DefaultCellEditor editor =
168 (DefaultCellEditor) editorMap.get(valueClass);
169 logger.debug("Located CellEditor for " + valueClass);
170 currentEditor = editor;
171
172 return currentEditor.getTableCellEditorComponent(table, value,
173 isSelected, row, column);
174 }
175
176 currentEditor = defaultEditor;
177 logger.debug("Cell value class " + valueClass +
178 " not know, using default editor");
179
180 Component c = defaultEditor.getTableCellEditorComponent(table, value,
181 isSelected, row, column);
182 table.setRowHeight( row, c.getPreferredSize().height );
183 return c;
184 }
185
186
187
188
189 public Object getCellEditorValue() {
190
191 return currentEditor.getCellEditorValue();
192 }
193
194 }
195
196 private class PluginPropertyTableModel extends AbstractTableModel {
197
198 private final PropertyDescriptor[] descriptors;
199 private final Plugin plugin;
200
201 private PluginPropertyTableModel(Plugin p)
202 throws IntrospectionException {
203 super();
204
205 BeanInfo beanInfo = Introspector.getBeanInfo(p.getClass());
206
207 List list = new ArrayList(Arrays.asList(
208 beanInfo.getPropertyDescriptors()));
209
210 list.sort((o1, o2) -> {
211
212 PropertyDescriptor d1 = (PropertyDescriptor) o1;
213 PropertyDescriptor d2 = (PropertyDescriptor) o2;
214
215 return d1.getDisplayName().compareToIgnoreCase(
216 d2.getDisplayName());
217 });
218 this.plugin = p;
219 this.descriptors = (PropertyDescriptor[]) list.toArray(
220 new PropertyDescriptor[0]);
221 }
222
223
224
225
226 public Object getValueAt(int row, int col) {
227
228 PropertyDescriptor d = descriptors[row];
229
230 switch (col) {
231
232 case 1:
233
234 try {
235
236 Object object = d.getReadMethod().invoke(plugin);
237
238 if (object != null) {
239
240 return object;
241 }
242 } catch (Exception e) {
243 logger.error(
244 "Error reading value for PropertyDescriptor " + d);
245 }
246
247 return "";
248
249 case 0:
250 return d.getName();
251 }
252
253 return null;
254 }
255
256
257
258
259 public int getColumnCount() {
260
261 return 2;
262 }
263
264
265
266
267 public int getRowCount() {
268
269 return descriptors.length;
270 }
271
272
273
274
275 public boolean isCellEditable(int rowIndex, int columnIndex) {
276
277
278 return columnIndex == 1 && descriptors[rowIndex].getWriteMethod() != null;
279
280 }
281
282
283
284
285 public String getColumnName(int column) {
286
287 return (column == 0) ? "Property" : "Value";
288 }
289
290
291
292
293 public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
294
295
296 if (columnIndex == 1) {
297
298 if (descriptors[rowIndex].getName().equalsIgnoreCase("name") && (aValue == null || aValue.toString().trim().equals(""))) {
299 logger.error("Name required");
300 return;
301 }
302 aValue = translateValueIfNeeded(rowIndex, aValue);
303 logger.debug(
304 "setValueAt, " + rowIndex + ", " + columnIndex +
305 ", value=" + aValue + ", valueClass" + aValue.getClass());
306
307 try {
308 descriptors[rowIndex].getWriteMethod().invoke(plugin,
309 aValue);
310 fireTableCellUpdated(rowIndex, columnIndex);
311 } catch (IllegalArgumentException e) {
312
313 } catch (Exception e) {
314 logger.error(
315 "Failed to modify the Plugin because of Exception", e);
316 }
317
318 } else {
319 super.setValueAt(aValue, rowIndex, columnIndex);
320 }
321
322
323 propertyTable.setRowHeight(ChainsawConstants.DEFAULT_ROW_HEIGHT);
324 }
325
326
327
328
329
330
331 private Object translateValueIfNeeded(int row, Object value) {
332
333 if ((descriptors[row].getPropertyType() == int.class) ||
334 (descriptors[row].getPropertyType() == Integer.class)) {
335
336 try {
337
338 return Integer.valueOf(value.toString());
339 } catch (Exception e) {
340 logger.error("Failed to convert to Integer type");
341 }
342 }
343
344 return value;
345 }
346
347
348
349
350 public final PropertyDescriptor[] getDescriptors() {
351 return descriptors;
352 }
353 }
354 }