]> WPIA git - gigi.git/blobdiff - util-testing/club/wpia/gigi/DevelLauncher.java
upd: rename package name and all references to it
[gigi.git] / util-testing / club / wpia / gigi / DevelLauncher.java
diff --git a/util-testing/club/wpia/gigi/DevelLauncher.java b/util-testing/club/wpia/gigi/DevelLauncher.java
new file mode 100644 (file)
index 0000000..69a47ec
--- /dev/null
@@ -0,0 +1,257 @@
+package club.wpia.gigi;
+
+import static club.wpia.gigi.Gigi.*;
+
+import java.awt.Desktop;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.kamranzafar.jtar.TarEntry;
+import org.kamranzafar.jtar.TarHeader;
+import org.kamranzafar.jtar.TarOutputStream;
+
+import club.wpia.gigi.dbObjects.ObjectCache;
+import club.wpia.gigi.dbObjects.User;
+import club.wpia.gigi.localisation.Language;
+import club.wpia.gigi.output.template.Template;
+import club.wpia.gigi.output.template.TranslateCommand;
+import club.wpia.gigi.pages.LoginPage;
+import club.wpia.gigi.pages.Page;
+import club.wpia.gigi.pages.account.certs.CertificateRequest;
+import club.wpia.gigi.pages.main.RegisterPage;
+import club.wpia.gigi.util.AuthorizationContext;
+import club.wpia.gigi.util.ServerConstants;
+
+public class DevelLauncher {
+
+    public static void main(String[] args) throws Exception {
+        Properties mainProps = new Properties();
+        try (FileInputStream inStream = new FileInputStream("config/gigi.properties")) {
+            mainProps.load(inStream);
+        }
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("--port")) {
+                mainProps.setProperty("port", args[i + 1]);
+            }
+            i++;
+        }
+        killPreviousInstance(mainProps);
+
+        ByteArrayOutputStream chunkConfig = new ByteArrayOutputStream();
+        DataOutputStream dos = new DataOutputStream(chunkConfig);
+        byte[] cacerts = Files.readAllBytes(Paths.get("config/cacerts.jks"));
+        byte[] keystore = null;
+        Path p = Paths.get("config/keystore.pkcs12");
+        if (p.toFile().exists()) {
+            keystore = Files.readAllBytes(p);
+        } else {
+            mainProps.setProperty("proxy", "true");
+        }
+
+        DevelLauncher.writeGigiConfig(dos, "changeit".getBytes("UTF-8"), "changeit".getBytes("UTF-8"), mainProps, cacerts, keystore);
+        dos.flush();
+        new Launcher().boot(new ByteArrayInputStream(chunkConfig.toByteArray()));
+        addDevelPage(true);
+        new Thread("ticket awaiter") {
+
+            @Override
+            public void run() {
+                try {
+                    Thread.sleep(8000);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+                try {
+                    if ( !ticketUsed) {
+                        Desktop.getDesktop().browse(new URL("http://" + ServerConstants.getWwwHostNamePort() + "/ticketWait").toURI());
+                    }
+                } catch (IOException e) {
+                    e.printStackTrace();
+                } catch (URISyntaxException e) {
+                    e.printStackTrace();
+                }
+            }
+        }.start();
+        BufferedReader br = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
+        System.out.println("Cacert-gigi system sucessfully started.");
+        System.out.println("Press enter to shutdown.");
+        br.readLine();
+        System.exit(0);
+    }
+
+    private static void killPreviousInstance(Properties mainProps) {
+        try {
+            String targetPort = mainProps.getProperty("http.port");
+            String targetHost = mainProps.getProperty("name.www");
+            URL u = new URL("http://" + targetHost + ":" + targetPort + "/kill");
+            u.openStream();
+        } catch (IOException e) {
+        }
+    }
+
+    public static void addDevelPage(boolean withToken) {
+        try {
+            Field instF = Gigi.class.getDeclaredField("instance");
+            Field pageF = Gigi.class.getDeclaredField("pages");
+            instF.setAccessible(true);
+            pageF.setAccessible(true);
+            Object gigi = instF.get(null);
+
+            // Check if we got a proper map (as much as we can tell)
+            Object pagesObj = pageF.get(gigi);
+            if ( !(pagesObj instanceof Map)) {
+                throw new Error("Invalid state when initializing page structure");
+            }
+
+            @SuppressWarnings("unchecked")
+            HashMap<String, Page> pages = new HashMap<>((Map<String, Page>) pagesObj);
+
+            pages.put("/manage", new Page("Page-manager") {
+
+                @Override
+                public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+                    ObjectCache.clearAllCaches();
+                    RegisterPage.RATE_LIMIT.bypass();
+                    LoginPage.RATE_LIMIT.bypass();
+                    CertificateRequest.RATE_LIMIT.bypass();
+                    resp.getWriter().println("All caches cleared.");
+                    System.out.println("Caches cleared.");
+
+                }
+
+                @Override
+                public boolean needsLogin() {
+                    return false;
+                }
+
+            });
+
+            pages.put("/kill", new Page("Kill") {
+
+                /**
+                 * The contained call to {@link System#exit(int)} is mainly
+                 * needed to kill this instance immediately if another
+                 * {@link DevelLauncher} is booting up to free all ports This is
+                 * required for fast development cycles.
+                 * 
+                 * @see #killPreviousInstance(Properties)
+                 */
+                @Override
+                public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+                    System.exit(0);
+                }
+
+                @Override
+                public boolean needsLogin() {
+                    return false;
+                }
+            });
+
+            if (withToken) {
+                addTicketPage(pages);
+            }
+
+            pageF.set(gigi, Collections.unmodifiableMap(pages));
+        } catch (ReflectiveOperationException e) {
+            e.printStackTrace();
+        }
+    }
+
+    static boolean ticketUsed = false;
+
+    private static void addTicketPage(HashMap<String, Page> pages) {
+        pages.put("/ticketWait", new Page("ticket") {
+
+            private final Template t = new Template(DevelLauncher.class.getResource("DevelTicketWait.templ"));
+
+            @Override
+            public boolean needsLogin() {
+                return false;
+            }
+
+            @Override
+            public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+                resp.setHeader("content-security-policy", "");
+                t.output(resp.getWriter(), getLanguage(req), new HashMap<String, Object>());
+            }
+
+        });
+        pages.put("/ticket", new Page("ticket") {
+
+            @Override
+            public boolean beforeTemplate(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+                // TODO Auto-generated method stub
+                if ( !ticketUsed) {
+                    HttpSession sess = req.getSession();
+                    User user = User.getById(1);
+                    if (user == null) {
+                        resp.getWriter().println("ticket consumed but no user available for that action");
+                        ticketUsed = true;
+                        return true;
+                    }
+                    sess.setAttribute(LOGGEDIN, true);
+                    sess.setAttribute(Language.SESSION_ATTRIB_NAME, user.getPreferredLocale());
+                    sess.setAttribute(AUTH_CONTEXT, new AuthorizationContext(user, user));
+                    req.getSession().setAttribute(LOGIN_METHOD, new TranslateCommand("Ticket"));
+                    resp.getWriter().println("ticket consumed");
+                    ticketUsed = true;
+                }
+                return true;
+            }
+
+            @Override
+            public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {}
+
+            @Override
+            public boolean needsLogin() {
+                return false;
+            }
+        });
+    }
+
+    public static void writeGigiConfig(OutputStream target, byte[] keystorepw, byte[] truststorepw, Properties mainprop, byte[] cacerts, byte[] keystore) throws IOException {
+        TarOutputStream tos = new TarOutputStream(target);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        mainprop.store(baos, "");
+
+        putTarEntry(baos.toByteArray(), tos, "gigi.properties");
+        putTarEntry(keystorepw, tos, "keystorepw");
+        putTarEntry(truststorepw, tos, "truststorepw");
+        putTarEntry(keystore, tos, "keystore.pkcs12");
+        putTarEntry(cacerts, tos, "cacerts.jks");
+        tos.close();
+
+    }
+
+    private static void putTarEntry(byte[] data, TarOutputStream tos, String name) throws IOException {
+        if (data == null) {
+            return;
+        }
+        TarHeader th = new TarHeader();
+        th.name = new StringBuffer(name);
+        th.size = data.length;
+        tos.putNextEntry(new TarEntry(th));
+        tos.write(data);
+    }
+
+}