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