View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.log4j.chainsaw.color;
19  
20  import org.apache.log4j.chainsaw.ChainsawConstants;
21  import org.apache.log4j.chainsaw.prefs.SettingsManager;
22  import org.apache.log4j.rule.ColorRule;
23  import org.apache.log4j.rule.ExpressionRule;
24  import org.apache.log4j.rule.Rule;
25  import org.apache.log4j.spi.LoggingEvent;
26  
27  import java.awt.*;
28  import java.beans.PropertyChangeListener;
29  import java.beans.PropertyChangeSupport;
30  import java.io.*;
31  import java.net.URLEncoder;
32  import java.util.*;
33  import java.util.List;
34  
35  
36  /**
37   * A colorizer supporting an ordered collection of ColorRules, including support for notification of
38   * color rule changes via a propertyChangeListener and the 'colorrule' property.
39   *
40   * @author Scott Deboy <sdeboy@apache.org>
41   */
42  public class RuleColorizer implements Colorizer {
43      private Map rules;
44      private final PropertyChangeSupport colorChangeSupport =
45          new PropertyChangeSupport(this);
46      private Map defaultRules = new HashMap();
47      private String currentRuleSet = ChainsawConstants.DEFAULT_COLOR_RULE_NAME;
48      private Rule findRule;
49      private Rule loggerRule;
50  
51      private static final String COLORS_EXTENSION = ".colors";
52  
53      private final Color WARN_DEFAULT_COLOR = new Color(255, 255, 153);
54      private final Color FATAL_OR_ERROR_DEFAULT_COLOR = new Color(255, 153, 153);
55      private final Color MARKER_DEFAULT_COLOR = new Color(153, 255, 153);
56  
57      private final String DEFAULT_WARN_EXPRESSION = "level == WARN";
58      private final String DEFAULT_FATAL_ERROR_EXCEPTION_EXPRESSION = "level == FATAL || level == ERROR || exception exists";
59      private final String DEFAULT_MARKER_EXPRESSION = "prop.marker exists";
60  
61      public RuleColorizer() {
62          List rulesList = new ArrayList();
63  
64          String expression = DEFAULT_FATAL_ERROR_EXCEPTION_EXPRESSION;
65          rulesList.add(
66              new ColorRule(
67                  expression, ExpressionRule.getRule(expression), FATAL_OR_ERROR_DEFAULT_COLOR,
68                  Color.black));
69          expression = DEFAULT_WARN_EXPRESSION;
70          rulesList.add(
71              new ColorRule(
72                  expression, ExpressionRule.getRule(expression), WARN_DEFAULT_COLOR,
73                  Color.black));
74  
75          expression = DEFAULT_MARKER_EXPRESSION;
76          rulesList.add(
77              new ColorRule(
78                  expression, ExpressionRule.getRule(expression), MARKER_DEFAULT_COLOR,
79                  Color.black));
80  
81          defaultRules.put(currentRuleSet, rulesList);
82          setRules(defaultRules);
83      }
84  
85      public void setLoggerRule(Rule loggerRule) {
86          this.loggerRule = loggerRule;
87          colorChangeSupport.firePropertyChange("colorrule", false, true);
88      }
89  
90      public void setFindRule(Rule findRule) {
91          this.findRule = findRule;
92          colorChangeSupport.firePropertyChange("colorrule", false, true);
93      }
94  
95      public Rule getFindRule() {
96          return findRule;
97      }
98  
99      public Rule getLoggerRule() {
100         return loggerRule;
101     }
102 
103     public void setRules(Map rules) {
104         this.rules = rules;
105         colorChangeSupport.firePropertyChange("colorrule", false, true);
106     }
107 
108     public Map getRules() {
109         return rules;
110     }
111 
112     public List getCurrentRules() {
113         return (List) rules.get(currentRuleSet);
114     }
115 
116     public void addRules(Map newRules) {
117 
118         for (Object o : newRules.entrySet()) {
119             Map.Entry entry = (Map.Entry) o;
120 
121             if (rules.containsKey(entry.getKey())) {
122                 ((List) rules.get(entry.getKey())).addAll((List) entry.getValue());
123             } else {
124                 rules.put(entry.getKey(), entry.getValue());
125             }
126         }
127 
128         colorChangeSupport.firePropertyChange("colorrule", false, true);
129     }
130 
131     public void addRule(String ruleSetName, ColorRule rule) {
132         if (rules.containsKey(ruleSetName)) {
133             ((List) rules.get(ruleSetName)).add(rule);
134         } else {
135             List list = new ArrayList();
136             list.add(rule);
137             rules.put(ruleSetName, list);
138         }
139 
140         colorChangeSupport.firePropertyChange("colorrule", false, true);
141     }
142 
143     public void removeRule(String ruleSetName, String expression) {
144         if (rules.containsKey(ruleSetName)) {
145             List list = (List) rules.get(ruleSetName);
146 
147             for (int i = 0; i < list.size(); i++) {
148                 ColorRule rule = (ColorRule) list.get(i);
149 
150                 if (rule.getExpression().equals(expression)) {
151                     list.remove(rule);
152 
153                     return;
154                 }
155             }
156         }
157     }
158 
159     public void setCurrentRuleSet(String ruleSetName) {
160         currentRuleSet = ruleSetName;
161     }
162 
163     public Color getBackgroundColor(LoggingEvent event) {
164         if (rules.containsKey(currentRuleSet)) {
165             List list = (List) rules.get(currentRuleSet);
166 
167             for (Object aList : list) {
168                 ColorRule rule = (ColorRule) aList;
169 
170                 if ((rule.getBackgroundColor() != null) && (rule.evaluate(event, null))) {
171                     return rule.getBackgroundColor();
172                 }
173             }
174         }
175 
176         return null;
177     }
178 
179     public Color getForegroundColor(LoggingEvent event) {
180         if (rules.containsKey(currentRuleSet)) {
181             List list = (List) rules.get(currentRuleSet);
182 
183             for (Object aList : list) {
184                 ColorRule rule = (ColorRule) aList;
185 
186                 if ((rule.getForegroundColor() != null) && (rule.evaluate(event, null))) {
187                     return rule.getForegroundColor();
188                 }
189             }
190         }
191 
192         return null;
193     }
194 
195     public void addPropertyChangeListener(PropertyChangeListener listener) {
196         colorChangeSupport.addPropertyChangeListener(listener);
197     }
198 
199     public void removePropertyChangeListener(PropertyChangeListener listener) {
200         colorChangeSupport.removePropertyChangeListener(listener);
201     }
202 
203     /**
204      * @param propertyName
205      * @param listener
206      */
207     public void addPropertyChangeListener(
208         String propertyName, PropertyChangeListener listener) {
209         colorChangeSupport.addPropertyChangeListener(propertyName, listener);
210     }
211 
212 
213     /**
214      * Save panel color settings
215      */
216     public void saveColorSettings(String name) {
217         ObjectOutputStream o = null;
218         try {
219             File f = new File(SettingsManager.getInstance().getSettingsDirectory(), URLEncoder.encode(name + COLORS_EXTENSION));
220 
221             o = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(f)));
222 
223             o.writeObject(getRules());
224             o.flush();
225         } catch (IOException ioe) {
226             ioe.printStackTrace();
227         } finally {
228             try {
229                 if (o != null) {
230                     o.close();
231                 }
232             } catch (IOException ioe) {
233                 ioe.printStackTrace();
234             }
235         }
236     }
237 
238     /**
239      * Load panel color settings if they exist - otherwise, load default color settings
240      */
241     public void loadColorSettings(String name) {
242         if (!doLoadColorSettings(name)) {
243             doLoadColorSettings(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
244         }
245     }
246 
247     private boolean doLoadColorSettings(String name) {
248         //first attempt to load encoded file
249         File f = new File(SettingsManager.getInstance().getSettingsDirectory(), URLEncoder.encode(name) + COLORS_EXTENSION);
250 
251         if (f.exists()) {
252             ObjectInputStream s = null;
253 
254             try {
255                 s = new ObjectInputStream(
256                     new BufferedInputStream(new FileInputStream(f)));
257 
258                 Map map = (Map) s.readObject();
259                 setRules(map);
260             } catch (EOFException eof) { //end of file - ignore..
261             } catch (IOException ioe) {
262                 ioe.printStackTrace();
263                 //unable to load file - delete it
264                 f.delete();
265             } catch (ClassNotFoundException cnfe) {
266                 cnfe.printStackTrace();
267             } finally {
268                 if (s != null) {
269                     try {
270                         s.close();
271                     } catch (IOException ioe) {
272                         ioe.printStackTrace();
273                     }
274                 }
275             }
276         }
277         return f.exists();
278     }
279 
280     public Vector getDefaultColors() {
281         Vector vec = new Vector();
282 
283         vec.add(Color.white);
284         vec.add(Color.black);
285         //add default alternating color & search backgrounds (both foreground are black)
286         vec.add(ChainsawConstants.COLOR_ODD_ROW_BACKGROUND);
287         vec.add(ChainsawConstants.FIND_LOGGER_BACKGROUND);
288 
289         vec.add(new Color(255, 255, 225));
290         vec.add(new Color(255, 225, 255));
291         vec.add(new Color(225, 255, 255));
292         vec.add(new Color(255, 225, 225));
293         vec.add(new Color(225, 255, 225));
294         vec.add(new Color(225, 225, 255));
295         vec.add(new Color(225, 225, 183));
296         vec.add(new Color(225, 183, 225));
297         vec.add(new Color(183, 225, 225));
298         vec.add(new Color(183, 225, 183));
299         vec.add(new Color(183, 183, 225));
300         vec.add(new Color(232, 201, 169));
301         vec.add(new Color(255, 255, 153));
302         vec.add(new Color(255, 153, 153));
303         vec.add(new Color(189, 156, 89));
304         vec.add(new Color(255, 102, 102));
305         vec.add(new Color(255, 177, 61));
306         vec.add(new Color(61, 255, 61));
307         vec.add(new Color(153, 153, 255));
308         vec.add(new Color(255, 153, 255));
309 
310         return vec;
311     }
312 
313 }