/**
* Copyright 2014
* SMEdit https://github.com/StarMade/SMEdit
* SMTools https://github.com/StarMade/SMTools
*
* 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 jo.util.io;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map.Entry;
import java.util.TimeZone;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
import jo.util.GlobalConfiguration;
import jo.util.OperatingSystem;
public class HttpClient {
private static final Logger log = Logger.getLogger(HttpClient.class
.getName());
private static String httpUserAgent = null;
public static String getHttpUserAgent() {
if (httpUserAgent == null) {
httpUserAgent = getDefaultHttpUserAgent();
}
return httpUserAgent;
}
private static String getDefaultHttpUserAgent() {
final boolean x64 = System.getProperty("sun.arch.data.model").equals("64");
final String os;
switch (GlobalConfiguration.getCurrentOperatingSystem()) {
case MAC:
os = "Macintosh; Intel Mac OS X 10_7_3";
break;
case LINUX:
os = "X11; Linux " + (x64 ? "x86_64" : "i686");
break;
default:
os = "Windows NT 6.1" + (x64 ? "; WOW64" : "");
break;
}
final StringBuilder buf = new StringBuilder(125);
buf.append("Mozilla/5.0 (").append(os).append(")");
buf.append(" AppleWebKit/534.55.3 (KHTML, like Gecko) Chrome/35.0.1985.125 Safari/534.55.3");
return buf.toString();
}
public static HttpURLConnection getHttpConnection(final URL url) throws IOException {
final HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.addRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
con.addRequestProperty("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
con.addRequestProperty("Accept-Encoding", "gzip");
con.addRequestProperty("Accept-Language", "en-us,en;q=0.5");
con.addRequestProperty("Host", url.getHost());
con.addRequestProperty("User-Agent", getHttpUserAgent());
con.setConnectTimeout(10000);
return con;
}
private static HttpURLConnection getConnection(final URL url) throws IOException {
final HttpURLConnection con = getHttpConnection(url);
con.setUseCaches(true);
return con;
}
public static URL getFinalURL(final URL url) throws IOException {
return getFinalURL(url, true);
}
private static URL getFinalURL(final URL url, final boolean httpHead) throws IOException {
final HttpURLConnection con = getConnection(url);
con.setInstanceFollowRedirects(false);
if (httpHead) {
con.setRequestMethod("HEAD");
}
con.connect();
switch (con.getResponseCode()) {
case HttpURLConnection.HTTP_MOVED_PERM:
case HttpURLConnection.HTTP_MOVED_TEMP:
case HttpURLConnection.HTTP_SEE_OTHER:
return getFinalURL(new URL(con.getHeaderField("Location")), true);
case HttpURLConnection.HTTP_BAD_METHOD:
return getFinalURL(url, false);
default:
return url;
}
}
private static HttpURLConnection cloneConnection(final HttpURLConnection con) throws IOException {
final HttpURLConnection cloned = (HttpURLConnection) con.getURL().openConnection();
for (final Entry<String, List<String>> prop : con.getRequestProperties().entrySet()) {
final String key = prop.getKey();
for (final String value : prop.getValue()) {
cloned.addRequestProperty(key, value);
}
}
return cloned;
}
public static boolean isModifiedSince(URL url, long date) {
try {
url = getFinalURL(url);
date -= TimeZone.getDefault().getOffset(date);
final HttpURLConnection con = getConnection(url);
con.setRequestMethod("HEAD");
con.connect();
final int resp = con.getResponseCode();
con.disconnect();
return resp != HttpURLConnection.HTTP_NOT_MODIFIED;
} catch (final IOException ignored) {
return true;
}
}
public static HttpURLConnection download(final HttpURLConnection con, final File file) throws IOException {
if (file.exists()) {
final HttpURLConnection head = cloneConnection(con);
final int offset = TimeZone.getDefault().getOffset(file.lastModified());
head.setIfModifiedSince(file.lastModified() - offset);
head.setRequestMethod("HEAD");
head.connect();
if (head.getResponseCode() == HttpURLConnection.HTTP_NOT_MODIFIED) {
log.fine("Using " + file.getName() + " from cache");
con.disconnect();
head.disconnect();
return head;
}
}
log.fine("Downloading new " + file.getName());
final byte[] buffer = downloadBinary(con);
if (!file.exists()) {
file.createNewFile();
}
if (file.exists() && (!file.canRead() || file.canWrite())) {
file.setReadable(true);
file.setWritable(true);
}
if (file.exists() && file.canRead() && file.canWrite()) {
final FileOutputStream fos = new FileOutputStream(file);
fos.write(buffer);
fos.flush();
fos.close();
}
if (con.getLastModified() != 0L) {
final int offset = TimeZone.getDefault().getOffset(con.getLastModified());
file.setLastModified(con.getLastModified() + offset);
}
con.disconnect();
return con;
}
public static byte[] download(final URL url) throws IOException {
final URLConnection uc = url.openConnection();
uc.setConnectTimeout(10000);
final DataInputStream di = new DataInputStream(uc.getInputStream());
final byte[] buffer = new byte[uc.getContentLength()];
di.readFully(buffer);
di.close();
return buffer;
}
public static HttpURLConnection download(final URL url, final File file)
throws IOException {
return download(getConnection(url), file);
}
public static String downloadAsString(final URL url) throws IOException {
return downloadAsString(getConnection(url));
}
public static String downloadAsString(final HttpURLConnection con) throws IOException {
final byte[] buffer = downloadBinary(con);
return new String(buffer);
}
public static byte[] downloadBinary(final URL url) throws IOException {
return downloadBinary(getConnection(url));
}
private static byte[] downloadBinary(final URLConnection con) throws IOException {
final DataInputStream di = new DataInputStream(con.getInputStream());
byte[] buffer;
final int len = con.getContentLength();
if (len == -1) {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
int b;
while ((b = di.read()) != -1) {
out.write(b);
}
buffer = out.toByteArray();
} else {
buffer = new byte[con.getContentLength()];
di.readFully(buffer);
}
di.close();
if (buffer != null) {
buffer = ungzip(buffer);
}
return buffer;
}
public static byte[] load(final InputStream is) throws IOException {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
final byte[] buffer = new byte[4096];
int n;
while ((n = is.read(buffer)) != -1) {
os.write(buffer, 0, n);
}
return os.toByteArray();
}
/**
* This method initializes url use opening the users web browser to link to
* a given url
*/
public static void openURL(final String url) {
final OperatingSystem os = GlobalConfiguration
.getCurrentOperatingSystem();
try {
if (os == OperatingSystem.MAC) {
final Class<?> fileMgr = Class
.forName("com.apple.eio.FileManager");
final Method openURL = fileMgr.getDeclaredMethod("openURL",
new Class[]{String.class});
openURL.invoke(null, url);
} else if (os == OperatingSystem.WINDOWS) {
Runtime.getRuntime().exec(
"rundll32 url.dll,FileProtocolHandler " + url);
} else { // assume Unix or Linux
final String[] browsers = {"firefox", "opera", "konqueror",
"epiphany", "mozilla", "netscape"};
String browser = null;
for (int count = 0; (count < browsers.length)
&& (browser == null); count++) {
if (Runtime.getRuntime()
.exec(new String[]{"which", browsers[count]})
.waitFor() == 0) {
browser = browsers[count];
}
}
if (browser == null) {
throw new Exception("Could not find web browser");
} else {
Runtime.getRuntime().exec(new String[]{browser, url});
}
}
} catch (final Exception e) {
}
}
private static byte[] ungzip(final byte[] data) {
if (data.length < 2) {
return data;
}
final int header = (data[0] | data[1] << 8) ^ 0xffff0000;
if (header != GZIPInputStream.GZIP_MAGIC) {
return data;
}
try {
final ByteArrayInputStream b = new ByteArrayInputStream(data);
final GZIPInputStream gzin = new GZIPInputStream(b);
final ByteArrayOutputStream out = new ByteArrayOutputStream(
data.length);
for (int c = gzin.read(); c != -1; c = gzin.read()) {
out.write(c);
}
return out.toByteArray();
} catch (final IOException e) {
e.printStackTrace();
return data;
}
}
/**
* @param aHttpUserAgent the httpUserAgent to set
*/
public static void setHttpUserAgent(String aHttpUserAgent) {
httpUserAgent = aHttpUserAgent;
}
private HttpClient() {
}
}