001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.log4j.lf5.viewer.configure; 018 019import java.awt.Color; 020import java.io.File; 021import java.io.FileWriter; 022import java.io.IOException; 023import java.io.PrintWriter; 024import java.util.ArrayList; 025import java.util.Enumeration; 026import java.util.Iterator; 027import java.util.List; 028import java.util.Map; 029 030import javax.swing.JCheckBoxMenuItem; 031import javax.swing.tree.TreePath; 032import javax.xml.parsers.DocumentBuilder; 033import javax.xml.parsers.DocumentBuilderFactory; 034 035import org.apache.log4j.lf5.LogLevel; 036import org.apache.log4j.lf5.LogLevelFormatException; 037import org.apache.log4j.lf5.viewer.LogBrokerMonitor; 038import org.apache.log4j.lf5.viewer.LogTable; 039import org.apache.log4j.lf5.viewer.LogTableColumn; 040import org.apache.log4j.lf5.viewer.LogTableColumnFormatException; 041import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryExplorerModel; 042import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryExplorerTree; 043import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryNode; 044import org.apache.log4j.lf5.viewer.categoryexplorer.CategoryPath; 045import org.w3c.dom.Document; 046import org.w3c.dom.NamedNodeMap; 047import org.w3c.dom.Node; 048import org.w3c.dom.NodeList; 049 050/** 051 * <p>ConfigurationManager handles the storage and retrival of the state of 052 * the CategoryExplorer 053 * 054 * @author Richard Hurst 055 * @author Brad Marlborough 056 */ 057 058// Contributed by ThoughtWorks Inc. 059 060public class ConfigurationManager extends Object { 061 //-------------------------------------------------------------------------- 062 // Constants: 063 //-------------------------------------------------------------------------- 064 private static final String CONFIG_FILE_NAME = "lf5_configuration.xml"; 065 private static final String NAME = "name"; 066 private static final String PATH = "path"; 067 private static final String SELECTED = "selected"; 068 private static final String EXPANDED = "expanded"; 069 private static final String CATEGORY = "category"; 070 private static final String FIRST_CATEGORY_NAME = "Categories"; 071 private static final String LEVEL = "level"; 072 private static final String COLORLEVEL = "colorlevel"; 073 private static final String RED = "red"; 074 private static final String GREEN = "green"; 075 private static final String BLUE = "blue"; 076 private static final String COLUMN = "column"; 077 private static final String NDCTEXTFILTER = "searchtext"; 078 //-------------------------------------------------------------------------- 079 // Protected Variables: 080 //-------------------------------------------------------------------------- 081 082 //-------------------------------------------------------------------------- 083 // Private Variables: 084 //-------------------------------------------------------------------------- 085 private LogBrokerMonitor _monitor = null; 086 private LogTable _table = null; 087 088 //-------------------------------------------------------------------------- 089 // Constructors: 090 //-------------------------------------------------------------------------- 091 public ConfigurationManager(LogBrokerMonitor monitor, LogTable table) { 092 super(); 093 _monitor = monitor; 094 _table = table; 095 load(); 096 } 097 //-------------------------------------------------------------------------- 098 // Public Methods: 099 //-------------------------------------------------------------------------- 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