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 org.opengion.fukurou.system.OgRuntimeException ;                         // 6.4.2.0 (2016/01/29)
019import org.opengion.fukurou.system.Closer ;
020import org.opengion.fukurou.system.DateSet;                                                     // 6.4.2.0 (2016/01/29)
021import org.opengion.fukurou.system.LogWriter;
022import org.opengion.fukurou.util.HybsEntry ;
023import org.opengion.fukurou.util.FileUtil ;
024import org.opengion.fukurou.util.StringUtil ;
025import static org.opengion.fukurou.system.HybsConst.CR;                         // 6.1.0.0 (2014/12/26) refactoring
026import static org.opengion.fukurou.system.HybsConst.BUFFER_MIDDLE;      // 6.1.0.0 (2014/12/26) refactoring
027
028import java.io.Reader;
029import java.io.Writer;
030import java.io.File;
031import java.io.IOException;
032import java.io.StringReader;
033
034import javax.xml.transform.TransformerException;
035import javax.xml.transform.TransformerConfigurationException;
036import javax.xml.transform.TransformerFactory;
037import javax.xml.transform.Transformer;
038import javax.xml.transform.stream.StreamSource;
039import javax.xml.transform.stream.StreamResult;
040import javax.xml.transform.ErrorListener;                                                       // 6.4.0.2 (2015/12/11)
041
042/**
043 * XML 入力ファイルに、XSL 入力ファイルを適用して、 XSLT変換を行います。
044 * 結果は、XML 出力ファイルにセーブします。
045 * 各ファイルの代わりに、Writer,Reader を設定することも可能です。
046 *
047 * このパーサーでは、内部で実行中の入力ファイル情報を パラメータとして設定できます。
048 * useFileInfo( true ) とセットすると、以下の4項目が内部的にセットされます。
049 * ただし、この設定が可能なのは、XML 入力ファイルに、Reader ではなく、ファイル名を
050 * 渡した場合のみです。ストリームの場合は、各種情報は取れません。
051 *
052 * 入力ファイル(inXMLのフルパス)     : FILEPATH  (例: G:\webapps\gf\jsp\DOC10\query.jsp)
053 * 入力親フォルダ(inXMLの親フォルダ) : ADDRESS   (例: DOC10)
054 * 入力ファイル(inXMLのファイル名)   : FILENAME  (例: query.jsp)
055 * 入力ファイル(inXMLの更新日付  )   : MODIFIED  (例: yyyyMMddHHmmss形式)
056 *
057 * xsl ファイルでは、パラメータ は、xsl:param で宣言し、xsl:value-of で取り出します。
058 * <xsl:param name="ADDRESS" select="" /> と宣言しておき、必要な箇所で
059 * <xsl:value-of select="$ADDRESS"     /> とすれば、取得できます。
060 *
061 *      String inXSTL  = "inXSLfile.xsl" ;   // 入力XSLファイル
062 *      String outFile = "outXMLfile.xml" ;  // 出力XMLファイル
063 *      String inXML   = "inXMLfile.xml" ;   // 入力XMLファイル
064 *
065 *      XSLT xslt = new XSLT();
066 *      xslt.setXslFile( inXSTL );
067 *      xslt.setOutFile( outFile,false );
068 *
069 *      xslt.transform( inXML );
070 *
071 * @version  4.0
072 * @author   Kazuhiko Hasegawa
073 * @since    JDK5.0,
074 */
075public class XSLT {
076        /** 初期 ENCODE 名 {@value}        */
077        public static final String ENCODE = "UTF-8" ;
078
079        private Transformer transformer ;
080
081        private String          encode          = ENCODE;
082        private String          xmlFile         ;
083        private String          xslFile         ;
084        private String          outFile         ;
085        private Reader          xslReader       ;
086        private Writer          outWriter       ;
087        private HybsEntry[] paramEntry  ;
088        private boolean         isFileInfo      ;
089        private boolean         isErrClose      = true;
090        private boolean         isErrXmlIn      ;                       // useErrXmlIn ⇒ isErrXmlIn 変更
091        private boolean         isInclude       = true;         // 4.2.3.0 (2008/05/26)
092        private StreamResult result             ;
093
094        private String          realPath        ;                       // 5.7.6.2 (2014/05/16) 新規追加
095        private String          debugMsg        ;                       // 5.6.7.1 (2013/08/09) デバッグ用
096
097        /**
098         * 入力XSLファイルを、指定します。
099         *
100         * @param       file    入力XSLファイル
101         * @see #setXslFile( Reader )
102         */
103        public void setXslFile( final String file ) {
104                xslFile = file;
105                setXslFile( FileUtil.getBufferedReader( new File( xslFile ),encode ) );
106        }
107
108        /**
109         * 入力XSLリーダーを、指定します。
110         *
111         * @param       reader  入力XSLリーダー
112         * @see #setXslFile( String )
113         */
114        public void setXslFile( final Reader reader ) {
115                transformer = null;
116                xslReader   = reader;
117        }
118
119        /**
120         * 結果XML ファイル名と、そのオープン方法を指定します。
121         * 結果XML ファイルを、追記する(append=true)か新規作成する(append=false)か指定します。
122         * なお、結果XML ファイル(outFile) を指定しない(=null)か、特別な名称 "System.out"
123         * 文字列を渡すと、標準出力に 結果を出力します。
124         *
125         * @param       file    出力ファイル名(null または、"System.out" 文字列時は、標準出力)
126         * @param append [true]追記する/false:新規作成する]
127         */
128        public void setOutFile( final String file,final boolean append ) {
129                outFile = file ;
130                setOutFile( FileUtil.getPrintWriter( new File( outFile ),encode,append ) );
131        }
132
133        /**
134         * 結果XML データを出力する、Writer を指定します。
135         * ファイル、標準出力、JSPWriter など、必要に応じて Writer を作成してください。
136         * 標準出力(System.out)の場合は、NonClosePrintWriter クラスなどの非close()処理系を、
137         * JSPWriterの場合は、NonFlushPrintWriter クラスなどの非flush()、close()処理系を、
138         * 使用してください。
139         *
140         * @param       writer  出力するWriter
141         */
142        public void setOutFile( final Writer writer ) {
143                Closer.ioClose( outWriter );
144                outWriter = writer ;
145                result = new StreamResult( outWriter );
146        }
147
148        /**
149         * 結果XML ライターに、指定のデータを書き出します。
150         *
151         * @og.rev 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
152         *
153         * @param       outData 書き出すデータ
154         */
155        public void setOutData( final String outData ) {
156                if( outData != null && outData.length() > 0 ) {
157                        // 6.3.9.0 (2015/11/06) コンストラクタで初期化されていないフィールドを null チェックなしで利用している(findbugs)
158                        if( outWriter == null ) {
159                                final String errMsg = "#setOutFile(Writer)を先に実行しておいてください。"      + CR
160                                                                + "   outData =" + outData      + CR;
161                                throw new OgRuntimeException( errMsg );
162                        }
163
164                        try {
165                                outWriter.write( outData );
166                                outWriter.write( CR );
167                        }
168                        catch( final IOException ex ) {
169                                final String errMsg = "ライターにデータ登録を失敗しました。" + CR
170                                                                + ex.getMessage() ;
171                                close();
172                                throw new OgRuntimeException( errMsg,ex );
173                        }
174                }
175        }
176
177        /**
178         * XML ファイルをXSLT変換します。
179         * XML 入力ファイルに、XSL 入力ファイルを適用して、 XSLT変換を行います。
180         * 結果は、XML ファイルにセーブします。
181         * 拡張子が『.jsp』で、かつ、isInclude=true の場合、jsp:directive.include 処理を行います。
182         *
183         * @og.rev 4.2.3.0 (2008/05/26) jsp:directive.include 処理の実施可否を引数指定します。
184         * @og.rev 5.2.1.0 (2010/10/01) JspIncludeReader#getString の第3引数を廃止
185         * @og.rev 5.6.7.1 (2013/08/09) デバッグ用に、ファイルリストを取得しておきます。
186         * @og.rev 5.7.6.2 (2014/05/16) #transform( String , boolean ) 廃止。realPath 追加
187         *
188         * @param       file    入力XMLファイル
189         */
190        public void transform( final String file ) {
191                xmlFile = file;
192
193                if( xmlFile.endsWith( ".jsp" ) && isInclude ) {
194                        // 5.6.7.1 (2013/08/09) デバッグ用に、ファイルリストを取得しておきます。
195                        final JspIncludeReader incReader = new JspIncludeReader();
196                        incReader.setRealPath( realPath );                              // 5.7.6.2 (2014/05/16) realPath 追加
197                        debugMsg = incReader.getIncludeFiles();
198
199                        final String incData = incReader.getString( new File( xmlFile ),encode );                               // 5.2.1.0 (2010/10/01)
200                        transform( new StringReader( incData ) );
201                }
202                else {
203                        transform( FileUtil.getBufferedReader( new File( xmlFile ),encode ) );
204                }
205        }
206
207        /**
208         * XML ファイルをXSLT変換します。
209         * XML 入力リーダーに、XSL 入力リーダーを適用して、 XSLT変換を行います。
210         * 結果は、XML ライターに書き出します。
211         * この処理の終了後に、入力XML リーダー は、close() されます。
212         *
213         * @og.rev 5.6.5.2 (2013/06/21) エラーメッセージが判りにくいので、追記します。
214         * @og.rev 5.6.7.1 (2013/08/09) デバッグ用に、ファイルリストを出力します。
215         * @og.rev 6.4.0.2 (2015/12/11) Transformer のエラーを、より詳細に出力します。
216         *
217         * @param       xmlReader       入力XML リーダー
218         * @see #transform( String )
219         */
220        public void transform( final Reader xmlReader ) {
221                HybsEntry[] entry = null;
222
223                // transformer は使いまわしますが、ErrorListener は、Reader 毎に再作成します。
224                final ErrorListener errListener = new HybsErrorListener();                      // 6.4.0.2 (2015/12/11)
225                try {
226                        if( transformer == null ) {
227                                init( errListener );                                                                            // 6.4.0.2 (2015/12/11)
228                        }
229                        else {
230                                transformer.reset();
231                                transformer.setErrorListener( errListener );                            // 6.4.0.2 (2015/12/11)
232                        }
233
234                        // 入力XMLファイルのファイル情報を設定します。
235                        if( isFileInfo && xmlFile != null ) {
236                                entry = getXmlParameter( xmlFile );
237                                parameterSet( transformer,entry );
238                        }
239                        xmlFile = null ;
240
241                        // 入力XMLリーダーからStreamSourceを作る
242                        final StreamSource data = new StreamSource( xmlReader );
243
244                        transformer.transform( data,result );
245                }
246                catch( final TransformerException ex ) {
247                        // 5.7.3.0 (2014/02/07) エラー情報をもう少し詳細に取得します。
248        //              final String errMsg = ex.getMessageAndLocation() ;
249                        final String errMsg = errListener.toString();                                   // 6.4.0.2 (2015/12/11) さらに詳細に出します。
250
251                        final StringBuilder errBuf = new StringBuilder( BUFFER_MIDDLE )
252                                .append( "=====================================================" ).append( CR )
253                                .append( "XML-XSLT 変換に失敗しました。" ).append( CR )
254                                .append( errMsg );
255
256                        // 6.3.1.0 (2015/06/28) デバッグ用メッセージを出力します。
257                        if( debugMsg != null && debugMsg.length() > 0 ) {
258                                errBuf.append( CR ).append( debugMsg );
259                        }
260
261                        // 5.6.5.2 (2013/06/21) エラーメッセージが判りにくいので、追記します。
262                        if( errMsg.indexOf( "プロローグにはコンテンツを指定できません" ) >= 0 ) {
263                                errBuf.append( CR ).append( "\t(UTF-8変換時に、BOMが付くとこのエラーが出ます。BOMを外してみてください。)" );
264                        }
265
266                        // 5.6.7.1 (2013/08/09) デバッグ用に、ファイルリストを出力します。
267                        if( errMsg.indexOf( "で終了する必要があります" ) >= 0 ) {
268                                errBuf.append( CR ).append( "\t(不整合は、includeファイルの可能性があります。)" );
269                        }
270                        errBuf.append( CR );
271
272                        if( isErrXmlIn ) { setOutData( toXmlRow( entry, ex ) ); }
273
274                        if( isErrClose ) { close(); }
275                        throw new OgRuntimeException( errBuf.toString(),ex );
276                }
277                finally {
278                        Closer.ioClose( xmlReader );
279                }
280        }
281
282        /**
283         * Transformer オブジェクトに対して、Parameter を設定します。
284         *
285         * 指定されたパラメーターキーは、xsl ファイルでは、xsl:param で宣言し、
286         * xsl:value-of で取り出します。
287         * <xsl:param name="ADDRESS" select="" /> と宣言しておき、必要な箇所で
288         * <xsl:value-of select="$ADDRESS"     /> とすれば、取得できます。
289         *
290         * @param       entry   HybsEntry配列(可変長引数)
291         */
292        public void setParamEntry( final HybsEntry... entry ) {
293                if( entry != null && entry.length > 0 ) {               // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。
294                        paramEntry = new HybsEntry[entry.length];
295                        System.arraycopy( entry,0,paramEntry,0,entry.length );
296                }
297        }
298
299        /**
300         * transform 処理中にエラーが発生した場合に、出力ファイルを閉じるかどうかを指定します。
301         *
302         * 処理途中でエラーが発生した場合に、そこで処理を中断するか、それとも、
303         * 無視して、さらに処理を進めるかを指定することが可能です。
304         * 継続して処理を進めたい場合は、出力ファイルを閉じないため、false を
305         * 設定します。ただし、エラー時には、RuntimeException は throw されます。
306         * 初期値は、true(閉じる)です。
307         *
308         * @param       flag    エラー時クローズ [true:閉じる/false:閉じない]
309         */
310        public void errClose( final boolean flag ) {
311                isErrClose = flag ;
312        }
313
314        /**
315         * transform 処理中エラーを、出力ファイルに、XML形式でエラーを追記するかどうかを指定します。
316         *
317         * 処理途中でエラーが発生した場合に、ログだけではなく、結果XMLファイルに、
318         * エラー内容や、エラーファイルなどを埋め込むと、XMLファイルとしてDB登録や、
319         * その他集計等に使えます。
320         * 今は、GE70 スキーマ形式のファイルしか作成できません。
321         * これは、#errClose( boolean ) メソッドと共に使用すると効果的です。
322         * つまり、errClose = false; にして、エラー時でも出力ファイルを閉じずに、
323         * 処理を続ける事で、エラーメッセージもXMLファイルとして蓄積できます。
324         * 初期値は、false(使用しない)です。
325         *
326         * @param       flag    エラー時XML形式 [false:使用しない/true:使用する]
327         */
328        public void useErrXmlIn( final boolean flag ) {
329                isErrXmlIn = flag ;
330        }
331
332        /**
333         * jsp:directive.include 発見時に、そのファイルを INCLUDE するかを指定するかどうかを指定します(初期値:true:使用する)
334         *
335         * 引数の処理対象ファイル(transformの引数ファイル)が、『.jsp』の場合、
336         * jsp:directive.include 発見時に、そのファイルを INCLUDE するかを指定するか
337         * どうかを指定します。
338         * インクルードされたファイルとあわせて、正規のXML にならないと、パーサー
339         * エラーが発生します。
340         * JSPソース解析を行うには、INCLUDE ファイルも考慮しないと正確な結果を
341         * 得られませんが、INCLUDE 先のファイルまで合わせる必要があるため、
342         * 場合によっては、INCLUDEファイルを無視しなければならないケースがあります。
343         * 初期値は、true(使用する)です。
344         *
345         * @param       flag    エラー時XML形式 [false:使用しない/true:使用する]
346         */
347        public void jspInclude( final boolean flag ) {
348                isInclude = flag ;
349        }
350
351        /**
352         * jspInclude=true 時に、/jsp/common/** 等の include ファイルが存在しない場合の共有取得場所を指定します。
353         *
354         * 引数の処理対象ファイル(transformの引数ファイル)が、『.jsp』で、かつ、jspInclude=true の場合、
355         * そのファイルを INCLUDE するのですが、/jsp/common/** 等の include ファイルは、
356         * エンジン共通として、jspCommon6.x.x.x.jar で提供しています。
357         * 従来は、処理対象jspの相対パスで、../../../gf/jsp/commom/** を取り込んでいましたが、
358         * Tomcat起動フォルダ以外のシステムのJSPチェックなどを行う場合は、gf フォルダが存在しない
359         * ケースがあります。
360         * そこで、確実にgf が存在する、処理をキックしている環境の gf を使用するように変更します。
361         * その環境とは、つまり、エンジン内部変数の REAL_PATH ですが、jsp などが実行していないと取得できません。
362         *
363         * @param       path    /jsp/common/** 等の include ファイルの共有取得場所
364         */
365        public void setRealPath( final String path ) {
366                realPath = path ;
367        }
368
369        /**
370         * 入力XSLファイルのストリームを閉じます。
371         *
372         * @og.rev 5.6.7.1 (2013/08/09) includeしたファイルのキャッシュをクリアします。
373         */
374        public void close() {
375                Closer.ioClose( outWriter );
376
377                // 5.6.7.1 (2013/08/09) includeしたファイルのキャッシュをクリア
378                JspIncludeReader.cacheClear();
379        }
380
381        /**
382         * XML ファイルをXSLT変換します。
383         * XML 入力ファイルに、XSL 入力ファイルを適用して、 XSLT変換を行います。
384         * 結果は、XML ファイルにセーブします。
385         * なお、結果XML ファイル(outFile) に、特別な名称 "System.out" 文字列を渡すと、
386         * 標準出力に 結果を出力します。
387         *
388         * @og.rev 5.6.7.1 (2013/08/09) includeしたファイルのキャッシュをクリアします。
389         * @og.rev 6.4.0.2 (2015/12/11) Transformer のエラーを、より詳細に出力します。
390         *
391         * @param       errListener ErrorListenerオブジェクト
392         */
393        private void init( final ErrorListener errListener ) {
394                try {
395                        // xsl属性からStreamSourceを作る
396                        final StreamSource style = new StreamSource( xslReader );
397
398                        // Transformerを作り、XMLを変換する
399                        final TransformerFactory tFactory = TransformerFactory.newInstance();
400
401                        // 6.4.0.2 (2015/12/11) Transformer のエラーを、より詳細に出力します。
402                        tFactory.setErrorListener( errListener );
403
404                        transformer = tFactory.newTransformer( style );
405                        // 6.4.0.2 (2015/12/11) Transformer のエラーを、より詳細に出力します。
406                        transformer.setErrorListener( errListener );
407
408                        parameterSet( transformer,paramEntry );
409
410                        // 5.6.7.1 (2013/08/09) includeしたファイルのキャッシュをクリア
411                        JspIncludeReader.cacheClear();
412                }
413                catch( final TransformerConfigurationException ex ) {
414                        final String errMsg = xslFile + "ファイルの XSLT 解析に失敗しました。" + CR
415        //                                                      + ex.getMessageAndLocation()    // 6.4.0.2 (2015/12/11) 行番号がうまく取り出せない。
416                                                                + errListener.toString();               // 6.4.0.2 (2015/12/11) エラー内容が重複するかも。
417                        throw new OgRuntimeException( errMsg,ex );
418                }
419                finally {
420                        Closer.ioClose( xslReader );
421                        xslReader = null;
422                }
423        }
424
425        /**
426         * 実行中の入力ファイル名などの属性情報を パラメータとして設定するかどうかを指定します。
427         *
428         * このパーサーでは、内部で実行中の入力ファイル情報を パラメータとして設定できます。
429         * useFileInfo( true ) とセットすると、以下の4項目が内部的にセットされます。
430         *
431         * 入力ファイル(inXMLのフルパス)     : FILEPATH  (例: G:\webapps\gf\jsp\DOC10\query.jsp)
432         * 入力親フォルダ(inXMLの親フォルダ) : ADDRESS   (例: DOC10)
433         * 入力ファイル(inXMLのファイル名)   : FILENAME  (例: query.jsp)
434         * 入力ファイル(inXMLの更新日付  )   : MODIFIED  (例: yyyyMMddHHmmss形式)
435         *
436         * @og.rev 4.0.0.0 (2007/09/25) ParameterMetaData を使用したパラメータ設定追加。
437         * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。
438         *
439         * xsl ファイルでは、xsl:param で宣言し、xsl:value-of で取り出します。
440         * <xsl:param name="ADDRESS" select="" /> と宣言しておき、必要な箇所で
441         * <xsl:value-of select="$ADDRESS"     /> とすれば、取得できます。
442         *
443         * 初期値は、false(セットしない) です。
444         *
445         * @param       flag    セットする:true/セットしない:false
446         */
447        public void useFileInfo( final boolean flag ) {
448                isFileInfo = flag;
449        }
450
451        /**
452         * ファイル名指定で XML,XSL,OUTファイルを指定する場合のエンコードを指定します。
453         *
454         * 初期値は、UTF-8 です。
455         *
456         * @param       encode  エンコード
457         */
458        public void useEncode( final String encode ) {
459                this.encode = encode;
460        }
461
462        /**
463         * 実行中の入力ファイル名などの属性情報を パラメータとして取得します。
464         *
465         * 入力ファイル(inXMLのフルパス)     : FILEPATH  (例: G:\webapps\gf\jsp\DOC10\query.jsp)
466         * 入力ファイル(inXMLのファイル名)   : FILENAME  (例: query.jsp)
467         * 入力親フォルダ(inXMLの親フォルダ) : ADDRESS   (例: DOC10)
468         * 入力ファイル(inXMLの更新日付  )   : MODIFIED  (例: yyyyMMddHHmmss形式)
469         *
470         * @og.rev 5.5.7.2 (2012/10/09) HybsDateUtil を利用するように修正します。
471         *
472         * @param       xmlIn   XML入力ファイル
473         *
474         * @return      HybsEntry配列
475         */
476        private HybsEntry[] getXmlParameter( final String xmlIn ) {
477                HybsEntry[] entry = new HybsEntry[4] ;
478
479                entry[0] = new HybsEntry( "FILEPATH" , xmlIn) ;
480
481                final File xmlFile = new File( xmlIn );
482                entry[1] = new HybsEntry( "FILENAME" , xmlFile.getName()) ;
483
484                final File parentFile = xmlFile.getParentFile() ;
485                // 6.4.1.1 (2016/01/16) PMD refactoring. Avoid if (x != y) ..; else ..;
486                entry[2] = parentFile == null
487                                                ? new HybsEntry( "ADDRESS"  , "" )
488                                                : new HybsEntry( "ADDRESS"  , parentFile.getName()) ;
489
490                final String lastDate = DateSet.getDate( xmlFile.lastModified() , "yyyyMMddHHmmss" ) ;          // 5.5.7.2 (2012/10/09) HybsDateUtil を利用
491                entry[3] = new HybsEntry( "MODIFIED" , lastDate ) ;
492
493                return entry ;
494        }
495
496        /**
497         * Transformer オブジェクト に、パラメータを設定します。
498         *
499         * 指定されたパラメーターキーは、xsl ファイルでは、xsl:param で宣言し、
500         * xsl:value-of で取り出します。
501         * <xsl:param name="ADDRESS" select="" /> と宣言しておき、必要な箇所で
502         * <xsl:value-of select="$ADDRESS"     /> とすれば、取得できます。
503         *
504         * @param former Transformerオブジェクト
505         * @param entry  パラメータ配列(可変長引数)
506         */
507        private void parameterSet( final Transformer former,final HybsEntry... entry ) {
508                if( entry != null && entry.length > 0 ) {               // 6.1.1.0 (2015/01/17) 可変長引数でもnullは来る。
509                        final int size   = entry.length;
510                        for( int i=0; i<size; i++ ) {
511                                final String key = entry[i].getKey() ;
512                                final String val = entry[i].getValue();
513                                former.setParameter( key , val );
514                        }
515                }
516        }
517
518        /**
519         * このオブジェクトの内部文字列表現を返します。
520         *
521         * 接続URL + "," + 接続ユーザー + " (" + 作成日付 + ")" です。
522         *
523         * @return 内部文字列表現
524         * @og.rtnNotNull
525         */
526        @Override
527        public String toString() {
528                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE )
529                        .append( "XSL File:" ).append( xslFile ).append( CR )
530                        .append( "XML File:" ).append( xmlFile ).append( CR )
531                        .append( "OUT File:" ).append( outFile ).append( CR );
532
533                return buf.toString() ;
534        }
535
536        /**
537         * エラー情報の内部XML文字列表現を返します。
538         *
539         * エラー時の情報も、XML化して保存する為の簡易処理。
540         * ここでは、XMLスキーマは、固定で、GF70 の形式になります。
541         *
542         * @og.rev 4.2.3.0 (2008/05/26) エラー発生時のXMLファイルを追加します。
543         * @og.rev 5.2.1.0 (2010/10/01) XML形式を変更します。(TEXT⇒TEXT_DATA)
544         *
545         * @param       entry   HybsEntry配列
546         * @param       ex              エラー情報
547         *
548         * @return XMLの部分文字列
549         * @og.rtnNotNull
550         */
551        private String toXmlRow( final HybsEntry[] entry,final TransformerException ex ) {
552                final StringBuilder buf = new StringBuilder( BUFFER_MIDDLE );
553
554                // 6.0.2.5 (2014/10/31) char を append する。
555                buf.append( "<ROW>" ).append( CR );
556                if( paramEntry != null ) {
557                        for( int i=0; i<paramEntry.length; i++ ) {
558                                final String key = paramEntry[i].getKey() ;
559                                final String val = paramEntry[i].getValue();
560                                buf.append( "  <" ).append( key ).append( '>' )
561                                        .append( val )
562                                        .append( "</" ).append( key ).append( '>' )
563                                        .append( CR );
564                        }
565                }
566
567                if( entry != null ) {
568                        for( int i=0; i<entry.length; i++ ) {
569                                final String key = entry[i].getKey() ;
570                                final String val = entry[i].getValue();
571                                buf.append( "  <" ).append( key ).append( '>' )
572                                        .append( val )
573                                        .append( "</" ).append( key ).append( '>' )
574                                        .append( CR );
575                        }
576                }
577
578                buf.append( "  <TAGNAME />" ).append( CR )
579                        .append( "  <MSGCD>XML_ERROR</MSGCD>" ).append( CR )
580                        .append( "  <MSGTXT>XML-XSLT 変換に失敗しました。</MSGTXT>" ).append( CR );
581
582                String errMsg = StringUtil.htmlFilter( ex.getMessage() );
583                final int indx = errMsg.lastIndexOf( "Exception:" );
584                if( indx >= 0 ) {
585                        errMsg = errMsg.substring( indx + "Exception:".length() );
586                }
587                buf.append( "  <TEXT_DATA>" ).append( errMsg ).append( CR )             // 5.2.1.0 (2010/10/01)
588                        .append( " Location:" ).append( ex.getLocationAsString() ).append( CR )
589                        .append( "</TEXT_DATA>" ).append( CR )          // 5.2.1.0 (2010/10/01)
590                        .append( "</ROW>" ).append( CR );
591
592                return buf.toString() ;
593
594/*
595           <ROW>
596                 <SYSTEM_ID>  </SYSTEM_ID>
597                 <ADDRESS  >  </ADDRESS>
598                 <FILENAME >  </FILENAME>
599                 <FILEPATH >  </FILEPATH>
600                 <MODIFIED >  </MODIFIED>
601                 <TAGNAME  >  </TAGNAME>
602                 <MSGCD    >  </MSGCD>
603                 <MSGTXT   >  </MSGTXT>
604                 <TEXT_DATA>  </TEXT_DATA>
605           </ROW>
606*/
607        }
608
609        /**
610         * テスト用のメインメソッド。
611         *
612         * java org.opengion.fukurou.xml.XSLT in_xml in_xsl out_xml
613         *
614         * @param       args    コマンド引数配列
615         * @throws IOException 入出力エラーが発生した場合
616         */
617        public static void main( final String[] args ) throws IOException {
618                if( args.length != 3 ) {
619                        LogWriter.log( "Usage: java org.opengion.fukurou.xml.XSLT in_xml in_xsl out_xml" );
620                        LogWriter.log( "  XML 入力ファイルに、XSL 入力ファイルを適用して、" );
621                        LogWriter.log( "  XSLT変換を行います。" );
622                        LogWriter.log( "  結果は、XML ファイルにセーブします。" );
623                        LogWriter.log( "  out_xml に System.out を指定すると標準出力に出力します。" );
624                        return ;
625                }
626
627                final XSLT xslt = new XSLT();
628                xslt.setXslFile( args[1] );
629                xslt.setOutFile( args[2],false );
630                xslt.transform( args[0] );
631                xslt.close();
632        }
633}