com.sunchenbin.store.feilong.core.net.URLConnectionUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.sunchenbin.store.feilong.core.net.URLConnectionUtil.java

Source

/*
 * Copyright (C) 2008 feilong
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.sunchenbin.store.feilong.core.net;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.SocketAddress;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sunchenbin.store.feilong.core.io.InputStreamUtil;
import com.sunchenbin.store.feilong.core.io.ReaderUtil;
import com.sunchenbin.store.feilong.core.io.UncheckedIOException;
import com.sunchenbin.store.feilong.core.tools.jsonlib.JsonUtil;
import com.sunchenbin.store.feilong.core.util.Validator;

/**
 * {@link java.net.HttpURLConnection}(?? {@link java.net.Proxy}).
 * 
 * <h3>:</h3>
 * 
 * <blockquote>
 * <p>
 * {@link java.net.HttpURLConnection}HTTP??,socket<br>
 * <span style="color:red"> ?timeout,,???</span> <br>
 * JDK1.5- ,???
 * </p>
 * <ul>
 * <li>System.setProperty("sun.net.client.defaultConnectTimeout", );</li>
 * <li>System.setProperty("sun.net.client.defaultReadTimeout", );</li>
 * </ul>
 * <p>
 * JDK1.5+,?HttpURLConnectionURLConnection
 * </p>
 * <ul>
 * <li>{@link URLConnection#setConnectTimeout(int)}??</li>
 * <li>{@link URLConnection#setReadTimeout(int)}????</li>
 * </ul>
 *
 * </blockquote>
 * 
 * 
 * <h3>?:</h3>
 * 
 * <blockquote>
 * <p>
 * JDK5-URLHttpConnection???,??URL.openConnection()???
 * </p>
 * 
 * <pre>
 * Properties properties = System.getProperties();
 * properties.put(&quot;http.proxyHost&quot;, &quot;120.0.0.1&quot;);
 * properties.put(&quot;http.proxyPort&quot;, &quot;1080&quot;);
 * </pre>
 * 
 * ?JDK5+ URL {@link URL#openConnection(Proxy)},???,?
 * 
 * <pre>
 * URL url = new URL("http://www.javatang.com");
 * <span style="color:green">// ??</span>
 * SocketAddress add = new InetSocketAddress("120.0.0.1", "1080");
 * Proxy proxy = new Proxy(Proxy.Type.SOCKS , add);
 * <span style="color:green">// </span>
 * HttpURLConnection conn = (HttpURLConnection)url.openConnection(proxy);                                                                                                                                                                       .openConnection(p);
 * </pre>
 * 
 * </blockquote>
 * 
 * 
 * <h3> {@link HttpURLConnection#setDoInput(boolean)} && {@link HttpURLConnection#setDoOutput(boolean)}</h3>
 * 
 * 
 * <blockquote>
 * 
 * 
 * <table border="1" cellspacing="0" cellpadding="4">
 * <tr style="background-color:#ccccff">
 * <th align="left"></th>
 * <th align="left"></th>
 * </tr>
 * <tr valign="top">
 * <td>httpUrlConnection.setDoOutput(true);</td>
 * <td>??conn.getOutputStream().write()<br>
 * get?conn.getOutputStream(),????,false<br>
 * post????,?httpbody?,??,??<br>
 * URL?URL,DoOutputtrue?,falsefalse</td>
 * </tr>
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>httpUrlConnection.setDoInput(true);</td>
 * <td>??conn.getInputStream().read();<br>
 * conn.getInputStream()???,true<br>
 * URL?URL,DoInputtrue?,falsetrue</td>
 * </tr>
 * </table>
 * 
 * <p>
 * ??? {@link "org.springframework.http.client.SimpleClientHttpRequestFactory#prepareConnection(HttpURLConnection, String)"} 
 * </p>
 * </blockquote>
 * 
 * 
 * <h3> {@link HttpURLConnection#connect()} && {@link HttpURLConnection#getOutputStream()}</h3>
 * 
 * <blockquote>
 * <p>
 * getOutputStream??connect(???connect(),?? httpURLConnection.connect(); ?).<br>
 *  URL ?. connected  true connect ,.<br>
 * ??tcp,??http.<br>
 * postget,httpHttpURLConnectiongetInputStream()?????.
 * </p>
 * </blockquote>
 *
 * @author feilong
 * @version 1.0 Sep 26, 2013 11:10:59 AM
 * @see java.net.HttpURLConnection
 * @see java.net.URLConnection
 * @see "org.springframework.http.client.SimpleClientHttpRequestFactory"
 * @since 1.0.2
 */
public final class URLConnectionUtil {

    /** The Constant LOGGER. */
    private static final Logger LOGGER = LoggerFactory.getLogger(URLConnectionUtil.class);

    /** Don't let anyone instantiate this class. */
    private URLConnectionUtil() {
        //AssertionError?. ?????. ???.
        //see Effective Java 2nd
        throw new AssertionError("No " + getClass().getName() + " instances for you!");
    }

    /**
     * Read line with proxy.
     *
     * @param urlString
     *            the url string
     * @return ?.???? ('\n')? ('\r') ???.
     * @see #readLine(String, ConnectionConfig)
     */
    public static String readLine(String urlString) {
        return readLine(urlString, null);
    }

    /**
     * Read line with proxy.
     *
     * @param urlString
     *            the url string
     * @param connectionConfig
     *            the connection config
     * @return ?.???? ('\n')? ('\r') ???.
     */
    public static String readLine(String urlString, ConnectionConfig connectionConfig) {
        InputStream inputStream = getInputStream(urlString, connectionConfig);
        BufferedReader bufferedReader = InputStreamUtil.toBufferedReader(inputStream,
                connectionConfig.getContentCharset());
        return ReaderUtil.readLine(bufferedReader);
    }

    //********************************************************************************************
    /**
     * Gets the response body as string.
     *
     * @param urlString
     *            the url string
     * @return the response body as string
     * @see #getResponseBodyAsString(String, ConnectionConfig)
     */
    public static String getResponseBodyAsString(String urlString) {
        return getResponseBodyAsString(urlString, null);
    }

    /**
     *  response body as string.
     *
     * @param urlString
     *            the url string
     * @param connectionConfig
     *            connectionConfig
     * @return the response body as string
     * @see #getInputStream(String, ConnectionConfig)
     * @see InputStreamUtil#inputStream2String(InputStream, String)
     */
    public static String getResponseBodyAsString(String urlString, ConnectionConfig connectionConfig) {
        ConnectionConfig useConnectionConfig = null == connectionConfig ? new ConnectionConfig() : connectionConfig;
        InputStream inputStream = getInputStream(urlString, useConnectionConfig);
        return InputStreamUtil.inputStream2String(inputStream, useConnectionConfig.getContentCharset());

    }

    /**
     *  input stream.
     *
     * @param urlString
     *            the url string
     * @return the input stream
     * @see #getInputStream(String, ConnectionConfig)
     */
    public static InputStream getInputStream(String urlString) {
        return getInputStream(urlString, null);
    }

    /**
     *  input stream.
     *
     * @param urlString
     *            the url string
     * @param connectionConfig
     *            the connection config
     * @return the input stream
     * @see #getInputStream(HttpRequest, ConnectionConfig)
     */
    public static InputStream getInputStream(String urlString, ConnectionConfig connectionConfig) {
        HttpRequest httpRequest = new HttpRequest();
        httpRequest.setUri(urlString);
        return getInputStream(httpRequest, connectionConfig);
    }

    /**
     *  input stream.
     *
     * @param httpRequest
     *            the http request
     * @param connectionConfig
     *            the connection config
     * @return the input stream
     * @since 1.2.0
     * @see "org.springframework.core.io.UrlResource#getInputStream()"
     */
    public static InputStream getInputStream(HttpRequest httpRequest, ConnectionConfig connectionConfig) {
        HttpURLConnection httpURLConnection = getHttpURLConnection(httpRequest, connectionConfig);
        try {
            return httpURLConnection.getInputStream();
        } catch (IOException e) {
            //???. disconnect() ????? HttpURLConnection .
            //? finally ?, ??inputstream

            // per Java's documentation, this is not necessary, and precludes keepalives. However in practise,
            // connection errors will not be released quickly enough and can cause a too many open files error.
            IOUtils.close(httpURLConnection); // Close the HTTP connection (if applicable). 

            throw new UncheckedIOException(e);
        }
    }

    // ****************************************************************************************
    /**
     *  {@link java.net.HttpURLConnection}.
     *
     * @param httpRequest
     *            the http request
     * @param connectionConfig
     *            the connection config
     * @return {@link java.net.HttpURLConnection}
     */
    private static HttpURLConnection getHttpURLConnection(HttpRequest httpRequest,
            ConnectionConfig connectionConfig) {
        if (Validator.isNullOrEmpty(httpRequest)) {
            throw new NullPointerException("httpRequest can't be null/empty!");
        }

        ConnectionConfig useConnectionConfig = null == connectionConfig ? new ConnectionConfig() : connectionConfig;
        try {
            HttpURLConnection httpURLConnection = openConnection(httpRequest, useConnectionConfig);
            prepareConnection(httpURLConnection, httpRequest, useConnectionConfig);
            return httpURLConnection;
        } catch (MalformedURLException e) {
            throw new UncheckedIOException(e);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    /**
     * Prepare connection.
     *
     * @param httpURLConnection
     *            the http url connection
     * @param httpRequest
     *            the http request
     * @param useConnectionConfig
     *            the use connection config
     * @throws IOException
     *             the IO exception
     * @since 1.4.0
     * @see "org.springframework.http.client.SimpleClientHttpRequestFactory#prepareConnection(HttpURLConnection, String)"
     */
    private static void prepareConnection(HttpURLConnection httpURLConnection, HttpRequest httpRequest,
            ConnectionConfig useConnectionConfig) throws IOException {
        HttpMethodType httpMethodType = httpRequest.getHttpMethodType();

        // ?HttpUrlConnectionconnectTimeout
        httpURLConnection.setConnectTimeout(useConnectionConfig.getConnectTimeout());
        httpURLConnection.setReadTimeout(useConnectionConfig.getReadTimeout());

        httpURLConnection.setRequestMethod(httpMethodType.getMethod().toUpperCase());//?,?  java.net.ProtocolException: Invalid HTTP method: get

        httpURLConnection.setDoOutput(HttpMethodType.POST == httpMethodType);

        Map<String, String> headerMap = httpRequest.getHeaderMap();
        if (null != headerMap) {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                httpURLConnection.setRequestProperty(entry.getKey(), entry.getValue());
            }
        }
    }

    /**
     * Open connection.
     *
     * @param httpRequest
     *            the http request
     * @param connectionConfig
     *            the connection config
     * @return the http url connection
     * @throws IOException
     *             the IO exception
     * @since 1.2.0
     */
    private static HttpURLConnection openConnection(HttpRequest httpRequest, ConnectionConfig connectionConfig)
            throws IOException {
        ConnectionConfig useConnectionConfig = null == connectionConfig ? new ConnectionConfig() : connectionConfig;
        LOGGER.debug("httpRequest:[{}],useConnectionConfig:[{}]", JsonUtil.format(httpRequest),
                JsonUtil.format(useConnectionConfig));
        URL url = new URL(httpRequest.getUri());

        Proxy proxy = getProxy(useConnectionConfig.getProxyAddress(), useConnectionConfig.getProxyPort());

        // urlConnection?URL??(http)?URLConnection?HttpURLConnection,
        //  HttpURLConnection, HttpURLConnectionAPI.
        if (Validator.isNotNullOrEmpty(proxy)) {
            LOGGER.debug("use proxy:{}", proxy.toString());
            return (HttpURLConnection) url.openConnection(proxy);
        }
        // ? URL ???? openConnection .
        return (HttpURLConnection) url.openConnection();
    }

    // ******************************************************************************************

    /**
     * ?.
     * 
     * @param proxyAddress
     *            the proxy address
     * @param proxyPort
     *            ?? <br>
     *            A valid port value is between 0 ~ 65535. <br>
     *            A port number of zero will let the system pick up an ephemeral port in a bind operation.
     * @return the proxy
     * @see java.net.Proxy.Type.HTTP
     * @see java.net.InetSocketAddress#InetSocketAddress(String, int)
     */
    private static Proxy getProxy(String proxyAddress, Integer proxyPort) {
        if (Validator.isNotNullOrEmpty(proxyAddress) && Validator.isNotNullOrEmpty(proxyPort)) {
            SocketAddress socketAddress = new InetSocketAddress(proxyAddress, proxyPort);
            return new Proxy(Proxy.Type.HTTP, socketAddress);
        }
        return null;
    }
}