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     */
016    package org.opengion.fukurou.xml;
017    
018    import org.opengion.fukurou.util.Closer ;
019    import org.opengion.fukurou.util.FileUtil ;
020    
021    import java.io.PrintWriter ;
022    import java.io.BufferedWriter ;
023    import java.io.OutputStreamWriter ;
024    import java.io.FileOutputStream ;
025    import java.io.IOException ;
026    import java.io.File;
027    import java.io.StringReader ;
028    import java.io.FileNotFoundException ;
029    import java.io.UnsupportedEncodingException;
030    import java.util.Stack;
031    import java.util.List;
032    import java.util.ArrayList;
033    import java.util.Map;
034    import java.util.HashMap;
035    
036    import org.xml.sax.Attributes;
037    import org.xml.sax.ext.DefaultHandler2;
038    import org.xml.sax.InputSource ;
039    import org.xml.sax.SAXException;
040    import org.xml.sax.SAXParseException;
041    import javax.xml.parsers.SAXParserFactory;
042    import javax.xml.parsers.SAXParser;
043    import javax.xml.parsers.ParserConfigurationException;
044    
045    /**
046     * JSP/XMLファイルを読み取って、OGNode/OGElement オブジェクトを取得する?パ?サークラスです?
047     *
048     * 自??身が?DefaultHandler2 を拡張して?す?で、パーサー本体になります?
049     * javax.xml.parsers および、org.w3c.dom の簡易??行います?
050     * read で、ト??レベルの OGNode を読み込み、write で、ファイルに書き?します?
051     * 通常の W3C 系の オブジェクトを利用しな??は、属?の並び?保障するためです?
052     * ただし?属?のタブ?改行?失われます?
053     * また?属?値に含まれるCR(復帰), LF(改?, TAB(タ?は?半角スペ?スに置き換えられます?
054     * これは、SAXParser 側での XML の仕様?関係で、属?は、正規化されるためです?
055     *
056     * @og.rev 5.1.8.0 (2010/07/01) 新規作?
057     * @og.rev 5.1.9.0 (2010/08/01) static メソ?を?。?常のオブジェクトクラスとして扱?す?
058     *
059     * @version  5.0
060     * @author   Kazuhiko Hasegawa
061     * @since    JDK6.0,
062     */
063    public class JspSaxParser extends DefaultHandler2 {
064            public static final String CR = System.getProperty("line.separator");
065    
066            private final List<JspParserFilter> filters = new ArrayList<JspParserFilter>();     // 5.1.9.0 (2010/08/01)
067            private SAXParser parser = null;
068    
069            // 以下?パ?ス時に使用する変数?パ?ス毎に初期化する?)
070            private Map<String,OGElement> idMap = null;               // 5.1.9.0 (2010/08/01)
071            private Stack<OGNode>               stack = null;
072    
073            private OGNode  ele                     = null;         // 現時点のエレメントノー?
074            private String  attTab          = "";           // tagBefore の?TEMP
075            private boolean inCDATA         = false;        // CDATA エレメント?中かど?の判?
076            private boolean inEntity        = false;        // Entity の中かど?の判?
077    //      private File    file            = null;         // 処?行中のファイル?
078            private String  filename        = null;         // 処?行中のファイル?
079    
080            /**
081             * XMLファイルを読み込み、OGDocument を返します?
082             *
083             * ??は、SAXParserFactory から、SAXParser を構築し、Property に?
084             * http://xml.org/sax/properties/lexical-handler を設定して?す?
085             * コメントノードを処?るためです?
086             *
087             * @og.rev 5.1.9.0 (2010/08/01) static からノ?マルに変更
088             *
089             * @param       aFile   XMLファイル
090             *
091             * @return      ファイルから読み取って構築したOGDocumentオブジェク?
092             */
093            public OGDocument read( final File aFile ) {
094    
095    //              JspSaxParser sxp = new JspSaxParser();
096    //              sxp.setFile( aFile );
097                    filename = aFile.getAbsolutePath() ;
098    
099                    try {
100                            if( parser == null ) {
101                                    // SAXパ?サーファクトリを生?
102                                    SAXParserFactory spfactory = SAXParserFactory.newInstance();
103    
104                                    // SAXパ?サーを生?
105                                    parser = spfactory.newSAXParser();
106    
107                                    parser.setProperty("http://xml.org/sax/properties/lexical-handler", this);      // LexicalHandler として
108                            }
109                            // XMLファイルを指定されたハンドラーで処?ま?
110                            parser.parse( aFile, this );
111    
112                    } catch ( ParserConfigurationException ex ) {
113                            String errMsg = "重大な構?エラーが発生しました?
114                                            + CR + "\t" + ex.getMessage()
115                                            + CR + "\t" + aFile ;
116                            throw new RuntimeException( errMsg,ex );
117            //      5.1.9.0 (2010/08/01) ?
118            //      } catch ( SAXNotRecognizedException ex ) {
119            //              String errMsg = "XMLReader は、認識されな??また?プロパティー識別子を検?しました?
120            //                              + CR + "\t" + ex.getMessage()
121            //                              + CR + "\t" + aFile ;
122            //              if( ex2 != null ) { errMsg = errMsg + CR + "\t" + ex2.getMessage(); }
123            //              throw new RuntimeException( errMsg,ex );
124            //      } catch ( SAXNotSupportedException ex ) {
125            //              String errMsg = "XMLReader は、要求された操?(状態また?値の設? を実行できませんでした?
126            //                              + CR + "\t" + ex.getMessage()
127            //                              + CR + "\t" + aFile ;
128            //              if( ex2 != null ) { errMsg = errMsg + CR + "\t" + ex2.getMessage(); }
129            //              throw new RuntimeException( errMsg,ex );
130                    } catch ( SAXException ex ) {
131                            String errMsg = "SAX の??エラーが発生しました?
132                                            + CR + "\t" + ex.getMessage()
133                                            + CR + "\t" + aFile ;
134                            Exception ex2 = ex.getException();
135                            if( ex2 != null ) { errMsg = errMsg + CR + "\t" + ex2.getMessage(); }
136                            throw new RuntimeException( errMsg,ex );
137                    } catch ( IOException ex ) {
138                            String errMsg = "ファイル読取時にエラーが発生しました?
139                                            + CR + "\t" + ex.getMessage()
140                                            + CR + "\t" + aFile ;
141                            throw new RuntimeException( errMsg,ex );
142            //      5.1.9.0 (2010/08/01) ?
143            //      } catch( RuntimeException ex ) {
144            //              String errMsg = "実行時エラーが発生しました?
145            //                              + CR + "\t" + ex.getMessage()
146            //                              + CR + "\t" + aFile ;
147            //              throw new RuntimeException( errMsg,ex );
148                    }
149    
150                    return getDocument() ;
151            }
152    
153            /**
154             * XML形式で表現された???(String) から、OGDocument を構築します?
155             *
156             * 処?には?read( File ) と同じで、取り?す?が???と??です?
157             * XMLファイルからの読み込みと異なり?通常は、Element を表現した??が作?されますが?
158             * 返されるのは、OGDocument オブジェクトです?
159             *
160             * @og.rev 5.1.9.0 (2010/08/01) static からノ?マルに変更
161             *
162             * @param       str     XML形式で表現された文字?
163             *
164             * @return      ファイルから読み取って構築し?OGDocumentオブジェク?
165             */
166            public OGDocument string2Node( final String str ) {
167    
168    //              JspSaxParser sxp = new JspSaxParser();
169                    filename = null ;
170    
171                    try {
172                            if( parser == null ) {
173                                    // SAXパ?サーファクトリを生?
174                                    SAXParserFactory spfactory = SAXParserFactory.newInstance();
175                                    // SAXパ?サーを生?
176                                    parser = spfactory.newSAXParser();
177    
178                                    parser.setProperty("http://xml.org/sax/properties/lexical-handler", this);      // LexicalHandler として
179                            }
180    
181                            // XMLファイルを指定された?ォルトハンドラーで処?ま?
182                            InputSource source = new InputSource( new StringReader( str ) );
183                            parser.parse( source, this );
184    
185                    } catch ( ParserConfigurationException ex ) {
186                            String errMsg = "重大な構?エラーが発生しました?
187                                            + CR + ex.getMessage();
188                            throw new RuntimeException( errMsg,ex );
189            //      5.1.9.0 (2010/08/01) ?
190            //      } catch ( SAXNotRecognizedException ex ) {
191            //              String errMsg = "XMLReader は、認識されな??また?プロパティー識別子を検?しました?
192            //                              + CR + ex.getMessage();
193            //              Exception ex2 = ex.getException();
194            //              if( ex2 != null ) { errMsg = errMsg + CR + "\t" + ex2.getMessage(); }
195            //              throw new RuntimeException( errMsg,ex );
196                    } catch ( SAXException ex ) {
197                            String errMsg = "SAX の??エラーが発生しました?
198                                            + CR + ex.getMessage();
199                            Exception ex2 = ex.getException();
200                            if( ex2 != null ) { errMsg = errMsg + CR + "\t" + ex2.getMessage(); }
201                            throw new RuntimeException( errMsg,ex );
202                    } catch ( IOException ex ) {
203                            String errMsg = "ストリー?ブジェクト作?時にエラーが発生しました?
204                                            + CR + ex.getMessage();
205                            throw new RuntimeException( errMsg,ex );
206            //      5.1.9.0 (2010/08/01) ?
207            //      } catch( RuntimeException ex ) {
208            //              String errMsg = "実行時エラーが発生しました?
209            //                              + CR + ex.getMessage();
210            //              throw new RuntimeException( errMsg,ex );
211                    }
212    
213                    return getDocument() ;
214            }
215    
216            /**
217             * OGDocument を所定?ファイルに、XML形式で書き?します?
218             *
219             * ここでは、UTF-8 ?コードでの書き?しです?
220             *
221             * @og.rev 5.1.9.0 (2010/08/01) static からノ?マルに変更
222             *
223             * @param       aFile   書き?すファイル
224             * @param       node    書き??OGDocument
225             */
226    //      public void write( final File aFile, final OGDocument node ) {
227    //              write( aFile,node,"UTF-8" );
228    //      }
229    
230            /**
231             * OGDocument を所定?ファイルに、XML形式で書き?します?
232             *
233             * @param       aFile   書き?すファイル
234             * @param       node    書き??OGDocument
235             */
236            public void write( final File aFile, final OGDocument node ) {
237                    PrintWriter out    = null;
238                    String      encode = node.getEncode();
239                    try {
240                            out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( new FileOutputStream(aFile),encode )));
241    //                      out.println( "<?xml version=\"1.0\" encoding=\"" + encode + "\"?>" );
242                            out.println( node.toString() );
243                    } catch ( FileNotFoundException ex ) {
244                            String errMsg = "?されたパス名で示されるファイルが存在しませんでした?
245                                            + CR + "\t" + ex.getMessage()
246                                            + CR + "\t" + aFile ;
247                            throw new RuntimeException( errMsg,ex );
248                    } catch ( UnsupportedEncodingException ex ) {
249                            String errMsg = "??エンコー?ング(" + encode + ")がサポ?トされて?せん?
250                                            + CR + "\t" + ex.getMessage()
251                                            + CR + "\t" + aFile ;
252                            throw new RuntimeException( errMsg,ex );
253            //      5.1.9.0 (2010/08/01) ?
254            //      } catch( RuntimeException ex ) {
255            //              String errMsg = "実行時エラーが発生しました?
256            //                              + CR + "\t" + ex.getMessage()
257            //                              + CR + "\t" + aFile ;
258            //              throw new RuntimeException( errMsg,ex );
259                    }
260                    finally {
261                            Closer.ioClose( out );
262                    }
263            }
264    
265            /**
266             * ?レクトリの再帰処?パ?ス処?行います?
267             *
268             * @og.rev 5.1.9.0 (2010/08/01) static からノ?マルに変更
269             *
270             * @param       fromFile        読み取りもとのファイル/フォル?
271             * @param       toFile  書き込み先?ファイル/フォル?
272             */
273            public void copyDirectry( final File fromFile, final File toFile ) {
274                    // コピ??ファイルの場合?コピ?して、終?る?
275                    if( fromFile.exists() && fromFile.isFile() ) {
276                            boolean isOK = false;
277                            String name = fromFile.getName();
278                            if( name.endsWith( ".jsp" ) || name.endsWith( ".xml" ) ) {
279                                    try {
280                                            OGDocument doc = read( fromFile );
281                                            if( doc != null && !filters.isEmpty() ) {
282                                                    for( JspParserFilter filter: filters ) {
283                                                            doc = filter.filter( doc );
284                                                            if( doc == null ) { break; }    // エラー、また?処??中止
285                                                    }
286                                            }
287                                            if( doc != null ) {
288                                                    write( toFile,doc );
289                                                    isOK = true;
290                                            }
291                                    }
292                                    catch( RuntimeException ex ) {
293                            //              ex.printStackTrace();
294                                            System.out.println( ex.getMessage() );
295                                    }
296                            }
297    
298                            // JSPやXMLでな??パ?スエラー、書き?しエラーなど正常終?きなかった?合?、バイナリコピ?
299                            if( !isOK ) {
300                                    FileUtil.copy( fromFile,toFile,true );
301                            }
302                            return ;
303                    }
304    
305                    // コピ?先ディレクトリが存在しなければ、作?する
306                    if( !toFile.exists() ) {
307                            if( !toFile.mkdirs() ) {
308                                    System.err.println( toFile + " の ?レクトリ作?に失敗しました? );
309                                    return ;
310                            }
311                    }
312    
313                    // ?レクトリ??ファイルをすべて取得す?
314                    File[] files = fromFile.listFiles();
315    
316                    // ?レクトリ??ファイルに対しコピ?処?行う
317                    for( int i = 0; i<files.length; i++ ){
318                            copyDirectry( files[i], new File( toFile, files[i].getName()) );
319                    }
320            }
321    
322            /**
323             * copyDirectry 処?、OGDocument をフィルター処?るオブジェクトを登録します?
324             *
325             * ?リストへフィルターを追?ます?
326             * フィルター処??、追?れた?行われます?
327             * ?リストへの追??できますが、削除はできません?
328             *
329             * @og.rev 5.1.9.0 (2010/08/01) 新規追?
330             *
331             * @param       filter  フィルターオブジェク?
332             */
333            public void addFilter( final JspParserFilter filter ) {
334                    filters.add( filter );
335            }
336    
337            /**
338             * サンプルプログラ?す?
339             *
340             * 引数の IN がファイルの場合?、OUTもファイルとして扱?す?
341             * IN がフォル??場合??層にしたがって、?帰?処?行い、OUT に出力します?
342             * フォル?層をパースして??に、XMLとして処?きな??処?にエラーが発生し?
343             * などの場合?、バイナリコピ?を行います?
344             *
345             * "Usage: JspSaxParser  &lt;inFile|inDir&gt; &lt;outFile|outDir&gt; [&lt;JspParserFilter1&gt; ??? ]"
346             *
347             * @param       args    コマンド引数配?
348             * @throws Exception なんらか?エラーが発生した??
349             */
350            public static void main( final String[] args ) throws Exception {
351                    if( args.length < 2 ) {
352                            System.out.println( "Usage: JspSaxParser  <inFile|inDir> <outFile|outDir> [<JspParserFilter1> ??? ]" );
353                    }
354    
355                    File in   = new File( args[0] );
356                    File out  = new File( args[1] );
357    
358                    JspSaxParser jsp = new JspSaxParser();
359    
360                    if( args.length >= 3 ) {
361                            for( int i=2; i<args.length; i++ ) {
362                                    JspParserFilter filter = (JspParserFilter)Class.forName( args[i] ).newInstance();
363                                    jsp.addFilter( filter );
364                            }
365                    }
366    
367                    jsp.copyDirectry( in,out );
368            }
369    
370            /**
371             * 処?のファイルオブジェクトを設定します?
372             *
373             * これは、エラー、ワーニング時?ファイル名を出力するために利用して?す?
374             *
375             * @og.rev 5.1.9.0 (2010/08/01) ?
376             *
377             * @param       file    処?のファイルオブジェク?
378             */
379    //      public void setFile( final File file ) {
380    //              this.file = file;
381    //      }
382    
383            // ********************************************************************************************** //
384            // **                                                                                          ** //
385            // ** ここから下?、DefaultHandler2 の実?なります?                                         ** //
386            // **                                                                                          ** //
387            // ********************************************************************************************** //
388    
389            /**
390             * ?の開始?知を受け取ります?
391             *
392             * インタフェース ContentHandler ?? startDocument
393             *
394             * @see org.xml.sax.helpers.DefaultHandler#startDocument()
395             * @see org.xml.sax.ContentHandler#startDocument()
396             */
397            @Override
398            public void startDocument() {
399                    stack   = new Stack<OGNode>();
400                    ele             = new OGDocument();
401                    ((OGDocument)ele).setFilename( filename );
402    
403                    idMap   = new HashMap<String,OGElement>();                // 5.1.9.0 (2010/08/01) 追?
404    
405                    attTab   = "";          // tagBefore の?TEMP
406                    inCDATA  = false;       // CDATA エレメント?中かど?の判?
407                    inEntity = false;       // Entity の中かど?の判?
408            }
409    
410            /**
411             * 要??開始?知を受け取ります?
412             *
413             * インタフェース ContentHandler ?? startElement
414             *
415             * @param       uri                     名前空????。要?名前空???? を持たな??合?また?名前空間??実行されな??合? null
416             * @param       localName       前置修飾子を含まな?ーカル名?名前空間??行われな??合?空??
417             * @param       qName           接頭辞を持つ修飾名?修飾名を使用できな??合?空??
418             * @param       attributes      要?付加された属?。属?が存在しな??合?空の Attributesオブジェク?
419             *
420             * @see org.xml.sax.helpers.DefaultHandler#startElement(String,String,String,Attributes)
421             * @see org.xml.sax.ContentHandler#startElement(String,String,String,Attributes)
422             */
423            @Override
424            public void startElement( final String uri, final String localName, final String qName, final Attributes attributes ) {
425    
426    //              OGElement newEle = new OGElement( qName,attTab,attributes,-1 );
427                    OGElement newEle = new OGElement( qName,attributes );
428                    String id = newEle.getId();
429                    if( id != null ) { idMap.put( id,newEle ); }            // 5.1.9.0 (2010/08/01) idをMapにキャ?ュ
430    
431                    ele.addNode( newEle );
432                    stack.push( ele );
433                    ele = newEle ;
434            }
435    
436            /**
437             * 要??の?データの通知を受け取ります?
438             *
439             * エン??ー?ど?を判断する、inEntity フラグ?true の間??
440             * 何も処?ません?
441             *
442             * インタフェース ContentHandler ?? characters
443             *
444             * @param       cbuf    ?データ配?
445             * @param       off             ??列?の開始位置
446             * @param       len             ??列から使用される文字数
447             *
448             * @see org.xml.sax.helpers.DefaultHandler#characters(char[],int,int)
449             * @see org.xml.sax.ContentHandler#characters(char[],int,int)
450             */
451            @Override
452            public void characters( final char[] cbuf, final int off, final int len ) {
453                    if( inEntity ) { return ; }             // &lt; ?< に変換される?で、エン???は、なにも??な??
454    
455                    String text = toText( cbuf,off,len );
456                    if( inCDATA ) {
457                            ele.addNode( text );
458                            return ;
459                    }
460    
461                    OGNode node = new OGNode( text );
462                    ele.addNode( node );
463    
464                    // '\r'(CR:復帰)+ '\n'(LF:改?の可能性があるが?'\n'(LF:改?が?より後ろにあるので、これで判定?
465                    int lastIdx = text.lastIndexOf( '\n' );
466                    if( lastIdx >= 0 ) {
467                            attTab = text.substring( lastIdx+1 );   // 改行から??までの部?字?
468                    }
469                    else {
470                            attTab = text;                                                  // 改行がな??で、すべて
471                    }
472            }
473    
474            /**
475             * CDATA セクションの開始を報告します?
476             *
477             * CDATA セクションのコン???、正規? characters イベントを介して報告されます?
478             * こ?イベント??の報告だけに使用されます?
479             *
480             * インタフェース LexicalHandler ?? startCDATA
481             *
482             * @see org.xml.sax.ext.DefaultHandler2#startCDATA()
483             * @see org.xml.sax.ext.LexicalHandler#startCDATA()
484             */
485            @Override
486            public void startCDATA() {
487                    OGNode node = new OGNode();
488                    node.setNodeType( OGNodeType.Cdata );
489    
490                    ele.addNode( node );
491                    stack.push( ele );
492                    ele = node ;
493                    inCDATA = true;
494            }
495    
496            /**
497             * CDATA セクションの終わりを報告します?
498             *
499             * インタフェース LexicalHandler ?? endCDATA
500             *
501             * @see org.xml.sax.ext.DefaultHandler2#endCDATA()
502             * @see org.xml.sax.ext.LexicalHandler#endCDATA()
503             */
504            @Override
505            public void endCDATA() {
506                    ele = stack.pop();
507                    inCDATA = false;
508            }
509    
510            /**
511             * DTD 宣?ある場合?そ?開始を報告します?
512             *
513             * start/endDTD イベント?、ContentHandler の
514             * start/endDocument イベント?の??の startElement イベント?前に出現します?
515             *
516             * インタフェース LexicalHandler ?? startDTD
517             *
518             * @param       name    ?型名
519             * @param       publicId        宣?れた外部 DTD サブセ?の公開識別子? 宣?れて???合? null
520             * @param       systemId        宣?れた外部 DTD サブセ?のシス?識別子? 宣?れて???合? null?
521             *                ドキュメント?ベ?ス URI に対しては解決されな?とに 注意すること
522             * @see org.xml.sax.ext.DefaultHandler2#startDTD( String , String , String )
523             * @see org.xml.sax.ext.LexicalHandler#startDTD( String , String , String )
524             */
525            @Override
526            public void startDTD( final String name, final String publicId, final String systemId ) {
527                    StringBuilder buf = new StringBuilder();
528                    buf.append( "<!DOCTYPE " ).append( name );
529                    if( publicId != null ) { buf.append( " PUBLIC \"" ).append( publicId ).append( "\"" ); }
530                    if( systemId != null ) { buf.append( "\"" ).append( systemId).append( "\"" ); }
531    
532                    OGNode node = new OGNode( buf.toString() );
533                    node.setNodeType( OGNodeType.DTD );
534                    ele.addNode( node );
535            }
536    
537            /**
538             * DTD 宣??終わりを報告します?
539             *
540             * こ?メソ?は、DOCTYPE 宣??終わりを報告するメソ?です?
541             * ここでは、何もしません?
542             *
543             * インタフェース LexicalHandler ?? endDTD
544             *
545             * @see org.xml.sax.ext.DefaultHandler2#endDTD()
546             * @see org.xml.sax.ext.LexicalHandler#endDTD()
547             */
548            @Override
549            public void endDTD() {
550                    // ここでは何もしません?
551            }
552    
553            /**
554             * ?および外部の XML エン??ーの?の開始を報告します?
555             *
556             * インタフェース LexicalHandler の記述:
557             *
558             * ※ ここでは?amp;lt; などの??が?lt と?名?エン??ーで
559             * 報告されるため、?の??きの??に復?て?す?
560             * エン??ー?ど?を判断する、inEntity フラグ?true にセ?します?
561             * inEntity=true の間??characters(char[],int,int) は、何も処?ません?
562             *
563             * @param       name    エン??ーの名前
564             * @see org.xml.sax.ext.LexicalHandler#startEntity(String)
565             */
566            @Override
567            public void startEntity( final String name ) {
568                    String text = "&" + name + ";" ;
569                    OGNode node = new OGNode( text );
570                    ele.addNode( node );
571                    inEntity = true;
572            }
573    
574            /**
575             * エン??ーの終わりを報告します?
576             *
577             * インタフェース LexicalHandler の記述:
578             *
579             * ※ ここでは、inEntity=false を設定するだけです?
580             *
581             * @param       name    エン??ーの名前
582             * @see org.xml.sax.ext.LexicalHandler#endEntity(String)
583             */
584            @Override
585            public void endEntity( final String name ) {
586                    inEntity = false;
587            }
588    
589            /**
590             * 要?ン??含まれる無視できる空白??通知を受け取ります?
591             *
592             * インタフェース ContentHandler ?? ignorableWhitespace
593             *
594             * @param       cbuf    ?データ配?(空白??
595             * @param       off             ??列?の開始位置
596             * @param       len             ??列から使用される文字数
597             *
598             * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[],int,int)
599             */
600            @Override
601            public void ignorableWhitespace( final char[] cbuf, final int off, final int len ) {
602                    String text = toText( cbuf,off,len );
603                    OGNode node = new OGNode( text );
604                    ele.addNode( node );
605            }
606    
607            /**
608             * ???任意?位置にある XML コメントを報告します?
609             *
610             * インタフェース LexicalHandler の記述:
611             *
612             * @param       cbuf    ?データ配?(コメント文?
613             * @param       off             配???開始位置
614             * @param       len             配?から読み取られる?数
615             *
616             * @see org.xml.sax.helpers.DefaultHandler#characters(char[],int,int)
617             */
618            @Override
619            public void comment( final char[] cbuf, final int off, final int len ) {
620                    String text = toText( cbuf,off,len );
621                    OGNode node = new OGNode( text );
622                    node.setNodeType( OGNodeType.Comment );
623                    ele.addNode( node );
624            }
625    
626            /**
627             * 要??終??知を受け取ります?
628             *
629             * @param       uri                     名前空????。要?名前空???? を持たな??合?また?名前空間??実行されな??合? null
630             * @param       localName       前置修飾子を含まな?ーカル名?名前空間??行われな??合?空??
631             * @param       qName           接頭辞を持つ修飾名?修飾名を使用できな??合?空??
632             *
633             * @see org.xml.sax.helpers.DefaultHandler#endElement(String,String,String)
634             * @see org.xml.sax.ContentHandler#endElement(String,String,String)
635             */
636            @Override
637            public void endElement( final String uri, final String localName, final String qName ) {
638                    ele = stack.pop();
639            }
640    
641            /**
642             * パ?サー警告?通知を受け取ります?
643             *
644             * インタフェース org.xml.sax.ErrorHandler ?? warning
645             *
646             * ここでは、パーサー警告??を標準エラーに表示します?
647             *
648             * @param       ex      例外として符号化された警告情報
649             * @see org.xml.sax.ErrorHandler#warning(SAXParseException)
650             */
651            @Override
652            public void warning( final SAXParseException ex ) {
653                    String errMsg = ex.getMessage() + ":" + ex.getPublicId()
654                                            + CR + "\t" + filename  + " (" + ex.getLineNumber() + ")";
655                    System.err.println( "WARNING:" + errMsg );
656            }
657    
658            /**
659             * ??列から???を作?します?(改行コード?統?
660             *
661             * 処?には、new String( cbuf,off,len ) ですが、XMLでリー?
662             * されたファイルは、改行コードが?\r'(CR:復帰)+ '\n'(LF:改?ではなく?
663             * '\n'(LF:改? のみに処?れます?(されるよ?す?規定不?)
664             * そこで、実行環??改行コー?System.getProperty("line.separator"))と
665             * 置き換えます?
666             *
667             * @param       cbuf    ?データ配?
668             * @param       off             配???開始位置
669             * @param       len             配?から読み取られる?数
670             *
671             * @return      ?的な、Stringオブジェク?
672             */
673            private String toText( final char[] cbuf, final int off, final int len ) {
674                    String text = new String( cbuf,off,len );
675                    return text.replaceAll( "\n", CR );
676            }
677    
678            /**
679             * OGDocument を取得します?
680             *
681             * @return      ?的な、OGNodeオブジェクトに相当しま?
682             */
683            private OGDocument getDocument() {
684                    OGDocument doc = null;
685                    if( ele != null && ele.getNodeType() == OGNodeType.Document ) {
686                            doc = (OGDocument)ele;
687                            doc.setIdMap( idMap );
688                    }
689                    return doc;
690            }
691    }