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.transfer;
017    
018    import java.io.IOException;
019    
020    import org.opengion.fukurou.db.Transaction;
021    import org.opengion.fukurou.util.StringUtil;
022    import org.opengion.fukurou.util.URLConnect;
023    
024    /**
025     * 伝é?要求に対してのHTTP経由で伝é?処ç�?‚’実行しますã?
026     *
027     * 読取方法により読み取ったデータをPOSTãƒ??タとして送信しã?リモートã?スト上で
028     * 伝é?処ç�?‚’実行しますã?
029     *
030     * 処ç�??流れとしては以下ã?ようになりますã?
031     * â‘?TTPで伝é?処ç�?‚’実行するためã?サーブレãƒ?ƒˆを呼び出すã?
032     * ②â‘?�§呼び出しされたサーブレãƒ?ƒˆがã?伝é?処ç�?‚’実行するためã?オブジェクトを生æ?しã?
033     *   伝é?処ç�?‚’実行するã?
034     * ③処ç�?µ‚äº?¾Œã?伝é?プロセスに制御が戻りã?読取方法に基づく後å?ç�?完äº??ç�?�¾たã?
035     *   エラー処ç�?が実行されますã?
036     *
037     * まず①につã�?�¦、呼び出しされるサーブレãƒ?ƒˆはã€?
038     *   [リモート接続å?URL]servlet/remoteControl?class=TransferExecWrapper になりますã?
039     *   [リモート接続å?URL]は、http://[ホスト名]:[ポã?ト番号]/[コンãƒ?‚­スト名]の形式になりますがã€?
040     *   これにつã�?�¦は、実行対象でæŒ?®šしますã?
041     * 次に②につã�?�¦、サーブレãƒ?ƒˆ経由で実行される伝é?処ç�?�«つã�?�¦、その実行方法ã?ã€?
042     *   具体的には、サブクラスのクラス名に対して、このクラス(親クラス)のクラスå�?"_" を除外した部åˆ?�Œ
043     *   実行方法として認識されますã?
044     *   具体的には、クラス名ã?æœ?¾Œã?"_"(アンãƒ??バã?)以降が実行方法として認識されã?
045     *   例として、サブクラス名がTransferExec_HTTP_CB01の場合ã?接続å?における実行方法ã?
046     *   旧伝é?DB登録(CB01)となりますã?
047     *   またã?リモートã?スト上で実行される伝é?処ç�??[リモート実行対象]は、å?の実行対象で設定しますã?
048     *   こã?ことから、HTTP経由で伝é?処ç�?‚’実行するå?合ã?å…??実行対象には、[リモート接続å?URL]と
049     *   [リモート実行対象]の2つを設定するå¿?¦�がありますã?
050     *   具体的な設定方法につã�?�¦はå�?‚µブクラスのJavaDocを参照して下さã�??
051     * æœ?¾Œに③につã�?�¦、接続時にエラーが発生したå?合や、レスポンスãƒ??タに対して"row_error"とã�?�†
052     *   æ–?­—å?が存在する場合ã?、エラーとして処ç�?�—ますã?
053     *   それ以外ã?場合ã?、正常終äº?�¨して処ç�?�—ますã?
054     *
055     * HTTP接続時には、以下ã?ポストデータがé?信されますã?
056     * [ポストデータ]
057     * ・KBREAD                     (読取方æ³?
058     * ・READOBJ            (読取対象)
059     * ・READPRM            (読取パラメーター)
060     * ・KBEXEC                     (実行方æ³? ※サブクラスのæœ?¾Œã?"_"(アンãƒ??バã?)以降ã?æ–?­—å?
061     * ・EXECDBID           (実行接続å?DBID)
062     * ・EXECOBJ            (リモート実行対象) ※ローカルの実行対象からリモート接続å?URLを除ã�?�Ÿæ–?­—å?
063     * ・EXECPRM            (実行パラメーター)
064     * ・ERROR_SENDTO       (読み取りå…??ストコーãƒ?
065     * ・HFROM (読み取りå…??ストコーãƒ?
066     * ・n (ãƒ??タ件数)
067     * ・v1?žvn (ãƒ??タ)
068     *
069     * @og.group 伝é?シスãƒ?ƒ 
070     *
071     * @version  5.0
072     * @author   Hiroki.Nakamura
073     * @since    JDK1.6
074     */
075    public abstract class TransferExec_HTTP implements TransferExec {
076    
077            // リモート制御サーブレãƒ?ƒˆå�?
078            private static final String REMOTE_SERVLET = "servlet/remoteControl?class=TransferExecWrapper";
079    
080            /**
081             * URL接続を実行しますã?
082             *
083             * @param vals 伝é?ãƒ??タ(配å?)
084             * @param config 伝é?設定オブジェクãƒ?
085             * @param tran トランザクションオブジェクãƒ?
086             */
087            @Override
088            public void execute( final String[] vals, final TransferConfig config, final Transaction tran ) {
089                    URLConnect conn = null;
090                    try {
091                            splitExecObj( config.getExecObj() );
092                            conn = new URLConnect( getRemoteHost() + REMOTE_SERVLET, TransferConfig.HTTP_AUTH_USER_PASS );
093                            if( config.getProxyHost() != null && config.getProxyHost().length() > 0 ) {
094                                    conn.setProxy( config.getProxyHost(), config.getProxyPort() );
095                            }
096    
097                            conn.setCharset( "UTF-8" );
098                            // ポストデータを生成しますã?
099                            conn.setPostData( getPostData( vals, config ) );
100    
101                            conn.connect();
102    
103                            String readData = conn.readData();
104                            // 返されたãƒ??タ中に"row_error"が存在する場合ã?エラーとして処ç�?�—ますã?
105                            if( readData != null && readData.indexOf( "row_error" ) >= 0 ) {
106                                    throw new RuntimeException( readData );
107                            }
108                    }
109                    catch( IOException ex ) {
110                            String errMsg = "URL接続時に例外が発生しましたã€?;
111                            throw new RuntimeException( errMsg, ex );
112                    }
113                    finally {
114                            if( conn != null ) { conn.disconnect(); }
115                    }
116            }
117    
118            /**
119             * ローカルの実行対象をã?リモート接続å?の実行対象とリモート接続å?URLにåˆ?§£しますã?
120             *
121             * @param localExecObj ローカルの実行対象
122             */
123            protected abstract void splitExecObj( final String localExecObj );
124    
125            /**
126             * リモート接続å?URLを返しますã?
127             * こã?メソãƒ?ƒ‰は、{@link #splitExecObj(String)}の後に呼び出しするå¿?¦�がありますã?
128             *
129             * @return リモート接続å?URL
130             */
131            protected abstract String getRemoteHost();
132    
133            /**
134             * リモート接続å?の実行対象を返しますã?
135             * こã?メソãƒ?ƒ‰は、{@link #splitExecObj(String)}の後に呼び出しするå¿?¦�がありますã?
136             *
137             * @return 接続URL
138             */
139            protected abstract String getRemoteExecObj();
140    
141            /**
142             * 伝é?ãƒ??タ及ã?伝é?設定をPOSTãƒ??タとしてシリアライズしますã?
143             *
144             * @param vals 伝é?ãƒ??タ(配å?)
145             * @param config 伝é?設定オブジェクãƒ?
146             *
147             * @return ポストデータ
148             */
149            private String getPostData( final String[] vals, final TransferConfig config ) {
150                    // サブクラス名から親クラスå�?"_"を除ã�?�Ÿ部åˆ?‚’実行方法とするã€?
151                    String kbExec = getClass().getName().replace( getClass().getSuperclass().getName() + "_", "" );
152    
153                    StringBuilder buf = new StringBuilder();
154                    buf.append( "KBREAD="           ).append( StringUtil.urlEncode( config.getKbRead() ) );
155                    buf.append( "&READOBJ="             ).append( StringUtil.urlEncode( config.getReadObj() ) );
156                    buf.append( "&READPRM="             ).append( StringUtil.urlEncode( config.getReadPrm() ) );
157                    buf.append( "&KBEXEC="              ).append( StringUtil.urlEncode( kbExec ) );
158                    buf.append( "&EXECDBID="    ).append( StringUtil.urlEncode( config.getExecDbid() )  );
159                    buf.append( "&EXECOBJ="             ).append( StringUtil.urlEncode( getRemoteExecObj() ) );
160                    buf.append( "&EXECPRM="             ).append( StringUtil.urlEncode( config.getExecPrm() ) );
161                    buf.append( "&ERROR_SENDTO=").append( StringUtil.urlEncode( config.getErrorSendto() ) );
162                    buf.append( "&HFROM="               ).append( StringUtil.urlEncode( config.getHfrom() ) ) ;
163    
164                    if( vals != null && vals.length > 0 ) {
165                            buf.append( "&n=" ).append( vals.length );
166                            for( int i=0; i<vals.length; i++ ) {
167                                    buf.append( "&v" ).append( i ).append( "=" );
168                                    buf.append( StringUtil.urlEncode( vals[i] ) );
169                            }
170                    }
171                    else {
172                            buf.append( "&n=0" );
173                    }
174    
175                    return buf.toString();
176            }
177    }