package org.appwork.utils.net; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.net.UnknownHostException; import java.util.HashMap; import java.util.Map.Entry; import java.util.logging.Level; import java.util.zip.GZIPInputStream; import org.appwork.utils.Application; import org.appwork.utils.IO; import org.appwork.utils.locale.Loc; import org.appwork.utils.logging.Log; public class SimpleHTTP { private static final Object CALL_LOCK = new Object(); private final HashMap<String, String> requestHeader; private HttpURLConnection connection; private int connectTimeout = 15000; private int readTimeout = 30000; private boolean followRedirects = true; public SimpleHTTP() { this.requestHeader = new HashMap<String, String>(); } public void clearRequestHeader() { this.requestHeader.clear(); } /** * @param url * @param progress * @param file * @throws InterruptedException * @throws IOException */ public void download(final URL url, final DownloadProgress progress, final File file) throws IOException, InterruptedException { BufferedOutputStream out = null; try { out = new BufferedOutputStream(new FileOutputStream(file)); try { this.download(url, progress, 0, out); } catch (final IOException e) { try { out.close(); } catch (final Throwable t) { } if (file.length() > 0) { final IOException ex = new HTTPException(this.connection, IO.readFileToString(file), e); file.delete(); throw ex; } } } finally { try { out.close(); } catch (final Throwable t) { } } } public byte[] download(final URL url, final DownloadProgress progress, final long maxSize) throws IOException, InterruptedException { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { this.download(url, progress, maxSize, baos); } catch (final IOException e) { if (baos.size() > 0) { throw new HTTPException(this.connection, new String(baos.toByteArray()), e); } } try { baos.close(); } catch (final Throwable t) { } return baos.toByteArray(); } /** * * Please do not forget to close the output stream. * * @param url * @param progress * @param maxSize * @param baos * @throws IOException * @throws InterruptedException */ public void download(final URL url, final DownloadProgress progress, final long maxSize, final OutputStream baos) throws IOException, InterruptedException { BufferedInputStream input = null; GZIPInputStream gzi = null; try { this.connection = (HttpURLConnection) url.openConnection(); this.connection.setInstanceFollowRedirects(this.followRedirects); this.connection.setConnectTimeout(this.connectTimeout); this.connection.setReadTimeout(this.readTimeout); try { final String loc = Loc.getLocale().split("_")[0]; this.connection.setRequestProperty("Accept-Language", loc); } catch (final Throwable e) { // Log.exception(Level.WARNING, e); } this.connection.setRequestProperty("User-Agent", "AppWork " + Application.getApplication()); this.connection.setRequestProperty("Connection", "Close"); for (final Entry<String, String> next : this.requestHeader.entrySet()) { this.connection.setRequestProperty(next.getKey(), next.getValue()); } this.connection.connect(); IOException exception = null; try { if (this.connection.getHeaderField("Content-Encoding") != null && this.connection.getHeaderField("Content-Encoding").equalsIgnoreCase("gzip")) { input = new BufferedInputStream(gzi = new GZIPInputStream(this.connection.getInputStream())); } else { input = new BufferedInputStream(this.connection.getInputStream()); } } catch (final IOException e) { exception = e; if (this.connection.getHeaderField("Content-Encoding") != null && this.connection.getHeaderField("Content-Encoding").equalsIgnoreCase("gzip")) { input = new BufferedInputStream(gzi = new GZIPInputStream(this.connection.getErrorStream())); } else { input = new BufferedInputStream(this.connection.getErrorStream()); } } if (maxSize > 0 && this.connection.getContentLength() > maxSize) { throw new IOException("Max size exeeded!"); } if (progress != null) { progress.setTotal(this.connection.getContentLength()); } final byte[] b = new byte[32767]; int len; long loaded = 0; while ((len = input.read(b)) != -1) { if (Thread.currentThread().isInterrupted()) { throw new InterruptedException(); } if (len > 0) { baos.write(b, 0, len); loaded += len; if (maxSize > 0 && loaded > maxSize) { throw new IOException("Max size exeeded!"); } } if (progress != null) { progress.increaseLoaded(len); } } if (exception != null) { throw exception; } } finally { try { input.close(); } catch (final Exception e) { } try { gzi.close(); } catch (final Exception e) { } try { this.connection.disconnect(); } catch (final Throwable e) { } } } public HttpURLConnection getConnection() { return this.connection; } public int getConnectTimeout() { return this.connectTimeout; } public String getPage(final URL url) throws IOException, InterruptedException { synchronized (SimpleHTTP.CALL_LOCK) { BufferedReader in = null; InputStreamReader isr = null; try { this.connection = (HttpURLConnection) url.openConnection(); this.connection.setInstanceFollowRedirects(this.followRedirects); this.connection.setConnectTimeout(this.connectTimeout); this.connection.setReadTimeout(this.readTimeout); try { final String loc = Loc.getLocale().split("_")[0]; this.connection.setRequestProperty("Accept-Language", loc); } catch (final Throwable e) { } this.connection.setRequestProperty("User-Agent", "AppWork " + Application.getApplication()); this.connection.setRequestProperty("Connection", "Close"); this.connection.setRequestProperty("Accept-Charset", "UTF-8"); for (final Entry<String, String> next : this.requestHeader.entrySet()) { this.connection.setRequestProperty(next.getKey(), next.getValue()); } int lookupTry = 0; while (true) { try { this.connection.connect(); break; } catch (final UnknownHostException e) { if (++lookupTry > 3) { throw e; } /* dns lookup failed, short wait and try again */ Thread.sleep(200); } } in = new BufferedReader(isr = new InputStreamReader(this.connection.getInputStream(), "UTF-8")); String str; final StringBuilder sb = new StringBuilder(); while ((str = in.readLine()) != null) { if (sb.length() > 0) { sb.append("\r\n"); } sb.append(str); } return sb.toString(); } finally { try { in.close(); } catch (final Throwable e) { } try { isr.close(); } catch (final Throwable e) { } try { this.connection.disconnect(); } catch (final Throwable e) { } } } } public int getReadTimeout() { return this.readTimeout; } /** * @return */ public HashMap<String, String> getRequestHeader() { return this.requestHeader; } public String getRequestHeader(final String key) { return this.requestHeader.get(key); } public String getResponseHeader(final String string) { synchronized (SimpleHTTP.CALL_LOCK) { if (this.connection == null) { return null; } return this.connection.getHeaderField(string); } } public boolean isFollowRedirects() { return this.followRedirects; } public HttpURLConnection openGetConnection(final URL url) throws IOException, InterruptedException { return this.openGetConnection(url, this.readTimeout); } public HttpURLConnection openGetConnection(final URL url, final int readTimeout) throws IOException, InterruptedException { boolean close = true; synchronized (SimpleHTTP.CALL_LOCK) { try { this.connection = (HttpURLConnection) url.openConnection(); this.connection.setConnectTimeout(this.connectTimeout); this.connection.setInstanceFollowRedirects(this.followRedirects); this.connection.setReadTimeout(readTimeout < 0 ? readTimeout : readTimeout); try { final String loc = Loc.getLocale().split("_")[0]; this.connection.setRequestProperty("Accept-Language", loc); } catch (final Throwable e) { // Log.exception(Level.WARNING, e); } this.connection.setRequestProperty("User-Agent", "AppWork " + Application.getApplication()); this.connection.setRequestProperty("Connection", "Close"); this.connection.setRequestProperty("Accept-Charset", "UTF-8"); for (final Entry<String, String> next : this.requestHeader.entrySet()) { this.connection.setRequestProperty(next.getKey(), next.getValue()); } int lookupTry = 0; while (true) { try { this.connection.connect(); break; } catch (final UnknownHostException e) { if (++lookupTry > 3) { throw e; } /* dns lookup failed, short wait and try again */ Thread.sleep(200); } } close = false; return this.connection; } finally { try { if (close) { this.connection.disconnect(); } } catch (final Throwable e2) { } } } } public HttpURLConnection openPostConnection(final URL url, final String postData, final HashMap<String, String> header) throws IOException, InterruptedException { boolean close = true; synchronized (SimpleHTTP.CALL_LOCK) { OutputStreamWriter writer = null; OutputStream outputStream = null; try { this.connection = (HttpURLConnection) url.openConnection(); this.connection.setInstanceFollowRedirects(this.followRedirects); this.connection.setConnectTimeout(this.connectTimeout); this.connection.setReadTimeout(this.readTimeout); this.connection.setRequestMethod("POST"); this.connection.setDoInput(true); this.connection.setUseCaches(false); this.connection.setDoOutput(true); try { final String loc = Loc.getLocale().split("_")[0]; this.connection.setRequestProperty("Accept-Language", loc); } catch (final Throwable e) { Log.exception(Level.WARNING, e); } this.connection.setRequestProperty("User-Agent", "AppWork " + Application.getApplication()); this.connection.setRequestProperty("Connection", "Close"); /* connection specific headers */ if (header != null) { for (final Entry<String, String> next : header.entrySet()) { this.connection.setRequestProperty(next.getKey(), next.getValue()); } } for (final Entry<String, String> next : this.requestHeader.entrySet()) { this.connection.setRequestProperty(next.getKey(), next.getValue()); } int lookupTry = 0; while (true) { try { this.connection.connect(); break; } catch (final UnknownHostException e) { if (++lookupTry > 3) { throw e; } /* dns lookup failed, short wait and try again */ Thread.sleep(200); } } outputStream = this.connection.getOutputStream(); writer = new OutputStreamWriter(outputStream); writer.write(postData); writer.flush(); close = false; return this.connection; } finally { try { if (close) { this.connection.disconnect(); } } catch (final Throwable e2) { } try { writer.close(); } catch (final Throwable e) { } try { outputStream.close(); } catch (final Throwable e) { } } } } public String postPage(final URL url, final String data) throws IOException, InterruptedException { synchronized (SimpleHTTP.CALL_LOCK) { OutputStreamWriter writer = null; BufferedReader reader = null; OutputStream outputStream = null; InputStreamReader isr = null; try { this.connection = (HttpURLConnection) url.openConnection(); this.connection.setInstanceFollowRedirects(this.followRedirects); this.connection.setConnectTimeout(this.connectTimeout); this.connection.setReadTimeout(this.readTimeout); this.connection.setRequestMethod("POST"); this.connection.setDoInput(true); this.connection.setUseCaches(false); this.connection.setDoOutput(true); try { final String loc = Loc.getLocale().split("_")[0]; this.connection.setRequestProperty("Accept-Language", loc); } catch (final Throwable e) { // } this.connection.setRequestProperty("User-Agent", "AppWork " + Application.getApplication()); this.connection.setRequestProperty("Connection", "Close"); for (final Entry<String, String> next : this.requestHeader.entrySet()) { this.connection.setRequestProperty(next.getKey(), next.getValue()); } int lookupTry = 0; while (true) { try { this.connection.connect(); break; } catch (final UnknownHostException e) { if (++lookupTry > 3) { throw e; } /* dns lookup failed, short wait and try again */ Thread.sleep(200); } } outputStream = this.connection.getOutputStream(); writer = new OutputStreamWriter(outputStream); writer.write(data); writer.flush(); reader = new BufferedReader(isr = new InputStreamReader(this.connection.getInputStream(), "UTF-8")); final StringBuilder sb = new StringBuilder(); String str; while ((str = reader.readLine()) != null) { if (sb.length() > 0) { sb.append("\r\n"); } sb.append(str); } return sb.toString(); } finally { try { reader.close(); } catch (final Throwable e) { } try { isr.close(); } catch (final Throwable e) { } try { writer.close(); } catch (final Throwable e) { } try { outputStream.close(); } catch (final Throwable e) { } try { this.connection.disconnect(); } catch (final Throwable e) { } } } } public void putRequestHeader(final String key, final String value) { this.requestHeader.put(key, value); } public void setConnectTimeout(final int connectTimeout) { this.connectTimeout = connectTimeout; } public void setFollowRedirects(final boolean followRedirects) { this.followRedirects = followRedirects; } public void setReadTimeout(final int readTimeout) { this.readTimeout = readTimeout; } }