package logbook.server.proxy; import java.net.BindException; import logbook.config.AppConfig; import logbook.gui.ApplicationMain; import logbook.internal.LoggerHolder; import org.apache.commons.lang3.StringUtils; import org.eclipse.jetty.proxy.ConnectHandler; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; import org.eclipse.jetty.servlet.ServletContextHandler; import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.MessageBox; /** * プロキシサーバーです * */ public final class ProxyServer { private static final LoggerHolder LOG = new LoggerHolder(ProxyServer.class); private static Server server; private static String host; private static int port; private static String proxyHost; private static int proxyPort; public static void start() { try { server = new Server(); updateSetting(); setConnector(); // httpsをプロキシできるようにConnectHandlerを設定 ConnectHandler proxy = new ConnectHandler(); server.setHandler(proxy); // httpはこっちのハンドラでプロキシ ServletContextHandler context = new ServletContextHandler(proxy, "/", ServletContextHandler.SESSIONS); ServletHolder holder = new ServletHolder(new ReverseProxyServlet()); holder.setInitParameter("maxThreads", "256"); holder.setInitParameter("timeout", "600000"); context.addServlet(holder, "/*"); try { server.start(); } catch (Exception e) { handleException(e); } } catch (Exception e) { LOG.get().fatal("Proxyサーバーの起動に失敗しました", e); throw new RuntimeException(e); } } public static void restart() { try { if (server == null) { return; } if (updateSetting()) { server.stop(); setConnector(); server.start(); ApplicationMain.logPrint("プロキシサーバを再起動しました"); } } catch (Exception e) { LOG.get().fatal("Proxyサーバーの起動に失敗しました", e); throw new RuntimeException(e); } } public static void end() { try { if (server != null) { server.stop(); server.join(); server = null; } } catch (Exception e) { e.printStackTrace(); } } /** * AppConfigの設定をローカルにコピーします。その際、更新があったか判定します。 * @return 更新があった */ private static boolean updateSetting() { String newHost = null; if (AppConfig.get().isAllowOnlyFromLocalhost() && AppConfig.get().isCloseOutsidePort()) { newHost = "localhost"; } int newPort = AppConfig.get().getListenPort(); String newProxyHost = null; int newProxyPort = 0; if (AppConfig.get().isUseProxy()) { newProxyHost = AppConfig.get().getProxyHost(); newProxyPort = AppConfig.get().getProxyPort(); } if (StringUtils.equals(newHost, host) && (newPort == port) && StringUtils.equals(newProxyHost, proxyHost) && (newProxyPort == proxyPort)) { return false; } host = newHost; port = newPort; proxyHost = newProxyHost; proxyPort = newProxyPort; return true; } private static void setConnector() { ServerConnector connector = new ServerConnector(server); connector.setPort(port); connector.setHost(host); server.setConnectors(new Connector[] { connector }); } private static void handleException(Exception e) { StringBuilder sb = new StringBuilder(); sb.append("プロキシサーバーが予期せず終了しました").append("\r\n"); sb.append("例外 : " + e.getClass().getName()).append("\r\n"); sb.append("原因 : " + e.getMessage()).append("\r\n"); if (e instanceof BindException) { sb.append("おそらく、二重起動か同じポートを使用しているアプリケーションがあります。").append("\r\n"); } final String message = sb.toString(); Display.getDefault().asyncExec(new Runnable() { @Override public void run() { MessageBox box = new MessageBox(ApplicationMain.main.getShell(), SWT.YES | SWT.ICON_ERROR); box.setText("プロキシサーバーが予期せず終了しました"); box.setMessage(message); box.open(); } }); } }