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