/*
 * ByteOrderMarkDetector.java, <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 java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;

public class ByteOrderMarkDetector
    extends AbstractCodepageDetector implements ICodepageDetector {

  /**
   * Generated serialVersionUID.
   */
  private static final long serialVersionUID = 3618977875919778866L;

  /**
   * @see ICodepageDetector#detectCodepage(java.io.InputStream, int)
   */
  public Charset detectCodepage(final InputStream in, final int length) throws IOException {
    // dumbest pragmatic code ever written (nearly a code generator would have
    // been faster). But it's proven fast.
    Charset result = UnknownCharset.getInstance();
    int readByte = 0;
    readByte = in.read();
    switch (readByte) {
      case (0x00): {
        // 0x 00
        readByte = in.read();
        switch (readByte) {
          case (0x00): {
            // 0x 00 00
            readByte = in.read();
            switch (readByte) {
              case (0xFE): {
                // 0x 00 00 FE
                // UCS-4, big-endian machine (1234 order)
                try {
                  result = Charset.forName("UCS-4BE");
                } catch (UnsupportedCharsetException uce) {
                  result = UnsupportedCharset.forName("UCS-4BE");
                }
                return result;

              }
              case (0xFF): {
                // 0x 00 00 FF
                // UCS-4, unusual octet order (2143)
                try {
                  result = Charset.forName("UCS-4");
                } catch (UnsupportedCharsetException uce) {
                  result = UnsupportedCharset.forName("UCS-4");
                }
                return result;

              }
              default:
                return result;
            }

          }
          default:
            return result;
        }
      }
      case (0xFE): {
        // 0x FE
        readByte = in.read();
        switch (readByte) {
          case (0xFF): {
            // 0x FE FF
            // from here on default to UTF-16, big-endian
            readByte = in.read();
            switch (readByte) {
              case (0x00): {
                // 0x FE FF 00
                readByte = in.read();
                switch (readByte) {
                  case (0x00): {
                    // 0x FE FF 00 00
                    // UCS-4, unusual octet order (3412)
                    try {
                      result = Charset.forName("UCS-4");
                    } catch (UnsupportedCharsetException uce) {
                      result = UnsupportedCharset.forName("UCS-4");
                    }
                    return result;
                  }
                  default: {
                    try {
                      result = Charset.forName("UTF-16BE");
                    } catch (UnsupportedCharsetException uce) {
                      result = UnsupportedCharset.forName("UTF-16BE");
                    }
                    return result;
                  }
                }

              }
              default: {
                try {
                  result = Charset.forName("UTF-16BE");
                } catch (UnsupportedCharsetException uce) {
                  result = UnsupportedCharset.forName("UTF-16BE");
                }
                return result;
              }

            }

          }
          default: {
            return result;
          }
        }
      }

      case (0xFF): {
        // 0x FF
        readByte = in.read();
        switch (readByte) {
          case (0xFE): {
            // 0x FF FE
            // from here on default to UTF-16, little-endian
            readByte = in.read();
            switch (readByte) {
              case (0x00): {
                // 0x FF FE 00
                readByte = in.read();
                switch (readByte) {
                  case (0x00): {
                    // 0x FF FE 00 00
                    // UCS-4, little-endian machine (4321 order)
                    try {
                      result = Charset.forName("UCS-4LE");
                    } catch (UnsupportedCharsetException uce) {
                      result = UnsupportedCharset.forName("UCS-4LE");
                    }
                    return result;

                  }
                  default: {
                    try {
                      result = Charset.forName("UTF-16LE");
                    } catch (UnsupportedCharsetException uce) {
                      result = UnsupportedCharset.forName("UTF-16LE");
                    }
                    return result;
                  }
                }
              }
              default: {
                try {
                  result = Charset.forName("UTF-16LE");
                } catch (UnsupportedCharsetException uce) {
                  result = UnsupportedCharset.forName("UTF-16LE");
                }
                return result;
              }
            }
          }
          default: {
            return result;
          }
        }
      }
      case (0xEF): {
        // 0x EF
        readByte = in.read();
        switch (readByte) {
          case (0xBB): {
            // 0x EF BB
            readByte = in.read();
            switch (readByte) {
              case (0xBF): {
                try {
                  result = Charset.forName("utf-8");
                } catch (UnsupportedCharsetException uce) {
                  result = UnsupportedCharset.forName("utf-8");
                }
                return result;

              }
              default: {
                return result;
              }
            }

          }
          default: {
            return result;
          }
        }

      }
      default:
        return result;

    }
  }

  /**
   *

   * Delegates to {@link #detectCodepage(java.io.InputStream, int)}with a buffered input stream of size 10
   * (8 needed as maximum).
   *

   *
   * @see ICodepageDetector#detectCodepage(java.net.URL)
   */
  public Charset detectCodepage(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.io.*;
import java.util.*;

/**
 * 属性帮助类
 * Created by xiongyingqi on 14-3-7.
 */
public class PropertiesHelper {

    /**
     * 读取属性文件
     *
     * @param propertiesFilePath
     */
    public static Map<String, String> readProperties(String propertiesFilePath) {
        return readProperties(new File(propertiesFilePath));
    }

    /**
     * 读取属性文件
     *
     * @param propertiesFile
     */
    public static Map<String, String> readProperties(File propertiesFile) {
        if (!propertiesFile.exists()) {
            return null;
        }
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(propertiesFile);
            return readProperties(inputStream);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    public static Map<String, String> readProperties(InputStream inputStream) {
        Map<String, String> propertiesMap = null;
        try {
            propertiesMap = new LinkedHashMap<String, String>();

            Properties properties = new Properties();
            properties.load(inputStream);

            Enumeration<?> enumeration = properties.propertyNames();
            while (enumeration.hasMoreElements()) {
                String key = (String) enumeration.nextElement();
                String value = (String) properties.get(key);
                propertiesMap.put(key, value);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return propertiesMap;
    }

    public static void save(Map<String, String> map, File file) throws IOException {
        Assert.notNull(map, "属性集合为空！");
        Properties properties = new Properties();
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            String key = entry.getKey();
            String value = entry.getValue();
            properties.setProperty(key, value);
        }
        save(properties, file);
    }

    public static void save(Properties properties, File file) throws IOException {
        Assert.notNull(properties, "存储的属性为空！");
        OutputStream outputStream = new FileOutputStream(file);
        properties.store(outputStream, "saved on " + DateHelper.getStringDate());
        outputStream.flush();
        outputStream.close();
    }

    public static void main(String[] args) throws IOException {
        File file = new File("test.properties");
        Map<String, String> map = readProperties(file);
        map.put("a", "测试");
        save(map, file);

//        File xmlFile = new File("test.xml");
//	    EntityHelper.print(file.getCanonicalPath());
//        System.out.println(file.exists());
//        FileOutputStream fileOutputStream = new FileOutputStream(file);
//        FileOutputStream fileOutputStreamXml = new FileOutputStream(xmlFile);
//        Properties properties = new Properties();
//        properties.put("test", "test");
//        properties.put("test2", "test");
//        properties.put("test3", "test");
//        properties.store(fileOutputStream, "属性测试");
//        properties.storeToXML(fileOutputStreamXml, "属性测试");
//        fileOutputStream.flush();
//        fileOutputStream.close();
//        fileOutputStreamXml.flush();
//        fileOutputStreamXml.close();
    }
}


/*
 * 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 org.xml.sax.ContentHandler;
import org.xml.sax.XMLReader;

import javax.xml.stream.*;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.stax.StAXResult;
import javax.xml.transform.stax.StAXSource;

/**
 * Convenience methods for working with the StAX API. Partly historic due to JAXP 1.3 compatibility;
 * as of Spring 4.0, relying on JAXP 1.4 as included in JDK 1.6 and higher.
 * <p>In particular, methods for using StAX ({@code javax.xml.stream}) in combination with the TrAX API
 * ({@code javax.xml.transform}), and converting StAX readers/writers into SAX readers/handlers and vice-versa.
 *
 * @author Arjen Poutsma
 * @author Juergen Hoeller
 * @since 3.0
 */
public abstract class StaxUtils {

    /**
     * Create a JAXP 1.4 {@link javax.xml.transform.stax.StAXSource} for the given {@link javax.xml.stream.XMLStreamReader}.
     *
     * @param streamReader the StAX stream reader
     * @return a source wrapping the {@code streamReader}
     */
    public static Source createStaxSource(XMLStreamReader streamReader) {
        return new StAXSource(streamReader);
    }

    /**
     * Create a JAXP 1.4 a {@link javax.xml.transform.stax.StAXSource} for the given {@link javax.xml.stream.XMLEventReader}.
     *
     * @param eventReader the StAX event reader
     * @return a source wrapping the {@code eventReader}
     */
    public static Source createStaxSource(XMLEventReader eventReader) throws XMLStreamException {
        return new StAXSource(eventReader);
    }

    /**
     * Create a custom, non-JAXP 1.4 StAX {@link javax.xml.transform.Source} for the given {@link javax.xml.stream.XMLStreamReader}.
     *
     * @param streamReader the StAX stream reader
     * @return a source wrapping the {@code streamReader}
     */
    public static Source createCustomStaxSource(XMLStreamReader streamReader) {
        return new StaxSource(streamReader);
    }

    /**
     * Create a custom, non-JAXP 1.4 StAX {@link javax.xml.transform.Source} for the given {@link javax.xml.stream.XMLEventReader}.
     *
     * @param eventReader the StAX event reader
     * @return a source wrapping the {@code eventReader}
     */
    public static Source createCustomStaxSource(XMLEventReader eventReader) {
        return new StaxSource(eventReader);
    }

    /**
     * Indicate whether the given {@link javax.xml.transform.Source} is a JAXP 1.4 StAX Source or
     * custom StAX Source.
     *
     * @return {@code true} if {@code source} is a JAXP 1.4 {@link javax.xml.transform.stax.StAXSource} or
     * custom StAX Source; {@code false} otherwise
     */
    public static boolean isStaxSource(Source source) {
        return (source instanceof StAXSource || source instanceof StaxSource);
    }

    /**
     * Return the {@link javax.xml.stream.XMLStreamReader} for the given StAX Source.
     *
     * @param source a JAXP 1.4 {@link javax.xml.transform.stax.StAXSource}
     * @return the {@link javax.xml.stream.XMLStreamReader}
     * @throws IllegalArgumentException if {@code source} isn't a JAXP 1.4 {@link javax.xml.transform.stax.StAXSource}
     *                                  or custom StAX Source
     */
    public static XMLStreamReader getXMLStreamReader(Source source) {
        if (source instanceof StAXSource) {
            return ((StAXSource) source).getXMLStreamReader();
        } else if (source instanceof StaxSource) {
            return ((StaxSource) source).getXMLStreamReader();
        } else {
            throw new IllegalArgumentException("Source '" + source + "' is neither StaxSource nor StAXSource");
        }
    }

    /**
     * Return the {@link javax.xml.stream.XMLEventReader} for the given StAX Source.
     *
     * @param source a JAXP 1.4 {@link javax.xml.transform.stax.StAXSource}
     * @return the {@link javax.xml.stream.XMLEventReader}
     * @throws IllegalArgumentException if {@code source} isn't a JAXP 1.4 {@link javax.xml.transform.stax.StAXSource}
     *                                  or custom StAX Source
     */
    public static XMLEventReader getXMLEventReader(Source source) {
        if (source instanceof StAXSource) {
            return ((StAXSource) source).getXMLEventReader();
        } else if (source instanceof StaxSource) {
            return ((StaxSource) source).getXMLEventReader();
        } else {
            throw new IllegalArgumentException("Source '" + source + "' is neither StaxSource nor StAXSource");
        }
    }

    /**
     * Create a JAXP 1.4 {@link javax.xml.transform.stax.StAXResult} for the given {@link javax.xml.stream.XMLStreamWriter}.
     *
     * @param streamWriter the StAX stream writer
     * @return a result wrapping the {@code streamWriter}
     */
    public static Result createStaxResult(XMLStreamWriter streamWriter) {
        return new StAXResult(streamWriter);
    }

    /**
     * Create a JAXP 1.4 {@link javax.xml.transform.stax.StAXResult} for the given {@link javax.xml.stream.XMLEventWriter}.
     *
     * @param eventWriter the StAX event writer
     * @return a result wrapping {@code streamReader}
     */
    public static Result createStaxResult(XMLEventWriter eventWriter) {
        return new StAXResult(eventWriter);
    }

    /**
     * Create a custom, non-JAXP 1.4 StAX {@link javax.xml.transform.Result} for the given {@link javax.xml.stream.XMLStreamWriter}.
     *
     * @param streamWriter the StAX stream writer
     * @return a source wrapping the {@code streamWriter}
     */
    public static Result createCustomStaxResult(XMLStreamWriter streamWriter) {
        return new StaxResult(streamWriter);
    }

    /**
     * Create a custom, non-JAXP 1.4 StAX {@link javax.xml.transform.Result} for the given {@link javax.xml.stream.XMLEventWriter}.
     *
     * @param eventWriter the StAX event writer
     * @return a source wrapping the {@code eventWriter}
     */
    public static Result createCustomStaxResult(XMLEventWriter eventWriter) {
        return new StaxResult(eventWriter);
    }

    /**
     * Indicate whether the given {@link javax.xml.transform.Result} is a JAXP 1.4 StAX Result or
     * custom StAX Result.
     *
     * @return {@code true} if {@code result} is a JAXP 1.4 {@link javax.xml.transform.stax.StAXResult} or
     * custom StAX Result; {@code false} otherwise
     */
    public static boolean isStaxResult(Result result) {
        return (result instanceof StAXResult || result instanceof StaxResult);
    }

    /**
     * Return the {@link javax.xml.stream.XMLStreamWriter} for the given StAX Result.
     *
     * @param result a JAXP 1.4 {@link javax.xml.transform.stax.StAXResult}
     * @return the {@link javax.xml.stream.XMLStreamReader}
     * @throws IllegalArgumentException if {@code source} isn't a JAXP 1.4 {@link javax.xml.transform.stax.StAXResult}
     *                                  or custom StAX Result
     */
    public static XMLStreamWriter getXMLStreamWriter(Result result) {
        if (result instanceof StAXResult) {
            return ((StAXResult) result).getXMLStreamWriter();
        } else if (result instanceof StaxResult) {
            return ((StaxResult) result).getXMLStreamWriter();
        } else {
            throw new IllegalArgumentException("Result '" + result + "' is neither StaxResult nor StAXResult");
        }
    }

    /**
     * Return the {@link javax.xml.stream.XMLEventWriter} for the given StAX Result.
     *
     * @param result a JAXP 1.4 {@link javax.xml.transform.stax.StAXResult}
     * @return the {@link javax.xml.stream.XMLStreamReader}
     * @throws IllegalArgumentException if {@code source} isn't a JAXP 1.4 {@link javax.xml.transform.stax.StAXResult}
     *                                  or custom StAX Result
     */
    public static XMLEventWriter getXMLEventWriter(Result result) {
        if (result instanceof StAXResult) {
            return ((StAXResult) result).getXMLEventWriter();
        } else if (result instanceof StaxResult) {
            return ((StaxResult) result).getXMLEventWriter();
        } else {
            throw new IllegalArgumentException("Result '" + result + "' is neither StaxResult nor StAXResult");
        }
    }

    /**
     * Create a SAX {@link org.xml.sax.ContentHandler} that writes to the given StAX {@link javax.xml.stream.XMLStreamWriter}.
     *
     * @param streamWriter the StAX stream writer
     * @return a content handler writing to the {@code streamWriter}
     */
    public static ContentHandler createContentHandler(XMLStreamWriter streamWriter) {
        return new StaxStreamContentHandler(streamWriter);
    }

    /**
     * Create a SAX {@link org.xml.sax.ContentHandler} that writes events to the given StAX {@link javax.xml.stream.XMLEventWriter}.
     *
     * @param eventWriter the StAX event writer
     * @return a content handler writing to the {@code eventWriter}
     */
    public static ContentHandler createContentHandler(XMLEventWriter eventWriter) {
        return new StaxEventContentHandler(eventWriter);
    }

    /**
     * Create a SAX {@link org.xml.sax.XMLReader} that reads from the given StAX {@link javax.xml.stream.XMLStreamReader}.
     *
     * @param streamReader the StAX stream reader
     * @return a XMLReader reading from the {@code streamWriter}
     */
    public static XMLReader createXMLReader(XMLStreamReader streamReader) {
        return new StaxStreamXMLReader(streamReader);
    }

    /**
     * Create a SAX {@link org.xml.sax.XMLReader} that reads from the given StAX {@link javax.xml.stream.XMLEventReader}.
     *
     * @param eventReader the StAX event reader
     * @return a XMLReader reading from the {@code eventWriter}
     */
    public static XMLReader createXMLReader(XMLEventReader eventReader) {
        return new StaxEventXMLReader(eventReader);
    }

    /**
     * Return a {@link javax.xml.stream.XMLStreamReader} that reads from a {@link javax.xml.stream.XMLEventReader}.
     * Useful because the StAX {@code XMLInputFactory} allows one to create an
     * event reader from a stream reader, but not vice-versa.
     *
     * @return a stream reader that reads from an event reader
     */
    public static XMLStreamReader createEventStreamReader(XMLEventReader eventReader) throws XMLStreamException {
        return new XMLEventStreamReader(eventReader);
    }

    /**
     * Return a {@link javax.xml.stream.XMLStreamWriter} that writes to a {@link javax.xml.stream.XMLEventWriter}.
     *
     * @return a stream writer that writes to an event writer
     * @since 3.2
     */
    public static XMLStreamWriter createEventStreamWriter(XMLEventWriter eventWriter) {
        return new XMLEventStreamWriter(eventWriter, XMLEventFactory.newFactory());
    }

    /**
     * Return a {@link javax.xml.stream.XMLStreamWriter} that writes to a {@link javax.xml.stream.XMLEventWriter}.
     *
     * @return a stream writer that writes to an event writer
     * @since 3.0.5
     */
    public static XMLStreamWriter createEventStreamWriter(XMLEventWriter eventWriter, XMLEventFactory eventFactory) {
        return new XMLEventStreamWriter(eventWriter, eventFactory);
    }

}


package com.xiongyingqi.util;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.io.*;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;

public class RsaUtils {
    /**
     * 指定加密算法为RSA
     */
    public static final String ALGORITHM = "RSA";
    /**
     * 密钥长度，用来初始化
     */
    private static final int KEYSIZE = 1024;
    /**
     * 指定公钥存放文件
     */
    private static String PUBLIC_KEY_FILE = "PublicKey";
    /**
     * 指定私钥存放文件
     */
    private static String PRIVATE_KEY_FILE = "PrivateKey";

    /**
     * 生成密钥对
     *
     * @throws Exception
     */
    private static void generateKeyPair() throws Exception {

//        /** RSA算法要求有一个可信任的随机数源 */
//        SecureRandom secureRandom = new SecureRandom();

        /** 为RSA算法创建一个KeyPairGenerator对象 */
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM);

        /** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
//        keyPairGenerator.initialize(KEYSIZE, secureRandom);
        keyPairGenerator.initialize(KEYSIZE);

        /** 生成密匙对 */
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        /** 得到公钥 */
        Key publicKey = keyPair.getPublic();

        /** 得到私钥 */
        Key privateKey = keyPair.getPrivate();

        ObjectOutputStream oos1 = null;
        ObjectOutputStream oos2 = null;
        try {
            /** 用对象流将生成的密钥写入文件 */
            oos1 = new ObjectOutputStream(new FileOutputStream(PUBLIC_KEY_FILE));
            oos2 = new ObjectOutputStream(new FileOutputStream(PRIVATE_KEY_FILE));
            oos1.writeObject(publicKey);
            oos2.writeObject(privateKey);
        } catch (Exception e) {
            throw e;
        } finally {
            /** 清空缓存，关闭文件输出流 */
            oos1.close();
            oos2.close();
        }
    }

    /**
     * 加密方法
     *
     * @param source 源数据
     * @return
     * @throws Exception
     * @deprecated
     */
    private static String encrypt(String source) throws Exception {
        generateKeyPair();
        Key publicKey;
        ObjectInputStream ois = null;
        try {
            /** 将文件中的公钥对象读出 */
            ois = new ObjectInputStream(new FileInputStream(
                    PUBLIC_KEY_FILE));
            publicKey = (Key) ois.readObject();
        } catch (Exception e) {
            throw e;
        } finally {
            ois.close();
        }

        /** 得到Cipher对象来实现对源数据的RSA加密 */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] b = source.getBytes();
        /** 执行加密操作 */
        byte[] b1 = cipher.doFinal(b);
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(b1);
    }

    /**
     * 解密算法
     *
     * @param cryptograph 密文
     * @return
     * @throws Exception
     */
    private static String decrypt(String cryptograph) throws Exception {
        Key privateKey;
        ObjectInputStream ois = null;
        try {
            /** 将文件中的私钥对象读出 */
            ois = new ObjectInputStream(new FileInputStream(
                    PRIVATE_KEY_FILE));
            privateKey = (Key) ois.readObject();
        } catch (Exception e) {
            throw e;
        } finally {
            ois.close();
        }

        /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] b1 = decoder.decodeBuffer(cryptograph);

        /** 执行解密操作 */
        byte[] b = cipher.doFinal(b1);
        return new String(b);
    }

    /**
     * 生成密钥对
     *
     */
    public KeyPair generatorKeyPair() throws NoSuchAlgorithmException {
        return generatorKeyPair(ALGORITHM, KEYSIZE);
    }

    /**
     * 生成密钥对
     *
     * @param algorithm
     * @param keySize
     * @return
     * @throws java.security.NoSuchAlgorithmException
     */
    public KeyPair generatorKeyPair(String algorithm, int keySize) throws NoSuchAlgorithmException {
        /** 为RSA算法创建一个KeyPairGenerator对象 */
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(algorithm);

        /** 利用上面的随机数据源初始化这个KeyPairGenerator对象 */
//        keyPairGenerator.initialize(KEYSIZE, secureRandom);
        keyPairGenerator.initialize(keySize);

        /** 生成密匙对 */
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair;
    }

    public String encrypt(String source, Key publicKey) throws Exception {
        return encrypt(source, publicKey, ALGORITHM);
    }

    public String encrypt(String source, Key publicKey, String algorithm) throws Exception {
        /** 得到Cipher对象来实现对源数据的RSA加密 */
        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] b = source.getBytes();
        /** 执行加密操作 */
        byte[] b1 = cipher.doFinal(b);
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(b1);
    }

    public String encrypt(String source, KeyPair keyPair) throws Exception {
        return encrypt(source, keyPair.getPublic());
    }

    public String decrypt(String cryptograph, Key privateKey) throws Exception {
        return decrypt(cryptograph, privateKey, ALGORITHM);
    }

    public String decrypt(String cryptograph, Key privateKey, String algorithm) throws Exception {
        /** 得到Cipher对象对已用公钥加密的数据进行RSA解密 */
        Cipher cipher = Cipher.getInstance(algorithm);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] b1 = decoder.decodeBuffer(cryptograph);

        /** 执行解密操作 */
        byte[] b = cipher.doFinal(b1);
        return new String(b);
    }

    /**
     * 解密算法
     *
     * @param cryptograph 密文
     * @return
     * @throws Exception
     */
    public String decrypt(String cryptograph, KeyPair keyPair) throws Exception {
        return decrypt(cryptograph, keyPair.getPrivate());
    }

    public static void main(String[] args) throws Exception {
//        String source = "恭喜发财!";// 要加密的字符串
//        System.out.println("准备用公钥加密的字符串为：" + source);
//
//        String cryptograph = encrypt(source);// 生成的密文
//        System.out.print("用公钥加密后的结果为:" + cryptograph);
//        System.out.println();
//
//        String target = decrypt(cryptograph);// 解密密文
//        System.out.println("用私钥解密后的字符串为：" + target);
//        System.out.println();

        RsaUtils rsaUtils = new RsaUtils();
        KeyPair keyPair = rsaUtils.generatorKeyPair();
        String secret = rsaUtils.encrypt(StringUtil.randomString(117), keyPair);
        String message = rsaUtils.decrypt(secret, keyPair);

        ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream outputStream = new ObjectOutputStream(arrayOutputStream);
        outputStream.writeObject(keyPair.getPrivate());
        outputStream.flush();
        outputStream.close();
        arrayOutputStream.flush();
        arrayOutputStream.close();
        EntityHelper.print(arrayOutputStream.toString().length());

        System.out.println(message);
        System.out.println(keyPair.getPrivate());
        System.out.println(keyPair.getPublic());
        System.out.println(secret);
    }
}


/*
 * 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;

import java.lang.reflect.Array;
import java.util.Arrays;

/**
 * Miscellaneous object utility methods.
 *
 *
Mainly for internal use within the framework; consider
 * Jakarta's Commons Lang
 * for a more comprehensive suite of object utilities.
 *
 *
Thanks to Alex Ruiz for contributing several enhancements to this class!
 *
 * @author Juergen Hoeller
 * @author Keith Donald
 * @author Rod Johnson
 * @author Rob Harrop
 * @author Chris Beams
 * @since 19.03.2004
 */
public abstract class ObjectUtils {

    private static final int INITIAL_HASH = 7;
    private static final int MULTIPLIER = 31;

    private static final String EMPTY_STRING = "";
    private static final String NULL_STRING = "null";
    private static final String ARRAY_START = "{";
    private static final String ARRAY_END = "}";
    private static final String EMPTY_ARRAY = ARRAY_START + ARRAY_END;
    private static final String ARRAY_ELEMENT_SEPARATOR = ", ";

    /**
     * Return whether the given throwable is a checked exception:
     * that is, neither a RuntimeException nor an Error.
     *
     * @param ex the throwable to check
     * @return whether the throwable is a checked exception
     * @see Exception
     * @see RuntimeException
     * @see Error
     */
    public static boolean isCheckedException(Throwable ex) {
        return !(ex instanceof RuntimeException || ex instanceof Error);
    }

    /**
     * Check whether the given exception is compatible with the exceptions
     * declared in a throws clause.
     *
     * @param ex                 the exception to checked
     * @param declaredExceptions the exceptions declared in the throws clause
     * @return whether the given exception is compatible
     */
    public static boolean isCompatibleWithThrowsClause(Throwable ex, Class<?>[] declaredExceptions) {
        if (!isCheckedException(ex)) {
            return true;
        }
        if (declaredExceptions != null) {
            int i = 0;
            while (i < declaredExceptions.length) {
                if (declaredExceptions[i].isAssignableFrom(ex.getClass())) {
                    return true;
                }
                i++;
            }
        }
        return false;
    }

    /**
     * Determine whether the given object is an array:
     * either an Object array or a primitive array.
     *
     * @param obj the object to check
     */
    public static boolean isArray(Object obj) {
        return (obj != null && obj.getClass().isArray());
    }

    /**
     * Determine whether the given array is empty:
     * i.e. {@code null} or of zero length.
     *
     * @param array the array to check
     */
    public static boolean isEmpty(Object[] array) {
        return (array == null || array.length == 0);
    }

    /**
     * Check whether the given array contains the given element.
     *
     * @param array   the array to check (may be {@code null},
     *                in which case the return value will always be {@code false})
     * @param element the element to check for
     * @return whether the element has been found in the given array
     */
    public static boolean containsElement(Object[] array, Object element) {
        if (array == null) {
            return false;
        }
        for (Object arrayEle : array) {
            if (nullSafeEquals(arrayEle, element)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Check whether the given array of enum constants contains a constant with the given name,
     * ignoring case when determining a match.
     *
     * @param enumValues the enum values to check, typically the product of a call to MyEnum.values()
     * @param constant   the constant name to find (must not be null or empty string)
     * @return whether the constant has been found in the given array
     */
    public static boolean containsConstant(Enum<?>[] enumValues, String constant) {
        return containsConstant(enumValues, constant, false);
    }

    /**
     * Check whether the given array of enum constants contains a constant with the given name.
     *
     * @param enumValues    the enum values to check, typically the product of a call to MyEnum.values()
     * @param constant      the constant name to find (must not be null or empty string)
     * @param caseSensitive whether case is significant in determining a match
     * @return whether the constant has been found in the given array
     */
    public static boolean containsConstant(Enum<?>[] enumValues, String constant, boolean caseSensitive) {
        for (Enum<?> candidate : enumValues) {
            if (caseSensitive ?
                    candidate.toString().equals(constant) :
                    candidate.toString().equalsIgnoreCase(constant)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Case insensitive alternative to {@link Enum#valueOf(Class, String)}.
     *
     * @param <E>        the concrete Enum type
     * @param enumValues the array of all Enum constants in question, usually per Enum.values()
     * @param constant   the constant to get the enum value of
     * @throws IllegalArgumentException if the given constant is not found in the given array
     *                                  of enum values. Use {@link #containsConstant(Enum[], String)} as a guard to avoid this exception.
     */
    public static <E extends Enum<?>> E caseInsensitiveValueOf(E[] enumValues, String constant) {
        for (E candidate : enumValues) {
            if (candidate.toString().equalsIgnoreCase(constant)) {
                return candidate;
            }
        }
        throw new IllegalArgumentException(
                String.format("constant [%s] does not exist in enum type %s",
                        constant, enumValues.getClass().getComponentType().getName())
        );
    }

    /**
     * Append the given object to the given array, returning a new array
     * consisting of the input array contents plus the given object.
     *
     * @param array the array to append to (can be {@code null})
     * @param obj   the object to append
     * @return the new array (of the same component type; never {@code null})
     */
    public static  A[] addObjectToArray(A[] array, O obj) {
        Class<?> compType = Object.class;
        if (array != null) {
            compType = array.getClass().getComponentType();
        } else if (obj != null) {
            compType = obj.getClass();
        }
        int newArrLength = (array != null ? array.length + 1 : 1);
        @SuppressWarnings("unchecked")
        A[] newArr = (A[]) Array.newInstance(compType, newArrLength);
        if (array != null) {
            System.arraycopy(array, 0, newArr, 0, array.length);
        }
        newArr[newArr.length - 1] = obj;
        return newArr;
    }

    /**
     * Convert the given array (which may be a primitive array) to an
     * object array (if necessary of primitive wrapper objects).
     *
A {@code null} source value will be converted to an
     * empty Object array.
     *
     * @param source the (potentially primitive) array
     * @return the corresponding object array (never {@code null})
     * @throws IllegalArgumentException if the parameter is not an array
     */
    public static Object[] toObjectArray(Object source) {
        if (source instanceof Object[]) {
            return (Object[]) source;
        }
        if (source == null) {
            return new Object[0];
        }
        if (!source.getClass().isArray()) {
            throw new IllegalArgumentException("Source is not an array: " + source);
        }
        int length = Array.getLength(source);
        if (length == 0) {
            return new Object[0];
        }
        Class<?> wrapperType = Array.get(source, 0).getClass();
        Object[] newArray = (Object[]) Array.newInstance(wrapperType, length);
        for (int i = 0; i < length; i++) {
            newArray[i] = Array.get(source, i);
        }
        return newArray;
    }

    //---------------------------------------------------------------------
    // Convenience methods for content-based equality/hash-code handling
    //---------------------------------------------------------------------

    /**
     * Determine if the given objects are equal, returning {@code true}
     * if both are {@code null} or {@code false} if only one is
     * {@code null}.
     *
Compares arrays with {@code Arrays.equals}, performing an equality
     * check based on the array elements rather than the array reference.
     *
     * @param o1 first Object to compare
     * @param o2 second Object to compare
     * @return whether the given objects are equal
     * @see java.util.Arrays#equals
     */
    public static boolean nullSafeEquals(Object o1, Object o2) {
        if (o1 == o2) {
            return true;
        }
        if (o1 == null || o2 == null) {
            return false;
        }
        if (o1.equals(o2)) {
            return true;
        }
        if (o1.getClass().isArray() && o2.getClass().isArray()) {
            if (o1 instanceof Object[] && o2 instanceof Object[]) {
                return Arrays.equals((Object[]) o1, (Object[]) o2);
            }
            if (o1 instanceof boolean[] && o2 instanceof boolean[]) {
                return Arrays.equals((boolean[]) o1, (boolean[]) o2);
            }
            if (o1 instanceof byte[] && o2 instanceof byte[]) {
                return Arrays.equals((byte[]) o1, (byte[]) o2);
            }
            if (o1 instanceof char[] && o2 instanceof char[]) {
                return Arrays.equals((char[]) o1, (char[]) o2);
            }
            if (o1 instanceof double[] && o2 instanceof double[]) {
                return Arrays.equals((double[]) o1, (double[]) o2);
            }
            if (o1 instanceof float[] && o2 instanceof float[]) {
                return Arrays.equals((float[]) o1, (float[]) o2);
            }
            if (o1 instanceof int[] && o2 instanceof int[]) {
                return Arrays.equals((int[]) o1, (int[]) o2);
            }
            if (o1 instanceof long[] && o2 instanceof long[]) {
                return Arrays.equals((long[]) o1, (long[]) o2);
            }
            if (o1 instanceof short[] && o2 instanceof short[]) {
                return Arrays.equals((short[]) o1, (short[]) o2);
            }
        }
        return false;
    }

    /**
     * Return as hash code for the given object; typically the value of
     * {@code Object#hashCode()}}. If the object is an array,
     * this method will delegate to any of the {@code nullSafeHashCode}
     * methods for arrays in this class. If the object is {@code null},
     * this method returns 0.
     *
     * @see #nullSafeHashCode(Object[])
     * @see #nullSafeHashCode(boolean[])
     * @see #nullSafeHashCode(byte[])
     * @see #nullSafeHashCode(char[])
     * @see #nullSafeHashCode(double[])
     * @see #nullSafeHashCode(float[])
     * @see #nullSafeHashCode(int[])
     * @see #nullSafeHashCode(long[])
     * @see #nullSafeHashCode(short[])
     */
    public static int nullSafeHashCode(Object obj) {
        if (obj == null) {
            return 0;
        }
        if (obj.getClass().isArray()) {
            if (obj instanceof Object[]) {
                return nullSafeHashCode((Object[]) obj);
            }
            if (obj instanceof boolean[]) {
                return nullSafeHashCode((boolean[]) obj);
            }
            if (obj instanceof byte[]) {
                return nullSafeHashCode((byte[]) obj);
            }
            if (obj instanceof char[]) {
                return nullSafeHashCode((char[]) obj);
            }
            if (obj instanceof double[]) {
                return nullSafeHashCode((double[]) obj);
            }
            if (obj instanceof float[]) {
                return nullSafeHashCode((float[]) obj);
            }
            if (obj instanceof int[]) {
                return nullSafeHashCode((int[]) obj);
            }
            if (obj instanceof long[]) {
                return nullSafeHashCode((long[]) obj);
            }
            if (obj instanceof short[]) {
                return nullSafeHashCode((short[]) obj);
            }
        }
        return obj.hashCode();
    }

    /**
     * Return a hash code based on the contents of the specified array.
     * If {@code array} is {@code null}, this method returns 0.
     */
    public static int nullSafeHashCode(Object[] array) {
        if (array == null) {
            return 0;
        }
        int hash = INITIAL_HASH;
        int arraySize = array.length;
        for (int i = 0; i < arraySize; i++) {
            hash = MULTIPLIER * hash + nullSafeHashCode(array[i]);
        }
        return hash;
    }

    /**
     * Return a hash code based on the contents of the specified array.
     * If {@code array} is {@code null}, this method returns 0.
     */
    public static int nullSafeHashCode(boolean[] array) {
        if (array == null) {
            return 0;
        }
        int hash = INITIAL_HASH;
        int arraySize = array.length;
        for (int i = 0; i < arraySize; i++) {
            hash = MULTIPLIER * hash + hashCode(array[i]);
        }
        return hash;
    }

    /**
     * Return a hash code based on the contents of the specified array.
     * If {@code array} is {@code null}, this method returns 0.
     */
    public static int nullSafeHashCode(byte[] array) {
        if (array == null) {
            return 0;
        }
        int hash = INITIAL_HASH;
        int arraySize = array.length;
        for (int i = 0; i < arraySize; i++) {
            hash = MULTIPLIER * hash + array[i];
        }
        return hash;
    }

    /**
     * Return a hash code based on the contents of the specified array.
     * If {@code array} is {@code null}, this method returns 0.
     */
    public static int nullSafeHashCode(char[] array) {
        if (array == null) {
            return 0;
        }
        int hash = INITIAL_HASH;
        int arraySize = array.length;
        for (int i = 0; i < arraySize; i++) {
            hash = MULTIPLIER * hash + array[i];
        }
        return hash;
    }

    /**
     * Return a hash code based on the contents of the specified array.
     * If {@code array} is {@code null}, this method returns 0.
     */
    public static int nullSafeHashCode(double[] array) {
        if (array == null) {
            return 0;
        }
        int hash = INITIAL_HASH;
        int arraySize = array.length;
        for (int i = 0; i < arraySize; i++) {
            hash = MULTIPLIER * hash + hashCode(array[i]);
        }
        return hash;
    }

    /**
     * Return a hash code based on the contents of the specified array.
     * If {@code array} is {@code null}, this method returns 0.
     */
    public static int nullSafeHashCode(float[] array) {
        if (array == null) {
            return 0;
        }
        int hash = INITIAL_HASH;
        int arraySize = array.length;
        for (int i = 0; i < arraySize; i++) {
            hash = MULTIPLIER * hash + hashCode(array[i]);
        }
        return hash;
    }

    /**
     * Return a hash code based on the contents of the specified array.
     * If {@code array} is {@code null}, this method returns 0.
     */
    public static int nullSafeHashCode(int[] array) {
        if (array == null) {
            return 0;
        }
        int hash = INITIAL_HASH;
        int arraySize = array.length;
        for (int i = 0; i < arraySize; i++) {
            hash = MULTIPLIER * hash + array[i];
        }
        return hash;
    }

    /**
     * Return a hash code based on the contents of the specified array.
     * If {@code array} is {@code null}, this method returns 0.
     */
    public static int nullSafeHashCode(long[] array) {
        if (array == null) {
            return 0;
        }
        int hash = INITIAL_HASH;
        int arraySize = array.length;
        for (int i = 0; i < arraySize; i++) {
            hash = MULTIPLIER * hash + hashCode(array[i]);
        }
        return hash;
    }

    /**
     * Return a hash code based on the contents of the specified array.
     * If {@code array} is {@code null}, this method returns 0.
     */
    public static int nullSafeHashCode(short[] array) {
        if (array == null) {
            return 0;
        }
        int hash = INITIAL_HASH;
        int arraySize = array.length;
        for (int i = 0; i < arraySize; i++) {
            hash = MULTIPLIER * hash + array[i];
        }
        return hash;
    }

    /**
     * Return the same value as {@link Boolean#hashCode()}}.
     *
     * @see Boolean#hashCode()
     */
    public static int hashCode(boolean bool) {
        return bool ? 1231 : 1237;
    }

    /**
     * Return the same value as {@link Double#hashCode()}}.
     *
     * @see Double#hashCode()
     */
    public static int hashCode(double dbl) {
        long bits = Double.doubleToLongBits(dbl);
        return hashCode(bits);
    }

    /**
     * Return the same value as {@link Float#hashCode()}}.
     *
     * @see Float#hashCode()
     */
    public static int hashCode(float flt) {
        return Float.floatToIntBits(flt);
    }

    /**
     * Return the same value as {@link Long#hashCode()}}.
     *
     * @see Long#hashCode()
     */
    public static int hashCode(long lng) {
        return (int) (lng ^ (lng >>> 32));
    }

    //---------------------------------------------------------------------
    // Convenience methods for toString output
    //---------------------------------------------------------------------

    /**
     * Return a String representation of an object's overall identity.
     *
     * @param obj the object (may be {@code null})
     * @return the object's identity as String representation,
     * or an empty String if the object was {@code null}
     */
    public static String identityToString(Object obj) {
        if (obj == null) {
            return EMPTY_STRING;
        }
        return obj.getClass().getName() + "@" + getIdentityHexString(obj);
    }

    /**
     * Return a hex String form of an object's identity hash code.
     *
     * @param obj the object
     * @return the object's identity code in hex notation
     */
    public static String getIdentityHexString(Object obj) {
        return Integer.toHexString(System.identityHashCode(obj));
    }

    /**
     * Return a content-based String representation if {@code obj} is
     * not {@code null}; otherwise returns an empty String.
     *
Differs from {@link #nullSafeToString(Object)} in that it returns
     * an empty String rather than "null" for a {@code null} value.
     *
     * @param obj the object to build a display String for
     * @return a display String representation of {@code obj}
     * @see #nullSafeToString(Object)
     */
    public static String getDisplayString(Object obj) {
        if (obj == null) {
            return EMPTY_STRING;
        }
        return nullSafeToString(obj);
    }

    /**
     * Determine the class name for the given object.
     *
Returns {@code "null"} if {@code obj} is {@code null}.
     *
     * @param obj the object to introspect (may be {@code null})
     * @return the corresponding class name
     */
    public static String nullSafeClassName(Object obj) {
        return (obj != null ? obj.getClass().getName() : NULL_STRING);
    }

    /**
     * Return a String representation of the specified Object.
     *
Builds a String representation of the contents in case of an array.
     * Returns {@code "null"} if {@code obj} is {@code null}.
     *
     * @param obj the object to build a String representation for
     * @return a String representation of {@code obj}
     */
    public static String nullSafeToString(Object obj) {
        if (obj == null) {
            return NULL_STRING;
        }
        if (obj instanceof String) {
            return (String) obj;
        }
        if (obj instanceof Object[]) {
            return nullSafeToString((Object[]) obj);
        }
        if (obj instanceof boolean[]) {
            return nullSafeToString((boolean[]) obj);
        }
        if (obj instanceof byte[]) {
            return nullSafeToString((byte[]) obj);
        }
        if (obj instanceof char[]) {
            return nullSafeToString((char[]) obj);
        }
        if (obj instanceof double[]) {
            return nullSafeToString((double[]) obj);
        }
        if (obj instanceof float[]) {
            return nullSafeToString((float[]) obj);
        }
        if (obj instanceof int[]) {
            return nullSafeToString((int[]) obj);
        }
        if (obj instanceof long[]) {
            return nullSafeToString((long[]) obj);
        }
        if (obj instanceof short[]) {
            return nullSafeToString((short[]) obj);
        }
        String str = obj.toString();
        return (str != null ? str : EMPTY_STRING);
    }

    /**
     * Return a String representation of the contents of the specified array.
     *
The String representation consists of a list of the array's elements,
     * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
     * by the characters {@code ", "} (a comma followed by a space). Returns
     * {@code "null"} if {@code array} is {@code null}.
     *
     * @param array the array to build a String representation for
     * @return a String representation of {@code array}
     */
    public static String nullSafeToString(Object[] array) {
        if (array == null) {
            return NULL_STRING;
        }
        int length = array.length;
        if (length == 0) {
            return EMPTY_ARRAY;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            if (i == 0) {
                sb.append(ARRAY_START);
            } else {
                sb.append(ARRAY_ELEMENT_SEPARATOR);
            }
            sb.append(String.valueOf(array[i]));
        }
        sb.append(ARRAY_END);
        return sb.toString();
    }

    /**
     * Return a String representation of the contents of the specified array.
     *
The String representation consists of a list of the array's elements,
     * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
     * by the characters {@code ", "} (a comma followed by a space). Returns
     * {@code "null"} if {@code array} is {@code null}.
     *
     * @param array the array to build a String representation for
     * @return a String representation of {@code array}
     */
    public static String nullSafeToString(boolean[] array) {
        if (array == null) {
            return NULL_STRING;
        }
        int length = array.length;
        if (length == 0) {
            return EMPTY_ARRAY;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            if (i == 0) {
                sb.append(ARRAY_START);
            } else {
                sb.append(ARRAY_ELEMENT_SEPARATOR);
            }

            sb.append(array[i]);
        }
        sb.append(ARRAY_END);
        return sb.toString();
    }

    /**
     * Return a String representation of the contents of the specified array.
     *
The String representation consists of a list of the array's elements,
     * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
     * by the characters {@code ", "} (a comma followed by a space). Returns
     * {@code "null"} if {@code array} is {@code null}.
     *
     * @param array the array to build a String representation for
     * @return a String representation of {@code array}
     */
    public static String nullSafeToString(byte[] array) {
        if (array == null) {
            return NULL_STRING;
        }
        int length = array.length;
        if (length == 0) {
            return EMPTY_ARRAY;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            if (i == 0) {
                sb.append(ARRAY_START);
            } else {
                sb.append(ARRAY_ELEMENT_SEPARATOR);
            }
            sb.append(array[i]);
        }
        sb.append(ARRAY_END);
        return sb.toString();
    }

    /**
     * Return a String representation of the contents of the specified array.
     *
The String representation consists of a list of the array's elements,
     * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
     * by the characters {@code ", "} (a comma followed by a space). Returns
     * {@code "null"} if {@code array} is {@code null}.
     *
     * @param array the array to build a String representation for
     * @return a String representation of {@code array}
     */
    public static String nullSafeToString(char[] array) {
        if (array == null) {
            return NULL_STRING;
        }
        int length = array.length;
        if (length == 0) {
            return EMPTY_ARRAY;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            if (i == 0) {
                sb.append(ARRAY_START);
            } else {
                sb.append(ARRAY_ELEMENT_SEPARATOR);
            }
            sb.append("'").append(array[i]).append("'");
        }
        sb.append(ARRAY_END);
        return sb.toString();
    }

    /**
     * Return a String representation of the contents of the specified array.
     *
The String representation consists of a list of the array's elements,
     * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
     * by the characters {@code ", "} (a comma followed by a space). Returns
     * {@code "null"} if {@code array} is {@code null}.
     *
     * @param array the array to build a String representation for
     * @return a String representation of {@code array}
     */
    public static String nullSafeToString(double[] array) {
        if (array == null) {
            return NULL_STRING;
        }
        int length = array.length;
        if (length == 0) {
            return EMPTY_ARRAY;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            if (i == 0) {
                sb.append(ARRAY_START);
            } else {
                sb.append(ARRAY_ELEMENT_SEPARATOR);
            }

            sb.append(array[i]);
        }
        sb.append(ARRAY_END);
        return sb.toString();
    }

    /**
     * Return a String representation of the contents of the specified array.
     *
The String representation consists of a list of the array's elements,
     * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
     * by the characters {@code ", "} (a comma followed by a space). Returns
     * {@code "null"} if {@code array} is {@code null}.
     *
     * @param array the array to build a String representation for
     * @return a String representation of {@code array}
     */
    public static String nullSafeToString(float[] array) {
        if (array == null) {
            return NULL_STRING;
        }
        int length = array.length;
        if (length == 0) {
            return EMPTY_ARRAY;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            if (i == 0) {
                sb.append(ARRAY_START);
            } else {
                sb.append(ARRAY_ELEMENT_SEPARATOR);
            }

            sb.append(array[i]);
        }
        sb.append(ARRAY_END);
        return sb.toString();
    }

    /**
     * Return a String representation of the contents of the specified array.
     *
The String representation consists of a list of the array's elements,
     * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
     * by the characters {@code ", "} (a comma followed by a space). Returns
     * {@code "null"} if {@code array} is {@code null}.
     *
     * @param array the array to build a String representation for
     * @return a String representation of {@code array}
     */
    public static String nullSafeToString(int[] array) {
        if (array == null) {
            return NULL_STRING;
        }
        int length = array.length;
        if (length == 0) {
            return EMPTY_ARRAY;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            if (i == 0) {
                sb.append(ARRAY_START);
            } else {
                sb.append(ARRAY_ELEMENT_SEPARATOR);
            }
            sb.append(array[i]);
        }
        sb.append(ARRAY_END);
        return sb.toString();
    }

    /**
     * Return a String representation of the contents of the specified array.
     *
The String representation consists of a list of the array's elements,
     * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
     * by the characters {@code ", "} (a comma followed by a space). Returns
     * {@code "null"} if {@code array} is {@code null}.
     *
     * @param array the array to build a String representation for
     * @return a String representation of {@code array}
     */
    public static String nullSafeToString(long[] array) {
        if (array == null) {
            return NULL_STRING;
        }
        int length = array.length;
        if (length == 0) {
            return EMPTY_ARRAY;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            if (i == 0) {
                sb.append(ARRAY_START);
            } else {
                sb.append(ARRAY_ELEMENT_SEPARATOR);
            }
            sb.append(array[i]);
        }
        sb.append(ARRAY_END);
        return sb.toString();
    }

    /**
     * Return a String representation of the contents of the specified array.
     *
The String representation consists of a list of the array's elements,
     * enclosed in curly braces ({@code "{}"}). Adjacent elements are separated
     * by the characters {@code ", "} (a comma followed by a space). Returns
     * {@code "null"} if {@code array} is {@code null}.
     *
     * @param array the array to build a String representation for
     * @return a String representation of {@code array}
     */
    public static String nullSafeToString(short[] array) {
        if (array == null) {
            return NULL_STRING;
        }
        int length = array.length;
        if (length == 0) {
            return EMPTY_ARRAY;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            if (i == 0) {
                sb.append(ARRAY_START);
            } else {
                sb.append(ARRAY_ELEMENT_SEPARATOR);
            }
            sb.append(array[i]);
        }
        sb.append(ARRAY_END);
        return sb.toString();
    }

}


package com.xiongyingqi.util;

import java.io.*;
import java.security.Key;
import java.util.Date;

/**
 * Created by 瑛琪xiongyingqi.com on 2014/4/28 0028.
 */
public class SerializeHelper {
    public static final String ENCODING = "UTF-8";
    private static byte index;

    /**
     * 将对象序列化到文件
     *
     * @param folder       父目录
     * @param serializable
     * @return
     * @throws java.io.IOException
     */
    public static File writeObjectToFile(File folder, Serializable serializable) throws IOException {
        Assert.notNull(folder, "文件夹不能为空");
        if (!folder.exists()) {
            folder.mkdirs();
        }
        Assert.isTrue(folder.isDirectory(), folder + "不是文件夹");
        File file = new File(folder, System.currentTimeMillis() + nextIndex() + "");
        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(file));
        outputStream.writeObject(serializable);
        outputStream.flush();
        outputStream.close();
        return file;
    }

    public static byte[] readObjectToBytes(Serializable serializable) {
        ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream outputStream = null;
        try {
            outputStream = new ObjectOutputStream(arrayOutputStream);
            outputStream.writeObject(serializable);
            outputStream.flush();
            outputStream.close();
            arrayOutputStream.flush();
            arrayOutputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return arrayOutputStream.toByteArray();
    }

    /**
     * 返回固定长度的
     *
     * @return
     */
    private static String nextIndex() {
        String rs = "";
        synchronized (SerializeHelper.class) {
            rs += ++index < 0 ? -index : index;
            int least = 3 - rs.length();
            for (int i = 0; i < least; i++) {
                rs = "0" + rs;
            }
            return rs;
        }
    }

    public static long getTimeOfTheName(String fileName) throws NumberFormatException{
        String longStr = fileName.substring(0, fileName.length() - 3);
        Long lo = Long.parseLong(longStr);
        return lo;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 1000; i++) {
            EntityHelper.print(nextIndex());
            String fileName = System.currentTimeMillis() + nextIndex();
            EntityHelper.print(getTimeOfTheName(fileName));
        }

        System.out.println(Base64.decodeToObject(Base64.encodeObject(new Date())));
    }

    public static Key readObjectFromFile(File privateKeyFile) throws IOException, ClassNotFoundException {
        Assert.notNull(privateKeyFile, "文件夹不能为空");
        Assert.isTrue(privateKeyFile.exists(), "私钥文件不存在");
        InputStream inputStream = new FileInputStream(privateKeyFile);
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        Key privateKey = (Key) objectInputStream.readObject();
        return privateKey;
    }

}


/*
 *  IClassFileFilter.java  cpdetector
 *  Copyright (C) 2004 Achim Westermann, created on 03.06.2004
 *
 * ***** 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 org.mozilla.intl.chardet.nsDetector;
import org.mozilla.intl.chardet.nsICharsetDetectionObserver;
import org.mozilla.intl.chardet.nsPSMDetector;

import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;

/**
 * A fac�ade for jchardet codepage detection. JChardet  is the java port of Frank Yung-Fong Tang's
 * Mozilla charset detector.
 *

 * This charset detector works on guessing the codepage. "The algorithm looks
 * into the byte sequence and based on the values of each byte uses a
 * elimination logic to narrow down to the final charset. If there is a tie
 * between EUC charsets, it uses the second logic to narrow down. This logic
 * uses the frequency statistics of characters in a given language." ( source of description ).
 *

 * It is a singleton for performance reasons (buffer allocation). Because it is
 * stateful (internal buffer) the method
 * {@link #detectCodepage(java.io.InputStream, int)}(delegated to by
 * {@link #detectCodepage(java.net.URL)}has to be synchronized.
 *

 *
 *
 * @author Achim Westermann
 *
 */
public final class JChardetFacade
    extends AbstractCodepageDetector implements nsICharsetDetectionObserver {
  private static JChardetFacade instance = null;

  private static nsDetector det;

  private byte[] buf = new byte[4096];

  private Charset codpage = null;

  private boolean m_guessing = true;

  private int amountOfVerifiers = 0;

  /**
   *
   */
  private JChardetFacade() {
    super();
    det = new nsDetector(nsPSMDetector.ALL);
    det.Init(this);
    this.amountOfVerifiers = det.getProbableCharsets().length;
  }

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

  /*
   * (non-Javadoc)
   *
   * @see cpdetector.io.ICodepageDetector#detectCodepage(java.io.InputStream)
   */
  public synchronized Charset detectCodepage(InputStream in, int length) throws IOException {
    this.Reset();
    int len;
    int read = 0;
    boolean done = false;
    boolean isAscii = true;
    Charset ret = null;
    do {
      len = in.read(buf, 0, Math.min(buf.length, length - read));
      if (len > 0) {
        read += len;
      }
      if (!done)
        done = det.DoIt(buf, len, false);
    } while (len > 0 && !done);
    det.DataEnd();
    if (this.codpage == null) {
      if (this.m_guessing) {
        ret = guess();
      } else {
        ret = UnknownCharset.getInstance();
      }
    } else {
      ret = this.codpage;
    }
    return ret;

  }

  /**
   *
   */
  private Charset guess() {
    Charset ret = null;
    String[] possibilities = det.getProbableCharsets();
    /*
     * Detect US-ASCII by the fact, that no exclusion of any Charset was
     * possible.
     */
    if (possibilities.length == this.amountOfVerifiers) {
      ret = Charset.forName("US-ASCII");
    } else {
      // He should better return an Array of length zero!
      String check = possibilities[0];
      if (check.equalsIgnoreCase("nomatch")) {
        ret = UnknownCharset.getInstance();
      } else {
        for (int i = 0; ret == null && i < possibilities.length; i++) {
          try {
            ret = Charset.forName(possibilities[i]);
          } catch (UnsupportedCharsetException uce) {
            ret = UnsupportedCharset.forName(possibilities[i]);
          }
        }
      }
    }
    return ret;

  }

 /**
  *
  * @see org.mozilla.intl.chardet.nsICharsetDetectionObserver#Notify(String)
  */
  public void Notify(final String charset) {
    this.codpage = Charset.forName(charset);
  }

  public void Reset() {
    det.Reset();
    this.codpage = null;
  }

  /**
   * @return Returns the m_guessing.
   */
  public boolean isGuessing() {
    return m_guessing;
  }

  /**
   *

   * If it was impossible to narrow down possible results to one, an internal
   * set of possible character encodings exists. By setting guessing to true,
   * the call to {@link #detectCodepage(java.io.InputStream, int)} and
   * {@link #detectCodepage(java.net.URL)} will return an arbitrary possible Charset.
   *

   *

   * Currently the following precedence is implemented to choose the possible
   * Charset:
   *

   *
 If US-ASCII is possible, it is chosen.
   *
 If US-ASCII is not possible, the first supported one in the set of
   * possible charsets is returned. No information about the semantics of the
   * order in that list is available. If no possibility is supported, an
   * instance of {@link UnsupportedCharset} is returned.
   *

   * ASCII indeed is never detected as possible: No internal verifier exists for
   * ASCII, as all Charsets support ASCII. The possibility of ASCII is detected,
   * when no Charset has been excluded: The amount of possible Charsets is equal
   * to the amount of all detectable Charsets.
   *
   * @param guessing
   *          The guessing to set.
   */
  public synchronized void setGuessing(final boolean guessing) {
    this.m_guessing = guessing;
  }
}


/*
 * 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.xml;

import com.xiongyingqi.util.Assert;

import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import java.util.*;

/**
 * Simple {@code javax.xml.namespace.NamespaceContext} implementation. Follows the standard
 * {@code NamespaceContext} contract, and is loadable via a {@code java.util.Map} or
 * {@code java.util.Properties} object
 *
 * @author Arjen Poutsma
 * @since 3.0
 */
public class SimpleNamespaceContext implements NamespaceContext {

    private Map<String, String> prefixToNamespaceUri = new HashMap<String, String>();

    private Map<String, List<String>> namespaceUriToPrefixes = new HashMap<String, List<String>>();

    private String defaultNamespaceUri = "";

    @Override
    public String getNamespaceURI(String prefix) {
        Assert.notNull(prefix, "prefix is null");
        if (XMLConstants.XML_NS_PREFIX.equals(prefix)) {
            return XMLConstants.XML_NS_URI;
        } else if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) {
            return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
        } else if (XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)) {
            return defaultNamespaceUri;
        } else if (prefixToNamespaceUri.containsKey(prefix)) {
            return prefixToNamespaceUri.get(prefix);
        }
        return "";
    }

    @Override
    public String getPrefix(String namespaceUri) {
        List<?> prefixes = getPrefixesInternal(namespaceUri);
        return prefixes.isEmpty() ? null : (String) prefixes.get(0);
    }

    @Override
    public Iterator<String> getPrefixes(String namespaceUri) {
        return getPrefixesInternal(namespaceUri).iterator();
    }

    /**
     * Sets the bindings for this namespace context. The supplied map must consist of string key value pairs.
     *
     * @param bindings the bindings
     */
    public void setBindings(Map<String, String> bindings) {
        for (Map.Entry<String, String> entry : bindings.entrySet()) {
            bindNamespaceUri(entry.getKey(), entry.getValue());
        }
    }

    /**
     * Binds the given namespace as default namespace.
     *
     * @param namespaceUri the namespace uri
     */
    public void bindDefaultNamespaceUri(String namespaceUri) {
        bindNamespaceUri(XMLConstants.DEFAULT_NS_PREFIX, namespaceUri);
    }

    /**
     * Binds the given prefix to the given namespace.
     *
     * @param prefix       the namespace prefix
     * @param namespaceUri the namespace uri
     */
    public void bindNamespaceUri(String prefix, String namespaceUri) {
        Assert.notNull(prefix, "No prefix given");
        Assert.notNull(namespaceUri, "No namespaceUri given");
        if (XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)) {
            defaultNamespaceUri = namespaceUri;
        } else {
            prefixToNamespaceUri.put(prefix, namespaceUri);
            getPrefixesInternal(namespaceUri).add(prefix);
        }
    }

    /**
     * Removes all declared prefixes.
     */
    public void clear() {
        prefixToNamespaceUri.clear();
    }

    /**
     * Returns all declared prefixes.
     *
     * @return the declared prefixes
     */
    public Iterator<String> getBoundPrefixes() {
        return prefixToNamespaceUri.keySet().iterator();
    }

    private List<String> getPrefixesInternal(String namespaceUri) {
        if (defaultNamespaceUri.equals(namespaceUri)) {
            return Collections.singletonList(XMLConstants.DEFAULT_NS_PREFIX);
        } else if (XMLConstants.XML_NS_URI.equals(namespaceUri)) {
            return Collections.singletonList(XMLConstants.XML_NS_PREFIX);
        } else if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceUri)) {
            return Collections.singletonList(XMLConstants.XMLNS_ATTRIBUTE);
        } else {
            List<String> list = namespaceUriToPrefixes.get(namespaceUri);
            if (list == null) {
                list = new ArrayList<String>();
                namespaceUriToPrefixes.put(namespaceUri, list);
            }
            return list;
        }
    }

    /**
     * Removes the given prefix from this context.
     *
     * @param prefix the prefix to be removed
     */
    public void removeBinding(String prefix) {
        if (XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)) {
            defaultNamespaceUri = "";
        } else {
            String namespaceUri = prefixToNamespaceUri.remove(prefix);
            List<String> prefixes = getPrefixesInternal(namespaceUri);
            prefixes.remove(prefix);
        }
    }
}


package com.xiongyingqi.util;

import info.monitorenter.cpdetector.io.ASCIIDetector;
import info.monitorenter.cpdetector.io.CodepageDetectorProxy;
import info.monitorenter.cpdetector.io.JChardetFacade;
import info.monitorenter.cpdetector.io.ParsingDetector;

import java.io.File;
import java.nio.charset.Charset;

/**
 * Created by 瑛琪xiongyingqi.com on 2014/9/23 0023.
 */
public class FileEncode {

    /**
     * 使用工具获取文件的编码方式
     *
     * @param file
     * @return
     */
    public static synchronized String getEncodeByUtil(File file) {
        CodepageDetectorProxy detector = CodepageDetectorProxy.getInstance();

        detector.add(new ParsingDetector(false));

        detector.add(JChardetFacade.getInstance());// 用到antlr.jar、chardet.jar
        // ASCIIDetector用于ASCII编码测定
        detector.add(ASCIIDetector.getInstance());
        // UnicodeDetector用于Unicode家族编码的测定
//        detector.add(UnicodeDetector.getInstance());
        Charset charset = null;
        try {
            charset = detector.detectCodepage(file.toURI().toURL());
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        if (charset != null)
            return charset.name();
        else
            return null;
    }
}


package com.xiongyingqi.util;

import java.lang.reflect.Field;
import java.util.Vector;

/**
 * Created by xiongyingqi on 14-3-10.
 */
public class ClassHelper {

    /**
     * 获取加载的所有类
     *
     * @return
     */
    public static Class[] getAllClasses() {
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        Class<?> cla = classLoader.getClass();
        while (cla != ClassLoader.class)
            cla = cla.getSuperclass();
        Field field = null;
        try {
            field = cla.getDeclaredField("classes");
            field.setAccessible(true);
            Vector<Class> v = null;
            try {
                v = (Vector<Class>) field.get(classLoader);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            for (int i = 0; i < v.size(); i++) {
                System.out.println(v.get(i));
            }
            return v.toArray(new Class[]{});
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 检查类是否直接或间接实现接口
     *
     * @param clazz
     * @param enterface
     * @return
     */
    public static boolean isImplementsInterface(Class clazz, Class enterface) {
        Assert.notNull(clazz);
        Assert.notNull(enterface);
        Class[] interfaces = clazz.getInterfaces();
        Class superclass = clazz.getSuperclass();
        if (superclass != null) {
            boolean implementsInterface = isImplementsInterface(superclass, enterface);
            if (implementsInterface) {
                return true;
            }
        }
        boolean flag = false;
        for (Class anInterface : interfaces) {
            if (enterface == anInterface) {
                return true;
            } else {
                flag = isImplementsInterface(anInterface, enterface);
                if (flag) {
                    return flag;
                }
            }
        }
        return flag;
    }

}


/*
 * 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;

import java.nio.charset.UnsupportedCharsetException;
import java.util.*;

/**
 * Miscellaneous {@link MimeType} utility methods.
 *
 * @author Arjen Poutsma
 * @author Rossen Stoyanchev
 * @since 4.0
 */
public abstract class MimeTypeUtils {

    /**
     * Public constant mime type that includes all media ranges (i.e. "*/*").
     */
    public static final MimeType ALL;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#ALL}.
     */
    public static final String ALL_VALUE = "*/*";

    /**
     * Public constant mime type for {@code application/atom+xml}.
     */
    public final static MimeType APPLICATION_ATOM_XML;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#APPLICATION_ATOM_XML}.
     */
    public final static String APPLICATION_ATOM_XML_VALUE = "application/atom+xml";

    /**
     * Public constant mime type for {@code application/x-www-form-urlencoded}.
     */
    public final static MimeType APPLICATION_FORM_URLENCODED;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#APPLICATION_FORM_URLENCODED}.
     */
    public final static String APPLICATION_FORM_URLENCODED_VALUE = "application/x-www-form-urlencoded";

    /**
     * Public constant mime type for {@code application/json}.
     */
    public final static MimeType APPLICATION_JSON;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#APPLICATION_JSON}.
     */
    public final static String APPLICATION_JSON_VALUE = "application/json";

    /**
     * Public constant mime type for {@code application/octet-stream}.
     */
    public final static MimeType APPLICATION_OCTET_STREAM;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#APPLICATION_OCTET_STREAM}.
     */
    public final static String APPLICATION_OCTET_STREAM_VALUE = "application/octet-stream";

    /**
     * Public constant mime type for {@code application/xhtml+xml}.
     */
    public final static MimeType APPLICATION_XHTML_XML;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#APPLICATION_XHTML_XML}.
     */
    public final static String APPLICATION_XHTML_XML_VALUE = "application/xhtml+xml";

    /**
     * Public constant mime type for {@code application/xml}.
     */
    public final static MimeType APPLICATION_XML;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#APPLICATION_XML}.
     */
    public final static String APPLICATION_XML_VALUE = "application/xml";

    /**
     * Public constant mime type for {@code image/gif}.
     */
    public final static MimeType IMAGE_GIF;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#IMAGE_GIF}.
     */
    public final static String IMAGE_GIF_VALUE = "image/gif";

    /**
     * Public constant mime type for {@code image/jpeg}.
     */
    public final static MimeType IMAGE_JPEG;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#IMAGE_JPEG}.
     */
    public final static String IMAGE_JPEG_VALUE = "image/jpeg";

    /**
     * Public constant mime type for {@code image/png}.
     */
    public final static MimeType IMAGE_PNG;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#IMAGE_PNG}.
     */
    public final static String IMAGE_PNG_VALUE = "image/png";

    /**
     * Public constant mime type for {@code multipart/form-data}.
     */
    public final static MimeType MULTIPART_FORM_DATA;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#MULTIPART_FORM_DATA}.
     */
    public final static String MULTIPART_FORM_DATA_VALUE = "multipart/form-data";

    /**
     * Public constant mime type for {@code text/html}.
     */
    public final static MimeType TEXT_HTML;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#TEXT_HTML}.
     */
    public final static String TEXT_HTML_VALUE = "text/html";

    /**
     * Public constant mime type for {@code text/plain}.
     */
    public final static MimeType TEXT_PLAIN;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#TEXT_PLAIN}.
     */
    public final static String TEXT_PLAIN_VALUE = "text/plain";

    /**
     * Public constant mime type for {@code text/xml}.
     */
    public final static MimeType TEXT_XML;

    /**
     * A String equivalent of {@link com.xiongyingqi.util.MimeTypeUtils#TEXT_XML}.
     */
    public final static String TEXT_XML_VALUE = "text/xml";

    static {
        ALL = MimeType.valueOf(ALL_VALUE);
        APPLICATION_ATOM_XML = MimeType.valueOf(APPLICATION_ATOM_XML_VALUE);
        APPLICATION_FORM_URLENCODED = MimeType.valueOf(APPLICATION_FORM_URLENCODED_VALUE);
        APPLICATION_JSON = MimeType.valueOf(APPLICATION_JSON_VALUE);
        APPLICATION_OCTET_STREAM = MimeType.valueOf(APPLICATION_OCTET_STREAM_VALUE);
        APPLICATION_XHTML_XML = MimeType.valueOf(APPLICATION_XHTML_XML_VALUE);
        APPLICATION_XML = MimeType.valueOf(APPLICATION_XML_VALUE);
        IMAGE_GIF = MimeType.valueOf(IMAGE_GIF_VALUE);
        IMAGE_JPEG = MimeType.valueOf(IMAGE_JPEG_VALUE);
        IMAGE_PNG = MimeType.valueOf(IMAGE_PNG_VALUE);
        MULTIPART_FORM_DATA = MimeType.valueOf(MULTIPART_FORM_DATA_VALUE);
        TEXT_HTML = MimeType.valueOf(TEXT_HTML_VALUE);
        TEXT_PLAIN = MimeType.valueOf(TEXT_PLAIN_VALUE);
        TEXT_XML = MimeType.valueOf(TEXT_XML_VALUE);
    }

    /**
     * Parse the given String into a single {@code MimeType}.
     *
     * @param mimeType the string to parse
     * @return the mime type
     * @throws InvalidMimeTypeException if the string cannot be parsed
     */
    public static MimeType parseMimeType(String mimeType) {
        if (!StringUtils.hasLength(mimeType)) {
            throw new InvalidMimeTypeException(mimeType, "'mimeType' must not be empty");
        }
        String[] parts = StringUtils.tokenizeToStringArray(mimeType, ";");

        String fullType = parts[0].trim();
        // java.net.HttpURLConnection returns a *; q=.2 Accept header
        if (MimeType.WILDCARD_TYPE.equals(fullType)) {
            fullType = "*/*";
        }
        int subIndex = fullType.indexOf('/');
        if (subIndex == -1) {
            throw new InvalidMimeTypeException(mimeType, "does not contain '/'");
        }
        if (subIndex == fullType.length() - 1) {
            throw new InvalidMimeTypeException(mimeType, "does not contain subtype after '/'");
        }
        String type = fullType.substring(0, subIndex);
        String subtype = fullType.substring(subIndex + 1, fullType.length());
        if (MimeType.WILDCARD_TYPE.equals(type) && !MimeType.WILDCARD_TYPE.equals(subtype)) {
            throw new InvalidMimeTypeException(mimeType, "wildcard type is legal only in '*/*' (all mime types)");
        }

        Map<String, String> parameters = null;
        if (parts.length > 1) {
            parameters = new LinkedHashMap<String, String>(parts.length - 1);
            for (int i = 1; i < parts.length; i++) {
                String parameter = parts[i];
                int eqIndex = parameter.indexOf('=');
                if (eqIndex != -1) {
                    String attribute = parameter.substring(0, eqIndex);
                    String value = parameter.substring(eqIndex + 1, parameter.length());
                    parameters.put(attribute, value);
                }
            }
        }

        try {
            return new MimeType(type, subtype, parameters);
        } catch (UnsupportedCharsetException ex) {
            throw new InvalidMimeTypeException(mimeType, "unsupported charset '" + ex.getCharsetName() + "'");
        } catch (IllegalArgumentException ex) {
            throw new InvalidMimeTypeException(mimeType, ex.getMessage());
        }
    }

    /**
     * Parse the given, comma-separated string into a list of {@code MimeType} objects.
     *
     * @param mimeTypes the string to parse
     * @return the list of mime types
     * @throws IllegalArgumentException if the string cannot be parsed
     */
    public static List<MimeType> parseMimeTypes(String mimeTypes) {
        if (!StringUtils.hasLength(mimeTypes)) {
            return Collections.emptyList();
        }
        String[] tokens = mimeTypes.split(",\\s*");
        List<MimeType> result = new ArrayList<MimeType>(tokens.length);
        for (String token : tokens) {
            result.add(parseMimeType(token));
        }
        return result;
    }

    /**
     * Return a string representation of the given list of {@code MimeType} objects.
     *
     * @param mimeTypes the string to parse
     * @return the list of mime types
     * @throws IllegalArgumentException if the String cannot be parsed
     */
    public static String toString(Collection<? extends MimeType> mimeTypes) {
        StringBuilder builder = new StringBuilder();
        for (Iterator<? extends MimeType> iterator = mimeTypes.iterator(); iterator.hasNext(); ) {
            MimeType mimeType = iterator.next();
            mimeType.appendTo(builder);
            if (iterator.hasNext()) {
                builder.append(", ");
            }
        }
        return builder.toString();
    }

    /**
     * Sorts the given list of {@code MimeType} objects by specificity.
     *
Given two mime types:
     *

     *
if either mime type has a {@linkplain MimeType#isWildcardType() wildcard type},
     * then the mime type without the wildcard is ordered before the other.

     *
if the two mime types have different {@linkplain MimeType#getType() types},
     * then they are considered equal and remain their current order.

     *
if either mime type has a {@linkplain MimeType#isWildcardSubtype() wildcard subtype}
     * , then the mime type without the wildcard is sorted before the other.

     *
if the two mime types have different {@linkplain MimeType#getSubtype() subtypes},
     * then they are considered equal and remain their current order.

     *
if the two mime types have a different amount of
     * {@linkplain MimeType#getParameter(String) parameters}, then the mime type with the most
     * parameters is ordered before the other.

     *

     *
For example:
audio/basic < audio/* < */*

     *
audio/basic;level=1 < audio/basic

     *
audio/basic == text/html

audio/basic ==
     * audio/wave

     *
     * @param mimeTypes the list of mime types to be sorted
     * @see HTTP 1.1, section
     * 14.1
     */
    public static void sortBySpecificity(List<MimeType> mimeTypes) {
        Assert.notNull(mimeTypes, "'mimeTypes' must not be null");
        if (mimeTypes.size() > 1) {
            Collections.sort(mimeTypes, SPECIFICITY_COMPARATOR);
        }
    }

    /**
     * Comparator used by {@link #sortBySpecificity(java.util.List)}.
     */
    public static final Comparator<MimeType> SPECIFICITY_COMPARATOR = new MimeType.SpecificityComparator<MimeType>();

}


/*
 *  Encoding.java, a facade to an ANTLR grammar based
 *  parser / lexer that searches for the "charset" attribute of a
 *  html page.
 *  Copyright (C) 2004 Achim Westermann, created on 20.07.2004, 10:35:46
 *
 * ***** 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 antlr.ANTLRException;
import info.monitorenter.cpdetector.io.parser.EncodingLexer;
import info.monitorenter.cpdetector.io.parser.EncodingParser;
import info.monitorenter.io.LimitedInputStream;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;

public class ParsingDetector
    extends AbstractCodepageDetector {
  /**
   * Generated serialVersionUID.
   */
  private static final long serialVersionUID = 3618977875919778866L;

  private boolean m_verbose = false;

  public ParsingDetector() {
    this(false);
  }

  public ParsingDetector(boolean verbose) {
    super();
    this.m_verbose = verbose;
  }

  /*
   * (non-Javadoc)
   *
   * @see cpdetector.io.ICodepageDetector#detectCodepage(java.io.InputStream)
   */
  public Charset detectCodepage(final InputStream in, final int length) throws IOException {
    EncodingLexer lexer;
    EncodingParser parser;
    Charset charset = null;
    String csName = null;
    InputStream limitedInputStream = new LimitedInputStream(in, length);
    if (this.m_verbose) {
      System.out
          .println("  parsing for html-charset/xml-encoding attribute with codepage: US-ASCII");
    }
    try {
      lexer = new EncodingLexer(new InputStreamReader(limitedInputStream, "US-ASCII"));
      parser = new EncodingParser(lexer);
      csName = parser.htmlDocument();
      if (csName != null) {
        // TODO: prepare document with illegal value, then test: Decide to catch
        // exception and return
        // UnsupportedCharset.
        try {
          charset = Charset.forName(csName);
        } catch (UnsupportedCharsetException uce) {
          charset = UnsupportedCharset.forName(csName);
        }
      } else {
        charset = UnknownCharset.getInstance();
      }
    } catch (ANTLRException ae) {
      if (this.m_verbose) {
        System.out.println("  ANTLR parser exception: " + ae.getMessage());
      }
    } catch (Exception deepdown) {
      if (this.m_verbose) {
        System.out.println("  Decoding Exception: " + deepdown.getMessage()
            + " (unsupported java charset).");
      }
      if (charset == null) {
        if (csName != null) {
          charset = UnsupportedCharset.forName(csName);
        } else {
          charset = UnknownCharset.getInstance();
        }
      }
    }
    return charset;
  }

}