package org.jeecg.modules.pay.serverPay;


import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.HashMap;
import java.util.Map;

public class HttpClientUtil
 {
   public static final String SunX509 = "SunX509";
   public static final String JKS = "JKS";
   public static final String PKCS12 = "PKCS12";
   public static final String TLS = "TLS";
   
   public static HttpURLConnection getHttpURLConnection(String strUrl)
     throws IOException
   {
     URL url = new URL(strUrl);
     HttpURLConnection httpURLConnection = (HttpURLConnection)url
       .openConnection();
     return httpURLConnection;
   }
   
 
 
   /**
	 * 发送HTTP_GET请求
	 * 
	 * @see 该方法会自动关闭连接,释放资源
	 * @param reqURL
	 *            请求地址(含参数)
	 * @param decodeCharset
	 *            解码字符集,解析响应数据时用之,其为null时默认采用UTF-8解码
	 * @return 远程主机响应正文
	 */
	public static String sendGetRequest(String reqURL, String decodeCharset) {
		long responseLength = 0; // 响应长度
		String responseContent = null; // 响应内容
		HttpClient httpClient = new DefaultHttpClient(); // 创建默认的httpClient实例
		HttpGet httpGet = new HttpGet(reqURL); // 创建org.apache.http.client.methods.HttpGet
		try {
			HttpResponse response = httpClient.execute(httpGet); // 执行GET请求
			HttpEntity entity = response.getEntity(); // 获取响应实体
			if (null != entity) {
				responseLength = entity.getContentLength();
				responseContent = EntityUtils.toString(entity, decodeCharset == null ? "UTF-8" : decodeCharset);
				EntityUtils.consume(entity); // Consume response content
			}
			System.out.println("请求地址: " + httpGet.getURI());
			System.out.println("响应状态: " + response.getStatusLine());
			System.out.println("响应长度: " + responseLength);
			System.out.println("响应内容: " + responseContent);
		} catch (ClientProtocolException e) {
			System.out.println("该异常通常是协议错误导致,比如构造HttpGet对象时传入的协议不对(将'http'写成'htp')或者服务器端返回的内容不符合HTTP协议要求等,堆栈信息如下");
		} catch (ParseException e) {
			System.out.println(e.getMessage());
		} catch (IOException e) {
			System.out.println("该异常通常是网络原因引起的,如HTTP服务器未启动等,堆栈信息如下");
		} finally {
			httpClient.getConnectionManager().shutdown(); // 关闭连接,释放资源
		}
		return responseContent;
	}
 
	/**
	 * 发送HTTP_POST请求
	 * 
	 * @see 该方法为
	 *      <code>sendPostRequest(String,String,boolean,String,String)</code>
	 *      的简化方法
	 * @see 该方法在对请求数据的编码和响应数据的解码时,所采用的字符集均为UTF-8
	 * @see 当<code>isEncoder=true</code>时,其会自动对<code>sendData</code>中的[中文][|][
	 *      ]等特殊字符进行<code>URLEncoder.encode(string,"UTF-8")</code>
	 * @param isEncoder
	 *            用于指明请求数据是否需要UTF-8编码,true为需要
	 */
	public static String sendPostRequest(String reqURL, String sendData, boolean isEncoder) {
		return sendPostRequest(reqURL, sendData, isEncoder, null, null,"application/json");
	}
	
	/**
	 * 发送HTTP_POST请求
	 * 
	 * @see 该方法会自动关闭连接,释放资源
	 * @see 当<code>isEncoder=true</code>时,其会自动对<code>sendData</code>中的[中文][|][
	 *      ]等特殊字符进行<code>URLEncoder.encode(string,encodeCharset)</code>
	 * @param reqURL
	 *            请求地址
	 * @param sendData
	 *            请求参数,若有多个参数则应拼接成param11=value11¶m22=value22¶m33=value33的形式后,
	 *            传入该参数中
	 * @param isEncoder
	 *            请求数据是否需要encodeCharset编码,true为需要
	 * @param encodeCharset
	 *            编码字符集,编码请求数据时用之,其为null时默认采用UTF-8解码
	 * @param decodeCharset
	 *            解码字符集,解析响应数据时用之,其为null时默认采用UTF-8解码
	 * @return 远程主机响应正文
	 */
	public static String sendPostRequest(String reqURL, String sendData, boolean isEncoder, String encodeCharset,
			String decodeCharset,String contentType) {
		String responseContent = null;
		HttpClient httpClient = new DefaultHttpClient();
 
		HttpPost httpPost = new HttpPost(reqURL);
		// httpPost.setHeader(HTTP.CONTENT_TYPE,
		// "application/x-www-form-urlencoded; charset=UTF-8");
		httpPost.setHeader(HTTP.CONTENT_TYPE, contentType);
		try {
			if (isEncoder) {
				httpPost.setEntity(new StringEntity(sendData, encodeCharset == null ? "UTF-8" : encodeCharset));
			} else {
				httpPost.setEntity(new StringEntity(sendData));
			}
			// 设置请求超时时间
			httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
			HttpResponse response = httpClient.execute(httpPost);
			HttpEntity entity = response.getEntity();
			if (null != entity) {
				responseContent = EntityUtils.toString(entity, decodeCharset == null ? "UTF-8" : decodeCharset);
				EntityUtils.consume(entity);
			}
		} catch (Exception e) {
			System.out.println("与[" + reqURL + "]通信过程中发生异常,堆栈信息如下");
			e.printStackTrace();
		} finally {
			httpClient.getConnectionManager().shutdown();
		}
		return responseContent;
	}
 
 
   public static HttpsURLConnection getHttpsURLConnection(String strUrl)
     throws IOException
   {
     URL url = new URL(strUrl);
     HttpsURLConnection httpsURLConnection = (HttpsURLConnection)url
       .openConnection();
     return httpsURLConnection;
   }
   
 
 
 
   public static String getURL(String strUrl)
   {
     if (strUrl != null) {
       int indexOf = strUrl.indexOf("?");
       if (-1 != indexOf) {
         return strUrl.substring(0, indexOf);
       }
       
       return strUrl;
     }
     
     return strUrl;
   }
 
 
 
   public static String getQueryString(String strUrl)
   {
     if (strUrl != null) {
       int indexOf = strUrl.indexOf("?");
       if (-1 != indexOf) {
         return strUrl.substring(indexOf + 1, strUrl.length());
       }
       
       return "";
     }
     
     return strUrl;
   }
   
 
 
   public static Map queryString2Map(String queryString)
   {
     if ((queryString == null) || ("".equals(queryString))) {
       return null;
     }
     
     Map m = new HashMap();
     String[] strArray = queryString.split("&");
     for (int index = 0; index < strArray.length; index++) {
       String pair = strArray[index];
       putMapByPair(pair, m);
     }
     
     return m;
   }
   
 
 
   public static void putMapByPair(String pair, Map m)
   {
     if ((pair == null) || ("".equals(pair))) {
       return;
     }
     
     int indexOf = pair.indexOf("=");
     if (-1 != indexOf) {
       String k = pair.substring(0, indexOf);
       String v = pair.substring(indexOf + 1, pair.length());
       if ((k != null) && (!"".equals(k))) {
         m.put(k, v);
       }
     } else {
       m.put(pair, "");
     }
   }
   
 
 
 
   public static String bufferedReader2String(BufferedReader reader)
     throws IOException
   {
     StringBuffer buf = new StringBuffer();
     String line = null;
     while ((line = reader.readLine()) != null) {
       buf.append(line);
       buf.append("\r\n");
     }
     
     return buf.toString();
   }
   
 
 
 
   public static void doOutput(OutputStream out, byte[] data, int len)
     throws IOException
   {
     int dataLen = data.length;
     int off = 0;
     while (off < dataLen) {
       if (len >= dataLen) {
         out.write(data, off, dataLen);
       } else {
         out.write(data, off, len);
       }
       
 
       out.flush();
       
       off += len;
       
       dataLen -= len;
     }
   }
   
 
 
 
   public static SSLContext getSSLContext(FileInputStream trustFileInputStream, String trustPasswd, FileInputStream keyFileInputStream, String keyPasswd)
     throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException, KeyManagementException
   {
     TrustManagerFactory tmf =
       TrustManagerFactory.getInstance("SunX509");
     KeyStore trustKeyStore = KeyStore.getInstance("JKS");
     trustKeyStore.load(trustFileInputStream, 
       str2CharArray(trustPasswd));
     tmf.init(trustKeyStore);
     
     char[] kp = str2CharArray(keyPasswd);
     KeyManagerFactory kmf =
       KeyManagerFactory.getInstance("SunX509");
     KeyStore ks = KeyStore.getInstance("PKCS12");
     ks.load(keyFileInputStream, kp);
     kmf.init(ks, kp);
     
     SecureRandom rand = new SecureRandom();
     SSLContext ctx = SSLContext.getInstance("TLS");
     ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), rand);
     
     return ctx;
   }
   
 
 
 
 
 
   public static Certificate getCertificate(File cafile)
     throws CertificateException, IOException
   {
     CertificateFactory cf = CertificateFactory.getInstance("X.509");
     FileInputStream in = new FileInputStream(cafile);
     Certificate cert = cf.generateCertificate(in);
     in.close();
     return cert;
   }
   
 
 
 
 
 
   public static char[] str2CharArray(String str)
   {
     if (str == null) {
       return null;
     }
     return str.toCharArray();
   }
   
 
 
 
 
 
 
   public static void storeCACert(Certificate cert, String alias, String password, OutputStream out)
     throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException
   {
     KeyStore ks = KeyStore.getInstance("JKS");
     
     ks.load(null, null);
     
     ks.setCertificateEntry(alias, cert);
     
 
     ks.store(out, str2CharArray(password));
   }
   
   public static InputStream String2Inputstream(String str)
   {
     return new ByteArrayInputStream(str.getBytes());
   }
 }