• 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  * LoggingURIResolver.java
25  *
26  */
27 package org.apache.qetest.trax;
28 
29 import java.util.Hashtable;
30 
31 import javax.xml.transform.Source;
32 import javax.xml.transform.TransformerException;
33 import javax.xml.transform.URIResolver;
34 import javax.xml.transform.stream.StreamSource;
35 
36 import org.apache.qetest.Logger;
37 import org.apache.qetest.LoggingHandler;
38 import org.apache.xml.utils.SystemIDResolver;
39 import org.xml.sax.InputSource;
40 //-------------------------------------------------------------------------
41 
42 /**
43  * Implementation of URIResolver that logs all calls.
44  * Currently just provides default service; returns null.
45  * @author shane_curcuru@lotus.com
46  * @version $Id$
47  */
48 public class LoggingURIResolver extends LoggingHandler implements URIResolver
49 {
50 
51     /** No-op sets logger to default.  */
LoggingURIResolver()52     public LoggingURIResolver()
53     {
54         setLogger(getDefaultLogger());
55     }
56 
57     /**
58      * Ctor that calls setLogger automatically.
59      *
60      * @param l Logger we should log to
61      */
LoggingURIResolver(Logger l)62     public LoggingURIResolver(Logger l)
63     {
64         setLogger(l);
65     }
66 
67 
68     /**
69      * Our default handler that we pass all events through to.
70      */
71     protected URIResolver defaultHandler = null;
72 
73 
74     /**
75      * Set a default handler for us to wrapper.
76      * Set a URIResolver for us to use.
77      * // Note that we don't currently have a default URIResolver,
78      * //  so the LoggingURIResolver class will just attempt
79      * //  to use the SystemIDResolver class instead
80      *
81      * @param default Object of the correct type to pass-through to;
82      * throws IllegalArgumentException if null or incorrect type
83      */
setDefaultHandler(Object defaultU)84     public void setDefaultHandler(Object defaultU)
85     {
86         try
87         {
88             defaultHandler = (URIResolver)defaultU;
89         }
90         catch (Throwable t)
91         {
92             throw new java.lang.IllegalArgumentException("setDefaultHandler illegal type: " + t.toString());
93         }
94     }
95 
96 
97     /**
98      * Accessor method for our default handler.
99      *
100      * @return default (Object) our default handler; null if unset
101      */
getDefaultHandler()102     public Object getDefaultHandler()
103     {
104         return (Object)defaultHandler;
105     }
106 
107 
108     /** Prefixed to all logger msg output.  */
109     public static final String prefix = "LUR:";
110 
111 
112     /**
113      * Counter for how many URIs we've resolved.
114      */
115     protected int[] counters = { 0 };
116 
117 
118     /**
119      * Get a list of counters of all items we've logged.
120      * Only a single array item is returned.
121      *
122      * @return array of int counter for each item we log
123      */
getCounters()124     public int[] getCounters()
125     {
126         return counters;
127     }
128 
129 
130     /**
131      * Really Cheap-o string representation of our state.
132      *
133      * @return String of getCounters() rolled up in minimal space
134      */
getQuickCounters()135     public String getQuickCounters()
136     {
137         return (prefix + "(" + counters[0] + ")");
138     }
139 
140 
141     /** Cheap-o string representation of last URI we resolved.  */
142     protected String lastItem = NOTHING_HANDLED;
143 
144 
145     /**
146      * Accessor for string representation of last event we got.
147      * @param s string to set
148      */
setLastItem(String s)149     protected void setLastItem(String s)
150     {
151         lastItem = s;
152     }
153 
154 
155     /**
156      * Accessor for string representation of last event we got.
157      * @return last event string we had
158      */
getLast()159     public String getLast()
160     {
161         return lastItem;
162     }
163 
164 
165     /** Expected value(s) for URIs we may resolve, default=ITEM_DONT_CARE. */
166     protected String[] expected = { ITEM_DONT_CARE };
167 
168 
169     /** Counter used when expected is an ordered array. */
170     protected int expectedCtr = 0;
171 
172 
173     /**
174      * Ask us to report checkPass/Fail for certain URIs we resolve.
175      *
176      * @param itemType ignored, we only do one type
177      * @param containsString a string to look for within whatever
178      * item we handle - usually checked for by seeing if the actual
179      * item we handle contains the containsString
180      */
setExpected(int itemType, String containsString)181     public void setExpected(int itemType, String containsString)
182     {
183         // Default to don't care on null
184         if (null == containsString)
185             containsString = ITEM_DONT_CARE;
186 
187         expected = new String[1];
188         expected[0] = containsString;
189     }
190 
191     /**
192      * Ask us to report checkPass/Fail for an ordered list of URIs
193      * we may resolve.
194      *
195      * Users can specify an array of expected URIs we should be
196      * resolving in order.  Both the specific items and the exact
197      * order must occour for us to call checkPass for each URI;
198      * we call checkFail for any URI that doesn't match or is out
199      * of order.  After we run off the end of the array, we
200      * go back to the defaul of ITEM_DONT_CARE.
201      * Reset by reset(), of course.
202      *
203      * @param containsStrings[] and array of items to look for in
204      * order: this allows you to test a stylesheet that has
205      * three xsl:imports, for example
206      */
setExpected(String[] containsStrings)207     public void setExpected(String[] containsStrings)
208     {
209         // Default to don't care on null
210         if ((null == containsStrings) || (0 == containsStrings.length))
211         {
212             expected = new String[1];
213             expected[0] = ITEM_DONT_CARE;
214         }
215         else
216         {
217             expected = new String[containsStrings.length];
218             System.arraycopy(containsStrings, 0, expected, 0, containsStrings.length);
219         }
220         expectedCtr = 0;
221     }
222 
223     /**
224      * Cheap-o worker method to get a string value.
225      * //@todo improve string return value
226      *
227      * @param i InputSource to get a string from
228      * @return some String representation thereof
229      */
getString(InputSource i)230     private String getString(InputSource i)
231     {
232         return i.toString();
233     }
234 
235 
236     /**
237      * Reset all items or counters we've handled.
238      */
reset()239     public void reset()
240     {
241         setLastItem(NOTHING_HANDLED);
242         counters[0] = 0;
243         expected = new String[1];
244         expected[0] = ITEM_DONT_CARE;
245         expectedCtr = 0;
246     }
247 
248 
249     /**
250      * Worker method to either log or call check* for this event.
251      * A simple way to validate for any kind of event.
252      *
253      * @param desc detail info from this kind of message
254      */
checkExpected(String desc, String resolvedTo)255     protected void checkExpected(String desc, String resolvedTo)
256     {
257         // Note the order of logging is important, which is why
258         //  we store these values and then log them later
259         final int DONT_CARE = 0;
260         final int PASS = 1;
261         final int FAIL = 2;
262         int checkResult = DONT_CARE;
263         String checkDesc = null;
264         StringBuffer extraInfo = new StringBuffer("");
265         Hashtable attrs = new Hashtable();
266         attrs.put("source", "LoggingURIResolver");
267         attrs.put("counters", getQuickCounters());
268         attrs.put("resolvedTo", resolvedTo);
269 
270         String tmp = getQuickCounters() + " " + desc;
271         if (expectedCtr > expected.length)
272         {
273             // Sanity check: prevent AIOOBE
274             expectedCtr = expected.length;
275             extraInfo.append(getQuickCounters()
276                           + " error: array overbounds " + expectedCtr + "\n");
277         }
278         // Either log the exception or call checkPass/checkFail
279         //  as requested by setExpected for this type
280         if (ITEM_DONT_CARE == expected[expectedCtr])
281         {
282             // We don't care about this, just log it
283             extraInfo.append("ITEM_DONT_CARE(" + expectedCtr + ") " + tmp + "\n");
284         }
285         else if (ITEM_CHECKFAIL == expected[expectedCtr])
286         {
287             // We shouldn't have been called here, so fail
288             checkResult = FAIL;
289             checkDesc = tmp + " was unexpected";
290         }
291         else if ((null != desc)
292                   && (desc.indexOf(expected[expectedCtr]) > -1))
293         {
294             // We got a warning the user expected, so pass
295             checkResult = PASS;
296             checkDesc = tmp + " matched";
297             // Also reset this counter
298             expected[expectedCtr] = ITEM_DONT_CARE;
299         }
300         else
301         {
302             // We got a warning the user didn't expect, so fail
303             checkResult = FAIL;
304             checkDesc = tmp + " did not match";
305             // Also reset this counter
306             expected[expectedCtr] = ITEM_DONT_CARE;
307         }
308         // If we have a list of expected items, increment
309         if (expected.length > 1)
310         {
311             expectedCtr++;
312             // If we run off the end, reset all expected
313             if (expectedCtr >= expected.length)
314             {
315                 extraInfo.append("Ran off end of expected items, resetting\n");
316                 expected = new String[1];
317                 expected[0] = ITEM_DONT_CARE;
318                 expectedCtr = 0;
319             }
320         }
321         logger.logElement(level, "loggingHandler", attrs, extraInfo);
322         if (PASS == checkResult)
323             logger.checkPass(checkDesc);
324         else if (FAIL == checkResult)
325             logger.checkFail(checkDesc);
326         // else - DONT_CARE is no-op
327     }
328 
329 
330     ////////////////// Implement URIResolver //////////////////
331     /**
332      * This will be called by the processor when it encounters
333      * an xsl:include, xsl:import, or document() function.
334      *
335      * @param href An href attribute, which may be relative or absolute.
336      * @param base The base URI in effect when the href attribute was encountered.
337      *
338      * @return A non-null Source object.
339      *
340      * @throws TransformerException
341      */
resolve(String href, String base)342     public Source resolve(String href, String base)
343             throws TransformerException
344     {
345         counters[0]++;
346         setLastItem("{" + base + "}" + href);
347         // Store the source we're about to resolve - note that the
348         //  order of logging and calling checkExpected is important
349         Source resolvedSource = null;
350         String resolvedTo = null;
351 
352         if (null != defaultHandler)
353         {
354             resolvedTo = "resolved by: " + defaultHandler;
355             resolvedSource = defaultHandler.resolve(href, base);
356         }
357         else
358         {
359             // Note that we don't currently have a default URIResolver,
360             //  so the LoggingURIResolver class will just attempt
361             //  to use the SystemIDResolver class instead
362             String sysId = SystemIDResolver.getAbsoluteURI(href, base);
363             resolvedTo = "resolved into new StreamSource(" + sysId + ")";
364             resolvedSource = new StreamSource(sysId);
365         }
366 
367         // Call worker method to log out various info and then
368         //  call check for us if needed
369         checkExpected(getLast(), resolvedTo);
370         return resolvedSource;
371     }
372 }
373