/* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.qetest.trax; import javax.xml.transform.ErrorListener; import javax.xml.transform.TransformerException; import org.apache.qetest.CheckingHandler; import static org.apache.qetest.CheckingHandler.Expectation.ITEM_CHECKPASS; import static org.apache.qetest.CheckingHandler.Expectation.ITEM_DONT_CARE; import static org.testng.Assert.fail; /** * Cheap-o ErrorListener for use by API tests. *

* Implements javax.xml.transform.ErrorListener and dumps everything to a * Logger; is separately settable as to when it will throw an exception; also * separately settable as to when we should validate specific events that we * handle.

*/ public class CheckingErrorListener implements CheckingHandler, ErrorListener { /** * Constants determining when we should throw exceptions. * */ public static final int THROW_NEVER = 0; /** * THROW_ON_WARNING - throw only on warnings. */ public static final int THROW_ON_WARNING = 1; /** * THROW_ON_ERROR - throw only on errors. */ public static final int THROW_ON_ERROR = 2; /** * THROW_ON_FATAL - throw only on fatalErrors - default. */ public static final int THROW_ON_FATAL = 4; /** * THROW_ALWAYS - always throw exceptions. */ public static final int THROW_ALWAYS = THROW_ON_WARNING | THROW_ON_ERROR | THROW_ON_FATAL; /** * If we should throw an exception for each message type. */ protected final int throwWhen; /** * Constructor set when we should re-throw exceptions. * * @param t THROW_WHEN_* constant as to when we should re-throw an exception * when we are called. */ public CheckingErrorListener(int t) { throwWhen = t; } /** * Default constructor will behave as default. Throw only when there is * non-recoverable error. */ public CheckingErrorListener() { this(THROW_ON_FATAL); } /** * Tells us when we should re-throw exceptions. * * @return THROW_WHEN_* constant as to when we should re-throw an exception * when we are called */ public int getThrowWhen() { return throwWhen; } /** * Constant for items returned in getCounters: messages. */ public static final int TYPE_WARNING = 0; /** * Constant for items returned in getCounters: errors. */ public static final int TYPE_ERROR = 1; /** * Constant for items returned in getCounters: fatalErrors. */ public static final int TYPE_FATALERROR = 2; /** * Expected values for events we may handle, default=ITEM_DONT_CARE. */ private final Expectation[] expected = { ITEM_DONT_CARE, /* warning */ ITEM_DONT_CARE, /* error */ ITEM_DONT_CARE /* fatalError */}; /** * Ask us to report checkPass/Fail for certain events we handle. Since we * may have to handle many events between when a test will be able to call * us, testers can set this to have us automatically call checkPass when we * see an item that matches, or to call checkFail when we get an unexpected * item. Generally, we only call check* methods when: * * Note that any time we handle a particular event that was expected, we * un-set the expected value for that item. This means that you can only ask * us to validate one occurrence of any particular event; all events after * that one will be treated as ITEM_DONT_CARE. Callers can of course call * setExpected again, of course, but this covers the case where we handle * multiple events in a single block, perhaps out of the caller's direct * control. Note that we first store the event via setLast(), then we * validate the event as above, and then we potentially re-throw the * exception as by setThrowWhen(). * * @param itemType which of the various types of items we might handle; * should be defined as a constant by subclasses * @param expectation expectation if we need check or not. */ @Override public void setExpected(int itemType, Expectation expectation) { expected[itemType] = expectation; } /** * Reset all items or counters we've handled. */ @Override public void reset() { for (int j = 0; j < expected.length; j++) { expected[j] = ITEM_DONT_CARE; } } /** * Grab basic info out of a TransformerException. Worker method to hide * implementation; currently just calls exception.getMessageAndLocation(). * * @param exception to get information from * @return simple string describing the exception (getMessageAndLocation()) */ public String getTransformerExceptionInfo(TransformerException exception) { if (exception == null) { return ""; // Don't return null, just to make other code here simpler } return exception.getMessageAndLocation(); } /** * Implementation of warning; calls logMsg with info contained in exception. * * @param exception provided by Transformer * @exception TransformerException thrown only if asked to or if loggers are * bad */ @Override public void warning(TransformerException exception) throws TransformerException { // Log or validate the exception if(expected[TYPE_WARNING] == ITEM_CHECKPASS) fail("Unexpected error: ex " + exception); // Also re-throw the exception if asked to if ((throwWhen & THROW_ON_WARNING) == THROW_ON_WARNING) { // Note: re-throw the SAME exception, not a new one! throw exception; } } /** * Implementation of error; calls logMsg with info contained in exception. * Only ever throws an exception itself if asked to or if loggers are bad. * * @param exception provided by Transformer * @exception TransformerException thrown only if asked to. */ @Override public void error(TransformerException exception) throws TransformerException { // validate the exception if(expected[TYPE_ERROR] == ITEM_CHECKPASS) fail("Unexpected error: ex " + exception); // Also re-throw the exception if asked to if ((throwWhen & THROW_ON_ERROR) == THROW_ON_ERROR) { // Note: re-throw the SAME exception, not a new one! throw exception; } } /** * Implementation of error; calls logMsg with info contained in exception. * Only ever throws an exception itself if asked to or if loggers are bad. * Note that this may cause unusual behavior since we may not actually * re-throw the exception, even though it was 'fatal'. * * @param exception provided by Transformer * @exception TransformerException thrown only if asked to. */ @Override public void fatalError(TransformerException exception) throws TransformerException { // validate the exception if(expected[TYPE_FATALERROR] == ITEM_CHECKPASS) fail("Unexpected fatal error: ex " + exception); // Also re-throw the exception if asked to if ((throwWhen & THROW_ON_FATAL) == THROW_ON_FATAL) { // Note: re-throw the SAME exception, not a new one! throw exception; } } }