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.hayabusa.servlet;
017
018import java.io.FileInputStream;
019import java.io.IOException;
020import java.io.PrintWriter;
021import java.io.UnsupportedEncodingException;
022import java.util.Enumeration;
023import java.util.HashMap;
024
025import java.util.regex.Pattern;                                                         // 7.2.9.4 (2020/11/20)
026import java.util.regex.Matcher;                                                         // 7.2.9.4 (2020/11/20)
027
028import javax.servlet.ServletException;
029import javax.servlet.ServletConfig;                                                     // 7.2.9.4 (2020/11/20)
030import javax.servlet.ServletOutputStream;
031import javax.servlet.http.HttpServlet;
032import javax.servlet.http.HttpServletRequest;
033import javax.servlet.http.HttpServletResponse;
034
035import org.opengion.fukurou.system.Closer;
036import org.opengion.hayabusa.common.HybsSystem;
037import org.opengion.hayabusa.common.HybsSystemException;
038import org.opengion.hayabusa.remote.RemoteControllable;
039
040/**
041 * 外部からキーと値を投げて処理をさせるサーブレットです。
042 * Post,Get両方に対応しています。
043 * classキーが必須です。(値はhayabusa/remote/内のクラス名)
044 *
045 * @og.rev 4.1.0.0 (2007/12/20) 新規作成
046 * @version  4.1
047 * @author   Masakazu Takahashi
048 * @since    JDK6.0,
049 *
050 */
051public class RemoteControlServlet extends HttpServlet {
052        private static final long serialVersionUID      = 542020111201L ;
053        private static final String REMOTE_PKG          = "org.opengion.hayabusa.remote.";
054
055        private Pattern filePattern ;                   // 7.2.9.4 (2020/11/20) ファイルアクセスの制約(指定がない場合は、処理しない)。
056
057        /**
058         * デフォルトコンストラクター
059         *
060         * @og.rev 6.4.2.0 (2016/01/29) PMD refactoring. Each class should declare at least one constructor.
061         */
062        public RemoteControlServlet() { super(); }              // これも、自動的に呼ばれるが、空のメソッドを作成すると警告されるので、明示的にしておきます。
063
064        /**
065         * Postメソッドで与えられたrequestをcallClassメソッドに渡します。
066         * callClassメソッドではclassパラメータの値を利用してクラスをロードし、処理を行います。
067         * 具体的な処理はcallClassメソッドをご覧下さい。
068         *
069         * @param request HttpServletRequestリクエスト
070         * @param response HttpServletResponseレスポンス
071         * @throws ServletException サーブレット関係のエラーが発生した場合、throw されます。
072         * @throws IOException 入出力エラーが発生したとき
073         */
074        @Override
075        public void doPost( final HttpServletRequest request, final HttpServletResponse response )      throws ServletException, IOException {
076                callClass( request, response );
077        }
078
079        /**
080         * Getメソッドで与えられたrequestをcallClassメソッドに渡します。
081         * callClassメソッドではclassパラメータの値を利用してクラスをロードし、処理を行います。
082         * 具体的な処理はcallClassメソッドをご覧下さい。
083         *
084         * @param request HttpServletRequestリクエスト
085         * @param response HttpServletResponseレスポンス
086         * @throws ServletException サーブレット関係のエラーが発生した場合、throw されます。
087         * @throws IOException 入出力エラーが発生したとき
088         */
089        @Override
090        public void doGet( final HttpServletRequest request, final HttpServletResponse response )       throws ServletException, IOException {
091                callClass( request, response );
092        }
093
094        /**
095         * Servlet の 初期値設定を行います。
096         *
097         * WEB-INF/web.xml ファイルで、<servlet> タグ内で初期値設定を行います。
098         * <init-param>
099         *     <param-name>filePattern</param-name>
100         *     <param-value>c:/opengionV7|c:/temp</param-value>
101         * </init-param>
102         *
103         * @og.rev 7.2.9.4 (2020/11/20) ファイルアクセスの制約(指定がない場合は、処理しない)。
104         *
105         * @param       config  ServletConfigオブジェクト
106         */
107        @Override
108        public void init( final ServletConfig config ) throws ServletException {
109                super.init( config );
110
111                final String filePtn = config.getInitParameter("filePattern");
112                if( filePtn != null && !filePtn.isEmpty() ) {
113                        filePattern = Pattern.compile( filePtn );
114                }
115        }
116
117        /**
118         * POSTとGETに対する実際の処理です
119         * 必須パラメータclassで与えられたクラス名でorg.opengion.hayabusa.remoteから
120         * クラスをロードし、MAPに格納したrequestパラメータをそのクラスに対して渡します。
121         * ロードするクラスはRemoteControllableを実装している必要があります。
122         * ロードしたクラスの処理が終了すると、返されたStringをresponseに出力して終了します。
123         * なお、classパラメータがnullの場合は何もせずに終了します。
124         *
125         * @og.rev 5.4.2.0 (2011/12/01) フォワード対応
126         * @og.rev 7.2.9.4 (2020/11/20) ファイルアクセスの制約(指定がない場合は、処理しない)。
127         *
128         * @param request リクエスト
129         * @param response レスポンス
130         * @throws ServletException サーブレット関係のエラーが発生した場合、throw されます。
131         * @throws IOException 入出力エラーが発生したとき
132         */
133        private void callClass( final HttpServletRequest request, final HttpServletResponse response ) throws ServletException, IOException {
134                // 5.4.2.0 (2011/12/01) リクエストのエンコードを指定
135                try {
136                        request.setCharacterEncoding( "UTF-8" );
137                }
138                catch( final UnsupportedEncodingException ex ) {
139                        throw new HybsSystemException( ex );
140                }
141
142                // 5.4.2.0 (2011/12/01) フォワード対応
143                // 7.2.9.4 (2020/11/20) ファイルアクセスの制約(指定がない場合は、処理しない)。
144                final String file = request.getParameter( "file" );
145//              if( file != null && file.length() > 0 ) {
146                if( file != null && !file.isEmpty() && filePattern != null ) {                  // 7.2.9.4 (2020/11/20)
147                        final Matcher match = filePattern.matcher( file );                                      // 7.2.9.4 (2020/11/20)
148                        if( match.matches() ) {                                                                                         // 7.2.9.4 (2020/11/20)
149                                response.setContentType( "application/octet-stream" );
150                                // ファイル内容の出力
151                                FileInputStream     fin = null;
152                                ServletOutputStream out = null;
153                                try {
154                                        // 対応済み:spotbugs:サーブレットの絶対パストラバーサル
155                                        fin = new FileInputStream( file );
156                                        out = response.getOutputStream();
157
158                                        // ファイル読み込み用バッファ
159                                        final byte buffer[]  = new byte[4096];
160                                        int size;
161                                        while((size = fin.read(buffer))!=-1) {
162                                                out.write(buffer,0, size);
163                                                out.flush();
164                                        }
165                                }
166                                finally {
167                                        Closer.ioClose( fin );
168                                        Closer.ioClose( out );
169                                }
170                        }
171                }
172                else {
173                        final String clazz = request.getParameter( "class" ); // パラメータ"class"だけは必ず必要
174                        if( clazz == null ) {
175                                return; // 暫定処理
176                        }
177
178                        final Enumeration<?> paramEnm = request.getParameterNames();            // 4.3.3.6 (2008/11/15) Generics警告対応
179                        final HashMap<String,String> paramMap = new HashMap<>();
180                        while( paramEnm.hasMoreElements() ) {
181                                final String key = ( String )( paramEnm.nextElement() );
182                                paramMap.put( key, request.getParameter( key ) );
183                        }
184
185                        final RemoteControllable rmtC = HybsSystem.newInstance( REMOTE_PKG + clazz );
186                        final String rtnString = rmtC.remoteControl( paramMap );
187                        response.setContentType( "text/xml; charset=UTF-8" );
188                        final PrintWriter out = response.getWriter();
189                        out.println( rtnString );
190                        out.flush();
191                        out.close();
192                }
193        }
194}