    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.fukurou.util;
    017
    018import java.io.BufferedInputStream;
    019import java.io.BufferedReader;
    020import java.io.File;
    021import java.io.IOException;
    022import java.io.InputStream;
    023import java.io.InputStreamReader;
    024import java.io.OutputStream;
    025import java.io.PrintStream;
    026import java.io.PrintWriter;
    027import java.io.UnsupportedEncodingException;
    028import java.net.HttpURLConnection;
    029import java.net.InetSocketAddress;
    030import java.net.Proxy;
    031import java.net.SocketAddress;
    032import java.net.URL;
    033import java.net.URLConnection;
    034
    035import org.apache.commons.codec.binary.Base64;
    036
    037/**
    038 * URLConnect は、指定のURL にアクセスして、情報/データを取得します。
    039 * URL へのアクセスにより、エンジンでは各種処理を実行させることが可能になります。
    040 * 例えば、帳票デーモンの起動や、長時間かかる処理の実行などです。
    041 * なお、URLに引数が付く場合は、ダブルコーテーションで括って下さい。
    042 * - 付き引数は、指定順番は、関係ありません。- 無し引数(url,user:passwd)は、
    043 * 順番があります。
    044 *
    045 * Usage: java org.opengion.fukurou.util.URLConnect [-info/-data] … url [user:passwd]
    046 *
    047 *   args[*] : [-info/-data]       情報の取得か、データの取得かを指定します(初期値:-data)。
    048 *   args[*] : [-post=ファイル名]  POSTメソッドを指定して、ファイルデータを送信します(初期値:-get)。
    049 *   args[*] : [-encode=UTF-8]     エンコードを指定します(通常は接続先のencodeを使用)。
    050 *   args[*] : [-out=ファイル名]   結果を指定されたファイルエンコードでファイルに出力します。
    051 *   args[*] : [-errEx=true/false] trueの場合、ﾚｽﾎﾟﾝｽｺｰﾄﾞが、4XX,5XX の時に RuntimeException を投げます(初期値:false)。
    052 *   args[A] : url                 ＵＲＬを指定します。GETの場合、パラメータは ?KEY=VALです。
    053 *   args[B] : [user:passwd]       BASIC認証のエリアへのアクセス時に指定します。
    054 *
    055 * ※ プロキシ設定の３つの方法
    056 * プロキシ設定には、３つの方法があります。
    057 *   1.
    058 *     URL url = URL( "http",proxyHost,proxyPort, url );
    059 *     URLConnection urlConn = url.openConnection();
    060 *   2.
    061 *     SocketAddress scaddr = new InetSocketAddress( proxyHost, proxyPort );
    062 *     Proxy proxy = new Proxy( Proxy.Type.HTTP, scaddr );
    063 *     URL url = new Url( url );
    064 *     URLConnection urlConn = url.openConnection( proxy );
    065 *   3.
    066 *     System.setProperty( "http.proxyHost",host );
    067 *     System.setProperty( "http.proxyPort",String.valueOf( port ) );
    068 *     URL url = new Url( url );
    069 *     URLConnection urlConn = url.openConnection();
    070 *     System.clearProperty( "http.proxyHost" );
    071 *     System.clearProperty( "http.proxyPort" );
    072 *
    073 * 1. 、2. の方法は、urlConn.getContentType() を実行すると、エラーになります。(原因不明)
    074 * 3. の方法では、マルチスレッドで実行する場合に、問題が発生します。
    075 * 本クラスでは、方法２ を使用しています。
    076 *
    077 * @version  4.0
    078 * @author   Kazuhiko Hasegawa
    079 * @since    JDK5.0,
    080 */
    081public class URLConnect {
    082        private static final String CR = System.getProperty("line.separator");
    083
    084//      private static final String     ENCODE  = "UTF-8";
    085
    086        private final String urlStr ;
    087        private final String userPass ;
    088
    089        private int                             rpsCode         = -1;
    090        private String                  rpsMethod       = null;
    091        private String                  rpsMessage      = null;
    092        private String                  type            = null;
    093        private String                  charset         = null;
    094        private String                  postData        = null;
    095        private int                             timeout         = -1;           // 5.8.8.1 (2015/06/12) timeout属性追加
    096        private long                    length          = -1;
    097        private long                    date            = -1;
    098        private long                    modified        = -1;
    099        private boolean                 isPost          = false;
    100        private URLConnection   conn            = null;
    101        private Proxy                   proxy           = Proxy.NO_PROXY;
    102
    103        // 5.8.3.0 (2015/01/09) 追加
    104        private String[]                propKeys;
    105        private String[]                propVals;
    106
    107        /**
    108         * コンストラクター
    109         *
    110         * @param       url     接続するアドレスを指定します。(http://server:port/dir/file.html)
    111         * @param       pass    ユーザー：パスワード(認証接続が必要な場合)
    112         */
    113        public URLConnect( final String url, final String pass ) {
    114                urlStr = url;
    115                userPass = pass;
    116        }
    117
    118        /**
    119         * 指定のURLに対して、コネクトするのに使用するプロキシ設定を行います。
    120         * このときに、ヘッダー情報を内部変数に設定しておきます。
    121         *
    122         * @param       host    接続するプロキシのホスト名
    123         * @param       port    接続するプロキシのポート番号
    124         */
    125        public void setProxy( final String host,final int port ) {
    126                // 方法2.
    127                SocketAddress scaddr = new InetSocketAddress( host, port );
    128                proxy = new Proxy( Proxy.Type.HTTP, scaddr );
    129        }
    130
    131        /**
    132         * 指定のURLに対して、コネクトします。
    133         * このときに、ヘッダー情報を内部変数に設定しておきます。
    134         *
    135         * @og.rev 4.0.1.0 (2007/12/12) Postで複数キーを使えるように修正
    136         * @og.rev 5.1.6.0 (2010/05/01) charsetを指定できるようにする
    137         * @throws  IOException 入出力エラーが発生したとき
    138         */
    139        public void connect() throws IOException {
    140                conn = getConnection();
    141
    142                if( isPost ) {
    143                        conn.setDoOutput( true );                       // POST可能にする
    144
    145                        OutputStream os = null;                         // POST用のOutputStream
    146                        PrintStream  ps = null;
    147                        try {
    148                                os = conn.getOutputStream();    // POST用のOutputStreamを取得
    149                                // 5.1.6.0 (2010/05/01)
    150                                if( charset != null ) {
    151                                        ps = new PrintStream( os, false, charset );
    152                                }
    153                                else {
    154                                        ps = new PrintStream( os );
    155                                }
    156                                ps.print( postData );                   // 4.1.0.0 (2007/12/22)
    157                        }
    158                        finally {
    159                                Closer.ioClose( ps );           // close 処理時の IOException を無視
    160                                Closer.ioClose( os );           // close 処理時の IOException を無視
    161                        }
    162                }
    163                else {
    164                        // GET 時のコネクション接続
    165                        conn.connect();
    166                }
    167
    168                setInfo( conn );
    169        }
    170
    171        /**
    172         * U接続先のデータを取得します。
    173         *
    174         * この処理の前に、connect() 処理を実行しておく必要があります。
    175         * 取得したデータは、指定のURL へのアクセスのみです。
    176         * 通常のWebブラウザは、イメージや、JavaScriptファイル、CSSファイルなど、
    177         * 各種ファイル毎にHTTP接続を行い、取得して、レンダリングします。
    178         * このメソッドでの処理では、それらのファイル内に指定されているURLの
    179         * 再帰的な取得は行いません。
    180         * よって、フレーム処理なども行いません。
    181         * 本来は、Stream のまま処理することで、バイナリデータも扱えますが、ここでは、
    182         * テキストデータ(String)に変換して使用できるデータのみ扱えます。
    183         *
    184         * @return      接続結果
    185         * @throws  IOException 入出力エラーが発生したとき
    186         */
    187        public String readData() throws IOException {
    188                if( conn == null ) {
    189                        String errMsg = "connect() されていません。データ取得前にconnect()してください。";
    190                        throw new RuntimeException( errMsg );
    191                }
    192
    193                BufferedReader reader = null;
    194                StringBuilder buf = new StringBuilder();
    195                try {
    196                        reader = getReader();
    197
    198                        String line ;
    199                        while( (line = reader.readLine()) != null ) {
    200                                buf.append( line ).append( CR );
    201                        }
    202                }
    203                catch( UnsupportedEncodingException ex ) {
    204                        String errMsg = "指定された文字エンコーディングがサポートされていません。" + CR
    205                                                + " url=[" + urlStr + "]"
    206                                                + " charset=[" + charset + "]" ;
    207                        throw new RuntimeException( errMsg,ex );
    208                }
    209                finally {
    210                        Closer.ioClose( reader );
    211                        disconnect();
    212                }
    213
    214                return buf.toString();
    215        }
    216
    217        /**
    218         * サーバへのほかの要求が今後発生しそうにないことを示します。
    219         *
    220         */
    221        public void disconnect() {
    222                if( conn instanceof HttpURLConnection ) {
    223                        ((HttpURLConnection)conn).disconnect() ;
    224                }
    225        }
    226
    227        /**
    228         * URL と ユーザー：パスワードを与えて、URLConnectionを返します。
    229         *
    230         * ユーザー：パスワード が null でない場合は、BASCI認証エリアへのアクセスの為、
    231         * BASE64Encoder を行って、Authorization プロパティーを設定します。
    232         * ここで返す URLConnection は、すでに、connect() メソッド実行済みの
    233         * リモート接続が完了した状態のオブジェクトです。
    234         *
    235         * @og.rev 5.8.3.0 (2015/01/09) ヘッダ等指定のためにsetRequestPropertyの値を指定できるようにします。
    236         * @og.rev 5.8.8.1 (2015/06/12)
    237         *
    238         * @return  URLConnectionオブジェクト
    239         * @throws  IOException 入出力エラーが発生したとき
    240         */
    241        // 5.1.5.0 (2010/04/01) SOAP対応により、PROTECTED化
    242        protected URLConnection getConnection() throws IOException {
    243//      private URLConnection getConnection() throws IOException {
    244                final URL url = new URL( urlStr );
    245
    246                // 方法2.
    247                URLConnection urlConn = url.openConnection( proxy );
    248
    249                if( userPass != null ) {
    250//                      byte[] encoded = Base64.encodeBase64( userPass.getBytes() );
    251//                      String userPassEnc = new String( encoded );
    252                        byte[] encoded = Base64.encodeBase64( userPass.getBytes( StringUtil.DEFAULT_CHARSET ) );        // 5.5.2.6 (2012/05/25) findbugs対応
    253                        String userPassEnc = new String( encoded,StringUtil.DEFAULT_CHARSET );          // 5.5.2.6 (2012/05/25) findbugs対応
    254                        urlConn.setRequestProperty( "Authorization","Basic " + userPassEnc );
    255                }
    256
    257                // 5.8.3.0 (2015/01/09) RequestPropertyのセット
    258                if( propKeys != null && propKeys.length > 0 ){
    259                        for(int i = 0; i < propKeys.length; i++){
    260                                urlConn.setRequestProperty( propKeys[i], propVals[i] );
    261                        }
    262                }
    263
    264                // 5.8.8.1 (2015/06/12) timeout属性追加
    265                if( timeout >= 0 ) {
    266                        urlConn.setConnectTimeout( timeout * 1000 );    // 引数は(秒)、設定は(ミリ秒)
    267                }
    268
    269                return urlConn ;
    270        }
    271
    272        /**
    273         * 接続先の情報を内部変数に設定します。
    274         *
    275         * ここでは、タイプ,エンコード,レスポンスコード,レスポンスメッセージ を設定します。
    276         * レスポンスコード,レスポンスメッセージは、接続コネクションが、HttpURLConnection の
    277         * 場合のみセットされます。
    278         * 途中でエラーが発生した場合でも、継続処理できるようにします。これは、プロキシ
    279         * 設定の方法により、conn.getContentType()  でエラーが発生する場合があるためです。
    280         *
    281         * @og.rev 5.5.9.1 (2012/12/07) charsetは、null の場合のみ設定します。
    282         *
    283         * @param   conn 接続先のコネクション
    284         */
    285        private void setInfo( final URLConnection conn ) {
    286                try {
    287                        // 5.5.9.1 (2012/12/07) charsetは、null の場合のみ設定します。
    288                        if( charset == null ) { charset = conn.getContentEncoding(); }
    289                        type    = conn.getContentType() ;
    290                        length  = conn.getContentLength();
    291                        date    = conn.getDate();
    292                        modified= conn.getLastModified();
    293
    294                        if( charset == null && type != null ) {
    295                                int adrs = type.indexOf( "charset" );
    296                                int adrs2 = type.indexOf( '=',adrs );
    297                                if( adrs > 0 && adrs2 > adrs ) {
    298                                        charset = type.substring( adrs2+1 ).trim();
    299                                }
    300                        }
    301
    302                        if( conn instanceof HttpURLConnection ) {
    303                                HttpURLConnection httpConn = (HttpURLConnection) conn;
    304                                rpsCode         = httpConn.getResponseCode();
    305                                rpsMethod       = httpConn.getRequestMethod();
    306                                rpsMessage      = httpConn.getResponseMessage() + code2Message( rpsCode );
    307                        }
    308                }
    309                // 4.0.0.0 (2007/11/29) Exception から、IOException と RuntimeException に変更
    310                catch( IOException ex ) {
    311                        System.out.println( ex.getMessage() );
    312                }
    313                catch( RuntimeException ex ) {
    314                        System.out.println( ex.getMessage() );
    315                }
    316        }
    317
    318        /**
    319         * URL 情報を取得します。
    320         *
    321         * @og.rev 4.3.4.4 (2009/01/01) メソッド名変更
    322         *
    323         * @return      URL情報
    324         */
    325        public String getUrl() { return urlStr; }
    326
    327        /**
    328         * setRequestPropertyでセットするデータを設定します。
    329         *
    330         * keys,vals各々、カンマ区切りで分解します。
    331         *
    332         * @og.rev 5.8.3.0 (2007/12/22) 追加
    333         * @param       keys    パラメータキー（カンマ区切り）
    334         * @param       vals    パラメータ（カンマ区切り）
    335         */
    336        public void setRequestProperty( final String keys, final String vals ) {
    337                if( keys != null && keys.length() > 0 && vals != null && vals.length() > 0 ){
    338                        propKeys = StringUtil.csv2Array( keys );
    339                        propVals = StringUtil.csv2Array( vals );
    340
    341                        if( propKeys.length != propVals.length ) {
    342                                final String errMsg = "パラメータのキーと、値の数が一致しません。"   + CR
    343                                                        + " key=[" + keys + "]"                                                                 + CR
    344                                                        + " val=[" + vals + "]" ;
    345                                throw new IllegalArgumentException( errMsg );
    346                        }
    347                }
    348        }
    349
    350        /**
    351         * POSTするデータを設定します。
    352         *
    353         * POSTする場合は、connect() 処理を行う前に、データを設定しておく必要があります。
    354         *
    355         * @og.rev 4.1.0.0 (2007/12/22) キーと値のセットを取得するよう変更
    356         * @param       data    POSTデータ
    357         */
    358        public void setPostData( final String data ) {
    359                postData = data;
    360                if( postData != null && "?".indexOf( postData ) == 0 ) { // 先頭の?を抜く
    361                        postData = postData.substring(1);
    362                }
    363                if( postData != null ) { isPost = true; }
    364        }
    365
    366        /**
    367         * タイプ 情報を取得します。
    368         *
    369         * @return      タイプ 情報
    370         */
    371        public String getType() { return type; }
    372
    373        /**
    374         * データ量 情報を取得します。
    375         *
    376         * @return      データ量 情報
    377         */
    378        public long getLength() { return length; }
    379
    380        /**
    381         * 作成日時 情報を取得します。
    382         *
    383         * @return      作成日時
    384         */
    385        public long getDate() { return date; }
    386
    387        /**
    388         * 更新日時 情報を取得します。
    389         *
    390         * @return      更新日時
    391         */
    392        public long getModified() { return modified; }
    393
    394        /**
    395         * 結果コード 情報(HttpURLConnection)を取得します。
    396         *
    397         * @return      結果コード 情報
    398         */
    399        public int getCode() { return rpsCode; }
    400
    401        /**
    402         * メソッド 情報(HttpURLConnection)を取得します。
    403         *
    404         * @return      メソッド 情報
    405         */
    406        public String getMethod() { return rpsMethod; }
    407
    408        /**
    409         * メッセージ 情報(HttpURLConnection)を取得します。
    410         *
    411         * @return      メッセージ 情報
    412         */
    413        public String getMessage() { return rpsMessage; }
    414
    415        /**
    416         * キャラクタ 情報を取得します。
    417         *
    418         * @return      キャラクタ 情報
    419         */
    420        public String getCharset() { return charset; }
    421
    422        /**
    423         * キャラクタ 情報を設定します。
    424         *
    425         * @param  chset キャラクタ 情報
    426         */
    427        public void setCharset( final String chset ) { charset = chset; }
    428
    429        /**
    430         * 接続タイムアウト時間を(秒)で指定します
    431         *
    432         * 実際には、java.net.URLConnection#setConnectTimeout(int) に 1000倍して設定されます。
    433         * 0 は、無限のタイムアウト、マイナスは、設定しません。(つまりJavaの初期値のまま)
    434         *
    435         * @og.rev 5.8.8.1 (2015/06/12) timeout属性追加
    436         *
    437         * @param       tout    タイムアウト時間(秒) (ゼロは、無制限)
    438         * @see         java.net.URLConnection#setConnectTimeout(int)
    439         */
    440        public void setTimeout( final int tout ) {
    441                timeout = tout;
    442        }
    443
    444        /**
    445         * 接続先のデータのリーダーを取得します。
    446         *
    447         * この処理の前に、connect() 処理を実行しておく必要があります。
    448         * 取得したデータは、指定のURL へのアクセスのみです。
    449         * 通常のWebブラウザは、イメージや、JavaScriptファイル、CSSファイルなど、
    450         * 各種ファイル毎にHTTP接続を行い、取得して、レンダリングします。
    451         * このメソッドでの処理では、それらのファイル内に指定されているURLの
    452         * 再帰的な取得は行いません。
    453         * よって、フレーム処理なども行いません。
    454         *
    455         * @return      接続結果のリーダー
    456         * @throws  IOException 入出力エラーが発生したとき
    457         */
    458        public BufferedReader getReader() throws IOException {
    459                InputStream in = conn.getInputStream();
    460
    461                final BufferedReader reader ;
    462                if( charset != null ) {
    463                        reader = new BufferedReader( new InputStreamReader( in,charset ) );
    464                }
    465                else {
    466//                      reader = new BufferedReader( new InputStreamReader( in ) );
    467                        reader = new BufferedReader( new InputStreamReader( in,StringUtil.DEFAULT_CHARSET ) );          // 5.5.2.6 (2012/05/25) findbugs対応
    468                }
    469
    470                return reader;
    471        }
    472
    473        /**
    474         * 接続先のデータの入力ストリームを取得します。
    475         *
    476         * この処理の前に、connect() 処理を実行しておく必要があります。
    477         * 取得したデータは、指定のURL へのアクセスのみです。
    478         * 通常のWebブラウザは、イメージや、JavaScriptファイル、CSSファイルなど、
    479         * 各種ファイル毎にHTTP接続を行い、取得して、レンダリングします。
    480         * このメソッドでの処理では、それらのファイル内に指定されているURLの
    481         * 再帰的な取得は行いません。
    482         * よって、フレーム処理なども行いません。
    483         *
    484         * @og.rev 5.4.2.0 (2011/12/01) 新規追加
    485         *
    486         * @return      接続結果の入力を出力します。
    487         * @throws  IOException 入出力エラーが発生したとき
    488         */
    489        public InputStream getInputStream() throws IOException {
    490//              InputStream in = new BufferedInputStream( conn.getInputStream() );
    491//              return in;
    492                return new BufferedInputStream( conn.getInputStream() );                // 5.5.2.4 (2012/05/16)
    493        }
    494
    495        /**
    496         * HttpURLConnection のレスポンスコードに対応するメッセージ文字列を返します。
    497         *
    498         * HttpURLConnection の getResponseCode() メソッドにより取得された、HTTPレスポンスコード
    499         * に対応する文字列を返します。この文字列は、HttpURLConnection で定義された
    500         * static 定数のコメントを、定義しています。
    501         *
    502         * @og.rev 5.6.7.0 (2013/07/27) レスポンスコード例 追加
    503         *
    504         * @param       code    HTTPレスポンスコード
    505         *
    506         * @return      レスポンスコードに対応する文字列
    507         * @see HttpURLConnection#HTTP_ACCEPTED
    508         */
    509        public static String code2Message( final int code ) {
    510                final String msg ;
    511                switch( code ) {
    512                        case 100                                                                                : msg = "100: 要求は続行可能です。"                                               ;       break;  // 5.6.7.0 (2013/07/27)
    513                        case 101                                                                                : msg = "101: プロトコルを切り替えます。"                            ;       break;  // 5.6.7.0 (2013/07/27)
    514                        case HttpURLConnection.HTTP_OK                                  : msg = "200: OK です。"                                                           ;       break;
    515                        case HttpURLConnection.HTTP_CREATED                     : msg = "201: 作成されました。"                                                 ;       break;
    516                        case HttpURLConnection.HTTP_ACCEPTED                    : msg = "202: 許可されました。"                                                 ;       break;
    517                        case HttpURLConnection.HTTP_NOT_AUTHORITATIVE   : msg = "203: 不当な情報です。"                                                 ;       break;
    518                        case HttpURLConnection.HTTP_NO_CONTENT                  : msg = "204: コンテンツがありません。"                                     ;       break;
    519                        case HttpURLConnection.HTTP_RESET                               : msg = "205: コンテンツをリセットします。"                           ;       break;
    520                        case HttpURLConnection.HTTP_PARTIAL                     : msg = "206: 部分的なコンテンツです。"                                     ;       break;
    521                        case HttpURLConnection.HTTP_MULT_CHOICE                 : msg = "300: 複数選択されています。"                                      ;       break;
    522                        case HttpURLConnection.HTTP_MOVED_PERM                  : msg = "301: 永続的に移動されました。"                                     ;       break;
    523                        case HttpURLConnection.HTTP_MOVED_TEMP                  : msg = "302: 一時的に切り替えます。"                                      ;       break;
    524                        case HttpURLConnection.HTTP_SEE_OTHER                   : msg = "303: 他を参照してください。"                                      ;       break;
    525                        case HttpURLConnection.HTTP_NOT_MODIFIED                : msg = "304: 修正されませんでした。"                                      ;       break;
    526                        case HttpURLConnection.HTTP_USE_PROXY                   : msg = "305: プロキシを使用してください。"                           ;       break;
    527                        case 306                                                                                : msg = "306: 仕様の拡張案です。"                                                ;       break;  // 5.6.7.0 (2013/07/27)
    528                        case 307                                                                                : msg = "307: 一時的なリダイレクトです。"                            ;       break;  // 5.6.7.0 (2013/07/27)
    529                        case HttpURLConnection.HTTP_BAD_REQUEST                 : msg = "400: 不当な要求です。"                                                 ;       break;
    530                        case HttpURLConnection.HTTP_UNAUTHORIZED                : msg = "401: 認証されませんでした。"                                      ;       break;
    531                        case HttpURLConnection.HTTP_PAYMENT_REQUIRED    : msg = "402: 支払いが必要です。"                                                ;       break;
    532                        case HttpURLConnection.HTTP_FORBIDDEN                   : msg = "403: 禁止されています。"                                                ;       break;
    533                        case HttpURLConnection.HTTP_NOT_FOUND                   : msg = "404: 見つかりませんでした。"                                      ;       break;
    534                        case HttpURLConnection.HTTP_BAD_METHOD                  : msg = "405: メソッドは許可されません。"                            ;       break;
    535                        case HttpURLConnection.HTTP_NOT_ACCEPTABLE              : msg = "406: 許容されません。"                                                 ;       break;
    536                        case HttpURLConnection.HTTP_PROXY_AUTH                  : msg = "407: プロキシの認証が必要です。"                            ;       break;
    537                        case HttpURLConnection.HTTP_CLIENT_TIMEOUT              : msg = "408: 要求が時間切れです。"                                               ;       break;
    538                        case HttpURLConnection.HTTP_CONFLICT                    : msg = "409: 重複しています。"                                                 ;       break;
    539                        case HttpURLConnection.HTTP_GONE                                : msg = "410: 存在しません。"                                                  ;       break;
    540                        case HttpURLConnection.HTTP_LENGTH_REQUIRED     : msg = "411: 長さが必要です。"                                                 ;       break;
    541                        case HttpURLConnection.HTTP_PRECON_FAILED               : msg = "412: 前提条件が正しくありません。"                           ;       break;
    542                        case HttpURLConnection.HTTP_ENTITY_TOO_LARGE    : msg = "413: 要求エンティティが長すぎます。"                  ;       break;
    543                        case HttpURLConnection.HTTP_REQ_TOO_LONG                : msg = "414: 要求 URL が長すぎます。"                                   ;       break;
    544                        case HttpURLConnection.HTTP_UNSUPPORTED_TYPE    : msg = "415: サポートされないメディアタイプです。"               ;       break;
    545                        case 416                                                                                : msg = "416: 要求された範囲は不十分です。"                           ;       break;  // 5.6.7.0 (2013/07/27)
    546                        case 417                                                                                : msg = "417: 要求どおりの処理が不可能です。"                  ;       break;  // 5.6.7.0 (2013/07/27)
    547                        case HttpURLConnection.HTTP_INTERNAL_ERROR              : msg = "500: 内部サーバエラーです。"                                      ;       break;
    548                        case HttpURLConnection.HTTP_NOT_IMPLEMENTED     : msg = "501: 実装されていません。"                                               ;       break;
    549                        case HttpURLConnection.HTTP_BAD_GATEWAY                 : msg = "502: 誤ったゲートウェイです。"                                     ;       break;
    550                        case HttpURLConnection.HTTP_UNAVAILABLE                 : msg = "503: サービスが利用できません。"                            ;       break;
    551                        case HttpURLConnection.HTTP_GATEWAY_TIMEOUT     : msg = "504: ゲートウェイが時間切れです。"                           ;       break;
    552                        case HttpURLConnection.HTTP_VERSION                     : msg = "505: HTTP バージョンがサポートされていません。"; break;
    553//                      default : msg = "-1: 未定義" ;
    554                        default : msg = code + ": 未定義" ;                // 5.6.7.0 (2013/07/27)
    555                }
    556                return msg ;
    557        }
    558
    559        /**
    560         * サンプル実行用のメインメソッド
    561         *
    562         * Usage: java org.opengion.fukurou.util.URLConnect [-info/-data] … url [user:passwd]
    563         *
    564         *   args[*] : [-info/-data]       情報の取得か、データの取得かを指定します(初期値:-data)。
    565         *   args[*] : [-post=ファイル名]  POSTメソッドを指定して、ファイルデータを送信します(初期値:-get)。
    566         *   args[*] : [-encode=UTF-8]     エンコードを指定します(通常は接続先のencodeを使用)
    567         *   args[*] : [-out=ファイル名]   結果をファイルに出力します。ファイルエンコードも指定します。
    568         *   args[*] : [-errEx=true/false] trueの場合、ﾚｽﾎﾟﾝｽｺｰﾄﾞが、4XX,5XX の時に RuntimeException を投げます(初期値:false)。
    569         *   args[A] : url                 ＵＲＬを指定します。GETの場合、パラメータは ?KEY=VALです。
    570         *   args[B] : [user:passwd]       BASIC認証のエリアへのアクセス時に指定します。
    571         *
    572         * @og.rev 5.6.7.0 (2013/07/27) -errEx 追加
    573         *
    574         * @param       args    コマンド引数配列
    575         * @throws IOException 入出力エラーが発生したとき
    576         */
    577        public static void main( final String[] args ) throws IOException {
    578                if( args.length < 3 ) {
    579                        LogWriter.log( "Usage: java org.opengion.fukurou.util.URLConnect [-info/-data] … url [user:passwd]"                             );
    580                        LogWriter.log( "   args[*] : [-info/-data]       情報の取得か、データの取得かを指定します(初期値:-data)"                       );
    581                        LogWriter.log( "   args[*] : [-post=ファイル名]  POSTメソッドを指定して、ファイルデータを送信します(初期値:-get)"      );
    582                        LogWriter.log( "   args[*] : [-encode=UTF-8]     エンコードを指定します。(通常は接続先のencodeを使用)"                                );
    583                        LogWriter.log( "   args[*] : [-out=ファイル名]   結果をファイルに出力します。ファイルエンコードも指定します"              );
    584                        LogWriter.log( "   args[*] : [-errEx=true/false] trueの場合、ﾚｽﾎﾟﾝｽｺｰﾄﾞが、4XX,5XX の時に RuntimeException を投げます(初期値:false)" );
    585                        LogWriter.log( "   args[A] : url                 ＵＲＬを指定します。GETの場合、パラメータは ?KEY=VALです"                    );
    586                        LogWriter.log( "   args[B] : [user:passwd]       BASIC認証のエリアへのアクセス時に指定します"                                              );
    587                        return;
    588                }
    589
    590                boolean isInfo  = false ;
    591                boolean isPost  = false ;
    592                String postKey  = null ;
    593                String postFile = null ;
    594                String encode   = null ;
    595                String outFile  = null ;
    596                boolean isEx    = false ;                               // 5.6.7.0 (2013/07/27) 追加
    597                String[] vals   = new String[2];                // url,userPass の順に引数設定
    598
    599                int adrs = 0;
    600                for( int i=0; i<args.length; i++ ) {
    601                        String arg = args[i];
    602                        if( arg.equalsIgnoreCase( "-info" ) ) {
    603                                isInfo = true;
    604                        }
    605                        else if( arg.equalsIgnoreCase( "-data" ) ) {
    606                                isInfo = false;
    607                        }
    608                        else if( arg.startsWith( "-post=" ) ) {
    609                                isPost = true;
    610                                int sepAdrs = arg.indexOf( ':',6 );
    611                                postKey  = arg.substring( 6,sepAdrs );
    612                                postFile = arg.substring( sepAdrs+1 );
    613                        }
    614                        else if( arg.startsWith( "-encode=" ) ) {
    615                                encode = arg.substring( 8 );
    616                        }
    617                        else if( arg.startsWith( "-out=" ) ) {
    618                                outFile = arg.substring( 5 );
    619                        }
    620                        else if( arg.startsWith( "-errEx=" ) ) {                                                        // 5.6.7.0 (2013/07/27) 追加
    621                                isEx = "true".equalsIgnoreCase( arg.substring( 7 ) );
    622                        }
    623                        else if( arg.startsWith( "-" ) ) {
    624                                System.out.println( "Error Argment:" + arg );
    625                        }
    626                        else {
    627                                vals[adrs++] = arg;
    628                        }
    629                }
    630
    631                String urlStr   = vals[0] ;
    632                String userPass = vals[1] ;
    633
    634                URLConnect conn = new URLConnect( urlStr,userPass );
    635
    636                // POST データは、connect() する前に、設定します。
    637                if( isPost ) {
    638                        FileString file = new FileString();
    639                        file.setFilename( postFile );
    640                        String postData = file.getValue();
    641
    642                        conn.setPostData( XHTMLTag.urlEncode(postKey, postData) );
    643                }
    644
    645                conn.connect();
    646                if( encode != null ) {
    647                        conn.setCharset( encode );              // encode 指定
    648                }
    649                else {
    650                        encode = conn.getCharset();             // 指定がなければ、接続先の charset を使用
    651                }
    652
    653                final PrintWriter writer ;
    654                if( outFile != null ) {
    655                        writer = FileUtil.getPrintWriter( new File( outFile ),encode );
    656                }
    657                else {
    658                        writer = FileUtil.getLogWriter( "System.out" );
    659                }
    660
    661                int code = conn.getCode();              // 5.6.7.0 (2013/07/27) レスポンスコードは、常に拾っておきます。
    662                if( isInfo ) {
    663                        writer.println( "URL    :" + conn.getUrl() );
    664                        writer.println( "Type   :" + conn.getType() );
    665//                      writer.println( "Code   :" + conn.getCode() );
    666                        writer.println( "Code   :" + code );                                    // 5.6.7.0 (2013/07/27) 取得済みの値を利用。
    667                        writer.println( "Message:" + conn.getMessage() );
    668                        writer.println( "Charset:" + conn.getCharset() );
    669                }
    670                else {
    671                        writer.println( conn.readData() );
    672                }
    673
    674                conn.disconnect();
    675
    676                Closer.ioClose( writer );
    677
    678                // 5.6.7.0 (2013/07/27) trueの場合、ﾚｽﾎﾟﾝｽｺｰﾄﾞが、4XX,5XX の時に RuntimeException を投げます
    679                if( isEx && code >= 400 ) {
    680                        String errMsg = URLConnect.code2Message( code );
    681                        throw new RuntimeException( errMsg );
    682                }
    683        }
    684}