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