]> WPIA git - gigi.git/blob - src/org/cacert/gigi/DevelLauncher.java
UPD: document and justify call to System.exit in /kill
[gigi.git] / src / org / cacert / gigi / DevelLauncher.java
1 package org.cacert.gigi;
2
3 import java.io.BufferedReader;
4 import java.io.ByteArrayInputStream;
5 import java.io.ByteArrayOutputStream;
6 import java.io.DataOutputStream;
7 import java.io.File;
8 import java.io.FileInputStream;
9 import java.io.IOException;
10 import java.io.InputStream;
11 import java.io.InputStreamReader;
12 import java.io.OutputStream;
13 import java.lang.reflect.Field;
14 import java.net.URL;
15 import java.nio.file.Files;
16 import java.nio.file.Paths;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.Properties;
21
22 import javax.servlet.http.HttpServletRequest;
23 import javax.servlet.http.HttpServletResponse;
24
25 import org.cacert.gigi.dbObjects.ObjectCache;
26 import org.cacert.gigi.pages.Page;
27 import org.kamranzafar.jtar.TarEntry;
28 import org.kamranzafar.jtar.TarHeader;
29 import org.kamranzafar.jtar.TarOutputStream;
30
31 public class DevelLauncher {
32
33     public static final boolean DEVEL = true;
34
35     public static void main(String[] args) throws Exception {
36         Properties mainProps = new Properties();
37         try (FileInputStream inStream = new FileInputStream("config/gigi.properties")) {
38             mainProps.load(inStream);
39         }
40         for (int i = 0; i < args.length; i++) {
41             if (args[i].equals("--port")) {
42                 mainProps.setProperty("port", args[i + 1]);
43             }
44             i++;
45         }
46         killPreviousInstance(mainProps);
47
48         ByteArrayOutputStream chunkConfig = new ByteArrayOutputStream();
49         DataOutputStream dos = new DataOutputStream(chunkConfig);
50         byte[] cacerts = Files.readAllBytes(Paths.get("config/cacerts.jks"));
51         byte[] keystore = Files.readAllBytes(Paths.get("config/keystore.pkcs12"));
52
53         DevelLauncher.writeGigiConfig(dos, "changeit".getBytes("UTF-8"), "changeit".getBytes("UTF-8"), mainProps, cacerts, keystore);
54         dos.flush();
55         InputStream oldin = System.in;
56         System.setIn(new ByteArrayInputStream(chunkConfig.toByteArray()));
57         Launcher.boot();
58         addDevelPage();
59         System.setIn(oldin);
60         BufferedReader br = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
61         System.out.println("Cacert-gigi system sucessfully started.");
62         System.out.println("Press enter to shutdown.");
63         br.readLine();
64         System.exit(0);
65     }
66
67     private static void killPreviousInstance(Properties mainProps) {
68         try {
69             String targetPort = mainProps.getProperty("http.port");
70             String targetHost = mainProps.getProperty("name.www");
71             URL u = new URL("http://" + targetHost + ":" + targetPort + "/kill");
72             u.openStream();
73         } catch (IOException e) {
74         }
75     }
76
77     public static void addDevelPage() {
78         try {
79             Field instF = Gigi.class.getDeclaredField("instance");
80             Field pageF = Gigi.class.getDeclaredField("pages");
81             instF.setAccessible(true);
82             pageF.setAccessible(true);
83             Object gigi = instF.get(null);
84
85             // Check if we got a proper map (as much as we can tell)
86             Object pagesObj = pageF.get(gigi);
87             @SuppressWarnings("unchecked")
88             HashMap<String, Page> pages = pagesObj instanceof Map ? new HashMap<>((Map<String, Page>) pagesObj) : null;
89
90             pages.put("/manage", new Page("Page-manager") {
91
92                 @Override
93                 public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
94                     ObjectCache.clearAllCaches();
95                     resp.getWriter().println("All caches cleared.");
96                     System.out.println("Caches cleared.");
97
98                 }
99
100                 @Override
101                 public boolean needsLogin() {
102                     return false;
103                 }
104
105             });
106
107             pages.put("/kill", new Page("Kill") {
108
109                 /**
110                  * The contained call to {@link System#exit(int)} is mainly
111                  * needed to kill this instance immediately if another
112                  * {@link DevelLauncher} is booting up to free all ports This is
113                  * required for fast development cycles.
114                  * 
115                  * @see #killPreviousInstance(Properties)
116                  */
117                 @Override
118                 public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
119                     System.exit(0);
120                 }
121
122                 @Override
123                 public boolean needsLogin() {
124                     return false;
125                 }
126             });
127
128             pageF.set(gigi, Collections.unmodifiableMap(pages));
129         } catch (ReflectiveOperationException e) {
130             e.printStackTrace();
131         }
132     }
133
134     public static void writeGigiConfig(OutputStream target, byte[] keystorepw, byte[] truststorepw, Properties mainprop, byte[] cacerts, byte[] keystore) throws IOException {
135         TarOutputStream tos = new TarOutputStream(target);
136         ByteArrayOutputStream baos = new ByteArrayOutputStream();
137         mainprop.store(baos, "");
138
139         putTarEntry(baos.toByteArray(), tos, "gigi.properties");
140         putTarEntry(keystorepw, tos, "keystorepw");
141         putTarEntry(truststorepw, tos, "truststorepw");
142         putTarEntry(keystore, tos, "keystore.pkcs12");
143         putTarEntry(cacerts, tos, "cacerts.jks");
144         tos.close();
145
146     }
147
148     private static void putTarEntry(byte[] data, TarOutputStream tos, String name) throws IOException {
149         TarHeader th = new TarHeader();
150         th.name = new StringBuffer(name);
151         th.size = data.length;
152         tos.putNextEntry(new TarEntry(th));
153         tos.write(data);
154     }
155
156     public static void writeChunk(DataOutputStream dos, byte[] chunk) throws IOException {
157         dos.writeInt(chunk.length);
158         dos.write(chunk);
159     }
160
161     public static void launch(Properties props, File cacerts, File keystore) throws IOException {
162         ByteArrayOutputStream config = new ByteArrayOutputStream();
163         props.store(config, "");
164     }
165 }