com.discovery.darchrow.net.URIUtil.java Source code

Java tutorial

Introduction

Here is the source code for com.discovery.darchrow.net.URIUtil.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.discovery.darchrow.net;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.discovery.darchrow.io.IOWriteUtil;
import com.discovery.darchrow.lang.ArrayUtil;
import com.discovery.darchrow.lang.CharsetType;
import com.discovery.darchrow.lang.StringUtil;
import com.discovery.darchrow.slf4j.Slf4jUtil;
import com.discovery.darchrow.util.CollectionsUtil;
import com.discovery.darchrow.util.Validator;

/**
 * ?{@link java.net.URI}(Uniform Resource Locator) {@link java.net.URL}(Uniform Resource Identifier) .
 * 
 * <h3>{@link java.net.URI} {@link java.net.URL}:</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>{@link java.net.URL URL}<br>
 * (Uniform Resource Locator)</td>
 * <td>???<br>
 * ???URI?URL???locate? <br>
 * See RFC 1738: Uniform Resource Locators (URL)</td>
 * </tr>
 * <tr valign="top" style="background-color:#eeeeff">
 * <td>{@link java.net.URI URI}<br>
 * (Uniform Resource Identifier)</td>
 * <td>
 * There are two types of URIs: URLs and URNs. <br>
 * See RFC 1630: Universal Resource Identifiers in WWW: A Unifying Syntax for the Expression of Names and Addresses of Objects on the
 * Network as used in the WWW.</td>
 * </tr>
 * </table>
 * 
 * URI??????URI;URL???????schema
 * </blockquote>
 * 
 * 
 * @author feilong
 * @version 1.0.0 2010-6-11 ?02:06:43
 * @see java.net.URI
 * @see java.net.URL
 * @see URIComponents
 * @since 1.0.0
 */
public final class URIUtil {

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

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

    /**
     * .
     * <p>
     * ??? .
     * </p>
     *
     * @param urlString
     *            ?<br>
     *            url ??
     * @param directoryName
     *            
     * @throws IOException
     *             the IO exception
     * @see IOWriteUtil#write(InputStream, String, String)
     */
    public static void download(String urlString, String directoryName) throws IOException {
        if (Validator.isNullOrEmpty(urlString)) {
            throw new NullPointerException("urlString can't be null/empty!");
        }
        if (Validator.isNullOrEmpty(directoryName)) {
            throw new NullPointerException("directoryName can't be null/empty!");
        }

        LOGGER.info("begin download,urlString:[{}],directoryName:[{}]", urlString, directoryName);

        URL url = new URL(urlString);
        InputStream inputStream = url.openStream();

        File file = new File(urlString);
        String fileName = file.getName();

        IOWriteUtil.write(inputStream, directoryName, fileName);

        LOGGER.info("end download,url:[{}],directoryName:[{}]", urlString, directoryName);
    }

    /**
     *  urlcharset {@link URI}. <br>
     *  {@link URI#create(String)}<br>
     * 
     * <p>
     * url????, {@link URI#create(String)}<br>
     * url???, {@link #getEncodedUrlByArrayMap(String, Map, String)}url,?  {@link URI#create(String)}
     * </p>
     *
     * @param url
     *            url
     * @param charsetType
     *            ??null empty,?,?<br>
     *            ??,??,ie?chrome ? url , ?
     * @return if isNullOrEmpty(url),return null;<br>
     *         if Exception,return null
     * @see <a
     *      href="http://stackoverflow.com/questions/15004593/java-request-getquerystring-value-different-between-chrome-and-ie-browser">java-request-getquerystring-value-different-between-chrome-and-ie-browser</a>
     * @see URI#create(String)
     * @see #getEncodedUrlByArrayMap(String, Map, String)
     */
    public static URI create(String url, String charsetType) {
        try {
            String encodeUrl = encodeUrl(url, charsetType);
            URI uri = URI.create(encodeUrl);
            return uri;
        } catch (Exception e) {
            LOGGER.error("Exception:", e);
            throw new URIParseException(e);
        }
    }

    /**
     *  urlcharset {@link URI} <br>
     *  {@link URI#create(String)}<br>
     * 
     * <p>
     * url????, {@link URI#create(String)}<br>
     * url???, {@link #getEncodedUrlByArrayMap(String, Map, String)}url,?  {@link URI#create(String)}
     * </p>
     * .
     *
     * @param url
     *            url
     * @param charsetType
     *            ??null empty,?,?<br>
     *            ??,??,ie?chrome ? url , ?
     * @return the string
     * @see <a
     *      href="http://stackoverflow.com/questions/15004593/java-request-getquerystring-value-different-between-chrome-and-ie-browser">java-request-getquerystring-value-different-between-chrome-and-ie-browser</a>
     * @see URI#create(String)
     * @see #getEncodedUrlByArrayMap(String, Map, String)
     */
    public static String encodeUrl(String url, String charsetType) {
        if (Validator.isNullOrEmpty(url)) {
            throw new NullPointerException("the url is null or empty!");
        }
        if (Validator.isNullOrEmpty(charsetType)) {
            throw new NullPointerException("the charsetType is null or empty!");
        }

        LOGGER.debug("in url:[{}],charsetType:{}", url, charsetType);

        // ?? ?
        // cmens/t-b-f-a-c-s-f-p400-600,0-200,200-400,600-up-gCold Gear-eBase Layer-i1-o.htm

        if (StringUtil.isContain(url, URIComponents.QUESTIONMARK)) {
            // ???
            String before = getBeforePath(url);

            String query = StringUtil.substring(url, URIComponents.QUESTIONMARK, 1);

            Map<String, String[]> map = parseQueryToArrayMap(query, charsetType);
            String encodeUrl = getEncodedUrlByArrayMap(before, map, charsetType);

            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("after url:{}", encodeUrl);
            }
            return encodeUrl;
        } else {
            // ?? ???
            return url;
        }
        // ?URI?URISyntaxException???create(String uri)
        //  new URI(str) 
    }

    /**
     * call {@link java.net.URI#URI(String)}.
     * <p>
     * StringURI???RFC 2396java.net.URISyntaxException.
     * </p>
     *
     * @param path
     *            the path
     * @return {@link java.net.URI#URI(String)}
     * @see java.net.URI#URI(String)
     */
    public static URI getURI(String path) {
        try {
            // StringURI???RFC 2396java.net.URISyntaxException.
            URI uri = new URI(path);
            return uri;
        } catch (URISyntaxException e) {
            LOGGER.error(Slf4jUtil.formatMessage("path:[{}]", path), e);
            throw new URIParseException(e);
        }
    }

    /**
     * ?path??.
     *
     * @param path
     *            ?
     * @return ??, <b>true </b>,? <b>false </b>
     */
    public static boolean isAbsolutePath(String path) {
        URI uri = getURI(path);

        if (null == uri) {
            return false;
        }
        return uri.isAbsolute();
    }

    /**
     * url(charsetType null,,?,url).
     *
     * @param beforeUrl
     *            ???, ?,    ?? keyAndValueMap
     * @param keyAndValueMap
     *            ?Map? Map
     * @param charsetType
     *            ??null empty,?,?<br>
     *            ??,??,ie?chrome ? url , ?
     * @return the encoded url1
     */
    public static String getEncodedUrlByValueMap(String beforeUrl, Map<String, String> keyAndValueMap,
            String charsetType) {
        Map<String, String[]> keyAndArrayMap = new HashMap<String, String[]>();

        if (Validator.isNotNullOrEmpty(keyAndValueMap)) {
            for (Map.Entry<String, String> entry : keyAndValueMap.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                keyAndArrayMap.put(key, new String[] { value });
            }
        }

        return getEncodedUrlByArrayMap(beforeUrl, keyAndArrayMap, charsetType);
    }

    /**
     * url(charsetType null,,?,url).
     *
     * @param beforeUrl
     *            ???, ?,    ?? keyAndArrayMap
     * @param keyAndArrayMap
     *            ?map value? request.getParameterMap
     * @param charsetType
     *            ??null empty,?,?<br>
     *            ??,??,ie?chrome ? url , ?
     * @return if isNullOrEmpty(keyAndArrayMap) return beforeUrl;
     * @see #combineQueryString(Map, String)
     */
    public static String getEncodedUrlByArrayMap(String beforeUrl, Map<String, String[]> keyAndArrayMap,
            String charsetType) {
        if (Validator.isNullOrEmpty(keyAndArrayMap)) {
            return beforeUrl;
        }

        // map ?  ?
        Map<String, String[]> appendMap = new HashMap<String, String[]>();
        appendMap.putAll(keyAndArrayMap);

        // ? action before ??
        // "action": "https://202.6.215.230:8081/purchasing/purchase.do?action=loginRequest",
        // "fullEncodedUrl":
        // "https://202.6.215.230:8081/purchasing/purchase.do?action=loginRequest?miscFee=0&descp=&klikPayCode=03BELAV220&callback=%2Fpatment1url&totalAmount=60000.00&payType=01&transactionNo=20140323024019&signature=1278794012&transactionDate=23%2F03%2F2014+02%3A40%3A19&currency=IDR",

        // *******************************************
        String beforePath = beforeUrl;

        // ??
        if (StringUtil.isContain(beforeUrl, URIComponents.QUESTIONMARK)) {
            // ???
            beforePath = getBeforePath(beforeUrl);
            String query = StringUtil.substring(beforeUrl, URIComponents.QUESTIONMARK, 1);

            Map<String, String[]> map = parseQueryToArrayMap(query, null);
            appendMap.putAll(map);
        }

        StringBuilder builder = new StringBuilder("");
        builder.append(beforePath);
        builder.append(URIComponents.QUESTIONMARK);

        // *******************************************
        String queryString = combineQueryString(appendMap, charsetType);
        builder.append(queryString);

        return builder.toString();
    }

    /**
     * map ?? queryString.
     *
     * @param appendMap
     *             request.getParamMap
     * @param charsetType
     *            {@link CharsetType} ??null empty,?,?<br>
     *            ??,??,ie?chrome ? url , ?
     * @return if isNullOrEmpty(appendMap) ,return ""
     * @see CharsetType
     */
    public static String combineQueryString(Map<String, String[]> appendMap, String charsetType) {
        if (Validator.isNullOrEmpty(appendMap)) {
            return "";
        }

        StringBuilder sb = new StringBuilder();

        int i = 0;
        int size = appendMap.size();
        for (Map.Entry<String, String[]> entry : appendMap.entrySet()) {
            String key = entry.getKey();
            String[] paramValues = entry.getValue();

            // **************************************************************
            if (Validator.isNotNullOrEmpty(charsetType)) {
                //  decode ? encode
                // ?
                key = encode(decode(key, charsetType), charsetType);
            }

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

            if (Validator.isNullOrEmpty(paramValues)) {
                LOGGER.warn("the param key:[{}] value is null", key);
                sb.append(key);
                sb.append("=");
                sb.append("");
            } else {
                List<String> paramValueList = null;
                // value isNotNullOrEmpty
                if (Validator.isNotNullOrEmpty(charsetType)) {
                    paramValueList = new ArrayList<String>();
                    for (String value : paramValues) {
                        if (Validator.isNotNullOrEmpty(value)) {
                            // ?queryString()?
                            // chrome query  encoded ???
                            // ie ????

                            // ??encoded, decode ? encode
                            // ? decode(query, charsetType)   ,? =
                            paramValueList.add(encode(decode(value.toString(), charsetType), charsetType));
                        } else {
                            paramValueList.add("");
                        }
                    }
                } else {
                    paramValueList = ArrayUtil.toList(paramValues);
                }

                for (int j = 0, z = paramValueList.size(); j < z; ++j) {
                    String value = paramValueList.get(j);
                    sb.append(key);
                    sb.append("=");
                    sb.append(value);
                    // ?& ?
                    if (j != z - 1) {
                        sb.append(URIComponents.AMPERSAND);
                    }
                }
            }

            // ?& ?
            if (i != size - 1) {
                sb.append(URIComponents.AMPERSAND);
            }
            ++i;
        }
        return sb.toString();
    }

    /**
     * {@code a=1&b=2}????map (charsetType ?nullempty  keyvalue).
     *
     * @param query
     *            the query
     * @param charsetType
     *            ??null empty,?,?<br>
     *            ??,??,ie?chrome ? url , ?
     * @return the {@code map<string, string>}
     * @see #parseQueryToArrayMap(String, String)
     */
    public static Map<String, String> parseQueryToValueMap(String query, String charsetType) {
        Map<String, String> returnMap = new HashMap<String, String>();
        Map<String, String[]> map = parseQueryToArrayMap(query, charsetType);
        if (Validator.isNotNullOrEmpty(map)) {
            for (Map.Entry<String, String[]> entry : map.entrySet()) {
                String key = entry.getKey();
                String[] value = entry.getValue();
                returnMap.put(key, value[0]);
            }
        }
        return returnMap;
    }

    /**
     * {@code a=1&b=2}????map (charsetType ?nullempty  keyvalue).
     *
     * @param query
     *            {@code a=1&b=2}?,?{@code a=1&a=1}? map
     * @param charsetType
     *            ??null empty,?,?<br>
     *            ??,??,ie?chrome ? url , ?
     * @return map value? {@link LinkedHashMap#LinkedHashMap(int, float)}
     *         <ul>
     *         <li>Validator.isNullOrEmpty(bianma) </li>
     *         <li>?, decode ? encode</li>
     *         </ul>
     */
    public static Map<String, String[]> parseQueryToArrayMap(String query, String charsetType) {
        if (Validator.isNotNullOrEmpty(query)) {
            String[] nameAndValueArray = query.split(URIComponents.AMPERSAND);

            if (Validator.isNotNullOrEmpty(nameAndValueArray)) {

                Map<String, String[]> map = new LinkedHashMap<String, String[]>();

                for (int i = 0, j = nameAndValueArray.length; i < j; ++i) {

                    String nameAndValue = nameAndValueArray[i];
                    String[] tempArray = nameAndValue.split("=", 2);

                    if (tempArray != null && tempArray.length == 2) {
                        String key = tempArray[0];
                        String value = tempArray[1];

                        if (Validator.isNullOrEmpty(charsetType)) {
                            // ? 
                        } else {

                            // ?queryString()?
                            // chrome query  encoded ???
                            // ie ????

                            // ??encoded, decode ? encode
                            // ?  decode(query, charsetType) ,? =

                            //  decode ? encode
                            // ?
                            key = encode(decode(key, charsetType), charsetType);
                            value = encode(decode(value, charsetType), charsetType);
                        }

                        String[] valuesArrayInMap = map.get(key);

                        List<String> list = null;
                        if (Validator.isNullOrEmpty(valuesArrayInMap)) {
                            list = new ArrayList<String>();
                        } else {
                            list = ArrayUtil.toList(valuesArrayInMap);
                        }
                        list.add(value);
                        map.put(key, CollectionsUtil.toArray(list));
                    }
                }
                return map;
            }
        }
        return null;
    }

    /**
     * ????(???).
     * 
     * @param url
     *            the url
     * @return if isNullOrEmpty(url),renturn ""
     * @deprecated will rename ???
     */
    //TODO will rename
    @Deprecated
    public static String getBeforePath(String url) {
        if (Validator.isNullOrEmpty(url)) {
            return "";
        }
        String before = "";
        // url???
        int index = url.indexOf(URIComponents.QUESTIONMARK);
        if (index == -1) {
            before = url;
        } else {
            before = url.substring(0, index);
        }
        return before;
    }

    /**
     * ???url, spec ? URL.  URL  URL  spec ?<br>
     * ?,{@link #getUnionUrl(URL, String)}
     * <p>
     * : URIUtil.getUnionUrl("E:\\test", "sanguo")-------------{@code >}file:/E:/test/sanguo
     *
     * @param context
     *            ??
     * @param spec
     *            the <code>String</code> to parse as a URL.
     * @return ???url
     */
    public static String getUnionUrl(String context, String spec) {
        URL parentUrl = getURL(context);
        return getUnionUrl(parentUrl, spec);
    }

    /**
     * ???url, spec ? URL.  URL  URL  spec ?<br>
     * ?,method
     * 
     * <pre>
     * {@code
     * : URIUtil.getUnionUrl("E:\\test", "sanguo")------------->file:/E:/test/sanguo
     * URL url = new URL("http://www.exiaoshuo.com/jinyiyexing/");
     * result = URIUtil.getUnionUrl(url, "/jinyiyexing/1173348/");
     * http://www.exiaoshuo.com/jinyiyexing/1173348/
     * }
     * </pre>
     *
     * @param context
     *            ??
     * @param spec
     *            the <code>String</code> to parse as a URL.
     * @return ???url
     */
    public static String getUnionUrl(URL context, String spec) {
        try {
            URL unionUrl = new URL(context, spec);
            return unionUrl.toString();
        } catch (MalformedURLException e) {
            LOGGER.error("MalformedURLException:", e);
            throw new URIParseException(e);
        }
    }

    /**
     * ?url.
     *
     * @param filePathName
     *            
     * @return url
     * @see java.io.File#toURI()
     * @see java.net.URI#toURL()
     */
    public static URL getURL(String filePathName) {
        if (Validator.isNullOrEmpty(filePathName)) {
            throw new NullPointerException("filePathName can't be null/empty!");
        }

        File file = new File(filePathName);
        try {
            // file.toURL() ?,? URL ?
            return file.toURI().toURL();
        } catch (MalformedURLException e) {
            LOGGER.error("MalformedURLException:", e);
            throw new URIParseException(e);
        }
    }

    // [start] encode/decode

    /**
     * iso-8859??.
     * 
     * @param str
     *            
     * @param bianma
     *            ?
     * @return ?<br>
     *         if isNullOrEmpty(str) return ""
     * @deprecated
     */
    @Deprecated
    public static String decodeLuanMaISO8859(String str, String bianma) {
        if (Validator.isNullOrEmpty(str)) {
            return "";
        }
        //StringUtil.toBytes(value, charsetName)

        try {
            return new String(str.trim().getBytes(CharsetType.ISO_8859_1), bianma);
        } catch (UnsupportedEncodingException e) {
            LOGGER.error(e.getClass().getName(), e);
        }
        return "";
    }

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

    /**
     * ?,?? <br>
     * 
     * <ul>
     * <li>? "a"  "z"?"A"  "Z"  "0"  "9" ????.</li>
     * <li> "."?"-"?"*"  "_" ????.</li>
     * <li> " " ?? "+".</li>
     * <li>???.<br>
     * ??? 3  "%xy"  xy ????.<br>
     * ??? UTF-8.<br>
     * ????.</li>
     * </ul>
     *
     * @param value
     *            the value
     * @param charsetType
     *            charsetType {@link CharsetType}
     * @return {@link java.net.URLEncoder#encode(String, String)}<br>
     *         if isNullOrEmpty(charsetType),  value<br>
     * @see URLEncoder#encode(String, String)
     * @see CharsetType
     */
    public static String encode(String value, String charsetType) {
        if (Validator.isNullOrEmpty(charsetType)) {
            return value;
        }
        try {
            return URLEncoder.encode(value, charsetType);
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("UnsupportedEncodingException:", e);
            throw new URIParseException(e);
        }
    }

    /**
     * ?,?? <br>
     * Decodes a <code>application/x-www-form-urlencoded</code> string using a specific encoding scheme. The supplied encoding is used to
     * determine what characters are represented by any consecutive sequences of the form "<code>%<i>xy</i></code>".
     * 
     * <p>
     * Not doing so may introduce incompatibilites.<br>
     * <em><strong>Note:</strong> 
     * <a href="http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars">World Wide Web Consortium Recommendation</a>UTF-8. ????.</em>
     * </p>
     *
     * @param value
     *            ??
     * @param charsetType
     *            charsetType {@link CharsetType}
     * @return the newly {@link java.net.URLDecoder#decode(String, String)} ??<br>
     *         if isNullOrEmpty(charsetType) , value<br>
     * @see URLEncoder#encode(java.lang.String, java.lang.String)
     * @see CharsetType
     */
    public static String decode(String value, String charsetType) {
        if (Validator.isNullOrEmpty(charsetType)) {
            return value;
        }
        try {
            return URLDecoder.decode(value, charsetType);
        } catch (UnsupportedEncodingException e) {
            LOGGER.error("UnsupportedEncodingException:", e);
            throw new URIParseException(e);
        }
    }

    /**
     * queryString.
     * 
     * <h3>:</h3>
     * <blockquote>
     * 
     * <pre class="code">
     * URIUtil.getQueryString({@code "http://127.0.0.1/cmens/t-b-f-a-c-s-f-p-g-e-i-o.htm?a=1&a=2"})
     * </pre>
     * 
     * : {@code a=1&a=2}
     * </blockquote>
     * 
     * @param uriString
     *            the uri
     * @return ? <code>uriString</code> isNullOrEmpty, {@link StringUtils#EMPTY};<br>
     *         ? <code>uriString</code> ???, {@link StringUtils#EMPTY};<br>
     *         ?????
     * @since 1.4.0
     */
    public static String getQueryString(String uriString) {
        if (Validator.isNullOrEmpty(uriString)) {
            return StringUtils.EMPTY;
        }
        // url???  XXX 
        int index = uriString.indexOf(URIComponents.QUESTIONMARK);
        return index == StringUtils.INDEX_NOT_FOUND ? StringUtils.EMPTY
                : StringUtil.substring(uriString, index + 1);
    }

    /**
     * ??queryStringpath,????( <span style="color:red">???</span>).
     *
     * @param uriString
     *            the uri
     * @return  isNullOrEmpty(url), {@link StringUtils#EMPTY}
     * @since 1.4.0
     */
    public static String getFullPathWithoutQueryString(String uriString) {
        if (Validator.isNullOrEmpty(uriString)) {
            return StringUtils.EMPTY;
        }
        // url???  XXX 
        int index = uriString.indexOf(URIComponents.QUESTIONMARK);
        return index == StringUtils.INDEX_NOT_FOUND ? uriString : uriString.substring(0, index);
    }

    // [end]
    //*********************************************************************************

    /**
     * url16?,url.
     * 
     * @param specialCharacter
     *            
     * @return url?
     * @deprecated ??
     */
    @Deprecated
    public static String specialCharToHexString(String specialCharacter) {

        Map<String, String> specialCharacterMap = new HashMap<String, String>();

        specialCharacterMap.put("+", "%2B");// URL +?
        specialCharacterMap.put(" ", "%20");// URL?+??
        specialCharacterMap.put("/", "%2F");// ?
        specialCharacterMap.put(URIComponents.QUESTIONMARK, "%3F");//  URL ?
        specialCharacterMap.put("%", "%25");// 
        specialCharacterMap.put("#", "%23");// 
        specialCharacterMap.put("&", "%26");// URL ?
        specialCharacterMap.put("=", "%3D");// URL ?

        if (specialCharacterMap.containsKey(specialCharacter)) {
            return specialCharacterMap.get(specialCharacter);
        }
        // ? url  
        return specialCharacter;
    }
}