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  package org.apache.log4j.lf5.viewer.configure;
18  
19  import java.awt.Color;
20  import java.io.File;
21  import java.io.FileWriter;
22  import java.io.IOException;
23  import java.io.PrintWriter;
24  import java.util.ArrayList;
25  import java.util.Enumeration;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  
30  import javax.swing.JCheckBoxMenuItem;
31  import javax.swing.tree.TreePath;
32  import javax.xml.parsers.DocumentBuilder;
33  import javax.xml.parsers.DocumentBuilderFactory;
34  
35  import org.apache.log4j.lf5.LogLevel;
36  import org.apache.log4j.lf5.LogLevelFormatException;
37  import org.apache.log4j.lf5.viewer.LogBrokerMonitor;
38  import org.apache.log4j.lf5.viewer.LogTable;
39  import org.apache.log4j.lf5.viewer.LogTableColumn;
40  import org.apache.log4j.lf5.viewer.LogTableColumnFormatException;
41  import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryExplorerModel;
42  import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryExplorerTree;
43  import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryNode;
44  import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryPath;
45  import org.w3c.dom.Document;
46  import org.w3c.dom.NamedNodeMap;
47  import org.w3c.dom.Node;
48  import org.w3c.dom.NodeList;
49  
50  /**
51   * <p>ConfigurationManager handles the storage and retrival of the state of
52   * the CategoryExplorer
53   *
54   * @author Richard Hurst
55   * @author Brad Marlborough
56   */
57  
58  // Contributed by ThoughtWorks Inc.
59  
60  public class ConfigurationManager extends Object {
61    //--------------------------------------------------------------------------
62    //   Constants:
63    //--------------------------------------------------------------------------
64    private static final String CONFIG_FILE_NAME = "lf5_configuration.xml";
65    private static final String NAME = "name";
66    private static final String PATH = "path";
67    private static final String SELECTED = "selected";
68    private static final String EXPANDED = "expanded";
69    private static final String CATEGORY = "category";
70    private static final String FIRST_CATEGORY_NAME = "Categories";
71    private static final String LEVEL = "level";
72    private static final String COLORLEVEL = "colorlevel";
73    private static final String RED = "red";
74    private static final String GREEN = "green";
75    private static final String BLUE = "blue";
76    private static final String COLUMN = "column";
77    private static final String NDCTEXTFILTER = "searchtext";
78    //--------------------------------------------------------------------------
79    //   Protected Variables:
80    //--------------------------------------------------------------------------
81  
82    //--------------------------------------------------------------------------
83    //   Private Variables:
84    //--------------------------------------------------------------------------
85    private LogBrokerMonitor _monitor = null;
86    private LogTable _table = null;
87  
88    //--------------------------------------------------------------------------
89    //   Constructors:
90    //--------------------------------------------------------------------------
91    public ConfigurationManager(LogBrokerMonitor monitor, LogTable table) {
92      super();
93      _monitor = monitor;
94      _table = table;
95      load();
96    }
97    //--------------------------------------------------------------------------
98    //   Public Methods:
99    //--------------------------------------------------------------------------
100 
101   public void save() {
102     CategoryExplorerModel model = _monitor.getCategoryExplorerTree().getExplorerModel();
103     CategoryNode root = model.getRootCategoryNode();
104 
105     StringBuffer xml = new StringBuffer(2048);
106     openXMLDocument(xml);
107     openConfigurationXML(xml);
108     processLogRecordFilter(_monitor.getNDCTextFilter(), xml);
109     processLogLevels(_monitor.getLogLevelMenuItems(), xml);
110     processLogLevelColors(_monitor.getLogLevelMenuItems(),
111         LogLevel.getLogLevelColorMap(), xml);
112     processLogTableColumns(LogTableColumn.getLogTableColumns(), xml);
113     processConfigurationNode(root, xml);
114     closeConfigurationXML(xml);
115     store(xml.toString());
116   }
117 
118   public void reset() {
119     deleteConfigurationFile();
120     collapseTree();
121     selectAllNodes();
122   }
123 
124   public static String treePathToString(TreePath path) {
125     // count begins at one so as to not include the 'Categories' - root category
126     StringBuffer sb = new StringBuffer();
127     CategoryNode n = null;
128     Object[] objects = path.getPath();
129     for (int i = 1; i < objects.length; i++) {
130       n = (CategoryNode) objects[i];
131       if (i > 1) {
132         sb.append(".");
133       }
134       sb.append(n.getTitle());
135     }
136     return sb.toString();
137   }
138 
139   //--------------------------------------------------------------------------
140   //   Protected Methods:
141   //--------------------------------------------------------------------------
142   protected void load() {
143     File file = new File(getFilename());
144     if (file.exists()) {
145       try {
146         DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.
147             newInstance();
148         DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
149         Document doc = docBuilder.parse(file);
150         processRecordFilter(doc);
151         processCategories(doc);
152         processLogLevels(doc);
153         processLogLevelColors(doc);
154         processLogTableColumns(doc);
155       } catch (Exception e) {
156         // ignore all error and just continue as if there was no
157         // configuration xml file but do report a message
158         System.err.println("Unable process configuration file at " +
159             getFilename() + ". Error Message=" + e.getMessage());
160       }
161     }
162 
163   }
164 
165   // Added in version 1.2 - reads in the NDC text filter from the
166   // xml configuration file.  If the value of the filter is not null
167   // or an empty string ("") then the manager will set the LogBrokerMonitor's
168   // LogRecordFilter to use the NDC LogRecordFilter.  Otherwise, the
169   // LogBrokerMonitor will use the default LogRecordFilter.
170   protected void processRecordFilter(Document doc) {
171     NodeList nodeList = doc.getElementsByTagName(NDCTEXTFILTER);
172 
173     // there is only one value stored
174     Node n = nodeList.item(0);
175     // add check for backwards compatibility  as this feature was added in
176     // version 1.2
177     if (n == null) {
178       return;
179     }
180 
181     NamedNodeMap map = n.getAttributes();
182     String text = getValue(map, NAME);
183 
184     if (text == null || text.equals("")) {
185       return;
186     }
187     _monitor.setNDCLogRecordFilter(text);
188   }
189 
190   protected void processCategories(Document doc) {
191     CategoryExplorerTree tree = _monitor.getCategoryExplorerTree();
192     CategoryExplorerModel model = tree.getExplorerModel();
193     NodeList nodeList = doc.getElementsByTagName(CATEGORY);
194 
195     // determine where the starting node is
196     NamedNodeMap map = nodeList.item(0).getAttributes();
197     int j = (getValue(map, NAME).equalsIgnoreCase(FIRST_CATEGORY_NAME)) ? 1 : 0;
198     // iterate backwards throught the nodeList so that expansion of the
199     // list can occur
200     for (int i = nodeList.getLength() - 1; i >= j; i--) {
201       Node n = nodeList.item(i);
202       map = n.getAttributes();
203       CategoryNode chnode = model.addCategory(new CategoryPath(getValue(map, PATH)));
204       chnode.setSelected((getValue(map, SELECTED).equalsIgnoreCase("true")) ? true : false);
205       if (getValue(map, EXPANDED).equalsIgnoreCase("true")) ;
206       tree.expandPath(model.getTreePathToRoot(chnode));
207     }
208 
209   }
210 
211   protected void processLogLevels(Document doc) {
212     NodeList nodeList = doc.getElementsByTagName(LEVEL);
213     Map menuItems = _monitor.getLogLevelMenuItems();
214 
215     for (int i = 0; i < nodeList.getLength(); i++) {
216       Node n = nodeList.item(i);
217       NamedNodeMap map = n.getAttributes();
218       String name = getValue(map, NAME);
219       try {
220         JCheckBoxMenuItem item =
221             (JCheckBoxMenuItem) menuItems.get(LogLevel.valueOf(name));
222         item.setSelected(getValue(map, SELECTED).equalsIgnoreCase("true"));
223       } catch (LogLevelFormatException e) {
224         // ignore it will be on by default.
225       }
226     }
227   }
228 
229   protected void processLogLevelColors(Document doc) {
230     NodeList nodeList = doc.getElementsByTagName(COLORLEVEL);
231     LogLevel.getLogLevelColorMap();
232 
233     for (int i = 0; i < nodeList.getLength(); i++) {
234       Node n = nodeList.item(i);
235       // check for backwards compatibility since this feature was added
236       // in version 1.3
237       if (n == null) {
238         return;
239       }
240 
241       NamedNodeMap map = n.getAttributes();
242       String name = getValue(map, NAME);
243       try {
244         LogLevel level = LogLevel.valueOf(name);
245         int red = Integer.parseInt(getValue(map, RED));
246         int green = Integer.parseInt(getValue(map, GREEN));
247         int blue = Integer.parseInt(getValue(map, BLUE));
248         Color c = new Color(red, green, blue);
249         if (level != null) {
250           level.setLogLevelColorMap(level, c);
251         }
252 
253       } catch (LogLevelFormatException e) {
254         // ignore it will be on by default.
255       }
256     }
257   }
258 
259   protected void processLogTableColumns(Document doc) {
260     NodeList nodeList = doc.getElementsByTagName(COLUMN);
261     Map menuItems = _monitor.getLogTableColumnMenuItems();
262     List selectedColumns = new ArrayList();
263     for (int i = 0; i < nodeList.getLength(); i++) {
264       Node n = nodeList.item(i);
265       // check for backwards compatibility since this feature was added
266       // in version 1.3
267       if (n == null) {
268         return;
269       }
270       NamedNodeMap map = n.getAttributes();
271       String name = getValue(map, NAME);
272       try {
273         LogTableColumn column = LogTableColumn.valueOf(name);
274         JCheckBoxMenuItem item =
275             (JCheckBoxMenuItem) menuItems.get(column);
276         item.setSelected(getValue(map, SELECTED).equalsIgnoreCase("true"));
277 
278         if (item.isSelected()) {
279           selectedColumns.add(column);
280         }
281       } catch (LogTableColumnFormatException e) {
282         // ignore it will be on by default.
283       }
284 
285       if (selectedColumns.isEmpty()) {
286         _table.setDetailedView();
287       } else {
288         _table.setView(selectedColumns);
289       }
290 
291     }
292   }
293 
294   protected String getValue(NamedNodeMap map, String attr) {
295     Node n = map.getNamedItem(attr);
296     return n.getNodeValue();
297   }
298 
299   protected void collapseTree() {
300     // collapse everything except the first category
301     CategoryExplorerTree tree = _monitor.getCategoryExplorerTree();
302     for (int i = tree.getRowCount() - 1; i > 0; i--) {
303       tree.collapseRow(i);
304     }
305   }
306 
307   protected void selectAllNodes() {
308     CategoryExplorerModel model = _monitor.getCategoryExplorerTree().getExplorerModel();
309     CategoryNode root = model.getRootCategoryNode();
310     Enumeration all = root.breadthFirstEnumeration();
311     CategoryNode n = null;
312     while (all.hasMoreElements()) {
313       n = (CategoryNode) all.nextElement();
314       n.setSelected(true);
315     }
316   }
317 
318   protected void store(String s) {
319 
320     try {
321       PrintWriter writer = new PrintWriter(new FileWriter(getFilename()));
322       writer.print(s);
323       writer.close();
324     } catch (IOException e) {
325       // do something with this error.
326       e.printStackTrace();
327     }
328 
329   }
330 
331   protected void deleteConfigurationFile() {
332     try {
333       File f = new File(getFilename());
334       if (f.exists()) {
335         f.delete();
336       }
337     } catch (SecurityException e) {
338       System.err.println("Cannot delete " + getFilename() +
339           " because a security violation occured.");
340     }
341   }
342 
343   protected String getFilename() {
344     String home = System.getProperty("user.home");
345     String sep = System.getProperty("file.separator");
346 
347     return home + sep + "lf5" + sep + CONFIG_FILE_NAME;
348   }
349 
350   //--------------------------------------------------------------------------
351   //   Private Methods:
352   //--------------------------------------------------------------------------
353   private void processConfigurationNode(CategoryNode node, StringBuffer xml) {
354     CategoryExplorerModel model = _monitor.getCategoryExplorerTree().getExplorerModel();
355 
356     Enumeration all = node.breadthFirstEnumeration();
357     CategoryNode n = null;
358     while (all.hasMoreElements()) {
359       n = (CategoryNode) all.nextElement();
360       exportXMLElement(n, model.getTreePathToRoot(n), xml);
361     }
362 
363   }
364 
365   private void processLogLevels(Map logLevelMenuItems, StringBuffer xml) {
366     xml.append("\t<loglevels>\r\n");
367     Iterator it = logLevelMenuItems.keySet().iterator();
368     while (it.hasNext()) {
369       LogLevel level = (LogLevel) it.next();
370       JCheckBoxMenuItem item = (JCheckBoxMenuItem) logLevelMenuItems.get(level);
371       exportLogLevelXMLElement(level.getLabel(), item.isSelected(), xml);
372     }
373 
374     xml.append("\t</loglevels>\r\n");
375   }
376 
377   private void processLogLevelColors(Map logLevelMenuItems, Map logLevelColors, StringBuffer xml) {
378     xml.append("\t<loglevelcolors>\r\n");
379     // iterate through the list of log levels being used (log4j, jdk1.4, custom levels)
380     Iterator it = logLevelMenuItems.keySet().iterator();
381     while (it.hasNext()) {
382       LogLevel level = (LogLevel) it.next();
383       // for each level, get the associated color from the log level color map
384       Color color = (Color) logLevelColors.get(level);
385       exportLogLevelColorXMLElement(level.getLabel(), color, xml);
386     }
387 
388     xml.append("\t</loglevelcolors>\r\n");
389   }
390 
391 
392   private void processLogTableColumns(List logTableColumnMenuItems, StringBuffer xml) {
393     xml.append("\t<logtablecolumns>\r\n");
394     Iterator it = logTableColumnMenuItems.iterator();
395     while (it.hasNext()) {
396       LogTableColumn column = (LogTableColumn) it.next();
397       JCheckBoxMenuItem item = _monitor.getTableColumnMenuItem(column);
398       exportLogTableColumnXMLElement(column.getLabel(), item.isSelected(), xml);
399     }
400 
401     xml.append("\t</logtablecolumns>\r\n");
402   }
403 
404   // Added in version 1.2 - stores the NDC text filter in the xml file
405   // for future use.
406   private void processLogRecordFilter(String text, StringBuffer xml) {
407     xml.append("\t<").append(NDCTEXTFILTER).append(" ");
408     xml.append(NAME).append("=\"").append(text).append("\"");
409     xml.append("/>\r\n");
410   }
411 
412   private void openXMLDocument(StringBuffer xml) {
413     xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n");
414   }
415 
416   private void openConfigurationXML(StringBuffer xml) {
417     xml.append("<configuration>\r\n");
418   }
419 
420   private void closeConfigurationXML(StringBuffer xml) {
421     xml.append("</configuration>\r\n");
422   }
423 
424   private void exportXMLElement(CategoryNode node, TreePath path, StringBuffer xml) {
425     CategoryExplorerTree tree = _monitor.getCategoryExplorerTree();
426 
427     xml.append("\t<").append(CATEGORY).append(" ");
428     xml.append(NAME).append("=\"").append(node.getTitle()).append("\" ");
429     xml.append(PATH).append("=\"").append(treePathToString(path)).append("\" ");
430     xml.append(EXPANDED).append("=\"").append(tree.isExpanded(path)).append("\" ");
431     xml.append(SELECTED).append("=\"").append(node.isSelected()).append("\"/>\r\n");
432   }
433 
434   private void exportLogLevelXMLElement(String label, boolean selected, StringBuffer xml) {
435     xml.append("\t\t<").append(LEVEL).append(" ").append(NAME);
436     xml.append("=\"").append(label).append("\" ");
437     xml.append(SELECTED).append("=\"").append(selected);
438     xml.append("\"/>\r\n");
439   }
440 
441   private void exportLogLevelColorXMLElement(String label, Color color, StringBuffer xml) {
442     xml.append("\t\t<").append(COLORLEVEL).append(" ").append(NAME);
443     xml.append("=\"").append(label).append("\" ");
444     xml.append(RED).append("=\"").append(color.getRed()).append("\" ");
445     xml.append(GREEN).append("=\"").append(color.getGreen()).append("\" ");
446     xml.append(BLUE).append("=\"").append(color.getBlue());
447     xml.append("\"/>\r\n");
448   }
449 
450   private void exportLogTableColumnXMLElement(String label, boolean selected, StringBuffer xml) {
451     xml.append("\t\t<").append(COLUMN).append(" ").append(NAME);
452     xml.append("=\"").append(label).append("\" ");
453     xml.append(SELECTED).append("=\"").append(selected);
454     xml.append("\"/>\r\n");
455   }
456   //--------------------------------------------------------------------------
457   //   Nested Top-Level Classes or Interfaces:
458   //--------------------------------------------------------------------------
459 
460 }
461 
462 
463 
464 
465 
466