    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 ファイルで、&lt;servlet&gt; タグ内で初期値設定を行います。
    098         * &lt;init-param&gt;
    099         *     &lt;param-name&gt;filePattern&lt;/param-name&gt;
    100         *     &lt;param-value&gt;c:/opengionV7|c:/temp&lt;/param-value&gt;
    101         * &lt;/init-param&gt;
    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}