| |
| package com.googlecode.android_scripting.facade.wifi; |
| |
| import java.io.BufferedInputStream; |
| import java.io.BufferedReader; |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.OutputStream; |
| import java.net.HttpURLConnection; |
| import java.net.ServerSocket; |
| import java.net.Socket; |
| import java.net.SocketException; |
| import java.net.URL; |
| import java.net.UnknownHostException; |
| import java.nio.charset.StandardCharsets; |
| import java.util.HashMap; |
| |
| import com.googlecode.android_scripting.Log; |
| import com.googlecode.android_scripting.facade.FacadeManager; |
| import com.googlecode.android_scripting.jsonrpc.RpcReceiver; |
| import com.googlecode.android_scripting.rpc.Rpc; |
| import com.googlecode.android_scripting.rpc.RpcParameter; |
| import com.googlecode.android_scripting.rpc.RpcOptional; |
| |
| /** |
| * Basic http operations. |
| */ |
| public class HttpFacade extends RpcReceiver { |
| |
| private ServerSocket mServerSocket = null; |
| private int mServerTimeout = -1; |
| private HashMap<Integer, Socket> mSockets = null; |
| private int socketCnt = 0; |
| |
| public HttpFacade(FacadeManager manager) throws IOException { |
| super(manager); |
| mSockets = new HashMap<Integer, Socket>(); |
| } |
| |
| private void inputStreamToOutputStream(InputStream in, OutputStream out) throws IOException { |
| if (in == null) { |
| Log.e("InputStream is null."); |
| return; |
| } |
| if (out == null) { |
| Log.e("OutputStream is null."); |
| return; |
| } |
| try { |
| int read = 0; |
| byte[] bytes = new byte[1024]; |
| while ((read = in.read(bytes)) != -1) { |
| out.write(bytes, 0, read); |
| } |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } finally { |
| in.close(); |
| out.close(); |
| } |
| |
| } |
| |
| private String inputStreamToString(InputStream in) throws IOException { |
| BufferedReader r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); |
| StringBuilder sb = new StringBuilder(); |
| String str = null; |
| while ((str = r.readLine()) != null) { |
| sb.append(str); |
| } |
| return sb.toString(); |
| } |
| |
| /** |
| * Send an http request and get the response. |
| * |
| * @param url The url to send request to. |
| * @return The HttpURLConnection object. |
| * @throws IOException When request failed to go through with response code 200. |
| */ |
| private HttpURLConnection httpRequest(String url) throws IOException { |
| URL targetURL = new URL(url); |
| HttpURLConnection urlConnection = null; |
| try { |
| urlConnection = (HttpURLConnection) targetURL.openConnection(); |
| urlConnection.connect(); |
| } catch (IOException e) { |
| Log.e("Failed to open a connection to " + url); |
| Log.e(e.toString()); |
| throw e; |
| } finally { |
| if (urlConnection != null) { |
| urlConnection.disconnect(); |
| } |
| } |
| return urlConnection; |
| } |
| |
| @Rpc(description = "Start waiting for a connection request on a specified port.", |
| returns = "The index of the connection.") |
| public Integer httpAcceptConnection(Integer port) throws IOException { |
| mServerSocket = new ServerSocket(port); |
| if (mServerTimeout > 0) { |
| mServerSocket.setSoTimeout(mServerTimeout); |
| } |
| Socket sock = mServerSocket.accept(); |
| socketCnt += 1; |
| mSockets.put(socketCnt, sock); |
| return socketCnt; |
| } |
| |
| @Rpc(description = "Download a file from specified url.") |
| public void httpDownloadFile(String url) throws IOException { |
| HttpURLConnection urlConnection = httpRequest(url); |
| String filename = null; |
| String contentDisposition = urlConnection.getHeaderField("Content-Disposition"); |
| // Try to figure out the name of the file being downloaded. |
| // If the server returned a filename, use it. |
| if (contentDisposition != null) { |
| int idx = contentDisposition.toLowerCase().indexOf("filename"); |
| if (idx != -1) { |
| filename = contentDisposition.substring(idx + 9); |
| Log.d("Using name returned by server: " + filename); |
| } |
| } |
| // If the server did not provide a filename to us, use the last part of url. |
| if (filename == null) { |
| int lastIdx = url.lastIndexOf('/'); |
| filename = url.substring(lastIdx + 1); |
| Log.d("Using name from url: " + filename); |
| } |
| InputStream in = new BufferedInputStream(urlConnection.getInputStream()); |
| String outPath = "/sdcard/Download/" + filename; |
| OutputStream output = new FileOutputStream(new File(outPath)); |
| inputStreamToOutputStream(in, output); |
| Log.d("Downloaded file at " + outPath); |
| } |
| |
| @Rpc(description = "Make an http request and return the response message.") |
| public HttpURLConnection httpPing(@RpcParameter(name = "url") String url) throws IOException { |
| try { |
| HttpURLConnection urlConnection = null; |
| urlConnection = httpRequest(url); |
| return urlConnection; |
| } catch (UnknownHostException e) { |
| return null; |
| } |
| } |
| |
| @Rpc(description = "Make an http request and return the response content as a string.") |
| public String httpRequestString(@RpcParameter(name = "url") String url) throws IOException { |
| HttpURLConnection urlConnection = httpRequest(url); |
| InputStream in = new BufferedInputStream(urlConnection.getInputStream()); |
| String result = inputStreamToString(in); |
| Log.d("Fetched: " + result); |
| return result; |
| } |
| |
| @Rpc(description = "Set how many milliseconds to wait for an incoming connection.") |
| public void httpSetServerTimeout(@RpcParameter(name = "timeout") Integer timeout) |
| throws SocketException { |
| mServerSocket.setSoTimeout(timeout); |
| mServerTimeout = timeout; |
| } |
| |
| @Rpc(description = "Ping to host(URL or IP), return success (true) or fail (false).") |
| // The optional timeout parameter is in unit of second. |
| public Boolean pingHost(@RpcParameter(name = "host") String hostString, |
| @RpcParameter(name = "timeout") @RpcOptional Integer timeout) { |
| try { |
| String host; |
| try { |
| URL url = new URL(hostString); |
| host = url.getHost(); |
| } catch (java.net.MalformedURLException e) { |
| Log.d("hostString is not URL, it may be IP address."); |
| host = hostString; |
| } |
| |
| Log.d("Host:" + host); |
| String pingCmdString = "ping -c 1 "; |
| if (timeout != null) { |
| pingCmdString = pingCmdString + "-W " + timeout + " "; |
| } |
| pingCmdString = pingCmdString + host; |
| Log.d("Execute command: " + pingCmdString); |
| Process p1 = java.lang.Runtime.getRuntime().exec(pingCmdString); |
| int returnVal = p1.waitFor(); |
| boolean reachable = (returnVal == 0); |
| Log.d("Ping return Value:" + returnVal); |
| return reachable; |
| } catch (Exception e){ |
| e.printStackTrace(); |
| return false; |
| } |
| /*TODO see b/18899134 for more information. |
| */ |
| } |
| |
| @Override |
| public void shutdown() { |
| for (int key : mSockets.keySet()) { |
| Socket sock = mSockets.get(key); |
| try { |
| sock.close(); |
| } catch (IOException e) { |
| Log.e("Failed to close socket " + key + " on port " + sock.getLocalPort()); |
| e.printStackTrace(); |
| } |
| } |
| } |
| } |