package loon.net;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Map.Entry;
import loon.LSystem;
import loon.core.LRelease;
import loon.net.Base64Coder;
import loon.utils.StringUtils;
/**
* Copyright 2008 - 2011
*
* 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.
*
* @project loonframework
* @author chenpeng
* @email:ceponline@yahoo.com.cn
* @version 0.1
*/
abstract class HttpClientAbstract implements LRelease {
final static String POST = "POST";
final static String GET = "GET";
final static String HTTPS = "HTTPS";
protected int timeOut, responseCode, responseLength, bufferedSize;
protected String cookie, method, postData, digest, userName, passWord;
protected HttpURLConnection connection;
protected HashMap<String, String> cookies;
protected HashMap<String, String> headerMap;
protected InputStream inputStream;
protected boolean isRunning;
private HttpHeader header;
private URL open;
private String urlString;
private String accept, acceptLanguage, acceptCharset;
public HttpClientAbstract(String urlString) {
try {
this.urlString = urlString;
this.open(new URL(urlString.startsWith("http://")
|| urlString.startsWith("https://")
|| urlString.startsWith("ftp://") ? urlString
: ("http://" + urlString).intern()));
} catch (MalformedURLException e) {
}
}
private javax.net.ssl.HostnameVerifier hv = new javax.net.ssl.HostnameVerifier() {
@Override
public boolean verify(String urlHostName,
javax.net.ssl.SSLSession session) {
return true;
}
};
protected static void trustAllHttpsCertificates() throws Exception {
javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
javax.net.ssl.TrustManager tm = new Trust();
trustAllCerts[0] = tm;
javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
.getInstance("SSL");
sc.init(null, trustAllCerts, null);
javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
.getSocketFactory());
}
public static class Trust implements javax.net.ssl.TrustManager,
javax.net.ssl.X509TrustManager {
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(
java.security.cert.X509Certificate[] certs) {
return true;
}
@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType)
throws java.security.cert.CertificateException {
return;
}
}
public HttpClientAbstract(URL url) {
open(url);
}
private void open(URL url) {
this.cookies = new HashMap<String, String>(10);
this.headerMap = new HashMap<String, String>(10);
this.open = url;
this.header = new HttpHeader();
this.method = "GET";
this.timeOut = 180000;
}
private void postCookies() {
StringBuffer sbr = new StringBuffer();
Iterator<?> it = cookies.entrySet().iterator();
do {
if (!it.hasNext()) {
break;
}
Entry<?, ?> entry = (Entry<?, ?>) it.next();
sbr.append(entry.getKey());
sbr.append("=");
sbr.append(entry.getValue());
if (it.hasNext()) {
sbr.append("; ");
}
} while (true);
if (sbr.length() > 0) {
connection.setRequestProperty("Cookie", cookie = sbr.toString());
header.setCookie(cookie);
}
}
public void start() {
try {
boolean foundRedirect;
do {
if (HTTPS.equalsIgnoreCase(open.getProtocol())) {
trustAllHttpsCertificates();
javax.net.ssl.HttpsURLConnection
.setDefaultHostnameVerifier(hv);
connection = (javax.net.ssl.HttpsURLConnection) open
.openConnection();
} else {
connection = (HttpURLConnection) open.openConnection();
// 设定Cookies
postCookies();
}
if (digest != null) {
connection.setRequestProperty("Authorization", digest);
}
connection.setDoOutput(POST.equalsIgnoreCase(method));
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(false);
// 超时设定
if (timeOut > 0) {
System.setProperty("sun.net.client.defaultConnectTimeout",
String.valueOf(timeOut));
System.setProperty("sun.net.client.defaultReadTimeout",
String.valueOf(timeOut));
}
connection.setRequestMethod(method);
connection.setRequestProperty("User-Agent", header
.getUserAgentValue());
connection
.setRequestProperty(
"Accept",
accept == null ? "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/msword, application/vnd.ms-excel, application/vnd.ms-powerpoint, */*"
: accept);
connection.setRequestProperty("Accept-Language",
acceptLanguage == null ? "zh-CN" : acceptLanguage);
connection
.setRequestProperty(
"Accept-Charset",
acceptCharset == null ? "ISO-8859-1,utf-8;q=0.7,*;q=0.7"
: acceptCharset);
connection.setRequestProperty("Content-type", "text/html");
connection.setRequestProperty("Cache-Control", "no-cache");
if (POST.equalsIgnoreCase(method)) {
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
if (postData != null) {
DataOutputStream out = new DataOutputStream(connection
.getOutputStream());
out.writeBytes(postData);
out.flush();
out.close();
}
}
if (headerMap != null && headerMap.size() > 0) {
Set<?> headersSet = headerMap.entrySet();
for (Iterator<?> it = headersSet.iterator(); it.hasNext();) {
Entry<?, ?> entry = (Entry<?, ?>) it.next();
connection.setRequestProperty((String) entry.getKey(),
(String) entry.getValue());
}
}
// 尝试连接
connection.connect();
cookie = connection.getHeaderField("Set-Cookie");
if (cookie != null) {
// 注入Cookies
setCookies(StringUtils.split(cookie, ";"));
}
// 获得响应状态
responseCode = connection.getResponseCode();
// 获得返回的数据长度
responseLength = connection.getContentLength();
if (responseCode == 302) {
// 重定向
String location = connection.getHeaderField("Location");
open = new URL(location);
foundRedirect = true;
} else {
if (responseCode == 200 || responseCode == 201) {
inputStream = connection.getInputStream();
} else {
inputStream = connection.getErrorStream();
}
bufferedSize = responseLength == -1 ? 2048 : responseLength;
foundRedirect = false;
}
// 如果重定向则继续
} while (foundRedirect);
} catch (Exception e) {
e.printStackTrace();
}
this.isRunning = true;
}
public HttpDownload getHttpDownload() {
return new HttpDownload(this);
}
public InputStream getInputStream() {
return inputStream;
}
/**
* 返回当前请求的端口号
*
* @return
*/
public int getPort() {
return ((open != null) && (open.getPort() != -1)) ? open.getPort() : 80;
}
/**
* 获得当前链接
*
* @return
*/
public HttpURLConnection getConnection() {
try {
if (HTTPS.equalsIgnoreCase(open.getProtocol())) {
trustAllHttpsCertificates();
javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(hv);
connection = (javax.net.ssl.HttpsURLConnection) open
.openConnection();
} else {
connection = (HttpURLConnection) open.openConnection();
}
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
/**
* 检查对应的本地文件是否存在
*
* @return
*/
public boolean exists() {
File file = new File(getFileName());
if (!file.exists()) {
return false;
}
int size = -1;
try {
HttpURLConnection connection = getConnection();
connection.connect();
size = connection.getContentLength();
connection.disconnect();
} catch (Exception e) {
}
return size == file.length();
}
/**
* 返回当前请求下载的文件名
*
* @return
*/
public String getFileName() {
if (open == null) {
return null;
}
return open.getPath().substring(open.getPath().lastIndexOf("/") + 1,
open.getPath().length());
}
/**
* 设定cookies
*
* @param key
* @param value
* @throws IOException
*/
public void setCookie(String key, String value) throws IOException {
cookies.put(key.trim(), value.trim());
}
/**
* 设定cookies
*
* @param cookie
* @throws IOException
*/
public void setCookies(HashMap<String, String> cookie) throws IOException {
if (cookie == null) {
return;
} else {
cookies.putAll(cookie);
return;
}
}
/**
* 设定cookies
*
* @param cookie
* @throws IOException
*/
public void setCookies(String[] cookie) throws IOException {
if (cookie == null) {
return;
}
try {
for (int i = 0; i < cookie.length; i++) {
String[] ret = cookie[i].split("=");
setCookie(ret[0], ret[1]);
}
} catch (Exception e) {
}
}
public String doHTML() {
return doHTML(null);
}
/**
* 以指定格式显示网页字符串
*
* @param encoding
* @return
*/
public String doHTML(String encoding) {
if (!isRunning) {
start();
}
if (connection == null) {
return "";
}
try {
if (encoding != null) {
return readString(inputStream, bufferedSize, encoding);
} else {
return readString(inputStream, bufferedSize, LSystem.encoding);
}
} catch (Exception e) {
return e.getMessage();
}
}
synchronized static String readString(InputStream in, int size,
final String encoding) throws IOException {
StringBuffer sbr = new StringBuffer();
int nSize = size;
if (nSize == 0) {
nSize = 2048;
}
char[] buffer = new char[nSize];
int offset = 0;
InputStreamReader isr = new InputStreamReader(in, encoding);
while ((offset = isr.read(buffer)) != -1) {
sbr.append(buffer, 0, offset);
}
try {
if (in != null) {
in.close();
in = null;
}
if (isr != null) {
isr.close();
isr = null;
}
} catch (Exception e) {
}
return sbr.toString();
}
public void setParameter(HashMap<?, ?> parameter) {
if (parameter != null) {
Set<?> entrySet = parameter.entrySet();
for (Iterator<?> it = entrySet.iterator(); it.hasNext();) {
Entry<?, ?> header = (Entry<?, ?>) it.next();
String key = (String) header.getKey();
String value = (String) header.getValue();
if ("user".equals(key)) {
userName = value;
} else if ("pass".equals(key)) {
passWord = value;
} else if ("method".equals(key)) {
method = value;
} else if ("data".equals(key)) {
postData = value;
} else {
headerMap.put(key, value);
}
}
}
if (userName != null && passWord != null) {
digest = "Basic "
+ Base64Coder
.encode((userName + ":" + passWord).getBytes());
}
}
public String getAccept() {
return accept;
}
public void setAccept(String accept) {
this.accept = accept;
}
public String getAcceptCharset() {
return acceptCharset;
}
public void setAcceptCharset(String acceptCharset) {
this.acceptCharset = acceptCharset;
}
public String getAcceptLanguage() {
return acceptLanguage;
}
public void setAcceptLanguage(String acceptLanguage) {
this.acceptLanguage = acceptLanguage;
}
public String getURLString() {
return urlString;
}
public URL getURL() {
return open;
}
public void stop() {
if (inputStream != null) {
try {
inputStream.close();
inputStream = null;
} catch (IOException e) {
}
}
if (connection != null) {
connection.disconnect();
connection = null;
}
this.isRunning = false;
}
}