001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.components.xslt;
018:
019: import javax.xml.transform.ErrorListener;
020: import javax.xml.transform.TransformerException;
021:
022: import org.apache.avalon.framework.logger.Logger;
023: import org.apache.cocoon.util.location.Location;
024: import org.apache.cocoon.util.location.LocationUtils;
025:
026: /**
027: * A smart error listener for <code>javax.xml.tranform</code> that does its best to provide
028: * useful error messages.
029: *
030: * @version $Id: TraxErrorListener.java 433543 2006-08-22 06:22:54Z crossley $
031: * @since 2.1.8
032: */
033: public class TraxErrorListener implements ErrorListener {
034:
035: private Logger logger;
036: private String uri;
037:
038: /** The exception we had from warning() */
039: private TransformerException warningEx;
040:
041: /** The exception we had from error() or fatalError() */
042: private TransformerException exception;
043:
044: public TraxErrorListener(Logger logger, String uri) {
045: this .logger = logger;
046: this .uri = uri;
047: }
048:
049: /**
050: * Get the exception that was catched by this listener, if any.
051: *
052: * @return the exception
053: */
054: public Throwable getThrowable() {
055: if (exception == null) {
056: return null;
057: }
058:
059: Location loc = LocationUtils.getLocation(exception);
060: if (LocationUtils.isKnown(loc)) {
061: // Has a location: don't loose this precious information!
062: return exception;
063: }
064:
065: // No location: if it's just a wrapper, consider only the wrapped exception
066: if (exception.getCause() != null) {
067: return exception.getCause();
068: }
069:
070: // That's the actual exception!
071: return exception;
072: }
073:
074: public void warning(TransformerException ex)
075: throws TransformerException {
076: // TODO: We may want here to allow some special formatting of the messages, such as
077: // "DEBUG:A debug message" or "INFO:Transforming <foo> in mode 'bar'" to use the different
078: // log levels. This can include also deprecation logs for system-defined stylesheets
079: // using "DEPRECATED:WARN:Styling 'foo' is replaced by 'bar'".
080:
081: if (logger.isWarnEnabled()) {
082: Location loc = LocationUtils.getLocation(ex);
083: logger.warn(ex.getMessage() + " at " + loc == null ? uri
084: : loc.toString());
085: }
086: // Keep the warning (see below)
087: warningEx = ex;
088: }
089:
090: public void error(TransformerException ex)
091: throws TransformerException {
092:
093: // If we had a warning previoulsy, and the current exception has no cause, then use the warning.
094: // This is how Xalan behaves on <xsl:message terminate="yes">: it first issues a warning with all
095: // the useful information, then a useless "stylesheed directed termination" error.
096: if (warningEx != null && ex.getCause() == null) {
097: ex = warningEx;
098: }
099: warningEx = null;
100:
101: // Keep the exception for later use.
102: exception = ex;
103: // and rethrow it
104: throw ex;
105: }
106:
107: public void fatalError(TransformerException ex)
108: throws TransformerException {
109: if (warningEx != null && ex.getCause() == null) {
110: ex = warningEx;
111: }
112: warningEx = null;
113:
114: exception = ex;
115: throw ex;
116: }
117: }
|