/******************************************************************************* * Copyright (c) 2015 Pivotal Software, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Pivotal Software, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.boot.dash.ngrok; import java.io.IOException; import java.net.URLEncoder; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.fluent.Request; import org.json.JSONArray; import org.json.JSONObject; /** * @author Martin Lippert */ public class NGROKClient { private static int CREATE_TUNNEL_TIMEOUT_SECONDS = 6; private String path; private NGROKProcess process; private NGROKTunnel tunnel; public NGROKClient(String path) { this.path = path; Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { @Override public void run() { if (process != null) { process.terminate(); } } })); } public NGROKTunnel getTunnel() { return tunnel; } public String getURL() { return process != null ? process.getApiURL() : null; } public NGROKTunnel startTunnel(String proto, String addr) throws Exception { process = NGROKProcess.startNGROK(path, proto, addr); if (process != null) { boolean success = false; int seconds = 0; while (!success && seconds < CREATE_TUNNEL_TIMEOUT_SECONDS) { NGROKTunnel[] tunnels = retrieveTunnels(); if (tunnels != null && tunnels.length > 0) { for (int i = 0; i < tunnels.length; i++) { if (tunnels[i].getAddr().endsWith(addr) && tunnels[i].getProto().equals(proto)) { tunnel = tunnels[i]; return tunnel; } } } seconds++; Thread.sleep(1000); } } return null; } public void shutdown() { if (tunnel != null) { shutdownTunnel(tunnel); tunnel = null; } if (process != null) { process.terminate(); process = null; } } private NGROKTunnel[] retrieveTunnels() { NGROKTunnel[] result = null; try { String response = Request.Get(process.getApiURL() + "/api/tunnels").execute().returnContent().asString(); JSONObject jsonResponse = new JSONObject(response); JSONArray tunnels = jsonResponse.getJSONArray("tunnels"); if (tunnels != null) { result = new NGROKTunnel[tunnels.length()]; for (int i = 0; i < result.length; i++) { JSONObject tunnel = tunnels.getJSONObject(i); String name = tunnel.getString("name"); String proto = tunnel.getString("proto"); String public_url = tunnel.getString("public_url"); String addr = tunnel.getJSONObject("config").getString("addr"); result[i] = new NGROKTunnel(name, proto, public_url, addr); } } } catch (Exception e) { System.out.println(e); // do nothing, might be the case that the ngrok process is not yet up } return result; } private void shutdownTunnel(NGROKTunnel ngrokTunnel) { try { String deleteURL = process.getApiURL() + "/api/tunnels/" + URLEncoder.encode(ngrokTunnel.getName(), "UTF-8"); HttpResponse response = Request.Delete(deleteURL).execute().returnResponse(); if (response.getStatusLine().getStatusCode() != 204) { System.err.println("errro closing tunnel"); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }