/*
* Copyright (c) 2015, 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.xsl;
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;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* Cheap-o ErrorHandler for use by API tests.
*/
public class CheckingSAXErrorHandler implements CheckingHandler, ErrorHandler {
/**
* Constants determining when we should throw exceptions.
*
Flags are combineable like a bitfield.
* - THROW_NEVER - never ever (always continue - note this may have
* unexpected effects when fatalErrors happen, see
* {@link javax.xml.transform.ErrorListener#fatalError(javax.xml.transform.TransformerException)}
* - THROW_ON_WARNING - throw only on warnings
* - THROW_ON_ERROR - throw only on errors
* - THROW_ON_FATAL - throw only on fatalErrors - default
* - THROW_ALWAYS - always 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.
*/
private 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 CheckingSAXErrorHandler(int t) {
throwWhen = t;
}
/**
* Default constructor will behave as default. Throw only when there is
* non-recoverable error.
*/
public CheckingSAXErrorHandler() {
this.throwWhen = 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:
*
* - containsString is not set, reset, or is ITEM_DONT_CARE, we do nothing
* (i.e. never call check* for this item)
* - containsString is ITEM_CHECKFAIL, we will always call checkFail with
* the contents of any item if it occurs
* - containsString is anything else, we will grab a String representation
* of every item of that type that comes along, and if the containsString is
* found, case-sensitive, within the handled item's string, call checkPass,
* otherwise call checkFail
*
* 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;
}
}
/**
* Receive notification of a warning. fail the test if it expects pass.
* Re-throw the exception when re-throw flag is set.
* @param exception The error information encapsulated in a
* SAX parse exception.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
*/
@Override
public void warning(SAXParseException exception) throws SAXException {
// 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;
}
}
/**
* Receive notification of a recoverable error. fail the test if it expects
* pass. Re-throw the exception when re-throw flag is set.
* @param exception The error information encapsulated in a
* SAX parse exception.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
*/
@Override
public void error(SAXParseException exception) throws SAXException {
// 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_ERROR) == THROW_ON_ERROR) {
// Note: re-throw the SAME exception, not a new one!
throw exception;
}
}
/**
* Receive notification of a non-recoverable error. fail the test if it
* expects pass. Re-throw the exception when re-throw flag is set.
* @param exception The error information encapsulated in a
* SAX parse exception.
* @exception org.xml.sax.SAXException Any SAX exception, possibly
* wrapping another exception.
*/
@Override
public void fatalError(SAXParseException exception) throws SAXException {
// validate the exception
if (expected[TYPE_ERROR] == 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;
}
}
}