• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * LoggingLexicalHandler.java
25  *
26  */
27 package org.apache.qetest.xsl;
28 
29 import org.apache.qetest.Logger;
30 import org.apache.qetest.LoggingHandler;
31 import org.xml.sax.SAXException;
32 import org.xml.sax.ext.LexicalHandler;
33 
34 /**
35  * Cheap-o LexicalHandler for use by API tests.
36  * <p>Implements LexicalHandler and dumps simplistic info
37  * everything to a Logger; a way to debug SAX stuff.</p>
38  * @author shane_curcuru@lotus.com
39  * @version $Id$
40  */
41 public class LoggingLexicalHandler extends LoggingHandler implements LexicalHandler
42 {
43 
44     /** No-op sets logger to default.  */
LoggingLexicalHandler()45     public LoggingLexicalHandler()
46     {
47         setLogger(getDefaultLogger());
48     }
49 
50     /**
51      * Ctor that calls setLogger automatically.
52      *
53      * @param l Logger we should log to
54      */
LoggingLexicalHandler(Logger l)55     public LoggingLexicalHandler(Logger l)
56     {
57         setLogger(l);
58     }
59 
60 
61     /**
62      * Our default handler that we pass all events through to.
63      */
64     protected LexicalHandler defaultHandler = null;
65 
66 
67     /**
68      * Set a default handler for us to wrapper.
69      * Set a LexicalHandler for us to use.
70      *
71      * @param default Object of the correct type to pass-through to;
72      * throws IllegalArgumentException if null or incorrect type
73      */
setDefaultHandler(Object defaultH)74     public void setDefaultHandler(Object defaultH)
75     {
76         try
77         {
78             defaultHandler = (LexicalHandler)defaultH;
79         }
80         catch (Throwable t)
81         {
82             throw new java.lang.IllegalArgumentException("setDefaultHandler illegal type: " + t.toString());
83         }
84     }
85 
86 
87     /**
88      * Accessor method for our default handler.
89      *
90      * @return default (Object) our default handler; null if unset
91      */
getDefaultHandler()92     public Object getDefaultHandler()
93     {
94         return (Object)defaultHandler;
95     }
96 
97 
98     /** Prefixed to all logger msg output.  */
99     public static final String prefix = "LLH:";
100 
101     /** Constant for items returned in getCounters: startDTD.  */
102     public static final int TYPE_STARTDTD = 0;
103 
104     /** Constant for items returned in getCounters: endDTD.  */
105     public static final int TYPE_ENDDTD = 1;
106 
107     /** Constant for items returned in getCounters: startEntity.  */
108     public static final int TYPE_STARTENTITY = 2;
109 
110     /** Constant for items returned in getCounters: endEntity.  */
111     public static final int TYPE_ENDENTITY = 3;
112 
113     /** Constant for items returned in getCounters: startCDATA.  */
114     public static final int TYPE_STARTCDATA = 4;
115 
116     /** Constant for items returned in getCounters: endCDATA.  */
117     public static final int TYPE_ENDCDATA = 5;
118 
119     /** Constant for items returned in getCounters: comment.  */
120     public static final int TYPE_COMMENT = 6;
121 
122 
123     /**
124      * Counters for how many events we've handled.
125      * Index into array are the TYPE_* constants.
126      */
127     protected int[] counters =
128     {
129         0, /* startDTD */
130         0, /* endDTD */
131         0, /* startEntity */
132         0, /* endEntity */
133         0, /* startCDATA */
134         0, /* endCDATA */
135         0  /* comment */
136     };
137 
138 
139     /**
140      * Get a list of counters of all items we've logged.
141      * Returned in order as startDTD, endDTD, startEntity,
142      * endEntity, startCDATA, endCDATA, comment.
143      * Index into array are the TYPE_* constants.
144      *
145      * @return array of int counters for each item we log
146      */
getCounters()147     public int[] getCounters()
148     {
149         return counters;
150     }
151 
152 
153     /**
154      * Really Cheap-o string representation of our state.
155      *
156      * @return String of getCounters() rolled up in minimal space
157      */
getQuickCounters()158     public String getQuickCounters()
159     {
160         return (prefix + "("
161                 + counters[TYPE_STARTDTD] + ", " + counters[TYPE_ENDDTD] + "; "
162                 + counters[TYPE_STARTENTITY] + ", " + counters[TYPE_ENDENTITY] + "; "
163                 + counters[TYPE_STARTCDATA] + ", " + counters[TYPE_ENDCDATA] + "; "
164                 + counters[TYPE_COMMENT] + ")");
165     }
166 
167 
168     /** Expected values for events we may handle, default=ITEM_DONT_CARE. */
169     protected String[] expected =
170     {
171         ITEM_DONT_CARE, /* startDTD */
172         ITEM_DONT_CARE, /* endDTD */
173         ITEM_DONT_CARE, /* startEntity */
174         ITEM_DONT_CARE, /* endEntity */
175         ITEM_DONT_CARE, /* startCDATA */
176         ITEM_DONT_CARE, /* endCDATA */
177         ITEM_DONT_CARE  /* comment */
178     };
179 
180 
181     /** Cheap-o string representation of last event we got.  */
182     protected String lastItem = NOTHING_HANDLED;
183 
184 
185     /**
186      * Accessor for string representation of last event we got.
187      * @param s string to set
188      */
setLastItem(String s)189     protected void setLastItem(String s)
190     {
191         lastItem = s;
192     }
193 
194 
195     /**
196      * Accessor for string representation of last event we got.
197      * @return last event string we had
198      */
getLast()199     public String getLast()
200     {
201         return lastItem;
202     }
203 
204 
205     /**
206      * Ask us to report checkPass/Fail for certain events we handle.
207      * Since we may have to handle many events between when a test
208      * will be able to call us, testers can set this to have us
209      * automatically call checkPass when we see an item that matches,
210      * or to call checkFail when we get an unexpected item.
211      * Generally, we only call check* methods when:
212      * <ul>
213      * <li>containsString is not set, reset, or is ITEM_DONT_CARE,
214      * we do nothing (i.e. never call check* for this item)</li>
215      * <li>containsString is ITEM_CHECKFAIL, we will always call
216      * checkFail with the contents of any item if it occours</li>
217      * <li>containsString is anything else, we will grab a String
218      * representation of every item of that type that comes along,
219      * and if the containsString is found, case-sensitive, within
220      * the handled item's string, call checkPass, otherwise
221      * call checkFail</li>
222      * <ul>
223      * Note that any time we handle a particular event that was
224      * expected, we un-set the expected value for that item.  This
225      * means that you can only ask us to validate one occourence
226      * of any particular event; all events after that one will
227      * be treated as ITEM_DONT_CARE.  Callers can of course call
228      * setExpected again, of course, but this covers the case where
229      * we handle multiple events in a single block, perhaps out of
230      * the caller's direct control.
231      * Note that we first store the event via setLast(), then we
232      * validate the event as above, and then we potentially
233      * re-throw the exception as by setThrowWhen().
234      *
235      * @param itemType which of the various types of items we might
236      * handle; should be defined as a constant by subclasses
237      * @param containsString a string to look for within whatever
238      * item we handle - usually checked for by seeing if the actual
239      * item we handle contains the containsString
240      */
setExpected(int itemType, String containsString)241     public void setExpected(int itemType, String containsString)
242     {
243         // Default to don't care on null
244         if (null == containsString)
245             containsString = ITEM_DONT_CARE;
246 
247         try
248         {
249             expected[itemType] = containsString;
250         }
251         catch (ArrayIndexOutOfBoundsException aioobe)
252         {
253             // Just log it for callers reference and continue anyway
254             logger.logMsg(level, prefix + " setExpected called with illegal type:" + itemType);
255         }
256     }
257 
258 
259     /**
260      * Reset all items or counters we've handled.
261      */
reset()262     public void reset()
263     {
264         setLastItem(NOTHING_HANDLED);
265         for (int i = 0; i < counters.length; i++)
266         {
267             counters[i] = 0;
268         }
269         for (int j = 0; j < expected.length; j++)
270         {
271             expected[j] = ITEM_DONT_CARE;
272         }
273     }
274 
275 
276     /**
277      * Worker method to either log or call check* for this event.
278      * A simple way to validate for any kind of event.
279      * Note that various events may store the various arguments
280      * they get differently, so you should check the code to
281      * ensure you're specifying the correct containsString.
282      *
283      * @param type of event (startdtd|enddtd|etc)
284      * @param desc detail info from this kind of message
285      */
logOrCheck(int type, String desc)286     protected void logOrCheck(int type, String desc)
287     {
288         String tmp = getQuickCounters() + " " + desc;
289         // Either log the exception or call checkPass/checkFail
290         //  as requested by setExpected for this type
291         if (ITEM_DONT_CARE == expected[type])
292         {
293             // We don't care about this, just log it
294             logger.logMsg(level, tmp);
295         }
296         else if (ITEM_CHECKFAIL == expected[type])
297         {
298             // We shouldn't have been called here, so fail
299             logger.checkFail(tmp + " was unexpected");
300         }
301         else if ((null != desc)
302                   && (desc.indexOf(expected[type]) > -1))
303         {
304             // We got a warning the user expected, so pass
305             logger.checkPass(tmp + " matched");
306             // Also reset this counter
307             //@todo needswork: this is very state-dependent, and
308             //  might not be what the user expects, but at least it
309             //  won't give lots of extra false fails or passes
310             expected[type] = ITEM_DONT_CARE;
311         }
312         else
313         {
314             // We got a warning the user didn't expect, so fail
315             logger.checkFail(tmp + " did not match");
316             // Also reset this counter
317             expected[type] = ITEM_DONT_CARE;
318         }
319     }
320 
321 
322     ////////////////// Implement LexicalHandler //////////////////
startDTD(String name, String publicId, String systemId)323     public void startDTD (String name, String publicId, String systemId)
324     	throws SAXException
325     {
326         // Note: this implies this class is !not! threadsafe
327         // Increment counter and save info
328         counters[TYPE_STARTDTD]++;
329         setLastItem("startDTD: " + name + ", " + publicId + ", " + systemId);
330         logOrCheck(TYPE_STARTDTD, getLast());
331         if (null != defaultHandler)
332             defaultHandler.startDTD(name, publicId, systemId);
333     }
334 
endDTD()335     public void endDTD ()
336 	    throws SAXException
337     {
338         counters[TYPE_ENDDTD]++;
339         setLastItem("endDTD");
340         logOrCheck(TYPE_ENDDTD, getLast());
341         if (null != defaultHandler)
342             defaultHandler.endDTD();
343     }
344 
startEntity(String name)345     public void startEntity (String name)
346     	throws SAXException
347     {
348         counters[TYPE_STARTENTITY]++;
349         setLastItem("startEntity: " + name);
350         logOrCheck(TYPE_STARTENTITY, getLast());
351         if (null != defaultHandler)
352             defaultHandler.startEntity(name);
353     }
354 
endEntity(String name)355     public void endEntity (String name)
356 	    throws SAXException
357     {
358         counters[TYPE_ENDENTITY]++;
359         setLastItem("endEntity: " + name);
360         logOrCheck(TYPE_ENDENTITY, getLast());
361         if (null != defaultHandler)
362             defaultHandler.endEntity(name);
363     }
364 
startCDATA()365     public void startCDATA ()
366     	throws SAXException
367     {
368         counters[TYPE_STARTCDATA]++;
369         setLastItem("startCDATA");
370         logOrCheck(TYPE_STARTCDATA, getLast());
371         if (null != defaultHandler)
372             defaultHandler.startCDATA();
373     }
374 
endCDATA()375     public void endCDATA ()
376 	    throws SAXException
377     {
378         counters[TYPE_ENDCDATA]++;
379         setLastItem("endCDATA");
380         logOrCheck(TYPE_ENDCDATA, getLast());
381         if (null != defaultHandler)
382             defaultHandler.endCDATA();
383     }
384 
comment(char ch[], int start, int length)385     public void comment (char ch[], int start, int length)
386     	throws SAXException
387     {
388         counters[TYPE_COMMENT]++;
389         StringBuffer buf = new StringBuffer("comment: ");
390         buf.append(ch);
391         buf.append(", ");
392         buf.append(start);
393         buf.append(", ");
394         buf.append(length);
395 
396         setLastItem(buf.toString());
397         logOrCheck(TYPE_COMMENT, getLast());
398         if (null != defaultHandler)
399             defaultHandler.comment(ch, start, length);
400     }
401 
402 }
403