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    }