1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 package org.apache.qetest.trax; 21 22 import javax.xml.transform.ErrorListener; 23 import javax.xml.transform.TransformerException; 24 import org.apache.qetest.CheckingHandler; 25 import static org.apache.qetest.CheckingHandler.Expectation.ITEM_CHECKPASS; 26 import static org.apache.qetest.CheckingHandler.Expectation.ITEM_DONT_CARE; 27 import static org.testng.Assert.fail; 28 29 /** 30 * Cheap-o ErrorListener for use by API tests. 31 * <p> 32 * Implements javax.xml.transform.ErrorListener and dumps everything to a 33 * Logger; is separately settable as to when it will throw an exception; also 34 * separately settable as to when we should validate specific events that we 35 * handle.</p> 36 */ 37 public class CheckingErrorListener implements CheckingHandler, ErrorListener { 38 39 /** 40 * Constants determining when we should throw exceptions. 41 * <ul>Flags are combineable like a bitfield. 42 * <li>THROW_NEVER - never ever (always continue - note this may have 43 * unexpected effects when fatalErrors happen, see 44 * {@link javax.xml.transform.ErrorListener#fatalError(javax.xml.transform.TransformerException)}</li> 45 * <li>THROW_ON_WARNING - throw only on warnings</li> 46 * <li>THROW_ON_ERROR - throw only on errors</li> 47 * <li>THROW_ON_FATAL - throw only on fatalErrors - default</li> 48 * <li>THROW_ALWAYS - always throw exceptions</li> 49 * </ul> 50 */ 51 public static final int THROW_NEVER = 0; 52 53 /** 54 * THROW_ON_WARNING - throw only on warnings. 55 */ 56 public static final int THROW_ON_WARNING = 1; 57 58 /** 59 * THROW_ON_ERROR - throw only on errors. 60 */ 61 public static final int THROW_ON_ERROR = 2; 62 63 /** 64 * THROW_ON_FATAL - throw only on fatalErrors - default. 65 */ 66 public static final int THROW_ON_FATAL = 4; 67 68 /** 69 * THROW_ALWAYS - always throw exceptions. 70 */ 71 public static final int THROW_ALWAYS = THROW_ON_WARNING | THROW_ON_ERROR 72 | THROW_ON_FATAL; 73 74 /** 75 * If we should throw an exception for each message type. 76 */ 77 protected final int throwWhen; 78 79 /** 80 * Constructor set when we should re-throw exceptions. 81 * 82 * @param t THROW_WHEN_* constant as to when we should re-throw an exception 83 * when we are called. 84 */ 85 public CheckingErrorListener(int t) { 86 throwWhen = t; 87 } 88 89 /** 90 * Default constructor will behave as default. Throw only when there is 91 * non-recoverable error. 92 */ 93 public CheckingErrorListener() { 94 this(THROW_ON_FATAL); 95 } 96 97 /** 98 * Tells us when we should re-throw exceptions. 99 * 100 * @return THROW_WHEN_* constant as to when we should re-throw an exception 101 * when we are called 102 */ 103 public int getThrowWhen() { 104 return throwWhen; 105 } 106 107 /** 108 * Constant for items returned in getCounters: messages. 109 */ 110 public static final int TYPE_WARNING = 0; 111 112 /** 113 * Constant for items returned in getCounters: errors. 114 */ 115 public static final int TYPE_ERROR = 1; 116 117 /** 118 * Constant for items returned in getCounters: fatalErrors. 119 */ 120 public static final int TYPE_FATALERROR = 2; 121 122 /** 123 * Expected values for events we may handle, default=ITEM_DONT_CARE. 124 */ 125 private final Expectation[] expected = { 126 ITEM_DONT_CARE, /* warning */ 127 ITEM_DONT_CARE, /* error */ 128 ITEM_DONT_CARE /* fatalError */}; 129 130 /** 131 * Ask us to report checkPass/Fail for certain events we handle. Since we 132 * may have to handle many events between when a test will be able to call 133 * us, testers can set this to have us automatically call checkPass when we 134 * see an item that matches, or to call checkFail when we get an unexpected 135 * item. Generally, we only call check* methods when: 136 * <ul> 137 * <li>containsString is not set, reset, or is ITEM_DONT_CARE, we do nothing 138 * (i.e. never call check* for this item)</li> 139 * <li>containsString is ITEM_CHECKFAIL, we will always call checkFail with 140 * the contents of any item if it occurs</li> 141 * <li>containsString is anything else, we will grab a String representation 142 * of every item of that type that comes along, and if the containsString is 143 * found, case-sensitive, within the handled item's string, call checkPass, 144 * otherwise call checkFail</li> 145 * </ul> 146 * Note that any time we handle a particular event that was expected, we 147 * un-set the expected value for that item. This means that you can only ask 148 * us to validate one occurrence of any particular event; all events after 149 * that one will be treated as ITEM_DONT_CARE. Callers can of course call 150 * setExpected again, of course, but this covers the case where we handle 151 * multiple events in a single block, perhaps out of the caller's direct 152 * control. Note that we first store the event via setLast(), then we 153 * validate the event as above, and then we potentially re-throw the 154 * exception as by setThrowWhen(). 155 * 156 * @param itemType which of the various types of items we might handle; 157 * should be defined as a constant by subclasses 158 * @param expectation expectation if we need check or not. 159 */ 160 @Override 161 public void setExpected(int itemType, Expectation expectation) { 162 expected[itemType] = expectation; 163 } 164 165 /** 166 * Reset all items or counters we've handled. 167 */ 168 @Override 169 public void reset() { 170 for (int j = 0; j < expected.length; j++) { 171 expected[j] = ITEM_DONT_CARE; 172 } 173 } 174 175 /** 176 * Grab basic info out of a TransformerException. Worker method to hide 177 * implementation; currently just calls exception.getMessageAndLocation(). 178 * 179 * @param exception to get information from 180 * @return simple string describing the exception (getMessageAndLocation()) 181 */ 182 public String getTransformerExceptionInfo(TransformerException exception) { 183 if (exception == null) { 184 return ""; // Don't return null, just to make other code here simpler 185 } 186 return exception.getMessageAndLocation(); 187 } 188 189 /** 190 * Implementation of warning; calls logMsg with info contained in exception. 191 * 192 * @param exception provided by Transformer 193 * @exception TransformerException thrown only if asked to or if loggers are 194 * bad 195 */ 196 @Override 197 public void warning(TransformerException exception) throws TransformerException { 198 // Log or validate the exception 199 if(expected[TYPE_WARNING] == ITEM_CHECKPASS) 200 fail("Unexpected error: ex " + exception); 201 202 // Also re-throw the exception if asked to 203 if ((throwWhen & THROW_ON_WARNING) == THROW_ON_WARNING) { 204 // Note: re-throw the SAME exception, not a new one! 205 throw exception; 206 } 207 } 208 209 /** 210 * Implementation of error; calls logMsg with info contained in exception. 211 * Only ever throws an exception itself if asked to or if loggers are bad. 212 * 213 * @param exception provided by Transformer 214 * @exception TransformerException thrown only if asked to. 215 */ 216 @Override 217 public void error(TransformerException exception) throws TransformerException { 218 // validate the exception 219 if(expected[TYPE_ERROR] == ITEM_CHECKPASS) 220 fail("Unexpected error: ex " + exception); 221 222 // Also re-throw the exception if asked to 223 if ((throwWhen & THROW_ON_ERROR) == THROW_ON_ERROR) { 224 // Note: re-throw the SAME exception, not a new one! 225 throw exception; 226 } 227 } 228 229 /** 230 * Implementation of error; calls logMsg with info contained in exception. 231 * Only ever throws an exception itself if asked to or if loggers are bad. 232 * Note that this may cause unusual behavior since we may not actually 233 * re-throw the exception, even though it was 'fatal'. 234 * 235 * @param exception provided by Transformer 236 * @exception TransformerException thrown only if asked to. 237 */ 238 @Override 239 public void fatalError(TransformerException exception) throws TransformerException { 240 // validate the exception 241 if(expected[TYPE_FATALERROR] == ITEM_CHECKPASS) 242 fail("Unexpected fatal error: ex " + exception); 243 244 // Also re-throw the exception if asked to 245 if ((throwWhen & THROW_ON_FATAL) == THROW_ON_FATAL) { 246 // Note: re-throw the SAME exception, not a new one! 247 throw exception; 248 } 249 } 250 }