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