1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 /* 19 * $Id$ 20 */ 21 22 /* 23 * 24 * LoggingHandler.java 25 * 26 */ 27 package org.apache.qetest; 28 29 30 /** 31 * Base class defining common functionality of logging handlers. 32 * <p>Common functionality used for testing when implementing 33 * various Handlers and Listeners. Provides common ways to set 34 * Loggers and levels, reset, and set expected errors or the 35 * like. Likely used to implement testing wrapper classes for 36 * things like javax.xml.transform.ErrorListener and 37 * org.xml.sax.ErrorHandler</p> 38 * <p>The best description for this class can be seen in an 39 * example; see trax.LoggingErrorHandler.java for one.</p> 40 * @author shane_curcuru@lotus.com 41 * @version $Id$ 42 */ 43 public class LoggingHandler 44 { 45 46 /** 47 * Set a default handler for us to wrapper. 48 * Often you may want to keep the default handler for some 49 * operation while you're logging. For subclasses that support 50 * this call, they will log every operation, and then simply 51 * call-through to this default handler. 52 * 53 * Subclasses should implement this and verify that the default 54 * is of an appropriate type to use. 55 * 56 * @param default Object of the correct type to pass-through to; 57 * throws IllegalArgumentException if null or incorrect type 58 */ setDefaultHandler(Object defaultHandler)59 public void setDefaultHandler(Object defaultHandler) 60 { 61 throw new java.lang.IllegalArgumentException("LoggingHandler.setDefaultHandler() is unimplemented!"); 62 } 63 64 65 /** 66 * Accessor method for our default handler; here returns null. 67 * 68 * @return default (Object) our default handler; null if unset 69 */ getDefaultHandler()70 public Object getDefaultHandler() 71 { 72 return null; 73 } 74 75 76 /** 77 * Get a list of counters of all items we've logged. 78 * LoggingHandlers each will have various kinds or types of 79 * things they handle (errors, warnings, messages, URIs, etc.). 80 * They should keep a running tally of how many of each kind of 81 * item they've 'handled'. 82 * 83 * @return array of int counters for each item we log; 84 * subclasses should define constants for what each slot is 85 */ getCounters()86 public int[] getCounters() 87 { 88 return NOTHING_HANDLED_CTR; 89 } 90 91 92 /** 93 * Get a string representation of last item we logged. 94 * For every item that we handle, subclasses should store a 95 * String representation and return it here if asked. Normally 96 * this will only be a copy of the very last item we logged - 97 * not necessarily what users might want, but the simplest to 98 * implement everywhere. 99 * 100 * @return String of the last item handled 101 */ getLast()102 public String getLast() 103 { 104 return NOTHING_HANDLED; 105 } 106 107 108 /** 109 * Reset any items or counters we've handled. 110 * Resets any data about what we've handled or logged so far, 111 * like getLast() and getCounters() data, as well as any 112 * expected items from setExpected(). Does not change our 113 * Logger or loggingLevel. 114 */ reset()115 public void reset() 116 { 117 /* no-op */; 118 } 119 120 121 /** 122 * Ask us to report checkPass/Fail for certain events we handle. 123 * Since we may have to handle many events between when a test 124 * will be able to call us, testers can set this to have us 125 * automatically call checkPass when we see an item that matches, 126 * or to call checkFail when we get an unexpected item. 127 * Generally, we only call check* methods when: 128 * <ul> 129 * <li>containsString is not set, reset, or is ITEM_DONT_CARE, 130 * we do nothing (i.e. never call check* for this item)</li> 131 * <li>containsString is ITEM_CHECKFAIL, we will always call 132 * checkFail with the contents of any item if it occours</li> 133 * <li>containsString is anything else, we will grab a String 134 * representation of every item of that type that comes along, 135 * and if the containsString is found, case-sensitive, within 136 * the handled item's string, call checkPass, otherwise 137 * call checkFail</li> 138 * <ul> 139 * Note that most implementations will only validate the first 140 * event of a specific type, and then will reset validation for 141 * that event type. This is because many events may be raised 142 * in between the time that a calling Test class could tell us 143 * of the 'next' expected event. 144 * //@todo improve this paradigm to allow users to specify an 145 * expected sequence of events. 146 * 147 * @param itemType which of the various types of items we might 148 * handle; should be defined as a constant by subclasses 149 * @param containsString a string to look for within whatever 150 * item we handle - usually checked for by seeing if the actual 151 * item we handle contains the containsString 152 */ setExpected(int itemType, String containsString)153 public void setExpected(int itemType, String containsString) 154 { 155 /* no-op */; 156 } 157 158 159 /** 160 * Accesor method for a brief description of this service. 161 * Subclasses should obviously override to provide useful info. 162 * 163 * @return String "LoggingHandler: default implementation, does nothing" 164 */ getDescription()165 public String getDescription() 166 { 167 return "LoggingHandler: default implementation, does nothing"; 168 } 169 170 171 /** 172 * Accesor methods for our Logger. 173 * 174 * @param l the Logger to have this test use for logging 175 * results; or null to use a default logger 176 */ setLogger(Logger l)177 public void setLogger(Logger l) 178 { 179 // if null, set a default one 180 if (null == l) 181 logger = getDefaultLogger(); 182 else 183 logger = l; 184 } 185 186 187 /** 188 * Accesor methods for our Logger. 189 * 190 * @return Logger we tell all our secrets to. 191 */ getLogger()192 public Logger getLogger() 193 { 194 return logger; 195 } 196 197 198 /** 199 * Get a default Logger for use with this Handler. 200 * Gets a default ConsoleLogger (only if a Logger isn't 201 * currently set!). 202 * 203 * @return current logger; if null, then creates a 204 * Logger.DEFAULT_LOGGER and returns that; if it cannot 205 * create one, throws a RuntimeException 206 */ getDefaultLogger()207 public Logger getDefaultLogger() 208 { 209 if (logger != null) 210 return logger; 211 212 try 213 { 214 Class rClass = Class.forName(Logger.DEFAULT_LOGGER); 215 return (Logger)rClass.newInstance(); 216 } 217 catch (Exception e) 218 { 219 // Must re-throw the exception, since returning 220 // null or the like could lead to recursion 221 e.printStackTrace(); 222 throw new RuntimeException(e.toString()); 223 } 224 } 225 226 227 /** 228 * Accesor methods for our loggingLevel. 229 * 230 * @param l what level we should call logger.logMsg() 231 */ setLoggingLevel(int l)232 public void setLoggingLevel(int l) 233 { 234 level = l; 235 } 236 237 238 /** 239 * Accesor methods for our loggingLevel. 240 * 241 * @return what level we call logger.logMsg() 242 */ getLoggingLevel()243 public int getLoggingLevel() 244 { 245 return level; 246 } 247 248 //----------------------------------------------------------- 249 //---- Instance Variables and Constants 250 //----------------------------------------------------------- 251 252 /** Our Logger, who we tell all our secrets to. */ 253 protected Logger logger = null; 254 255 /** What loggingLevel to use for reporter.logMsg(). */ 256 protected int level = Logger.DEFAULT_LOGGINGLEVEL; 257 258 /** Default return value from getCounters() after a reset(). */ 259 public static final int[] NOTHING_HANDLED_CTR = { 0 }; 260 261 /** Default return value from getLast() after a reset(). */ 262 public static final String NOTHING_HANDLED = "NOTHING_HANDLED"; 263 264 /** Token for setExpected that we don't care (default value) about the event. */ 265 public static final String ITEM_DONT_CARE = "ITEM_DONT_CARE"; 266 267 /** Token for setExpected that we should call checkFail if we get the event. */ 268 public static final String ITEM_CHECKFAIL = "ITEM_CHECKFAIL"; 269 } 270