/*
 * UnicodeDetector,  <enter purpose here>.
 * Copyright (C) 2005  Achim Westermann, Achim.Westermann@gmx.de
 *
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this collection are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the cpDetector code in [sub] packages info.monitorenter and
 * cpdetector.
 *
 * The Initial Developer of the Original Code is
 * Achim Westermann <achim.westermann@gmx.de>.
 *
 * Portions created by the Initial Developer are Copyright (c) 2007
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** *
 *
 * If you modify or optimize the code in a useful way please let me know.
 * Achim.Westermann@gmx.de
 */
package info.monitorenter.cpdetector.io;

import info.monitorenter.cpdetector.io.AbstractCodepageDetector;
import info.monitorenter.cpdetector.io.ICodepageDetector;
import info.monitorenter.cpdetector.io.UnknownCharset;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.Charset;

public class UnicodeDetector extends AbstractCodepageDetector {
    private static ICodepageDetector instance;

    /**
     * Singleton constructor
     */
    private UnicodeDetector() {
        super();
    }

    public static ICodepageDetector getInstance() {
        if (instance == null) {
            instance = new UnicodeDetector();
        }
        return instance;
    }

    /*
     * (non-Javadoc) It is assumed that the inputstream is at the start of the file or String (in order to read the
     * BOM).
     *
     * @see cpdetector.io.ICodepageDetector#detectCodepage(java.io.InputStream, int)
     *
     */
    public Charset detectCodepage(InputStream in, int length) throws IOException {
        byte[] bom = new byte[4]; // Get the byte-order mark, if there is one
        in.read(bom, 0, 4);
        // Unicode formats => read BOM
        byte b = (byte)0xEF;
        if (bom[0] == (byte)0x00 && bom[1] == (byte)0x00 && bom[2] == (byte)0xFE
                && bom[2] == (byte)0xFF) // utf-32BE
            return Charset.forName("UTF-32BE");
        if (bom[0] == (byte)0xFF && bom[1] == (byte)0xFE && bom[2] == (byte)0x00
                && bom[2] == (byte)0x00) // utf-32BE
            return Charset.forName("UTF-32LE");
        if (bom[0] == (byte)0xEF && bom[1] == (byte)0xBB && bom[2] == (byte)0xBF) // utf-8
            return Charset.forName("UTF-8");
        if (bom[0] == (byte)0xff && bom[1] == (byte)0xfe) // ucs-2le, ucs-4le, and ucs-16le
            return Charset.forName("UTF-16LE");
        if (bom[0] == (byte)0xfe && bom[1] == (byte)0xff) // utf-16 and ucs-2
            return Charset.forName("UTF-16BE");
        if (bom[0] == (byte)0 && bom[1] == (byte)0 && bom[2] == (byte)0xfe && bom[3] == (byte)0xff) // ucs-4
            return Charset.forName("UCS-4");
        return UnknownCharset.getInstance();
    }

    /**
     * @see info.monitorenter.cpdetector.io.ICodepageDetector#detectCodepage(java.net.URL)
     */
    public Charset detectCodepage(final URL url) throws IOException {
        Charset result;
        BufferedInputStream in = new BufferedInputStream(url.openStream());
        result = this.detectCodepage(in, Integer.MAX_VALUE);
        in.close();
        return result;
    }

}


package com.xiongyingqi.util;

import java.util.Collection;
import java.util.Map;

/**
 * Created by 瑛琪xiongyingqi.com on 2014/8/11 0011.
 */
public class Judgment {
    /**
     * 判断String对象是否包含字符（如果全部为空格也返回false）
     *
     * @param string
     * @return
     */
    public static boolean hasText(String... string) {
        if (string == null) {
            return false;
        }

        boolean flag = true;
        for (String s : string) {
            flag = flag && (s != null && !"".equals(s.trim()));
            if (!flag) {
                return false;
            }
        }
        return flag;
    }

    public static boolean isNull(Object... o) {
        if (o != null) {
            return false;
        }

        boolean flag = true;
        for (Object o1 : o) {
            flag = flag && (o1 == null);
            if (!flag) {
                return false;
            }
        }
        return flag;
    }

    public static boolean notNull(Object... o) {
        if (o == null) {
            return false;
        }

        boolean flag = true;
        for (Object o1 : o) {
            flag = flag && (o1 != null);
            if (!flag) {
                return false;
            }
        }
        return flag;
    }

    public static boolean notEmpty(Collection... collection) {
        if (collection == null) {
            return false;
        }

        boolean flag = true;
        for (Collection o1 : collection) {
            flag = flag && (o1 != null && o1.size() > 0);
            if (!flag) {
                return false;
            }
        }
        return flag;
    }

    public static boolean hasEntry(Map... map) {
        if (map == null) {
            return false;
        }

        boolean flag = true;
        for (Map o1 : map) {
            flag = flag && (o1 != null && o1.size() > 0);
            if (!flag) {
                return false;
            }
        }
        return flag;
    }

    public static boolean isTrue(boolean... flag) {
        boolean _flag = true;
        for (boolean b : flag) {
            _flag = _flag && b;
            if (!_flag) {
                return false;
            }
        }
        return _flag;
    }

}


package com.xiongyingqi.utils.baidu.ip;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiongyingqi.http.BuildNameValuePairsHelper;
import com.xiongyingqi.http.HttpAccess;
import com.xiongyingqi.http.HttpBuilder;
import com.xiongyingqi.util.EntityHelper;
import com.xiongyingqi.util.MD5Helper;
import com.xiongyingqi.util.UnicodeHelper;
import com.xiongyingqi.util.comparator.StringComparator;
import com.xiongyingqi.utils.baidu.CommonUtil;
import com.xiongyingqi.utils.baidu.ip.vo.IpAddressVo;
import org.apache.http.NameValuePair;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;

/**
 * Created by 瑛琪xiongyingqi.com on 2014/5/4 0004.
 */
public class IpAddress {

    public IpAddressVo getIp(String ip) throws IOException {
        HttpBuilder httpBuilder = HttpBuilder.newBuilder().get().charset("UTF-8").param("ip", ip).param("ak", CommonUtil.ak);
        httpBuilder.url(CommonUtil.ipLocationApiUrl + "?" + BuildNameValuePairsHelper.buildParameters(httpBuilder.getNameValuePairs()));
        if (CommonUtil.sn) {
            String sign = calculateAKSN(CommonUtil.ak, CommonUtil.sk, CommonUtil.ipLocationApiUrl, httpBuilder.getNameValuePairs(), "POST");
            httpBuilder.param("sn", sign);
        }
        String rs = HttpAccess.execute(HttpAccess.getClient(), httpBuilder.build());
        rs = UnicodeHelper.unicodeToUtf8(rs);
        ObjectMapper mapper = CommonUtil._mapper.get();
        IpAddressVo ipAddressVo = mapper.readValue(rs, IpAddressVo.class);
        return ipAddressVo;
    }

    /**
     * sn = MD5(urlencode(basicString + sk))
     *

     * 其中 basicString 的算法如下：
     *

     * (1) get 请求
     *

     * url 中 http://域名{uri}
     *

     * basicString = uri
     *

     * (2) post 请求
     *

     * url 中 http://域名{uri} POST 参数按照key进行从小大到字母排序
     *

     * 然后拼装成：k1=v1&k2=v2&k3=v3&...&kn=vn的格式=> {params}
     *

     * basicString = uri +?+ params
     *
     * @param ak             access key
     * @param sk             secret key
     * @param url            url值，例如: /geosearch/nearby 不能带hostname和querstring，也不能带？
     * @param nameValuePairs $querystring_arrays 参数数组，key=>value形式。在计算签名后不能重新排序，也不能添加或者删除数据元素
     * @param method         method 只能为'POST'或者'GET'
     * @return 计算SN签名算法
     */
    public String calculateAKSN(String ak, String sk, String url, List<NameValuePair> nameValuePairs, String method) {
        String params = "";
        if (method.equals("POST")) {
            Collections.sort(nameValuePairs, new Comparator<NameValuePair>() {
                @Override
                public int compare(NameValuePair o1, NameValuePair o2) {
                    StringComparator comparator = new StringComparator();
                    return comparator.compare(o1.getName(), o2.getName());
                }
            });

            StringBuilder stringBuilder = new StringBuilder();
            for (Iterator<NameValuePair> iterator = nameValuePairs.iterator(); iterator.hasNext(); ) {
                NameValuePair nameValuePair = iterator.next();
                String name = nameValuePair.getName();
                String value = nameValuePair.getValue();
                stringBuilder.append(name);
                stringBuilder.append("=");
                stringBuilder.append(value);
                if (iterator.hasNext()) {
                    stringBuilder.append("&");
                }
            }
            params = stringBuilder.toString();
        }

        String basicString = url + "? " + params;
        String sn = null;
        try {
            sn = MD5Helper.encrypt(URLEncoder.encode(basicString + sk, "UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return sn;
    }

    public static void main(String[] args) {
        EntityHelper.print(IpAddress.class.getClassLoader().getResource("baidu_api.properties").getPath());
        EntityHelper.print(IpAddress.class.getClassLoader().getResource("baidu_api.properties").getFile());

        List<String> strs = new ArrayList<String>();
        strs.add("a");
        strs.add("421");
        strs.add("cc");
        strs.add("dd");
        strs.add("123");
        strs.add("bb");
        Collections.sort(strs, new StringComparator());
        EntityHelper.print(strs);
        StringComparator comparator = new StringComparator();
        EntityHelper.print(comparator.compare("a", "b"));
        EntityHelper.print(comparator.compare("a", "a"));
        EntityHelper.print(comparator.compare("a", "ab"));
        EntityHelper.print(comparator.compare("ab", "ac"));

        IpAddress ipAddress = new IpAddress();
        try {
            IpAddressVo ip = ipAddress.getIp("");
            EntityHelper.print(ip);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


/*
 * Copyright 2002-2013 the original author or authors.
 *
 * 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.xiongyingqi.util.xml;

import com.xiongyingqi.util.Assert;
import org.w3c.dom.CharacterData;
import org.w3c.dom.*;
import org.xml.sax.ContentHandler;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * Convenience methods for working with the DOM API, in particular for working with DOM Nodes and DOM Elements.
 *
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @author Costin Leau
 * @author Arjen Poutsma
 * @author Luke Taylor
 * @see org.w3c.dom.Node
 * @see org.w3c.dom.Element
 * @since 1.2
 */
public abstract class DomUtils {

    /**
     * Retrieves all child elements of the given DOM element that match any of the given element names.
     * Only looks at the direct child level of the given element; do not go into further depth
     * (in contrast to the DOM API's {@code getElementsByTagName} method).
     *
     * @param ele           the DOM element to analyze
     * @param childEleNames the child element names to look for
     * @return a List of child {@code org.w3c.dom.Element} instances
     * @see org.w3c.dom.Element
     * @see org.w3c.dom.Element#getElementsByTagName
     */
    public static List<Element> getChildElementsByTagName(Element ele, String[] childEleNames) {
        Assert.notNull(ele, "Element must not be null");
        Assert.notNull(childEleNames, "Element names collection must not be null");
        List<String> childEleNameList = Arrays.asList(childEleNames);
        NodeList nl = ele.getChildNodes();
        List<Element> childEles = new ArrayList<Element>();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element && nodeNameMatch(node, childEleNameList)) {
                childEles.add((Element) node);
            }
        }
        return childEles;
    }

    /**
     * Retrieves all child elements of the given DOM element that match the given element name.
     * Only look at the direct child level of the given element; do not go into further depth
     * (in contrast to the DOM API's {@code getElementsByTagName} method).
     *
     * @param ele          the DOM element to analyze
     * @param childEleName the child element name to look for
     * @return a List of child {@code org.w3c.dom.Element} instances
     * @see org.w3c.dom.Element
     * @see org.w3c.dom.Element#getElementsByTagName
     */
    public static List<Element> getChildElementsByTagName(Element ele, String childEleName) {
        return getChildElementsByTagName(ele, new String[]{childEleName});
    }

    /**
     * Utility method that returns the first child element identified by its name.
     *
     * @param ele          the DOM element to analyze
     * @param childEleName the child element name to look for
     * @return the {@code org.w3c.dom.Element} instance, or {@code null} if none found
     */
    public static Element getChildElementByTagName(Element ele, String childEleName) {
        Assert.notNull(ele, "Element must not be null");
        Assert.notNull(childEleName, "Element name must not be null");
        NodeList nl = ele.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element && nodeNameMatch(node, childEleName)) {
                return (Element) node;
            }
        }
        return null;
    }

    /**
     * Utility method that returns the first child element value identified by its name.
     *
     * @param ele          the DOM element to analyze
     * @param childEleName the child element name to look for
     * @return the extracted text value, or {@code null} if no child element found
     */
    public static String getChildElementValueByTagName(Element ele, String childEleName) {
        Element child = getChildElementByTagName(ele, childEleName);
        return (child != null ? getTextValue(child) : null);
    }

    /**
     * Retrieves all child elements of the given DOM element
     *
     * @param ele the DOM element to analyze
     * @return a List of child {@code org.w3c.dom.Element} instances
     */
    public static List<Element> getChildElements(Element ele) {
        Assert.notNull(ele, "Element must not be null");
        NodeList nl = ele.getChildNodes();
        List<Element> childEles = new ArrayList<Element>();
        for (int i = 0; i < nl.getLength(); i++) {
            Node node = nl.item(i);
            if (node instanceof Element) {
                childEles.add((Element) node);
            }
        }
        return childEles;
    }

    /**
     * Extracts the text value from the given DOM element, ignoring XML comments.
     * <p>Appends all CharacterData nodes and EntityReference nodes into a single
     * String value, excluding Comment nodes. Only exposes actual user-specified
     * text, no default values of any kind.
     *
     * @see org.w3c.dom.CharacterData
     * @see org.w3c.dom.EntityReference
     * @see org.w3c.dom.Comment
     */
    public static String getTextValue(Element valueEle) {
        Assert.notNull(valueEle, "Element must not be null");
        StringBuilder sb = new StringBuilder();
        NodeList nl = valueEle.getChildNodes();
        for (int i = 0; i < nl.getLength(); i++) {
            Node item = nl.item(i);
            if ((item instanceof CharacterData && !(item instanceof Comment)) || item instanceof EntityReference) {
                sb.append(item.getNodeValue());
            }
        }
        return sb.toString();
    }

    /**
     * Namespace-aware equals comparison. Returns {@code true} if either
     * {@link org.w3c.dom.Node#getLocalName} or {@link org.w3c.dom.Node#getNodeName} equals
     * {@code desiredName}, otherwise returns {@code false}.
     */
    public static boolean nodeNameEquals(Node node, String desiredName) {
        Assert.notNull(node, "Node must not be null");
        Assert.notNull(desiredName, "Desired name must not be null");
        return nodeNameMatch(node, desiredName);
    }

    /**
     * Returns a SAX {@code ContentHandler} that transforms callback calls to DOM {@code Node}s.
     *
     * @param node the node to publish events to
     * @return the content handler
     */
    public static ContentHandler createContentHandler(Node node) {
        return new DomContentHandler(node);
    }

    /**
     * Matches the given node's name and local name against the given desired name.
     */
    private static boolean nodeNameMatch(Node node, String desiredName) {
        return (desiredName.equals(node.getNodeName()) || desiredName.equals(node.getLocalName()));
    }

    /**
     * Matches the given node's name and local name against the given desired names.
     */
    private static boolean nodeNameMatch(Node node, Collection<?> desiredNames) {
        return (desiredNames.contains(node.getNodeName()) || desiredNames.contains(node.getLocalName()));
    }

}


/*
 *  StreamTableRenderer.java
 *  Copyright (c) 2007 Achim Westermann, created on 21.10.2004, 23:22:23
 *
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this collection are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the cpDetector code in [sub] packages info.monitorenter and
 * cpdetector.
 *
 * The Initial Developer of the Original Code is
 * Achim Westermann <achim.westermann@gmx.de>.
 *
 * Portions created by the Initial Developer are Copyright (c) 2007
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** *
 *
 * If you modify or optimize the code in a useful way please let me know.
 * Achim.Westermann@gmx.de
 */
package info.monitorenter.cpdetector.util.collections.ui;

import java.io.IOException;
import java.io.Writer;

import javax.swing.table.TableModel;

/**
 * @author Achim Westermann
 *
 */
public abstract class StreamTableRenderer implements ITableRenderer {

  final static int FIRST_CELL_IN_ROW = 0;
  final static int LAST_CELL_IN_ROW = 1;

  protected Writer m_out;
  public StreamTableRenderer(Writer out){
    this.m_out = out;
  }

  protected final void renderHeader(TableModel model) throws IOException{
    int cols = model.getColumnCount();
    for(int i=0;i<cols;i++){
      this.renderHeaderCell(model.getColumnName(i),(i==0)?FIRST_CELL_IN_ROW:(i==cols-1)?LAST_CELL_IN_ROW:2);
    }
  }

  /**
   * @throws java.io.IOException
   *
   */
  private final void renderHeaderCell(String columnName, int firstOrLast) throws IOException {
    m_out.write(this.HeadCellStartTag((firstOrLast==FIRST_CELL_IN_ROW)));
    m_out.write(columnName);
    m_out.write(this.HeadCellStopTag((firstOrLast==LAST_CELL_IN_ROW)));
  }

  protected abstract String HeadRowStartTag();
  protected abstract String HeadRowStopTag();

  protected abstract String HeadCellStopTag(boolean firstOrLast);

  protected abstract String HeadCellStartTag(boolean firstOrLast);

  protected final void renderRow(TableModel model, int row) throws IOException{
    m_out.write(RowStartTag());
    int cols = model.getColumnCount();
    for(int i=0;i<cols;i++){
      this.renderCell(model.getValueAt(row,i),(i==0)?FIRST_CELL_IN_ROW:(i==cols-1)?LAST_CELL_IN_ROW:2);
    }
    m_out.write(RowStopTag());
  }

  protected abstract String RowStartTag();
  protected abstract String RowStopTag();

  protected final void renderCell(Object content,int firstOrLast) throws IOException{
    m_out.write(this.CellStartTag((firstOrLast==FIRST_CELL_IN_ROW)));
    if(content instanceof TableModel){
      this.render((TableModel)content);
    }
    else{
      m_out.write(content.toString());
    }
    m_out.write(this.CellStopTag((firstOrLast==LAST_CELL_IN_ROW)));
  }

  protected abstract String CellStartTag(boolean rowstart);
  protected abstract String CellStopTag(boolean rowend);

  /* (non-Javadoc)
   * @see cpdetector.util.collections.ui.ITableRenderer#render(javax.swing.table.TableModel)
   */
  public final void render(TableModel model) throws IOException {
    this.m_out.write(this.TableStartTag());
    int rows = model.getRowCount();
    // write header
    m_out.write(this.HeadRowStartTag());
    this.renderHeader(model);
    m_out.write(this.HeadRowStopTag());

    for(int i=0;i<rows;i++){
      this.renderRow(model,i);
    }
    this.m_out.write(this.TableStopTag());
  }

  protected abstract String TableStartTag();
  protected abstract String TableStopTag();
}


package com.xiongyingqi.util;

public class DomainHelper {
    /**
     * 移除主机字符，例如传入admin@xiongyingqi.com，那么该方法将截取@之前的字符返回admin
     *
     * @param str
     * @return
     */
    public static String removeDomain(String str) {
        if (str != null && !"".equals(str)) {
            int index = str.indexOf("@");
            if (index >= 0) {
                str = str.substring(0, index);
            }
        }
        return str;
    }
}


/*
 * StringUtil.java, helpers for strings.
 * Copyright (C) 2001 Achim Westermann
 *
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this collection are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is the cpDetector code in [sub] packages info.monitorenter and
 * cpdetector.
 *
 * The Initial Developer of the Original Code is
 * Achim Westermann <achim.westermann@gmx.de>.
 *
 * Portions created by the Initial Developer are Copyright (c) 2007
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** *
 *
 * If you modify or optimize the code in a useful way please let me know.
 * Achim.Westermann@gmx.de *
 */package info.monitorenter.util;

import java.lang.reflect.Array;
import java.util.List;
import java.util.Map;

/**
 * Nice static helpers for working with Strings.
 *

 * Maybe not always the fastest solution to call in here, but working. Also
 * usable for seeing examples and cutting code for manual inlining.
 *

 *
 * @author Achim.Westermann@gmx.de
 *
 * @version $Revision: 1.3 $
 */
public final class StringUtil {

  /** Singleton instance. */
  private static StringUtil instance = null;

  /**
   * Appends the given amount of spaces to the String.
   *

   *
   * Not intended for big append -operations because in a loop alway just one
   * space is added.
   *

   *
   * @param s
   *          the base String to append spaces to.
   *
   * @param count
   *          the amount of spaces to append.
   *
   * @return a String consisting of s and count trailing whitespaces.
   */
  public static final String appendSpaces(final String s, final int count) {
    StringBuffer tmp = new StringBuffer(s);
    for (int i = 0; i < count; i++) {
      tmp.append(" ");
    }
    return tmp.toString();
  }

  /**
   * If the given Object is no Array, it's toString - method is invoked.
   * Primitive type - Arrays and Object - Arrays are introspected using
   * java.lang.reflect.Array. Convention for creation fo String -
   * representation:

   *
   * @see info.monitorenter.util.StringUtil#arrayToString(Object, String)
   *
   * @param isArr
   *          The Array to represent as String.
   *
   * @return a String-representation of the Object.
   *
   *
   */
  public static final String arrayToString(final Object isArr) {
    String result = StringUtil.arrayToString(isArr, ",");
    return result;
  }

  /**
   * If the given Object is no Array, it's toString - method is invoked.
   * Primitive type - Arrays and Object - Arrays are introspected using
   * java.lang.reflect.Array. Convention for creation for String -
   * representation:

   *
   *
   * // Primitive arrays:
   * "["+isArr[0]+"<separator>"+isArr[1]+.. ..+isArr[isArr.length-1]+"]"
   *
   *
   * //Object arrays :
   * "["+isArr[0].toString()+"<separator>"+.. ..+isArr[isArr.length-1].toString+"]"
   * // Two or three - dimensional Arrays are not supported
   * //(should be reflected in a special output method, e.g.as a field)
   *
   * // other Objects:
   * toString()
   *
   *
   * @param separator put in-between each array element in the resulting string.
   *
   * @param isArr
   *          The Array to represent as String.
   *
   * @return a String-representation of the Object.
   *
   *
   */
  public static final String arrayToString(final Object isArr, final String separator) {
    String result;
    if (isArr == null) {
      result = "null";
    } else {
      Object element;
      StringBuffer tmp = new StringBuffer();
      try {
        int length = Array.getLength(isArr);
        tmp.append("[");
        for (int i = 0; i < length; i++) {
          element = Array.get(isArr, i);
          if (element == null) {
            tmp.append("null");
          } else {
            tmp.append(element.toString());
          }
          if (i < length - 1) {
            tmp.append(separator);
          }
        }
        tmp.append("]");
        result = tmp.toString();
      } catch (ArrayIndexOutOfBoundsException bound) {
        // programming mistake or bad Array.getLength(obj).
        tmp.append("]");
        result = tmp.toString();

      } catch (IllegalArgumentException noarr) {
        result = isArr.toString();
      }
    }
    return result;
  }

  /**
   * Returns the system - dependent line separator.
   *

   *
   * Only call this method once (not in a loop) and keep the result.
   *

   *
   * @return the system - dependent line separator.
   */
  public static String getNewLine() {
    return  System.getProperty("line.separator");
  }

  /**
   * Returns the singleton instance of this class.
   *

   *
   * This method is useless for now as all methods are static. It may be used in
   * future if VM-global configuration will be put to the state of the instance.
   *

   * #
   *
   * @return the singleton instance of this class.
   */
  public static StringUtil instance() {
    if (StringUtil.instance == null) {
      StringUtil.instance = new StringUtil();
    }
    return StringUtil.instance;
  }

  /**
   * Returns true if the argument is null or consists of whitespaces only.
   *

   *
   * @param test
   *          the String to test.
   *
   * @return true if the argument is null or consists of whitespaces only.
   */
  public static boolean isEmpty(final String test) {
    boolean result;
    if (test == null) {
      result = true;
    } else {
      result = test.trim().length() == 0;
    }
    return result;
  }

  /**
   * Little String output - helper that modifies the given LinkedList by getting
   * it's Objects and replace them by their toString() - representation.
   *

   *
   * What is special?

   * If an Object in the given List is an Array (of Objects or primitive data
   * types) reflection will be used to create a String - representation of them.
   * The changes are reflected in the Objects that are in the given List. So
   * keep a reference to it. If you are sure, that your List does not contain
   * Arrays do not use this method to avoid overhead.
   *

   *
   * Avoid structural modifications (remove) of the list while using this
   * method. This method or better: the given List is only thread - safe if the
   * list is synchronized.
   *

   *
   * A clever VM (hotspot) will be able to inline this function because of void
   * return.
   *

   *
   * @param objects
   *          the List of objects that will be changed to a list of the String
   *          representation of the Objects with respect to special array
   *          treatment.
   *
   */
  public static final void listOfArraysToString(final List<Object> objects) {
    if (objects == null) {
      return;
    }
    int stop = objects.size();
    for (int i = 0; i < stop; i++) {
      objects.add(i, StringUtil.arrayToString(objects.remove(i)));
    }
  }

  /**
   * Returns the maximum length of a {@link Object#toString()} result in
   * characters within the given List.
   *

   *
   * No data is changed in the given List at all. But the String -
   * representation of all Objects, even Arrays is build to inspect.

   * Convention for creation fo String - representation:

   *
   *

   *        Primitive Arrays : as performed by this classes @see #ArrayToString.
   *        Object Arrays    : as performed by this classes @see #ArrayToString
   *        other Objects    : toString()  (as performed by this classes @see #ArrayToString).
   *

   *
   * @param objects
   *          the List<Object> to inspect for the maximum
   *          length of a {@link Object#toString()} result.
   *
   * @return The length of the longest String - representation of an Object in
   *         the List or 0 if objects was null or of size 0.
   */
  public static final int longestStringRepresentation(final List<Object> objects) {
    int result;
    if (objects == null) {
      result = 0;
    } else {
      int maxsize = 0;
      int tint = 0;
      String tmp;
      int stop = objects.size();
      for (int i = 0; i < stop; i++) {
        tmp = StringUtil.arrayToString(objects.get(i));
        tint = tmp.length();
        if (tint > maxsize) {
          maxsize = tint;
        }
      }
      // maximum size known.
      result = maxsize;
    }
    return result;
  }

  public static Map.Entry<String, String> prefixIntersection(String a, String b) {
    Map.Entry<String,String> ret = null;
    String key;
    String value;
    int index = b.indexOf(a);
    if (index != -1) {
      key = a;
      value = b.substring(a.length());
    } else {
      key = "";
      value = "";
    }
    ret = new Entry<String,String>(key, value);
    return ret;
  }

  /**
   * Appends the necessary amount of spaces to the string until it has the givn
   * length. No Exception is thrown, if the length of the String is shorter than
   * the given length, but nothing will happen and a message will be printed to
   * the System.out.
   *
   *
   * @param s
   *          the String to expand.
   * @param length
   *          the desired length of the String to be returned.
   * @return A String that represents the content of the old String including
   *         extra whitespaces.
   */
  public static final String setSize(final String s, final int length) {
    String result = s;
    int oldlen = s.length();
    if (oldlen > length) {
      System.err.println("greenpeace.util.setSize(String s,int length): length (" + length
          + ") is smaller than s.length(" + oldlen + ") : " + s);
    } else {
      int tofill = length - oldlen;
      result = StringUtil.appendSpaces(s, tofill);
    }
    return result;
  }

  /**
   * Modifies the given LinkedList by getting it's Objects and replace them by
   * their toString() - representation concatenated with the necessary amount of
   * white spaces that every String in the List will have the same amount of
   * characters.
   *

   *
   * Only use this method in following case:

   *

   *
You have got an AbstractList or subclass containing Objects you do not
   * know.

   *
You want to transform all Elements in the List to Strings.

   *
There might be Array's in the Object (whose toString method will return
   * only their hashcode).

   *

   *

   *
   * What happens?
   *

   *
All Objects, even primitive Arrays in your List will be turned to
   * String- representation.

   *
The result will replace the old position of the Object in the given
   * List. The old Objects will get lost!

   *
All Strings will be filled with whitespaces until each String has the
   * same length.

   *

   * At least this method will be speeded up by a hotspot VM by inlining this
   * method.

   * An example:

   * You just retrieved data from a db using jdbc and a generic class
   * (resultset.getObject()). You want to print the data to System.out or to
   * save it to a file, but do not know, if Arrays are contained. You want the
   * output to be formatted (each line).
   *

   *
   * @param objects
   *          contains the Objects to replace by their toString()
   *          representation.
   */
  public static final void toLongestString(final List<Object> objects) {
    if (objects == null) {
      return;
    }
    int maxsize = 0;
    int tint = 0;
    String tmp;
    int stop = objects.size();
    for (int i = 0; i < stop; i++) {
      StringUtil.arrayToString(objects.get(i));
      tmp = (String) objects.get(i);
      tint = tmp.length();
      if (tint > maxsize) {
        maxsize = tint;
      }
      objects.add(i, tmp);
    }
    // maximum size known.
    for (int i = 0; i < stop; i++) {
      objects.add(i, StringUtil.setSize((String) objects.remove(i), maxsize));
    }
  }
  /**
   * Avoids creation from outside for singleton support.
   *

   *
   */
  private StringUtil() {
    // nop
  }
}


package com.xiongyingqi.http;

import com.xiongyingqi.Logger;
import com.xiongyingqi.util.EntityHelper;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * Created by 瑛琪xiongyingqi.com on 2014/4/18 0018.
 */
public class HttpBuilder {
    private String method = "GET";
    private String host = "";
    private int port = -1;
    private String url = "";
    private String uri = "";
    private Collection headers = new ArrayList();
    private List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
    private Charset charset = Charset.forName("UTF-8");
    private String protocol = "http";

    public static HttpBuilder newBuilder() {
        return new HttpBuilder();
    }

    public HttpBuilder host(String host) {
        this.host = host;
        return this;
    }

    public HttpBuilder port(int port) {
        this.port = port;
        return this;
    }

    public HttpBuilder url(String url) {
        this.url = url;
        return this;
    }

    public HttpBuilder uri(String uri) {
        this.uri = uri;
        return this;
    }

    public HttpBuilder header(String name, String value) {
        Header header = new BasicHeader(name, value);
        this.headers.add(header);
        return this;
    }

    /**
     * 增加参数，默认使用urlEncoding
     * @param name
     * @param value
     * @return
     */
    public HttpBuilder param(String name, String value) {
        return param(name, value, true);
    }

    /**
     * 增加参数
     * @param name
     * @param value
     * @param urlEncoding
     * @return
     */
    public HttpBuilder param(String name, String value, boolean urlEncoding) {
        String encodedValue = null;
        if(urlEncoding && value != null){
            try {
                encodedValue = URLEncoder.encode(value, charset.name());
            } catch (UnsupportedEncodingException e) {
                Logger.error(e);
            }
        }
        if (encodedValue == null) {
            encodedValue = value;
        }
        NameValuePair nameValuePair = new BasicNameValuePair(name, encodedValue);
        this.nameValuePairs.add(nameValuePair);
        return this;
    }

    public HttpBuilder http() {
        this.protocol = "http";
        return this;
    }

    public HttpBuilder https() {
        this.protocol = "https";
        return this;
    }

    public HttpBuilder post() {
        this.method = "POST";
        return this;
    }

    public HttpBuilder get() {
        this.method = "GET";
        return this;
    }

    public HttpBuilder delete() {
        this.method = "DELETE";
        return this;
    }

    public HttpBuilder put() {
        this.method = "PUT";
        return this;
    }

    public HttpBuilder charset(String charset) {
        Charset charsetVar = null;
        try {
            charsetVar = Charset.forName(charset);
        } catch (UnsupportedCharsetException e) {
            charsetVar = Charset.forName("UTF-8");
        }
        this.charset = charsetVar;
        return this;
    }

    private String buildUrl() {
        if (this.url != null && !"".equals(this.url.trim())) {
            if (!this.url.startsWith("http://") && !this.url.startsWith("https://")) {
                this.url = protocol + "://" + this.url;
            }
            return this.url;
        }
        String url = "";
        if (!this.url.startsWith(protocol + "://")) {
            url = protocol + "://";
        }
        url += host;
        if (port <= 0) {
            url += port;
        }
        if (!url.endsWith("/") && !url.endsWith("\\")) {
            url += "/";
        }
        url += uri;
        return url;
    }

    private HttpRequestBase buildMethod() {
        HttpRequestBase httpRequestBase = null;
        if (method.equals("GET")) {
            httpRequestBase = new HttpGet();
        } else if (method.equals("POST")) {
            httpRequestBase = new HttpPost();
        } else if (method.equals("PUT")) {
            httpRequestBase = new HttpPut();
        } else if (method.equals("DELETE")) {
            httpRequestBase = new HttpDelete();
        }
        return httpRequestBase;
    }

    public HttpRequestBase build() {
        String url = buildUrl();

        HttpRequestBase requestBase = buildMethod();
        for (Header header : headers) {
            requestBase.addHeader(header);
        }

        if (nameValuePairs != null && nameValuePairs.size() > 0) {
            if (requestBase instanceof HttpPost) {// 如果是post
                HttpEntity requestEntity = new UrlEncodedFormEntity(nameValuePairs, charset);
                ((HttpPost) requestBase).setEntity(requestEntity);
            } else { // 如果是其他方法
                StringBuilder builder = new StringBuilder(url);
                String start = "&";
                if (!url.contains("?")) {
                    start = "?";
                }

                NameValuePair nameValuePairStart = nameValuePairs.get(0);
                String nameStart = nameValuePairStart.getName();
                String valueStart = nameValuePairStart.getValue();
                builder.append(start);// ?a=b    &a=b
                builder.append(nameStart);
                builder.append("=");
                builder.append(valueStart);

                for (int i = 1; i < nameValuePairs.size(); i++) {
                    NameValuePair nameValuePair = nameValuePairs.get(i);
                    String name = nameValuePair.getName();
                    String value = nameValuePair.getValue();
                    builder.append("&");
                    builder.append(name);
                    builder.append("=");
                    builder.append(value);
                }
                url = builder.toString();
            }
        }
        requestBase.setURI(URI.create(url));
        Logger.debug(getClass(), "nameValuePairs: " + nameValuePairs + ", headers: " + headers + ", url: " + url);
        return requestBase;
    }

    public void test() {
        try {
            String rs = HttpAccess.execute(HttpAccess.getClient(), HttpBuilder.newBuilder().url("http://www.baidu.com").get().build());
            EntityHelper.print(rs);

            String encode = URLEncoder.encode("?", "UTF-8");
            System.out.println(encode);

            HttpRequestBase requestBase = HttpBuilder.newBuilder()
                    .get()
                    .url("http://xueqiu.com/stock/f10/bonus.json")
                    .param("symbol", "SZ002261")
                    .param("page", "1")
                    .param("size", "4")
                    .build();
//        InputStream inputStream = HttpAccess.executeAndGetInputStream(httpClient, requestBase);
            String s = HttpAccess.execute(HttpAccess.getClient(), requestBase);
            EntityHelper.print(s);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args){
        new HttpBuilder().test();
    }

    public List<NameValuePair> getNameValuePairs() {
        return nameValuePairs;
    }
}


/**
 * YIXUN_1.5_EE
 */
package com.xiongyingqi.util;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author 瑛琪 xiongyingqi.com
 * @version 2013-11-22 下午4:33:04
 */
public class CosineSimilarAlgorithm {
    public static void main(String[] args) {
        System.out.println(getSimilarity("中国人", "中华人"));
    }

    public static double getSimilarity(String doc1, String doc2) {
        if (doc1 != null && doc1.trim().length() > 0 && doc2 != null
                && doc2.trim().length() > 0) {

            Map<Integer, int[]> AlgorithmMap = new HashMap<Integer, int[]>();

            //将两个字符串中的中文字符以及出现的总数封装到，AlgorithmMap中
            for (int i = 0; i < doc1.length(); i++) {
                char d1 = doc1.charAt(i);
                if (isHanZi(d1)) {
                    int charIndex = getGB2312Id(d1);
                    if (charIndex != -1) {
                        int[] fq = AlgorithmMap.get(charIndex);
                        if (fq != null && fq.length == 2) {
                            fq[0]++;
                        } else {
                            fq = new int[2];
                            fq[0] = 1;
                            fq[1] = 0;
                            AlgorithmMap.put(charIndex, fq);
                        }
                    }
                }
            }

            for (int i = 0; i < doc2.length(); i++) {
                char d2 = doc2.charAt(i);
                if (isHanZi(d2)) {
                    int charIndex = getGB2312Id(d2);
                    if (charIndex != -1) {
                        int[] fq = AlgorithmMap.get(charIndex);
                        if (fq != null && fq.length == 2) {
                            fq[1]++;
                        } else {
                            fq = new int[2];
                            fq[0] = 0;
                            fq[1] = 1;
                            AlgorithmMap.put(charIndex, fq);
                        }
                    }
                }
            }

            Iterator<Integer> iterator = AlgorithmMap.keySet().iterator();
            double sqdoc1 = 0;
            double sqdoc2 = 0;
            double denominator = 0;
            while (iterator.hasNext()) {
                int[] c = AlgorithmMap.get(iterator.next());
                denominator += c[0] * c[1];
                sqdoc1 += c[0] * c[0];
                sqdoc2 += c[1] * c[1];
            }

            return denominator / Math.sqrt(sqdoc1 * sqdoc2);
        } else {
            throw new NullPointerException(
                    " the Document is null or have not cahrs!!");
        }
    }

    public static boolean isHanZi(char ch) {
        // 判断是否汉字
        return (ch >= 0x4E00 && ch <= 0x9FA5);

    }

    /**
     * 根据输入的Unicode字符，获取它的GB2312编码或者ascii编码，
     *
     * @param ch 输入的GB2312中文字符或者ASCII字符(128个)
     * @return ch在GB2312中的位置，-1表示该字符不认识
     */
    public static short getGB2312Id(char ch) {
        try {
            byte[] buffer = Character.toString(ch).getBytes("GB2312");
            if (buffer.length != 2) {
                // 正常情况下buffer应该是两个字节，否则说明ch不属于GB2312编码，故返回'?'，此时说明不认识该字符
                return -1;
            }
            int b0 = (int) (buffer[0] & 0x0FF) - 161; // 编码从A1开始，因此减去0xA1=161
            int b1 = (int) (buffer[1] & 0x0FF) - 161; // 第一个字符和最后一个字符没有汉字，因此每个区只收16*6-2=94个汉字
            return (short) (b0 * 94 + b1);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return -1;
    }
}


/**
 * YIXUN_1.5_EE
 */
package com.xiongyingqi.util;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.lang.reflect.Method;
import java.util.*;

/**
 * @author 瑛琪 xiongyingqi.com
 * @version 2013-10-17 下午12:19:48
 */
public class SpringMVCHelper {
	/**
	 * 获取包下所有被Controller注解的类所表示的路径

	 * 2013-10-17 下午1:02:45
	 *
	 * @param pkg
	 * @return
	 */
	public static Collection<String> getAnnotationMappedPaths(Package pkg) {
		if (pkg == null) {
			return null;
		}
		Collection<String> rs = new LinkedHashSet<String>();
		Set<Class<?>> classes = PackageUtil.getclass(pkg);
		for (Iterator iterator = classes.iterator(); iterator.hasNext();) {
			Class<?> clazz = (Class<?>) iterator.next();
			if (clazz.isAnnotationPresent(Controller.class)) {
				String[] clazzPaths = null;
				if (clazz.isAnnotationPresent(RequestMapping.class)) {
					RequestMapping typeMapping = clazz.getAnnotation(RequestMapping.class);
					clazzPaths = typeMapping.value();
				}

				String[] methodPaths = null;
				Collection<String> methodPathCollection = new ArrayList<String>();
				Method[] methods = clazz.getDeclaredMethods();
				for (int i = 0; i < methods.length; i++) {
					Method method = methods[i];
					if (method.isAnnotationPresent(RequestMapping.class)) {
						RequestMapping typeMapping = method.getAnnotation(RequestMapping.class);
						String[] methodPathsVar = typeMapping.value();
						Collections.addAll(methodPathCollection, methodPathsVar);
					}
				}
				if (methodPathCollection.size() > 0) {
					methodPaths = methodPathCollection.toArray(new String[] {});
				}

				if (clazzPaths != null && clazzPaths.length > 0 && methodPaths != null
						&& methodPaths.length > 0) {
					for (int i = 0; i < clazzPaths.length; i++) {
						String typePath = clazzPaths[i];
						typePath = checkForPath(typePath);
						for (int j = 0; j < methodPaths.length; j++) {
							String methodPath = methodPaths[j];
							methodPath = checkForPath(methodPath);
							String mappedPath = typePath + methodPath;
							rs.add(mappedPath);
						}
					}
				} else if ((clazzPaths != null && clazzPaths.length > 0)
						&& (methodPaths == null || methodPaths.length == 0)) {
					for (int i = 0; i < clazzPaths.length; i++) {
						String typePath = clazzPaths[i];
						typePath = checkForPath(typePath);
						rs.add(typePath);
					}
				} else if ((methodPaths != null && methodPaths.length > 0)
						&& (clazzPaths == null || clazzPaths.length == 0)) {
                    EntityHelper.print(methodPaths);
                    for (int i = 0; i < clazzPaths.length; i++) {
						String typePath = clazzPaths[i];
						typePath = checkForPath(typePath);
						rs.add(typePath);
					}
				}
			}
		}
		return rs;
	}

	private static String checkForPath(String path) {
		if (!path.startsWith("/")) {
			path = "/" + path;
		}
		if (path.endsWith("/")) {
			path = path.substring(0, path.length() - 1);
		}
		return path;
	}
}


/*
 * Copyright 2002-2012 the original author or authors.
 *
 * 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.xiongyingqi.util;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

/**
 * Track references to arbitrary objects using proxy and weak references. To
 * monitor a handle, one should call {@link #monitor(Object, com.xiongyingqi.util.WeakReferenceMonitor.ReleaseListener)},
 * with the given handle object usually being a holder that uses the target
 * object underneath, and the release listener performing cleanup of the
 * target object once the handle is not strongly referenced anymore.
 *
When a given handle becomes weakly reachable, the specified listener
 * will be called by a background thread. This thread will only be started
 * lazily and will be stopped once no handles are registered for monitoring
 * anymore, to be restarted if further handles are added.
 *
Thanks to Tomasz Wysocki for the suggestion and the original
 * implementation of this class!
 *
 * @author Colin Sampaleanu
 * @author Juergen Hoeller
 * @see #monitor
 * @since 1.2
 */
public class WeakReferenceMonitor {

    private static final Log logger = LogFactory.getLog(WeakReferenceMonitor.class);

    // Queue receiving reachability events
    private static final ReferenceQueue<Object> handleQueue = new ReferenceQueue<Object>();

    // All tracked entries (WeakReference => ReleaseListener)
    private static final Map<Reference<?>, ReleaseListener> trackedEntries = new HashMap<Reference<?>, ReleaseListener>();

    // Thread polling handleQueue, lazy initialized
    private static Thread monitoringThread = null;

    /**
     * Start to monitor given handle object for becoming weakly reachable.
     * When the handle isn't used anymore, the given listener will be called.
     *
     * @param handle   the object that will be monitored
     * @param listener the listener that will be called upon release of the handle
     */
    public static void monitor(Object handle, ReleaseListener listener) {
        if (logger.isDebugEnabled()) {
            logger.debug("Monitoring handle [" + handle + "] with release listener [" + listener + "]");
        }

        // Make weak reference to this handle, so we can say when
        // handle is not used any more by polling on handleQueue.
        WeakReference<Object> weakRef = new WeakReference<Object>(handle, handleQueue);

        // Add monitored entry to internal map of all monitored entries.
        addEntry(weakRef, listener);
    }

    /**
     * Add entry to internal map of tracked entries.
     * Internal monitoring thread is started if not already running.
     *
     * @param ref   reference to tracked handle
     * @param entry the associated entry
     */
    private static void addEntry(Reference<?> ref, ReleaseListener entry) {
        synchronized (WeakReferenceMonitor.class) {
            // Add entry, the key is given reference.
            trackedEntries.put(ref, entry);

            // Start monitoring thread lazily.
            if (monitoringThread == null) {
                monitoringThread = new Thread(new MonitoringProcess(), WeakReferenceMonitor.class.getName());
                monitoringThread.setDaemon(true);
                monitoringThread.start();
            }
        }
    }

    /**
     * Remove entry from internal map of tracked entries.
     *
     * @param reference the reference that should be removed
     * @return entry object associated with given reference
     */
    private static ReleaseListener removeEntry(Reference<?> reference) {
        synchronized (WeakReferenceMonitor.class) {
            return trackedEntries.remove(reference);
        }
    }

    /**
     * Check whether to keep the monitoring thread alive,
     * i.e. whether there are still entries being tracked.
     */
    private static boolean keepMonitoringThreadAlive() {
        synchronized (WeakReferenceMonitor.class) {
            if (!trackedEntries.isEmpty()) {
                return true;
            } else {
                logger.debug("No entries left to track - stopping reference monitor thread");
                monitoringThread = null;
                return false;
            }
        }
    }

    /**
     * Thread implementation that performs the actual monitoring.
     */
    private static class MonitoringProcess implements Runnable {

        @Override
        public void run() {
            logger.debug("Starting reference monitor thread");
            // Check if there are any tracked entries left.
            while (keepMonitoringThreadAlive()) {
                try {
                    Reference<?> reference = handleQueue.remove();
                    // Stop tracking this reference.
                    ReleaseListener entry = removeEntry(reference);
                    if (entry != null) {
                        // Invoke listener callback.
                        try {
                            entry.released();
                        } catch (Throwable ex) {
                            logger.warn("Reference release listener threw exception", ex);
                        }
                    }
                } catch (InterruptedException ex) {
                    synchronized (WeakReferenceMonitor.class) {
                        monitoringThread = null;
                    }
                    logger.debug("Reference monitor thread interrupted", ex);
                    break;
                }
            }
        }
    }

    /**
     * Listener that is notified when the handle is being released.
     * To be implemented by users of this reference monitor.
     */
    public static interface ReleaseListener {

        /**
         * This callback method is invoked once the associated handle has been released,
         * i.e. once there are no monitored strong references to the handle anymore.
         */
        void released();
    }

}


/**
 * spark_src
 */
package com.xiongyingqi.util;

import org.apache.log4j.Logger;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.Parser;
import org.apache.tika.sax.BodyContentHandler;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;

/**
 * @author XiongYingqi
 * @version 2013-6-24 下午10:47:33
 */
public class FileHelper {
    public static final Logger LOGGER = Logger.getLogger(FileHelper.class);

    public static final long KB = 1024;
    public static final long MB = 1024 * KB;
    public static final long GB = 1024 * MB;
    public static final long TB = 1024 * GB;
    public static final long PB = 1024 * TB;

    //	public static final long EB = 1024 * PB;
    //	public static final long ZB = 1024 * EB;
    //	public static final long YB = 1024 * ZB;
    //	public static final long BB = 1024 * YB;
    //	public static final long NB = 1024 * BB;
    //	public static final long DB = 1024 * NB;

    public static boolean checkFileSizeLessThen(File file, long size) {
        try {
            fileNotFullAndExists(file);
        } catch (Exception e) {
            return false;
        }

        return file.length() <= size;
    }

    public static File appendStringToFile(File file, String string) {
        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(file, true);
            fileWriter.append(string);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileWriter.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    public static File appendBytesToFile(File file, byte[] bts) {
        OutputStream outputStream = null;
        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(file, true));
            outputStream.write(bts);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.flush();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return file;
    }

    /**
     * 获取文件类型

     * 2013-9-2 下午9:08:51
     *
     * @param data
     * @return
     */
    public static String getMimeType(File data) {
        if (!data.exists()) {
            return null;
        }
        ContentHandler contenthandler = new BodyContentHandler();
        Metadata metadata = new Metadata();
        metadata.set(Metadata.RESOURCE_NAME_KEY, data.getName());
        Parser parser = new AutoDetectParser();
        try {
            parser.parse(new FileInputStream(data), contenthandler, metadata, null);
        } catch (FileNotFoundException e) {
            LOGGER.error(e);
        } catch (IOException e) {
            LOGGER.error(e);
        } catch (SAXException e) {
            LOGGER.error(e);
        } catch (TikaException e) {
            LOGGER.error(e);
        }
        // System.out.println("Mime: " + metadata.get(Metadata.CONTENT_TYPE));
        // System.out.println("Mime str: " + metadata.toString());
        return metadata.get(Metadata.CONTENT_TYPE);
    }

    /**
     * 根据后缀名从文件夹获取文件

     * 2013-9-6 下午3:15:56
     *
     * @param folder
     * @param suffix
     * @return
     */
    public static File[] listFilesBySuffix(File folder, final String suffix) {
        File[] files = folder.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File paramFile, String paramString) {
                String newSuffix = suffix;
                if (!newSuffix.startsWith(".")) {
                    newSuffix = "." + newSuffix;
                }
                if (paramString.endsWith(newSuffix)) {
                    return true;
                }
                return false;
            }
        });
        return files;
    }

    public static File readBufferImage(BufferedImage bufferedImage) {
        File file = null;
        FileOutputStream outputStream = null;
        try {
            file = File.createTempFile(System.currentTimeMillis() + StringUtil.randomString(8),
                    "gif");
            outputStream = new FileOutputStream(file);
            ImageIO.write(bufferedImage, "gif", outputStream);
        } catch (IOException e) {
            LOGGER.error(e);
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.flush();
                    outputStream.close();
                } catch (IOException e) {
                    LOGGER.error(e);
                }
            }
        }
        return file;
    }

    /**
     * 从url地址读取文件信息并写入到临时文件

     * 2013-9-2 下午2:57:15
     *
     * @param urlStr
     * @return
     * @throws java.io.IOException
     */
    public static File readURL(String urlStr) throws IOException {
        URL url = new URL(urlStr);
        // System.out.println(" ----------------- url ----------------- ");
        // System.out.println(urlStr);
        // System.out.println(url.getPath());
        // System.out.println(url.getHost());
        // System.out.println(" ---------------------------------- ");
        InputStream inputStream = null;
        if (url.getHost().trim().equals("")) {
            // inputStream = new FileInputStream(url.getFile());
            File file = new File(url.getFile());
            return file;
        } else {
            inputStream = url.openStream();
        }
        return readInputStream(inputStream);
    }

    public static String readInputStreamToString(InputStream inputStream, Charset charset) {
        byte[] bts = null;
        try {
            bts = readInputStreamToBytes(inputStream);
            if (bts == null) {
                return null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        String content = new String(bts, charset);
        return content;

//        String rs = null;
//        try {
//            Reader reader = new InputStreamReader(inputStream, charset);
//            BufferedReader bufferedReader = new BufferedReader(reader);
//            StringBuilder builder = new StringBuilder();
//            String line = null;
//            while ((line = bufferedReader.readLine()) != null) {
//                builder.append(line);
//            }
//            rs = builder.toString();
//
////            ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024 * 1024);
////            int length = -1;
////            int bufferSize = 128;
////            byte[] buffer = new byte[bufferSize];
////            while ((length = inputStream.read(buffer)) != -1) {
////                if (length != bufferSize) {
////                    System.arraycopy(buffer, 0, buffer, 0, length);
////                }
////                EntityHelper.print(new String(buffer));
////                byteBuffer.put(buffer);
////            }
////            rs = new String(byteBuffer.array(), encoding);
//        } catch (IOException e) {
//            e.printStackTrace();
//        } finally {
//            // try {
//            // inputStream.close();
//            // } catch (IOException e1) {
//            // e1.printStackTrace();
//            // }
//            try {
//                inputStream.close();
//            } catch (IOException e1) {
//                e1.printStackTrace();
//            }
//        }
//        return rs;
    }

    public static String readInputStreamToString(InputStream inputStream, String encoding) {
        return readInputStreamToString(inputStream, Charset.forName(encoding));
    }

    public static InputStream openStream(File file) {
        Assert.isTrue(file.exists(), "文件：" + file + "不存在！");
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(file);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return inputStream;
    }

    public static Reader openReader(File file) {
        Assert.isTrue(file.exists(), "文件：" + file + "不存在！");
        Reader reader = null;
        try {
            reader = new FileReader(file);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return reader;
    }

    public static BufferedReader openBufferedReader(File file) {
        BufferedReader bufferedReader = new BufferedReader(openReader(file));
        return bufferedReader;
    }

    public static String readInputStreamToString(InputStream inputStream) {
        return readInputStreamToString(inputStream, "UTF-8");
    }

//    public static String readInputStreamToString(InputStream inputStream, String encoding) {
//        String rs = null;
//        try {
//            ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024 * 1024);
//            int length = -1;
//            int bufferSize = 128;
//            byte[] buffer = new byte[bufferSize];
//            while ((length = inputStream.read(buffer)) != -1) {
//                if (length != bufferSize) {
//                    System.arraycopy(buffer, 0, buffer, 0, length);
//                }
//                byteBuffer.put(buffer);
//            }
//            rs = new String(byteBuffer.array(), encoding);
//        } catch (IOException e) {
//            LOGGER.error(e);
//        } finally {
//            // try {
//            // inputStream.close();
//            // } catch (IOException e1) {
//            // e1.printStackTrace();
//            // }
//            try {
//                inputStream.close();
//            } catch (IOException e1) {
//                e1.printStackTrace();
//            }
//        }
//        return rs;
//    }

    /**
     * 从流读取文件内容

     * 2013-9-2 下午2:52:39
     *
     * @param inputStream
     * @return
     */
    public static File readInputStream(InputStream inputStream) {
        String filePath = System.getProperty("java.io.tmpdir", "tmp/");
        filePath += System.currentTimeMillis() + StringUtil.randomString(8) + ".tmp";
        return readInputStream(inputStream, filePath);
    }

    /**
     * 将文件转换为URL地址

     * 2013-9-2 下午10:07:14
     *
     * @param file
     * @return
     */
    public static URL toURL(File file) {
        if (file == null || !file.exists()) {
            return null;
        }
        URI uri = file.toURI();
        URL url = null;
        try {
            url = uri.toURL();
        } catch (MalformedURLException e) {
            LOGGER.error(e);
        }
        return url;
    }

    /**
     * 将流读入到文件内

     * 2013-9-2 下午10:04:17
     *
     * @param inputStream
     * @param file
     * @return
     */
    public static File readInputStream(InputStream inputStream, File file) {
        try {
            validateFile(file);
        } catch (Exception e2) {
            e2.printStackTrace();
        }
        try {
            FileOutputStream outputStream = new FileOutputStream(file);
            int length = -1;
            try {
                int bufferSize = 128;
                byte[] buffer = new byte[bufferSize];
                while ((length = inputStream.read(buffer)) != -1) {
                    if (length != bufferSize) {
                        System.arraycopy(buffer, 0, buffer, 0, length);
                    }
                    outputStream.write(buffer);
                }
            } catch (IOException e) {
                LOGGER.error(e);
            } finally {
                // try {
                // inputStream.close();
                // } catch (IOException e1) {
                // e1.printStackTrace();
                // }
                try {
                    inputStream.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
                try {
                    outputStream.flush();
                } catch (IOException e) {
                    LOGGER.error(e);
                }
                try {
                    outputStream.close();
                } catch (IOException e) {
                    LOGGER.error(e);
                }
            }
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
            return null;
        }
        return file;
    }

    public static File readInputStream(InputStream inputStream, String path) {
        File file = new File(path);
        return readInputStream(inputStream, file);
    }

    /**
     * 读取指定路径的文件内容（以String的形式）

     * 2013-8-30 下午5:28:25
     *
     * @param fileName
     * @return
     */
    public static String readFileToString(String fileName) {
        return readFileToString(new File(fileName));
    }

    /**
     * 读取指定文件的文件内容（以String的形式）

     * 2013-8-30 下午5:26:55
     *
     * @param file
     * @return
     */
    public static String readFileToString(File file) {
        byte[] bts = null;
        try {
            bts = readFileToBytes(file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String content = null;
        try {
            content = new String(bts, getEncode(file));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return content;
    }

    /**
     * 获取文本文档的编码
     *
2013年12月5日 下午5:27:07
     *
     * @param file
     * @return
     */
//    public static String getEncode(File file) {
//        InputStream inputStream = null;
//        String code = "UTF-8";
//        try {
//            inputStream = new FileInputStream(file);
//            byte[] head = new byte[3];
//            inputStream.read(head);
//            if (head[0] == -1 && head[1] == -2) {
//                code = "UTF-16";
//            }
//            if (head[0] == -2 && head[1] == -1) {
//                code = "Unicode";
//            }
//            if (head[0] == -17 && head[1] == -69 && head[2] == -65) {
//                code = "UTF-8";
//            }
//
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        } catch (IOException e) {
//            e.printStackTrace();
//        } finally {
//            try {
//                inputStream.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
//        return code;
//    }

    /**
     * 获取文本文档的编码
     *
2013年12月5日 下午5:27:07
     *
     * @param file
     * @return
     */
    public static String getEncode(File file) {
        return FileEncode.getEncodeByUtil(file);
    }

    public static File validateFile(File file) throws Exception {
        if (file != null) {
            if (file.isDirectory()) {
                if (!file.exists()) {
                    file.mkdirs();
                }
            } else {
                File parentFolder = file.getParentFile();
                if (parentFolder != null && !parentFolder.exists()) {
                    parentFolder.mkdirs();
                }
                file.createNewFile();
            }
        } else {
            throw new Exception("传入 的引用为null！");
        }
        return file;
    }

    public static void copyFile(String originFilePath, String targetFilePath) {
        File originFile = new File(originFilePath);
        File targetFile = new File(targetFilePath);
        copyFile(originFile, targetFile);
    }

    public static void copyFile(URL originURL, File targetFile) {
        try {
            copyFile(originURL.openStream(), targetFile);
        } catch (IOException e) {
            LOGGER.error(e);
        }
    }

    public static void copyFile(InputStream inputStream, File targetFile) {
        if (inputStream == null) {
            return;
        }
        if (!targetFile.getParentFile().exists()) {
            targetFile.getParentFile().mkdirs();
        }
        if (!targetFile.exists()) {
            try {
                targetFile.createNewFile();
            } catch (IOException e) {
                LOGGER.error(e);
            }
        }
        OutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(targetFile);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }

        byte[] buffer = new byte[1024 * 1024]; // 1M的缓存
        try {
            int length = inputStream.read(buffer);
            while (length > 0) {
                byte[] targetBuffer = new byte[length];
                System.arraycopy(buffer, 0, targetBuffer, 0, length);
                outputStream.write(targetBuffer);
                length = inputStream.read(buffer);
            }
        } catch (IOException e) {
            LOGGER.error(e);
        } finally {
            try {
                outputStream.flush();
                outputStream.close();
                inputStream.close();
            } catch (IOException e) {
                LOGGER.error(e);
            }
        }
    }

    public static void copyFile(File originFile, File targetFile) {

        if (originFile.length() == targetFile.length()) {
            return;
        }
        try {
            validateFile(targetFile);
        } catch (Exception e2) {
            e2.printStackTrace();
        }
        if (!targetFile.exists()) {
            try {
                targetFile.createNewFile();
            } catch (IOException e) {
                LOGGER.error(e);
            }
        }
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            inputStream = new FileInputStream(originFile);

            outputStream = new FileOutputStream(targetFile);
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        }
        // System.out.println("Copy file: " + originFile);
        // System.out.println("Target file: " + targetFile);
        byte[] buffer = new byte[1024 * 1024]; // 1M的缓存
        try {
            int length = inputStream.read(buffer);
            while (length > 0) {
                byte[] targetBuffer = new byte[length];
                System.arraycopy(buffer, 0, targetBuffer, 0, length);
                outputStream.write(targetBuffer);
                length = inputStream.read(buffer);
            }
        } catch (IOException e) {
            LOGGER.error(e);
        } finally {
            try {
                outputStream.flush();
                outputStream.close();
                inputStream.close();
            } catch (IOException e) {
                LOGGER.error(e);
            }
        }

    }

    /**
     * 将源文件剪切到目标文件
     *
     * @param originFile 源文件
     * @param targetFile 目标文件
     * @return
     */
    public static boolean cutFile(File originFile, File targetFile) {
        Assert.notNull(originFile);
        Assert.notNull(targetFile);
        copyFile(originFile, targetFile);
        if (originFile.length() == targetFile.length()) {
            return originFile.delete();
        }
        return false;
    }

    /**
     * 检查文件不为空且存在

     * 2013-6-24 下午10:52:54
     *
     * @param file
     * @throws Exception
     */
    public static void fileNotFullAndExists(File file) throws Exception {
        if (file == null || !file.exists()) {
            throw new Exception("文件不存在！");
        }
    }

    /**
     * 读取inputStream并返回字节数组

     * 2013-9-3 下午12:10:06
     *
     * @param inputStream
     * @return
     */
    public static byte[] readInputStreamToBytes(InputStream inputStream) throws Exception {
        byte[] data = null;
        try {
            int bufferSize = 128;
            byte[] buffer = new byte[bufferSize];
            int offset = 0;
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            int length = -1;
            while ((length = inputStream.read(buffer)) != -1) {
                // if(length != bufferSize){
                // System.arraycopy(buffer, 0, data, offset, length);
                // }
//                    System.arraycopy(buffer, 0, data, offset, length);// 从缓冲区拷贝数组
                if (offset + length > byteBuffer.limit()) {
                    byteBuffer = growByteBuffer(byteBuffer, (int) (byteBuffer.limit() * 1.5));
                }
                byteBuffer.put(buffer, 0, length);
                offset += length;
            }
            byteBuffer.flip();
//            byteBuffer.limit(offset);
            data = new byte[offset];
            byteBuffer.get(data, 0, offset);
//            data = byteBuffer.array();
        } catch (IOException e) {
            LOGGER.error(e);
        } finally {
            try {
                inputStream.close();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }
        return data;
    }

    public static ByteBuffer growByteBuffer(ByteBuffer byteBuffer, int size) {
        Assert.isTrue(size > byteBuffer.limit(), "扩容的大小小于已经存在的字节缓冲！");
        ByteBuffer byteBufferNew = ByteBuffer.allocate(size);
        byteBuffer.flip();
        byteBufferNew.put(byteBuffer);
        return byteBufferNew;
    }

    /**
     * 读取文件内容并返回字节数组

     * 2013-9-3 下午12:10:06
     *
     * @param iconFile
     * @return
     */
    public static byte[] readFileToBytes(File iconFile) throws Exception {
        try {
            validateFile(iconFile);
        } catch (Exception e2) {
            e2.printStackTrace();
        }
        long fileSize = iconFile.length();
        if (fileSize > Integer.MAX_VALUE) {
            throw new Exception("读取的文件过大！");
        }
        byte[] data = new byte[(int) fileSize];// 由于文件已经确定，因此大小也可以确定

        try {
            int length = -1;

            FileInputStream inputStream = new FileInputStream(iconFile);
            try {
                int bufferSize = 128;
                byte[] buffer = new byte[bufferSize];
                int offset = 0;
                while ((length = inputStream.read(buffer)) != -1) {
                    // if(length != bufferSize){
                    // System.arraycopy(buffer, 0, data, offset, length);
                    // }
                    System.arraycopy(buffer, 0, data, offset, length);// 从缓冲区拷贝数组
                    offset += length;
                }
            } catch (IOException e) {
                LOGGER.error(e);
            } finally {
                try {
                    inputStream.close();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
            return null;
        }
        return data;
    }

    /**
     * 将字节组写入文件

     * 2013-9-3 下午2:39:21
     *
     * @param data
     * @param file
     */
    public static File writeBytesToFile(byte[] data, File file) {
        try {
            validateFile(file);
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(file);
            outputStream.write(data);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            LOGGER.error(e);
        } catch (IOException e) {
            e.printStackTrace();
            LOGGER.error(e);
        } finally {
            if (outputStream != null) {
                try {
                    outputStream.flush();
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    LOGGER.error(e);
                }
            }
        }
        return file;

    }

    /**
     * 将字符串写入文件

     * 2013-9-6 下午12:09:45
     *
     * @param file
     * @param string
     * @return
     */
    public static File writeStringToFile(File file, String string) {
        try {
            byte[] bts = string.getBytes(getEncode(file));
            file = writeBytesToFile(bts, file);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            ;
            LOGGER.error(e);
        }
        return file;
    }

    /**
     * 将对象写入文件

     * 2013-9-6 下午1:08:58
     *
     * @param targetFile
     * @param serializable
     */
    public static void serializeObjectToFile(File targetFile, Serializable serializable) {
        FileOutputStream fileOutputStream = null;
        ObjectOutputStream objectOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(targetFile);
            try {
                objectOutputStream = new ObjectOutputStream(fileOutputStream);
                objectOutputStream.writeObject(serializable);
            } catch (IOException e) {
                LOGGER.error(e);
            }
        } catch (FileNotFoundException e) {
            LOGGER.error(e);
        } finally {
            closeOutStream(objectOutputStream);
            closeOutStream(fileOutputStream);
        }
    }

    public static void closeInputStream(InputStream inputStream) {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                LOGGER.error(e);
            }
        }
    }

    public static void closeOutStream(OutputStream outputStream) {
        if (outputStream != null) {
            try {
                outputStream.flush();
            } catch (IOException e) {
                LOGGER.error(e);
            }
            try {
                outputStream.close();
            } catch (IOException e) {
                LOGGER.error(e);
            }
        }
    }

    public static Object unSerializeObjectFromFile(File targetFile) {
        FileInputStream fileInputStream = null;
        ObjectInputStream objectInputStream = null;
        Object object = null;
        try {
            fileInputStream = new FileInputStream(targetFile);
            try {
                objectInputStream = new ObjectInputStream(fileInputStream);
                try {
                    object = objectInputStream.readObject();
                } catch (ClassNotFoundException e) {
                    LOGGER.error(e);
                }
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        } catch (FileNotFoundException e) {
            LOGGER.error(e);
        } finally {
            closeInputStream(objectInputStream);
            closeInputStream(fileInputStream);
        }
        return object;
    }

    public static void main(String[] args) {
        // try {
        // File file = new File("tmp/a.html");
        // byte[] data = readFileToBytes(file);
        // String encodeStr = Base64.encodeBytes(data);
        // byte[] data2 = Base64.decode(encodeStr);
        // File rsfile = FileHelper.readBytesToFile(data2,
        // File.createTempFile(System.currentTimeMillis() +
        // StringUtil.randomString(8), ".html"));
        // System.out.println(rsfile);
        // System.out.println(encodeStr);
        // System.out.println(data.length);
        // System.out.println(file.length());
        // } catch (Exception e) {
        // LOGGER.error(e);
        // }

        // MessageVO messageVO = new MessageVO();
        // File objFile = new File("C:/Users/瑛琪/Desktop/b.obj");
        // serializeObjectToFile(objFile, messageVO);
        // Object object = unSerializeObjectFromFile(objFile);
        // System.out.println(object.equals(messageVO));
        //
        // File[] files = listFilesBySuffix(new File("C:/Users/瑛琪/Desktop/"),
        // "obj");
        // for (int i = 0; i < files.length; i++) {
        // File file = files[i];
        // System.out.println(file);
        // }
//        EntityHelper.print(getMimeType(new File(
//                "C:\\Users\\blade_000\\Desktop\\ad.html")));
//        EntityHelper.print(getEncodeByUtil(new File(
//                "D:\\workspace_JavaEE\\YIXUN_1.5\\YIXUN_1.5_ENTITY\\src\\main\\java\\com\\kingray\\domain\\bk2\\bk\\BizBank.java")));
//        EntityHelper.print(getEncode(new File(
//                "D:\\workspace_JavaEE\\YIXUN_1.5\\YIXUN_1.5_ENTITY\\src\\main\\java\\com\\kingray\\domain\\bk2\\bk\\BizBank.java")));
//        EntityHelper.print(getEncodeByUtil(new File(
//                "C:\\Users\\瑛琪\\Desktop\\ad.html")));
        File file = new File(
                "C:\\Users\\瑛琪\\Desktop\\test.txt");
        File file_bak = new File(
                "C:\\Users\\瑛琪\\Desktop\\test2.txt");
        String charset = getEncode(file);
        EntityHelper.print(charset);

        byte[] content = new byte[0];
        try {
            content = FileHelper.readFileToBytes(file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            EntityHelper.print(new String(content, charset));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        FileHelper.writeBytesToFile(content, file_bak);

    }

    public static void closeReader(Reader reader) {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void closeWriter(Writer writer) {
        if (writer != null) {
            try {
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void flushAndCloseWriter(Writer writer) {
        if (writer != null) {
            try {
                writer.flush();
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static boolean initFile(File file) {
        if (file == null) {
            return false;
        }
        File parentFile = file.getParentFile();
        if (!parentFile.exists()) {
            return parentFile.mkdirs();
        }
        return false;
    }
}


/*
 * Copyright 2002-2012 the original author or authors.
 *
 * 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.xiongyingqi.util;

/**
 * Helper class for resolving placeholders in texts. Usually applied to file paths.
 * <p>A text may contain {@code ${...}} placeholders, to be resolved as system properties: e.g.
 * {@code ${user.dir}}.  Default values can be supplied using the ":" separator between key
 * and value.
 *
 * @author Juergen Hoeller
 * @author Rob Harrop
 * @author Dave Syer
 * @see #PLACEHOLDER_PREFIX
 * @see #PLACEHOLDER_SUFFIX
 * @see System#getProperty(String)
 * @since 1.2.5
 */
public abstract class SystemPropertyUtils {

    /**
     * Prefix for system property placeholders: "${"
     */
    public static final String PLACEHOLDER_PREFIX = "${";

    /**
     * Suffix for system property placeholders: "}"
     */
    public static final String PLACEHOLDER_SUFFIX = "}";

    /**
     * Value separator for system property placeholders: ":"
     */
    public static final String VALUE_SEPARATOR = ":";

    private static final PropertyPlaceholderHelper strictHelper =
            new PropertyPlaceholderHelper(PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, VALUE_SEPARATOR, false);

    private static final PropertyPlaceholderHelper nonStrictHelper =
            new PropertyPlaceholderHelper(PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, VALUE_SEPARATOR, true);

    /**
     * Resolve ${...} placeholders in the given text, replacing them with corresponding system property values.
     *
     * @param text the String to resolve
     * @return the resolved String
     * @throws IllegalArgumentException if there is an unresolvable placeholder
     * @see #PLACEHOLDER_PREFIX
     * @see #PLACEHOLDER_SUFFIX
     */
    public static String resolvePlaceholders(String text) {
        return resolvePlaceholders(text, false);
    }

    /**
     * Resolve ${...} placeholders in the given text, replacing them with corresponding system property values.
     * Unresolvable placeholders with no default value are ignored and passed through unchanged if the
     * flag is set to true.
     *
     * @param text                           the String to resolve
     * @param ignoreUnresolvablePlaceholders flag to determine is unresolved placeholders are ignored
     * @return the resolved String
     * @throws IllegalArgumentException if there is an unresolvable placeholder and the flag is false
     * @see #PLACEHOLDER_PREFIX
     * @see #PLACEHOLDER_SUFFIX
     */
    public static String resolvePlaceholders(String text, boolean ignoreUnresolvablePlaceholders) {
        PropertyPlaceholderHelper helper = (ignoreUnresolvablePlaceholders ? nonStrictHelper : strictHelper);
        return helper.replacePlaceholders(text, new SystemPropertyPlaceholderResolver(text));
    }

    private static class SystemPropertyPlaceholderResolver implements PropertyPlaceholderHelper.PlaceholderResolver {

        private final String text;

        public SystemPropertyPlaceholderResolver(String text) {
            this.text = text;
        }

        @Override
        public String resolvePlaceholder(String placeholderName) {
            try {
                String propVal = System.getProperty(placeholderName);
                if (propVal == null) {
                    // Fall back to searching the system environment.
                    propVal = System.getenv(placeholderName);
                }
                return propVal;
            } catch (Throwable ex) {
                System.err.println("Could not resolve placeholder '" + placeholderName + "' in [" +
                        this.text + "] as system property: " + ex);
                return null;
            }
        }
    }

}