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