1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.chainsaw;
19
20 import java.awt.Point;
21 import java.awt.event.InputEvent;
22 import java.awt.event.KeyAdapter;
23 import java.awt.event.KeyEvent;
24 import java.awt.event.MouseAdapter;
25 import java.awt.event.MouseEvent;
26
27 import javax.swing.DefaultListModel;
28 import javax.swing.JList;
29 import javax.swing.JPopupMenu;
30 import javax.swing.JScrollPane;
31 import javax.swing.ListModel;
32 import javax.swing.text.JTextComponent;
33
34 import org.apache.log4j.chainsaw.filter.FilterModel;
35 import org.apache.log4j.rule.RuleFactory;
36 import org.apache.log4j.spi.LoggingEventFieldResolver;
37
38
39
40
41
42
43
44 public class ExpressionRuleContext extends KeyAdapter {
45 RuleFactory factory = RuleFactory.getInstance();
46 LoggingEventFieldResolver resolver = LoggingEventFieldResolver.getInstance();
47 JPopupMenu contextMenu = new JPopupMenu();
48 JList list = new JList();
49 FilterModel filterModel;
50 JScrollPane scrollPane = new JScrollPane(list);
51 final JTextComponent textComponent;
52 private DefaultListModel fieldModel = new DefaultListModel();
53 private DefaultListModel operatorModel = new DefaultListModel();
54
55 public ExpressionRuleContext(
56 final FilterModel filterModel, final JTextComponent textComponent) {
57 this.filterModel = filterModel;
58 this.textComponent = textComponent;
59 fieldModel.addElement("LOGGER");
60 fieldModel.addElement("LEVEL");
61 fieldModel.addElement("CLASS");
62 fieldModel.addElement("FILE");
63 fieldModel.addElement("LINE");
64 fieldModel.addElement("METHOD");
65 fieldModel.addElement("MSG");
66 fieldModel.addElement("NDC");
67 fieldModel.addElement("EXCEPTION");
68 fieldModel.addElement("TIMESTAMP");
69 fieldModel.addElement("THREAD");
70 fieldModel.addElement("PROP.");
71
72 operatorModel.addElement("&&");
73 operatorModel.addElement("||");
74 operatorModel.addElement("!");
75 operatorModel.addElement("!=");
76 operatorModel.addElement("==");
77 operatorModel.addElement("~=");
78 operatorModel.addElement("LIKE");
79 operatorModel.addElement("EXISTS");
80 operatorModel.addElement("<");
81 operatorModel.addElement(">");
82 operatorModel.addElement("<=");
83 operatorModel.addElement(">=");
84
85
86 list.setVisibleRowCount(13);
87
88 PopupListener popupListener = new PopupListener();
89 textComponent.addMouseListener(popupListener);
90
91 list.addKeyListener(
92 new KeyAdapter() {
93 public void keyPressed(KeyEvent e) {
94 if (e.getKeyCode() == KeyEvent.VK_ENTER) {
95 String value = list.getSelectedValue().toString();
96 String contextKey = getContextKey();
97 if (contextKey != null && (!(contextKey.endsWith(".")))) {
98 value = "'"+value+"'";
99 }
100
101 updateField(value);
102 contextMenu.setVisible(false);
103 }
104 }
105 });
106
107 list.addMouseListener(
108 new MouseAdapter() {
109 public void mouseClicked(MouseEvent e) {
110 if (e.getClickCount() == 2) {
111 String value = list.getSelectedValue().toString();
112 String contextKey = getContextKey();
113 if (contextKey != null && (!(contextKey.endsWith(".")))) {
114 value = "'"+value+"'";
115 }
116
117 updateField(value);
118 contextMenu.setVisible(false);
119 }
120 }
121 });
122
123 contextMenu.insert(scrollPane, 0);
124 }
125
126 private void updateField(String value) {
127 if (textComponent.getSelectedText() == null) {
128 if (!(value.endsWith("."))) {
129 value = value + " ";
130 }
131 }
132
133 textComponent.replaceSelection(value);
134 }
135
136 public void keyPressed(KeyEvent e) {
137 if (
138 (e.getKeyCode() == KeyEvent.VK_SPACE)
139 && (e.getModifiers() == InputEvent.CTRL_MASK)) {
140 displayContext();
141 }
142 }
143
144 public void displayContext() {
145 String lastField = getContextKey();
146
147 if (lastField != null) {
148 ListModel model = filterModel.getContainer().getModel(lastField);
149 if (model == null) {
150 return;
151 }
152 list.setModel(model);
153 list.setSelectedIndex(0);
154
155 Point p = textComponent.getCaret().getMagicCaretPosition();
156 contextMenu.doLayout();
157 contextMenu.show(textComponent, p.x, (p.y + (textComponent.getHeight() - 5)));
158 list.requestFocus();
159 } else {
160 if (isOperatorContextValid()) {
161 list.setModel(operatorModel);
162 list.setSelectedIndex(0);
163
164 Point p = textComponent.getCaret().getMagicCaretPosition();
165 contextMenu.doLayout();
166 contextMenu.show(textComponent, p.x, (p.y + (textComponent.getHeight() - 5)));
167 list.requestFocus();
168 } else if (isFieldContextValid()) {
169 list.setModel(fieldModel);
170 list.setSelectedIndex(0);
171
172 Point p = textComponent.getCaret().getMagicCaretPosition();
173
174 if (p == null) {
175 p = new Point(
176 textComponent.getLocation().x,
177 (textComponent.getLocation().y - textComponent.getHeight() + 5));
178 }
179 contextMenu.doLayout();
180 contextMenu.show(textComponent, p.x, (p.y + (textComponent.getHeight() - 5)));
181 list.requestFocus();
182 }
183 }
184 }
185
186 private boolean isFieldContextValid() {
187 String text = textComponent.getText();
188 int currentPosition = textComponent.getSelectionStart();
189
190 return ((currentPosition == 0)
191 || (text.charAt(currentPosition - 1) == ' '));
192 }
193
194 private String getContextKey() {
195 String field = getField();
196
197 if (field == null) {
198 field = getSubField();
199 }
200
201 return field;
202 }
203
204 private boolean isOperatorContextValid() {
205 String text = textComponent.getText();
206
207 int currentPosition = textComponent.getSelectionStart();
208
209 if ((currentPosition < 1) || (text.charAt(currentPosition - 1) != ' ')) {
210 return false;
211 }
212
213 int lastFieldPosition = text.lastIndexOf(" ", currentPosition - 1);
214
215 if (lastFieldPosition == -1) {
216 return false;
217 }
218
219 int lastFieldStartPosition =
220 Math.max(0, text.lastIndexOf(" ", lastFieldPosition - 1));
221 String field =
222 text.substring(lastFieldStartPosition, lastFieldPosition).toUpperCase()
223 .trim();
224
225 if (resolver.isField(field)) {
226 return true;
227 }
228
229 return false;
230 }
231
232
233
234
235 private String getField() {
236 String text = textComponent.getText();
237
238 int currentPosition = textComponent.getSelectionStart();
239
240 if ((currentPosition < 1) || (text.charAt(currentPosition - 1) != ' ')) {
241 return null;
242 }
243
244 int symbolPosition = text.lastIndexOf(" ", currentPosition - 1);
245
246 if (symbolPosition < 0) {
247 return null;
248 }
249
250 int lastFieldPosition = text.lastIndexOf(" ", symbolPosition - 1);
251
252 if (lastFieldPosition < 0) {
253 return null;
254 }
255
256 int lastFieldStartPosition =
257 Math.max(0, text.lastIndexOf(" ", lastFieldPosition - 1));
258 String lastSymbol =
259 text.substring(lastFieldPosition + 1, symbolPosition).trim();
260
261 String lastField =
262 text.substring(lastFieldStartPosition, lastFieldPosition).trim();
263
264 if (
265 factory.isRule(lastSymbol)
266 && filterModel.getContainer().modelExists(lastField)) {
267 return lastField;
268 }
269
270 return null;
271 }
272
273
274
275 private String getSubField() {
276 int currentPosition = textComponent.getSelectionStart();
277 String text = textComponent.getText();
278
279 if (text.substring(0, currentPosition).toUpperCase().endsWith("PROP.")) {
280 return "PROP.";
281 }
282 return null;
283 }
284
285 class PopupListener extends MouseAdapter {
286 PopupListener() {
287 }
288
289 public void mousePressed(MouseEvent e) {
290 checkPopup(e);
291 }
292
293 public void mouseReleased(MouseEvent e) {
294 checkPopup(e);
295 }
296
297 private void checkPopup(MouseEvent e) {
298 if (e.isPopupTrigger()) {
299 displayContext();
300 }
301 }
302 }
303 }