1 | /* |
2 | * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, |
3 | * and the EPL 1.0 (http://h2database.com/html/license.html). |
4 | * Initial Developer: H2 Group |
5 | */ |
6 | package org.h2.server.web; |
7 | |
8 | import java.io.IOException; |
9 | import java.net.InetAddress; |
10 | import java.net.UnknownHostException; |
11 | import java.util.ArrayList; |
12 | import java.util.Enumeration; |
13 | import java.util.Properties; |
14 | |
15 | import javax.servlet.ServletConfig; |
16 | import javax.servlet.ServletOutputStream; |
17 | import javax.servlet.http.HttpServlet; |
18 | import javax.servlet.http.HttpServletRequest; |
19 | import javax.servlet.http.HttpServletResponse; |
20 | |
21 | import org.h2.engine.Constants; |
22 | import org.h2.util.New; |
23 | |
24 | /** |
25 | * This servlet lets the H2 Console be used in a standard servlet container |
26 | * such as Tomcat or Jetty. |
27 | */ |
28 | public class WebServlet extends HttpServlet { |
29 | |
30 | private static final long serialVersionUID = 1L; |
31 | private transient WebServer server; |
32 | |
33 | @Override |
34 | public void init() { |
35 | ServletConfig config = getServletConfig(); |
36 | Enumeration<?> en = config.getInitParameterNames(); |
37 | ArrayList<String> list = New.arrayList(); |
38 | while (en.hasMoreElements()) { |
39 | String name = en.nextElement().toString(); |
40 | String value = config.getInitParameter(name); |
41 | if (!name.startsWith("-")) { |
42 | name = "-" + name; |
43 | } |
44 | list.add(name); |
45 | if (value.length() > 0) { |
46 | list.add(value); |
47 | } |
48 | } |
49 | String[] args = new String[list.size()]; |
50 | list.toArray(args); |
51 | server = new WebServer(); |
52 | server.setAllowChunked(false); |
53 | server.init(args); |
54 | } |
55 | |
56 | @Override |
57 | public void destroy() { |
58 | server.stop(); |
59 | } |
60 | |
61 | private boolean allow(HttpServletRequest req) { |
62 | if (server.getAllowOthers()) { |
63 | return true; |
64 | } |
65 | String addr = req.getRemoteAddr(); |
66 | try { |
67 | InetAddress address = InetAddress.getByName(addr); |
68 | return address.isLoopbackAddress(); |
69 | } catch (UnknownHostException e) { |
70 | return false; |
71 | } catch (NoClassDefFoundError e) { |
72 | // Google App Engine does not allow java.net.InetAddress |
73 | return false; |
74 | } |
75 | } |
76 | |
77 | private String getAllowedFile(HttpServletRequest req, String requestedFile) { |
78 | if (!allow(req)) { |
79 | return "notAllowed.jsp"; |
80 | } |
81 | if (requestedFile.length() == 0) { |
82 | return "index.do"; |
83 | } |
84 | return requestedFile; |
85 | } |
86 | |
87 | @Override |
88 | public void doGet(HttpServletRequest req, HttpServletResponse resp) |
89 | throws IOException { |
90 | req.setCharacterEncoding("utf-8"); |
91 | String file = req.getPathInfo(); |
92 | if (file == null) { |
93 | resp.sendRedirect(req.getRequestURI() + "/"); |
94 | return; |
95 | } else if (file.startsWith("/")) { |
96 | file = file.substring(1); |
97 | } |
98 | file = getAllowedFile(req, file); |
99 | |
100 | // extract the request attributes |
101 | Properties attributes = new Properties(); |
102 | Enumeration<?> en = req.getAttributeNames(); |
103 | while (en.hasMoreElements()) { |
104 | String name = en.nextElement().toString(); |
105 | String value = req.getAttribute(name).toString(); |
106 | attributes.put(name, value); |
107 | } |
108 | en = req.getParameterNames(); |
109 | while (en.hasMoreElements()) { |
110 | String name = en.nextElement().toString(); |
111 | String value = req.getParameter(name); |
112 | attributes.put(name, value); |
113 | } |
114 | |
115 | WebSession session = null; |
116 | String sessionId = attributes.getProperty("jsessionid"); |
117 | if (sessionId != null) { |
118 | session = server.getSession(sessionId); |
119 | } |
120 | WebApp app = new WebApp(server); |
121 | app.setSession(session, attributes); |
122 | String ifModifiedSince = req.getHeader("if-modified-since"); |
123 | |
124 | String hostAddr = req.getRemoteAddr(); |
125 | file = app.processRequest(file, hostAddr); |
126 | session = app.getSession(); |
127 | |
128 | String mimeType = app.getMimeType(); |
129 | boolean cache = app.getCache(); |
130 | |
131 | if (cache && server.getStartDateTime().equals(ifModifiedSince)) { |
132 | resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); |
133 | return; |
134 | } |
135 | byte[] bytes = server.getFile(file); |
136 | if (bytes == null) { |
137 | resp.sendError(HttpServletResponse.SC_NOT_FOUND); |
138 | bytes = ("File not found: " + file).getBytes(Constants.UTF8); |
139 | } else { |
140 | if (session != null && file.endsWith(".jsp")) { |
141 | String page = new String(bytes, Constants.UTF8); |
142 | page = PageParser.parse(page, session.map); |
143 | bytes = page.getBytes(Constants.UTF8); |
144 | } |
145 | resp.setContentType(mimeType); |
146 | if (!cache) { |
147 | resp.setHeader("Cache-Control", "no-cache"); |
148 | } else { |
149 | resp.setHeader("Cache-Control", "max-age=10"); |
150 | resp.setHeader("Last-Modified", server.getStartDateTime()); |
151 | } |
152 | } |
153 | if (bytes != null) { |
154 | ServletOutputStream out = resp.getOutputStream(); |
155 | out.write(bytes); |
156 | } |
157 | } |
158 | |
159 | @Override |
160 | public void doPost(HttpServletRequest req, HttpServletResponse resp) |
161 | throws IOException { |
162 | doGet(req, resp); |
163 | } |
164 | |
165 | } |