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