]> WPIA git - gigi.git/blob - util-testing/org/cacert/gigi/DevelLauncher.java
add: login ticket into the devel launcher
[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.URL;
17 import java.nio.file.Files;
18 import java.nio.file.Paths;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.Map;
22 import java.util.Properties;
23
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26 import javax.servlet.http.HttpSession;
27
28 import org.cacert.gigi.dbObjects.ObjectCache;
29 import org.cacert.gigi.dbObjects.User;
30 import org.cacert.gigi.localisation.Language;
31 import org.cacert.gigi.pages.Page;
32 import org.cacert.gigi.util.RandomToken;
33 import org.cacert.gigi.util.ServerConstants;
34 import org.kamranzafar.jtar.TarEntry;
35 import org.kamranzafar.jtar.TarHeader;
36 import org.kamranzafar.jtar.TarOutputStream;
37
38 public class DevelLauncher {
39
40     public static void main(String[] args) throws Exception {
41         Properties mainProps = new Properties();
42         try (FileInputStream inStream = new FileInputStream("config/gigi.properties")) {
43             mainProps.load(inStream);
44         }
45         for (int i = 0; i < args.length; i++) {
46             if (args[i].equals("--port")) {
47                 mainProps.setProperty("port", args[i + 1]);
48             }
49             i++;
50         }
51         killPreviousInstance(mainProps);
52
53         ByteArrayOutputStream chunkConfig = new ByteArrayOutputStream();
54         DataOutputStream dos = new DataOutputStream(chunkConfig);
55         byte[] cacerts = Files.readAllBytes(Paths.get("config/cacerts.jks"));
56         byte[] keystore = Files.readAllBytes(Paths.get("config/keystore.pkcs12"));
57
58         DevelLauncher.writeGigiConfig(dos, "changeit".getBytes("UTF-8"), "changeit".getBytes("UTF-8"), mainProps, cacerts, keystore);
59         dos.flush();
60         InputStream oldin = System.in;
61         System.setIn(new ByteArrayInputStream(chunkConfig.toByteArray()));
62         new Launcher().boot();
63         final String token = RandomToken.generateToken(32);
64         addDevelPage(token);
65         Desktop.getDesktop().browse(new URL("http://" + ServerConstants.getWwwHostNamePort() + "/ticket?token=" + token).toURI());
66         System.setIn(oldin);
67         BufferedReader br = new BufferedReader(new InputStreamReader(System.in, "UTF-8"));
68         System.out.println("Cacert-gigi system sucessfully started.");
69         System.out.println("Press enter to shutdown.");
70         br.readLine();
71         System.exit(0);
72     }
73
74     private static void killPreviousInstance(Properties mainProps) {
75         try {
76             String targetPort = mainProps.getProperty("http.port");
77             String targetHost = mainProps.getProperty("name.www");
78             URL u = new URL("http://" + targetHost + ":" + targetPort + "/kill");
79             u.openStream();
80         } catch (IOException e) {
81         }
82     }
83
84     public static void addDevelPage(String token) {
85         try {
86             Field instF = Gigi.class.getDeclaredField("instance");
87             Field pageF = Gigi.class.getDeclaredField("pages");
88             instF.setAccessible(true);
89             pageF.setAccessible(true);
90             Object gigi = instF.get(null);
91
92             // Check if we got a proper map (as much as we can tell)
93             Object pagesObj = pageF.get(gigi);
94             @SuppressWarnings("unchecked")
95             HashMap<String, Page> pages = pagesObj instanceof Map ? new HashMap<>((Map<String, Page>) pagesObj) : null;
96
97             pages.put("/manage", new Page("Page-manager") {
98
99                 @Override
100                 public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
101                     ObjectCache.clearAllCaches();
102                     resp.getWriter().println("All caches cleared.");
103                     System.out.println("Caches cleared.");
104
105                 }
106
107                 @Override
108                 public boolean needsLogin() {
109                     return false;
110                 }
111
112             });
113
114             pages.put("/kill", new Page("Kill") {
115
116                 /**
117                  * The contained call to {@link System#exit(int)} is mainly
118                  * needed to kill this instance immediately if another
119                  * {@link DevelLauncher} is booting up to free all ports This is
120                  * required for fast development cycles.
121                  * 
122                  * @see #killPreviousInstance(Properties)
123                  */
124                 @Override
125                 public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
126                     System.exit(0);
127                 }
128
129                 @Override
130                 public boolean needsLogin() {
131                     return false;
132                 }
133             });
134
135             if (token != null) {
136                 addTicketPage(pages, token);
137             }
138
139             pageF.set(gigi, Collections.unmodifiableMap(pages));
140         } catch (ReflectiveOperationException e) {
141             e.printStackTrace();
142         }
143     }
144
145     private static void addTicketPage(HashMap<String, Page> pages, final String token) {
146         pages.put("/ticket", new Page("ticket") {
147
148             boolean used = false;
149
150             @Override
151             public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
152                 if ( !used && token.equals(req.getParameter("token"))) {
153                     HttpSession sess = req.getSession();
154                     User user = User.getById(1);
155                     sess.setAttribute(LOGGEDIN, true);
156                     sess.setAttribute(Language.SESSION_ATTRIB_NAME, user.getPreferredLocale());
157                     sess.setAttribute(USER, user);
158                     req.getSession().setAttribute(LOGIN_METHOD, "Ticket");
159                     resp.sendRedirect("/");
160                 }
161             }
162
163             @Override
164             public boolean needsLogin() {
165                 return false;
166             }
167         });
168     }
169
170     public static void writeGigiConfig(OutputStream target, byte[] keystorepw, byte[] truststorepw, Properties mainprop, byte[] cacerts, byte[] keystore) throws IOException {
171         TarOutputStream tos = new TarOutputStream(target);
172         ByteArrayOutputStream baos = new ByteArrayOutputStream();
173         mainprop.store(baos, "");
174
175         putTarEntry(baos.toByteArray(), tos, "gigi.properties");
176         putTarEntry(keystorepw, tos, "keystorepw");
177         putTarEntry(truststorepw, tos, "truststorepw");
178         putTarEntry(keystore, tos, "keystore.pkcs12");
179         putTarEntry(cacerts, tos, "cacerts.jks");
180         tos.close();
181
182     }
183
184     private static void putTarEntry(byte[] data, TarOutputStream tos, String name) throws IOException {
185         TarHeader th = new TarHeader();
186         th.name = new StringBuffer(name);
187         th.size = data.length;
188         tos.putNextEntry(new TarEntry(th));
189         tos.write(data);
190     }
191
192 }