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 java.io.File;
019    import java.io.IOException;
020    import java.io.BufferedReader;
021    
022    import org.opengion.fukurou.util.FileUtil;
023    import org.opengion.fukurou.util.Closer;
024    import org.opengion.fukurou.util.LogWriter;
025    
026    /**
027     * ã“ã?クラスã¯ã€jspファイルã®XSLT変æ›ã«ç‰¹åŒ–ã—ãŸã?Readerオブジェクトを作æ?ã™ã‚‹ã‚¯ãƒ©ã‚¹ã§ã™ã?
028     * jspファイル ã«è¨˜è¿°ã•れるã?jsp:directive.include を見ã¤ã‘ã¦ã€ãã®ãƒ•ァイル属æ?ã«
029     * 記述ã•れã¦ã?‚‹ãƒ•ァイルをã?インクルードã—ã¾ã™ã?
030     * Tomcat ã®ç‰¹æ€§ä¸Šã?インクルード時ã®ãƒ•ァイルã¯ã€?¼?­‰ã?エスケープを処ç?—ã¦ãŠã
031     * å¿?¦ãŒã‚りã¾ã™ã?
032     * <del>(ã¤ã¾ã‚Šã?オリジナルã¯ã€ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—å?ç?ªã—ã§ã€ã‚¤ãƒ³ã‚¯ãƒ«ãƒ¼ãƒ‰ã•れるファイルã¯ã€?
033     * 属æ?部åˆ??ã¿ã€ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—å?ç?Œå¿?¦ã§ã™ã?)</del>
034     * エスケープã?å‰å?ç??ã€jsp:root ã‚¿ã‚°ã®ã‚ã‚‹ãªã—ã§åˆ¤å®šã—ã¾ã™ã?
035     * ç¾æ™‚点ã§ã¯ã€?& , < , <= , > , >= ã‚’å‰å‡¦ç?—ã¾ã™ã?
036     *
037     * <del>ã‚¿ã‚°ã®BODY部ã«è¨˜è¿°ã•れã¦ã?‚‹ ??ãªã©ã‚‚ã?パã?スã®å¯¾è±¡ã«ãªã‚Šã¾ã™ãŒã€?
038     * 擬似çš?«å‡¦ç?—ã¦ã?¾ã™ã?
039     * ãれã¯ã€ã?&nbsp;ã€ã?< ã€ã?<=ã€ã«ã¤ã?¦ã€å?ç?—ã¦ã?¾ã™ã?
040     * ã“ã?形以外ã?処ç??ã€ä»Šã?入れã¦ã?¾ã›ã‚“ã€?/del>
041     *
042     * JSP ã§ã¯ã€og:head ã‚¿ã‚°ã§ã€?html> ã‚’å?力ã—ãŸã‚Šã€htmlend.jsp インクルードã§
043     * </body></html> ã‚’å?力ã—ã¦ã?¾ã™ãŒã€ãƒ•レーãƒ?‚„ã€ãƒ•ォワードãªã©ã€æ•´åˆæ?ãŒå–れãªã?
044     * ケースãŒã‚りã¾ã™ã?ã§ã€XML処ç?”¨ã¨ã—ã¦ã€?html> ã‚’å?力ã—ã¦ã?¾ã›ã‚“ã€?
045     * 変æ›çµæžœã‚’ã?æ­£å¼ãª HTML ファイルã¨ã—ã¦å†åˆ©ç”¨ã•れるå?åˆã?ã€ã”注æ„ãã?•ã??
046     *
047     * @og.rev 4.0.0.2 (2007/12/10) æ–°è¦è¿½åŠ?
048     *
049     * @version  4.0
050     * @author   Kazuhiko Hasegawa
051     * @since    JDK5.0,
052     */
053    public class JspIncludeReader {
054            private static final String CR = System.getProperty("line.separator");
055    
056            // ã‚¿ã‚°ã®å±žæ?ã®å€¤ã®ã¿ã‚’抜ãå?ã—ã¦ã?¾ã™ã?特ã«ã€?>& ã‚’å«ã‚??åˆã?
057            // 5.2.1.0 (2010/10/01) ä»®å»?­¢
058            //      private static final Pattern ptn = Pattern.compile( "=[ \t]*\"([^\"]*[<>&].[^\"]*)\"" );
059    
060            /**
061             *      JSP ã®ã‚¤ãƒ³ã‚¯ãƒ«ãƒ¼ãƒ‰ã‚’è€??ã—ãŸã€Reader オブジェクトを返ã—ã¾ã™ã?
062             *
063             * @param file File
064             * @param encode String
065             *
066             * @return Reader
067             */
068    //      public Reader getReader( final File file,final String encode ) {
069    //              return new StringReader( getString( file,encode,false ) );
070    //      }
071    
072            /**
073             * JSP ã®ã‚¤ãƒ³ã‚¯ãƒ«ãƒ¼ãƒ‰ã‚’è€??ã—ãŸã€JSPファイルをã?String ã§è¿”ã—ã¾ã™ã?
074             * ã“ã?メソãƒ?ƒ‰ã¯ã€å?部ã§å†å¸°å®šç¾©ã•れã¦ã?¾ã™ã?ã¤ã¾ã‚Šã?jsp:directive.include
075             * æ–?­—å?ãŒè¦‹ã¤ã‹ã£ãŸå?åˆã?ã€ãã®ä»£ã‚りã«ã€ãƒ•ァイルåã‚’å–å?ã—ã¦ã€ã‚‚ã?¸?º¦
076             * ã“ã?メソãƒ?ƒ‰ã‚’呼ã³å‡ºã—ã¾ã™ã?
077             * <del>Tomcat ã®ç‰¹æ€§ä¸Šã?インクルード時ã®ãƒ•ァイルã¯ã€?¼?­‰ã?エスケープを処ç?—ã¦ãŠã
078             * å¿?¦ãŒã‚りã¾ã™ãŒã€ã‚ªãƒªã‚¸ãƒŠãƒ«ã¯ã€ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—å?ç?—ã¾ã›ã‚“ã€?
079             * ãã?åˆ?‚Šæ›¿ãˆã‚’ã€ç¬¬?“引数㮠isEscape ã§åˆ¶å¾¡ã—ã¦ã?¾ã™ã?</del>
080             * Ver4 以é™ã§ã€ã‚¤ãƒ³ã‚¯ãƒ«ãƒ¼ãƒ‰ãƒ•ァイルã«ã€XML宣è¨?¨ã€jsp:root を付与ã™ã‚‹ã‚±ãƒ¼ã‚¹ãŒã‚りã¾ã™ã?
081             * 擬似çš?«å–り込ã‚?¨ãã«ã¯ã€XML宣è¨??削除ã—ã¾ã™ã?
082             *
083             * @og.rev 5.2.1.0 (2010/10/01) directive.include ã§ã€XMLã‚¿ã‚°ã¨root ã‚¿ã‚°ã¯å–り込ã¾ãªã??
084             * @og.rev 5.2.1.0 (2010/10/01) エスケープå?ç??引数をå»?­¢ã—ã¾ã™ã?
085             * @og.rev 5.6.5.2 (2013/06/21) å°ç´°å·¥å†?®¹ã®å¤‰æ›´ã€‚replaceAll ã«ã™ã‚‹ã®ã¨ã€ã‚¹ãƒšã?スã¾ãŸã?タブを使用ã—ã¾ã™ã?
086             *
087             * @param       file    JSPファイル
088             * @param       encode  ファイルã®ã‚¨ãƒ³ã‚³ãƒ¼ãƒ?
089             *
090             * @return      インクルードをè€??ã—ãŸã€JSPファイル
091             */
092    //      public String getString( final File file,final String encode,final boolean isEscape ) {
093            public String getString( final File file,final String encode ) {
094                    StringBuilder buf = new StringBuilder() ;
095                    BufferedReader reader = FileUtil.getBufferedReader( file,encode );
096    
097                    // ファイルãŒã?jsp 直下ã‹ã©ã?‹ã‚’判断ã—ã¾ã™ã?
098                    String parentFile = file.getParent() ;
099                    boolean isUnder = parentFile.endsWith( "\\jsp" );
100    
101                    int  cmntIn    = -1;
102                    int  cmntOut   = -1;
103                    boolean isCmnt = false;
104                    boolean isEscape = true;        // エスケープã™ã‚‹ã‹ã©ã?‹(true:ã™ã‚‹/false:ã—ãªã?
105                    try {
106                            String line ;
107                            while((line = reader.readLine()) != null) {
108                                    // 5.2.1.0 (2010/10/01) directive.include ã§ã€XMLã‚¿ã‚°ã¯å–り込ã¾ãªã??
109                                    if( line.indexOf( "<?xml" ) >= 0 && line.indexOf( "?>" ) >= 0 ) { continue; }
110                                    // jsp:root ãŒã‚れã?ã€ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—å?ç?‚’行ã‚ãªã?
111                                    if( line.indexOf( "<jsp:root" ) >= 0 ) { isEscape = false; }
112    
113                                    // コメントã?削除
114                                    cmntIn  = line.indexOf( "<!--" );
115                                    cmntOut = line.indexOf( "-->" );
116                                    if( cmntIn >= 0 && cmntOut >= 0 ) {
117                                            line = line.substring( 0,cmntIn ) + line.substring( cmntOut );
118                                    }
119                                    else if( cmntIn >= 0 && cmntOut < 0 ) {
120                                            line = line.substring( 0,cmntIn );
121                                            isCmnt = true;
122                                    }
123                                    else if( cmntIn < 0  && cmntOut >= 0 ) {
124                                            line = line.substring( cmntOut );
125                                            isCmnt = false;
126                                    }
127                                    else if( isCmnt && cmntIn < 0 && cmntOut < 0 ) { continue; }
128    
129                                    // 特殊å?ç?¼šog:head ã§ html ã‚¿ã‚°ã‚’å?力ã—ã¦ã?‚‹ã€?
130            //                      if( line.indexOf( "<og:head" ) >= 0 ) {
131            //                              buf.append( "<html>" );
132            //                      }
133    
134                                    if( isEscape ) {
135                                            // 5.6.5.2 (2013/06/21) å°ç´°å·¥å†?®¹ã®å¤‰æ›´ã€‚replaceAll ã«ã™ã‚‹ã®ã¨ã€ã‚¹ãƒšã?スã¾ãŸã?タブを使用ã—ã¾ã™ã?
136                                            // & , < , <= , > , >= ã‚’å‰å‡¦ç?—ã¾ã™ã?
137    //                                      line = line.replace( "&"  ,"&amp;" );           // ã¡ã‚?£ã¨å°ç´°å·¥
138    //                                      line = line.replace( " < "," &lt; " );           // ã¡ã‚?£ã¨å°ç´°å·¥
139    //                                      line = line.replace( " > "," &gt; " );           // ã¡ã‚?£ã¨å°ç´°å·¥
140    //                                      line = line.replace( " <="," &lt;=" );           // ã¡ã‚?£ã¨å°ç´°å·¥
141    //                                      line = line.replace( " >="," &gt;=" );           // ã¡ã‚?£ã¨å°ç´°å·¥
142                                            line = line.replaceAll( "&"  ,"&amp;" );                                // ã¡ã‚?£ã¨å°ç´°å·¥
143                                            line = line.replaceAll( "[ \\t]<[ \\t]"," &lt; " );              // ã¡ã‚?£ã¨å°ç´°å·¥
144                                            line = line.replaceAll( "[ \\t]>[ \\t]"," &gt; " );              // ã¡ã‚?£ã¨å°ç´°å·¥
145                                            line = line.replaceAll( "[ \\t]<="," &lt;=" );                   // ã¡ã‚?£ã¨å°ç´°å·¥
146                                            line = line.replaceAll( "[ \\t]>="," &gt;=" );                   // ã¡ã‚?£ã¨å°ç´°å·¥
147            // 5.2.1.0 (2010/10/01) ä»®å»?­¢
148            //                              Matcher mtch = ptn.matcher( line );
149            //                              int adrs = 0;
150            //                              StringBuilder buf2 = new StringBuilder();
151            //                              while( mtch.find(adrs) ) {
152            //                                      String grp = mtch.group(1);
153            //                                      String htm = StringUtil.htmlFilter( grp );
154            //                                      int in = mtch.start(1);
155            //                                      buf2.append( line.substring( adrs,in ) ).append( htm );
156            //                                      adrs = mtch.end(1);
157            //                              }
158            //                              buf2.append( line.substring( adrs ) );
159            //                              line = buf2.toString();
160                                    }
161    
162                                    int st = line.indexOf( "<jsp:directive.include" );
163                                    if( st < 0 ) { buf.append( line ); } // include ãŒç„¡ã‘れã°ã€ãã®ã¾ã¾è¿½åŠ?
164                                    else {
165                                            buf.append( line.substring( 0,st ) );
166                                            int fin = line.indexOf( '\"',st );              // ãƒ•ã‚¡ã‚¤ãƒ«ã®æœ??
167                                            int fout= line.indexOf( '\"',fin+1 );   // ãƒ•ã‚¡ã‚¤ãƒ«ã®æœ?¾?
168                                            String fname = line.substring( fin+1,fout );    // ファイルå?
169    
170                                            // htmlend.jsp 㮠インクルードã?行ã‚ãªã??
171                                            if( fname.endsWith( "htmlend.jsp" ) ) {
172                                                    if( buf.indexOf( "<body" ) >= 0 && buf.indexOf( "</body>" ) < 0 ) {
173                                                            buf.append( "</body>" );
174                                                    }
175    
176            //                                      if( buf.indexOf( "<html" ) >= 0 ) {
177            //                                              buf.append( "</html>" );
178            //                                      }
179                                            }
180                                            else {
181                                                    // ã¡ã‚?£ã¨å°ç´°å·¥
182                                                    // include ã™ã‚‹ãƒ•ァイルã¯ã€?jsp/ ã‹ã‚‰ã®çµ¶å¯¾ãƒ‘スã€?
183                                                    // jsp 直下ã?å ´åˆã?ã€?/ ã€ãれ以外ã?ã€?./ ã¨ç½®ãæ›ãˆã¾ã™ã?
184                                                    if( isUnder ) { fname = fname.replace( "/jsp/","./" ); }
185                                                    else              { fname = fname.replace( "/jsp/","../" ); }
186                                                    File newfile = new File( parentFile,fname );
187                                                    buf.append( getString( newfile,encode ) );
188                                            }
189                                            int tagout = line.indexOf( "/>",fout+1 );    // ã‚¿ã‚°ã®æœ?¾?
190    
191                                            buf.append( line.substring( tagout+2 ) );
192                                    }
193    
194                                    // og:commonForward を見ã¤ã‘ãŸå ´åˆã?ã€æœ€å¾Œã« html ã‚¿ã‚°ã‚’å?力ã™ã‚‹ã?
195            //                      if( line.indexOf( "<og:commonForward" ) >= 0 ) {
196            //                              buf.append( "</html>" );
197            //                      }
198    
199                                    buf.append( CR );
200                            }
201                    }
202                    catch( IOException ex ) {
203                            LogWriter.log( ex );
204                    }
205                    finally {
206                            Closer.ioClose( reader );
207                    }
208                    return buf.toString();
209            }
210    
211            /**
212             * ãƒ?‚¹ãƒˆç”¨ã® main メソãƒ?ƒ‰
213             *
214             * @param       args    コマンド引数é…å?
215             */
216            public static void main( final String[] args ) {
217                    JspIncludeReader reader = new JspIncludeReader();
218    //              String xml = reader.getString( new File( args[0] ),"UTF-8",false );
219                    String xml = reader.getString( new File( args[0] ),"UTF-8" );
220    
221                    if( args.length > 1 ) {
222                            java.io.PrintWriter writer = FileUtil.getPrintWriter( new File( args[1] ),"UTF-8" );
223                            writer.print( xml );
224                            Closer.ioClose( writer );
225                    }
226                    else {
227                            System.out.println( xml );
228                    }
229            }
230    }