]> WPIA git - gigi.git/blob - 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
1 package club.wpia.gigi;
2
3 import static club.wpia.gigi.Gigi.*;
4
5 import java.awt.Desktop;
6 import java.io.BufferedReader;
7 import java.io.ByteArrayInputStream;
8 import java.io.ByteArrayOutputStream;
9 import java.io.DataOutputStream;
10 import java.io.FileInputStream;
11 import java.io.IOException;
12 import java.io.InputStreamReader;
13 import java.io.OutputStream;
14 import java.lang.reflect.Field;
15 import java.net.URISyntaxException;
16 import java.net.URL;
17 import java.nio.file.Files;
18 import java.nio.file.Path;
19 import java.nio.file.Paths;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.Properties;
24
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27 import javax.servlet.http.HttpSession;
28
29 import org.kamranzafar.jtar.TarEntry;
30 import org.kamranzafar.jtar.TarHeader;
31 import org.kamranzafar.jtar.TarOutputStream;
32
33 import club.wpia.gigi.dbObjects.ObjectCache;
34 import club.wpia.gigi.dbObjects.User;
35 import club.wpia.gigi.localisation.Language;
36 import club.wpia.gigi.output.template.Template;
37 import club.wpia.gigi.output.template.TranslateCommand;
38 import club.wpia.gigi.pages.LoginPage;
39 import club.wpia.gigi.pages.Page;
40 import club.wpia.gigi.pages.account.certs.CertificateRequest;
41 import club.wpia.gigi.pages.main.RegisterPage;
42 import club.wpia.gigi.util.AuthorizationContext;
43 import club.wpia.gigi.util.ServerConstants;
44
45 public class DevelLauncher {
46
47     public static void main(String[] args) throws Exception {
48         Properties mainProps = new Properties();
49         try (FileInputStream inStream = new FileInputStream("config/gigi.properties")) {
50             mainProps.load(inStream);
51         }
52         for (int i = 0; i < args.length; i++) {
53             if (args[i].equals("--port")) {
54                 mainProps.setProperty("port", args[i + 1]);
55             }
56             i++;
57         }
58         killPreviousInstance(mainProps);
59
60         ByteArrayOutputStream chunkConfig = new ByteArrayOutputStream();
61         DataOutputStream dos = new DataOutputStream(chunkConfig);
62         byte[] cacerts = Files.readAllBytes(Paths.get("config/cacerts.jks"));
63         byte[] keystore = null;
64         Path p = Paths.get("config/keystore.pkcs12");
65         if (p.toFile().exists()) {
66             keystore = Files.readAllBytes(p);
67         } else {
68             mainProps.setProperty("proxy", "true");
69         }
70
71         DevelLauncher.writeGigiConfig(dos, "changeit".getBytes("UTF-8"), "changeit".getBytes("UTF-8"), mainProps, cacerts, keystore);
72         dos.flush();
73         new Launcher().boot(new ByteArrayInputStream(chunkConfig.toByteArray()));
74         addDevelPage(true);
75         new Thread("ticket awaiter") {
76
77             @Override
78             public void run() {
79                 try {
80                     Thread.sleep(8000);
81                 } catch (InterruptedException e) {
82                     e.printStackTrace();
83                 }
84                 try {
85                     if ( !ticketUsed) {
86                         Desktop.getDesktop().browse(new URL("http://" + ServerConstants.getWwwHostNamePort() + "/ticketWait").toURI());
87                     }
88                 } catch (IOException e) {
89                     e.printStackTrace();
90                 } catch (URISyntaxException e) {
91                     e.printStackTrace();
92                 }
93             }
94         }.start();
95         BufferedReader br = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
96         System.out.println("Cacert-gigi system sucessfully started.");
97         System.out.println("Press enter to shutdown.");
98         br.readLine();
99         System.exit(0);
100     }
101
102     private static void killPreviousInstance(Properties mainProps) {
103         try {
104             String targetPort = mainProps.getProperty("http.port");
105             String targetHost = mainProps.getProperty("name.www");
106             URL u = new URL("http://" + targetHost + ":" + targetPort + "/kill");
107             u.openStream();
108         } catch (IOException e) {
109         }
110     }
111
112     public static void addDevelPage(boolean withToken) {
113         try {
114             Field instF = Gigi.class.getDeclaredField("instance");
115             Field pageF = Gigi.class.getDeclaredField("pages");
116             instF.setAccessible(true);
117             pageF.setAccessible(true);
118             Object gigi = instF.get(null);
119
120             // Check if we got a proper map (as much as we can tell)
121             Object pagesObj = pageF.get(gigi);
122             if ( !(pagesObj instanceof Map)) {
123                 throw new Error("Invalid state when initializing page structure");
124             }
125
126             @SuppressWarnings("unchecked")
127             HashMap<String, Page> pages = new HashMap<>((Map<String, Page>) pagesObj);
128
129             pages.put("/manage", new Page("Page-manager") {
130
131                 @Override
132                 public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
133                     ObjectCache.clearAllCaches();
134                     RegisterPage.RATE_LIMIT.bypass();
135                     LoginPage.RATE_LIMIT.bypass();
136                     CertificateRequest.RATE_LIMIT.bypass();
137                     resp.getWriter().println("All caches cleared.");
138                     System.out.println("Caches cleared.");
139
140                 }
141
142                 @Override
143                 public boolean needsLogin() {
144                     return false;
145                 }
146
147             });
148
149             pages.put("/kill", new Page("Kill") {
150
151                 /**
152                  * The contained call to {@link System#exit(int)} is mainly
153                  * needed to kill this instance immediately if another
154                  * {@link DevelLauncher} is booting up to free all ports This is
155                  * required for fast development cycles.
156                  * 
157                  * @see #killPreviousInstance(Properties)
158                  */
159                 @Override
160                 public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
161                     System.exit(0);
162                 }
163
164                 @Override
165                 public boolean needsLogin() {
166                     return false;
167                 }
168             });
169
170             if (withToken) {
171                 addTicketPage(pages);
172             }
173
174             pageF.set(gigi, Collections.unmodifiableMap(pages));
175         } catch (ReflectiveOperationException e) {
176             e.printStackTrace();
177         }
178     }
179
180     static boolean ticketUsed = false;
181
182     private static void addTicketPage(HashMap<String, Page> pages) {
183         pages.put("/ticketWait", new Page("ticket") {
184
185             private final Template t = new Template(DevelLauncher.class.getResource("DevelTicketWait.templ"));
186
187             @Override
188             public boolean needsLogin() {
189                 return false;
190             }
191
192             @Override
193             public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
194                 resp.setHeader("content-security-policy", "");
195                 t.output(resp.getWriter(), getLanguage(req), new HashMap<String, Object>());
196             }
197
198         });
199         pages.put("/ticket", new Page("ticket") {
200
201             @Override
202             public boolean beforeTemplate(HttpServletRequest req, HttpServletResponse resp) throws IOException {
203                 // TODO Auto-generated method stub
204                 if ( !ticketUsed) {
205                     HttpSession sess = req.getSession();
206                     User user = User.getById(1);
207                     if (user == null) {
208                         resp.getWriter().println("ticket consumed but no user available for that action");
209                         ticketUsed = true;
210                         return true;
211                     }
212                     sess.setAttribute(LOGGEDIN, true);
213                     sess.setAttribute(Language.SESSION_ATTRIB_NAME, user.getPreferredLocale());
214                     sess.setAttribute(AUTH_CONTEXT, new AuthorizationContext(user, user));
215                     req.getSession().setAttribute(LOGIN_METHOD, new TranslateCommand("Ticket"));
216                     resp.getWriter().println("ticket consumed");
217                     ticketUsed = true;
218                 }
219                 return true;
220             }
221
222             @Override
223             public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {}
224
225             @Override
226             public boolean needsLogin() {
227                 return false;
228             }
229         });
230     }
231
232     public static void writeGigiConfig(OutputStream target, byte[] keystorepw, byte[] truststorepw, Properties mainprop, byte[] cacerts, byte[] keystore) throws IOException {
233         TarOutputStream tos = new TarOutputStream(target);
234         ByteArrayOutputStream baos = new ByteArrayOutputStream();
235         mainprop.store(baos, "");
236
237         putTarEntry(baos.toByteArray(), tos, "gigi.properties");
238         putTarEntry(keystorepw, tos, "keystorepw");
239         putTarEntry(truststorepw, tos, "truststorepw");
240         putTarEntry(keystore, tos, "keystore.pkcs12");
241         putTarEntry(cacerts, tos, "cacerts.jks");
242         tos.close();
243
244     }
245
246     private static void putTarEntry(byte[] data, TarOutputStream tos, String name) throws IOException {
247         if (data == null) {
248             return;
249         }
250         TarHeader th = new TarHeader();
251         th.name = new StringBuffer(name);
252         th.size = data.length;
253         tos.putNextEntry(new TarEntry(th));
254         tos.write(data);
255     }
256
257 }