001/*
002 * Copyright (c) 2009 The openGion Project.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
013 * either express or implied. See the License for the specific language
014 * governing permissions and limitations under the License.
015 */
016package org.opengion.fukurou.xml;
017
018import javax.xml.transform.TransformerException ;
019import javax.xml.transform.ErrorListener;
020import javax.xml.transform.SourceLocator;
021
022import org.xml.sax.ErrorHandler;
023import org.xml.sax.SAXParseException;
024
025import static org.opengion.fukurou.system.HybsConst.CR;
026import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;              // 6.4.2.1 (2016/02/05) refactoring
027
028/**
029 * TransformerFactory、Transformer 等で発生するエラーや警告を補足する ErrorListener の実装クラスです。
030 * さらに、XMLReader 等で発生するエラーや警告を補足する ErrorHandler の実装クラスも兼ねています。
031 *
032 * ErrorListener や、ErrorHandler で捕らえたエラーを、内部の StringBuilder に書き出して、
033 * エラー発生時にその内容を、読み出します。
034 *
035 * TransformerFactory と Transformer に、同じオブジェクトを渡すことで、エラー発生時の
036 * 状況に応じて、メッセージが設定されていきます。
037 * 取り出しは、セットしたオブジェクトを、取り出して、toString() するだけにしています。
038 *
039 * @og.rev 6.4.0.2 (2015/12/11) 新規作成
040 * @og.rev 6.4.3.2 (2016/02/19) 新規作成
041 *
042 * @version  6.4
043 * @author   Kazuhiko Hasegawa
044 * @since    JDK8.0,
045 */
046public class HybsErrorListener implements ErrorListener , ErrorHandler {
047        // 6.4.3.2 (2016/02/19) 最初から用意しておきます。
048        private final StringBuilder errBuf = new StringBuilder( BUFFER_MIDDLE ) ;
049
050        /**
051         * 引数なしのコンストラクタ。
052         *
053         * @og.rev 6.4.3.2 (2016/02/19) 内部の StringBuilder は、最初から用意しておきます。
054         */
055        public HybsErrorListener() { super(); }         // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
056
057        /**
058         * TransformerFactory,Transformer処理の、警告の通知を受け取ります。
059         *
060         * @param       ex Transformer例外にカプセル化されたエラー情報
061         * @see         javax.xml.transform.ErrorListener#warning( TransformerException )
062         */
063        @Override       // ErrorListener
064        public void warning( final TransformerException ex ) { errMsg( "Warning:" , ex ); }
065
066        /**
067         * TransformerFactory,Transformer処理の、回復可能なエラーの通知を受け取ります。
068         *
069         * @param       ex Transformer例外にカプセル化されたエラー情報
070         * @see         javax.xml.transform.ErrorListener#error( TransformerException )
071         */
072        @Override       // ErrorListener
073        public void error( final TransformerException ex ) { errMsg( "Error:" , ex ); }
074
075        /**
076         * TransformerFactory,Transformer処理の、回復できないエラーの通知を受け取ります。
077         *
078         * @param       ex Transformer例外にカプセル化されたエラー情報
079         * @see         javax.xml.transform.ErrorListener#fatalError( TransformerException )
080         */
081        @Override       // ErrorListener
082        public void fatalError( final TransformerException ex ) { errMsg( "Fatal:" , ex ); }
083
084        /**
085         * XML構文解析エラーまたは警告の、警告の通知を受け取ります。
086         *
087         * @param       ex SAXParseException例外にカプセル化されたエラー情報
088         * @see         org.xml.sax.ErrorHandler#warning( SAXParseException )
089         */
090        @Override       // ErrorHandler
091        public void warning( final SAXParseException ex ) { errMsg( "Warning:" , ex ); }
092
093        /**
094         * XML構文解析エラーまたは警告の、回復可能なエラーの通知を受け取ります。
095         *
096         * @param       ex SAXParseException例外にカプセル化されたエラー情報
097         * @see         org.xml.sax.ErrorHandler#error( SAXParseException )
098         */
099        @Override       // ErrorHandler
100        public void error( final SAXParseException ex ) { errMsg( "Error:" , ex ); }
101
102        /**
103         * XML構文解析エラーまたは警告の、回復できないエラーの通知を受け取ります。
104         *
105         * @param       ex SAXParseException例外にカプセル化されたエラー情報
106         * @see         org.xml.sax.ErrorHandler#fatalError( SAXParseException )
107         */
108        @Override       // ErrorHandler
109        public void fatalError( final SAXParseException ex ) { errMsg( "Fatal:" , ex ); }
110
111        /**
112         * warning,error,fatalErrorの通知を受け取ります。
113         *
114         * @param       type 例外の発生元( "Warning:","Error:","Fatal:" )
115         * @param       ex       Transformer例外にカプセル化されたエラー情報
116         */
117        private void errMsg( final String type , final TransformerException ex ) {
118                final SourceLocator locator = ex.getLocator();          // 例外発生元情報の取得
119                if( locator != null ) {
120                        errBuf.append( " (" ).append( locator.getLineNumber() ).append( "): " );
121                }
122
123                final String errMsg = ex.getMessage();
124                // null という文字列が取得されているようです。
125                if( errMsg != null && !"null".equals( errMsg ) ) {
126                        errBuf.append( type ).append( errMsg ).append( CR );
127                }
128
129                Throwable cause = ex.getException();                    // この例外がラップする例外を取得
130                if( cause instanceof TransformerException ) {
131                        errMsg( "ラップ:" , (TransformerException)cause );
132                }
133
134                cause = ex.getCause();                                                  // この例外の原因となる例外を取得
135                if( cause instanceof TransformerException ) {
136                        errMsg( "原因:" , (TransformerException)cause );
137                }
138        }
139
140        /**
141         * warning,error,fatalErrorの通知を受け取ります。
142         *
143         * @param       type 例外の発生元( "Warning:","Error:","Fatal:" )
144         * @param       ex       SAXParseException例外にカプセル化されたエラー情報
145         */
146        private void errMsg( final String type , final SAXParseException ex ) {
147                final int lineNo = ex.getLineNumber();          // 発生元テキストの終わりの行番号(最初は1、使用できない場合は、-1
148                if( lineNo >= 0 ) {
149                        errBuf.append( " (" ).append( lineNo ).append( "): " );
150                }
151
152                final String errMsg = ex.getMessage();
153                // null という文字列が取得されるかどうかは、未確認です。
154                if( errMsg != null && !"null".equals( errMsg ) ) {
155                        errBuf.append( type ).append( errMsg ).append( CR );
156                }
157
158                Throwable cause = ex.getException();                    // この例外がラップする例外を取得
159                if( cause instanceof SAXParseException ) {
160                        errMsg( "ラップ:" , (SAXParseException)cause );
161                }
162
163                cause = ex.getCause();                                                  // この例外の原因となる例外を取得
164                if( cause instanceof SAXParseException ) {
165                        errMsg( "原因:" , (SAXParseException)cause );
166                }
167        }
168
169        /**
170         * 内部で保管しているエラーメッセージを返します。
171         *
172         * メソッド的には、getMessage() がよいのですが、ErrorListener のまま、
173         * オブジェクトとして文字列(メッセージ)を取り出すには、Objectから継承している
174         * toString() メソッドが、便利なので、こちらにしておきます。
175         *
176         * @return      エラーメッセー
177         */
178        @Override       // Object
179        public String toString() { return errBuf.toString(); }
180}