1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.admincentral;
35
36 import info.magnolia.cms.util.ServletUtil;
37
38 import java.io.BufferedWriter;
39 import java.io.IOException;
40 import java.io.OutputStreamWriter;
41 import java.io.PrintWriter;
42 import java.util.List;
43
44 import javax.inject.Inject;
45 import javax.servlet.ServletException;
46 import javax.servlet.ServletOutputStream;
47 import javax.servlet.http.HttpServletRequest;
48 import javax.servlet.http.HttpServletResponse;
49
50 import org.jsoup.nodes.Element;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53
54 import com.vaadin.server.BootstrapFragmentResponse;
55 import com.vaadin.server.BootstrapListener;
56 import com.vaadin.server.BootstrapPageResponse;
57 import com.vaadin.server.DeploymentConfiguration;
58 import com.vaadin.server.RequestHandler;
59 import com.vaadin.server.ServiceException;
60 import com.vaadin.server.SessionInitEvent;
61 import com.vaadin.server.SessionInitListener;
62 import com.vaadin.server.UIProvider;
63 import com.vaadin.server.VaadinServlet;
64 import com.vaadin.server.VaadinServletRequest;
65 import com.vaadin.server.VaadinServletResponse;
66 import com.vaadin.server.VaadinServletService;
67 import com.vaadin.server.communication.ServletBootstrapHandler;
68 import com.vaadin.shared.ApplicationConstants;
69
70
71
72
73 public class AdmincentralVaadinServlet extends VaadinServlet {
74
75 private static final Logger log = LoggerFactory.getLogger(AdmincentralVaadinServlet.class);
76
77 private static final String ERROR_PAGE_STYLE = "<style>a {color: inherit; text-decoration:none;}" +
78 "html, body {height:100%; margin:0;}" +
79 ".error-message {color:#fff; font-family: Verdana, sans-serif; padding:24px; line-height:1.3; overflow-x:hidden; overflow-y:auto;}" +
80 "h2 {font-size:5em; font-family:DINWebPro, sans-serif; font-weight: normal; margin:0;}" +
81 ".v-button-link {font-size: 2em;} .v-button-link .v-button-caption {text-decoration:none;}" +
82 "#stacktrace {font-family: monospace; display:none; color:#3e5900;}" +
83 ".viewerror {color:#aabf2f;} .v-button-link:hover, .v-button-link:focus {color:#93bac6;}</style>";
84
85
86
87
88 public static final String RESTART_APPLICATION_PARAM = "?restartApplication";
89
90 private UIProvider admincentralUiProvider;
91
92 @Inject
93 public AdmincentralVaadinServlet(UIProvider admincentralUiProvider) {
94 this.admincentralUiProvider = admincentralUiProvider;
95 }
96
97 @Override
98 protected void servletInitialized() throws ServletException {
99 super.servletInitialized();
100 getService().addSessionInitListener(new SessionInitListener() {
101 @Override
102 public void sessionInit(SessionInitEvent event) {
103 event.getSession().addBootstrapListener(new BootstrapListener() {
104
105 @Override
106 public void modifyBootstrapPage(BootstrapPageResponse response) {
107 Element ieMode = response.getDocument().head().getElementsByAttributeValue("http-equiv", "X-UA-Compatible").first();
108 if (ieMode != null) {
109 ieMode.attr("content", "IE=9;chrome=1");
110 }
111 response.getDocument().head().append("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\" />");
112 }
113
114 @Override
115 public void modifyBootstrapFragment(BootstrapFragmentResponse response) {
116 }
117 });
118
119
120 if (admincentralUiProvider != null) {
121 event.getSession().addUIProvider(admincentralUiProvider);
122 } else {
123 log.error("Could not inject AdmincentralUIProvider.");
124 }
125 }
126 });
127 }
128
129 @Override
130 protected void service(HttpServletRequest request, HttpServletResponse response) throws IOException {
131 try {
132 String requestURI = ServletUtil.stripPathParameters(request.getRequestURI());
133 if (requestURI != null && requestURI.endsWith("undefined.cache.js")) {
134 writeUnsupportedBrowserPage(request, response);
135 } else {
136 super.service(request, response);
137 }
138 } catch (Exception e) {
139 log.error("An internal error has occurred in the VaadinServlet.", e);
140 writeServerErrorPage(request, response, e);
141 }
142 }
143
144 @Override
145 protected void criticalNotification(VaadinServletRequest request, VaadinServletResponse response, String caption, String message, String details, String url) throws IOException {
146
147 if (isUidlRequest(request)) {
148 super.criticalNotification(request, response, caption, message, details, url);
149 }
150 }
151
152 private void writeServerErrorPage(HttpServletRequest request, HttpServletResponse response, Exception e) throws IOException {
153 if (!isUidlRequest(request)) {
154
155
156
157 String url = request.getRequestURL().toString() + RESTART_APPLICATION_PARAM;
158 String fragment = request.getParameter("v-loc");
159 if (fragment != null && fragment.indexOf("#") != -1) {
160 url += fragment.substring(fragment.indexOf("#"));
161 }
162
163 final StringBuilder output = new StringBuilder();
164 output.append(ERROR_PAGE_STYLE)
165 .append("<div class=\"v-magnolia-shell\" style=\"height:100%;\">")
166 .append("<div id=\"main-launcher\"><a href=\"" + url + "\"><img id=\"logo\" src=\"./../VAADIN/themes/admincentraltheme/img/logo-magnolia.svg\" /></a></div>")
167 .append("<div class=\"error-message v-shell-viewport-slot\">")
168
169 .append("<h2>Whoops!</h2>")
170 .append("<p>The server has encountered an internal error.</p>")
171
172 .append("<div class=\"v-button v-widget link v-button-link\" tabindex=\"0\" role=\"button\">")
173 .append("<a href=\"" + url + "\">[<span class=\"v-button-caption\">Click here to attempt to recover from this</span>]</a></div>")
174
175 .append("<p>We apologize for any inconvenience caused.</p>")
176 .append("<p>If you keep experiencing difficulties, please contact your system administrator.</p>")
177 .append("<p>Please check your log files for the complete stack trace.</p>");
178
179 output.append("</div></div>");
180
181
182 output.insert(0, "<html><head><meta charset=\"UTF-8\"/><meta content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\" name=\"viewport\"/><title>Magnolia 5</title><link rel=\"stylesheet\" type=\"text/css\" href=\"./../VAADIN/themes/admincentral/styles.css\"/></head><body>");
183 output.append("</body></html>");
184
185
186 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
187 writeResponse(response, "text/html; charset=UTF-8", output.toString());
188 }
189 }
190
191 private void writeUnsupportedBrowserPage(HttpServletRequest request, HttpServletResponse response) throws IOException {
192
193 final StringBuilder output = new StringBuilder();
194 output.append(ERROR_PAGE_STYLE)
195 .append("<div class=\"v-magnolia-shell\" style=\"height:100%;\">")
196 .append("<div id=\"main-launcher\"><a href=\"#\"><img id=\"logo\" src=\"./../VAADIN/themes/admincentraltheme/img/logo-magnolia.svg\"></a></div>")
197 .append("<div class=\"error-message v-shell-viewport-slot\">")
198 .append("<h2>Sorry.</h2>")
199 .append("<p>You're trying to use Magnolia 5 on a browser we currently do not support.</p>")
200 .append("<p>Please log in using either Firefox, Chrome, Safari or IE8+.<br />")
201 .append("We apologize for any inconvenience caused.</p>")
202 .append("</div></div>");
203
204
205 output.replace(0, output.length(), output.toString().replaceAll("\\\"", "\\\\\\\""));
206 output.insert(0, "document.body.innerHTML = \"");
207 output.append("\";");
208
209 writeResponse(response, "text/javascript; charset=UTF-8", output.toString());
210 }
211
212
213
214
215 private boolean isUidlRequest(HttpServletRequest request) {
216 String prefix = ApplicationConstants.UIDL_PATH + '/';
217 String pathInfo = request.getPathInfo();
218
219 if (pathInfo == null) {
220 return false;
221 }
222
223 if (!prefix.startsWith("/")) {
224 prefix = '/' + prefix;
225 }
226
227 return pathInfo.startsWith(prefix);
228 }
229
230
231
232
233 private void writeResponse(HttpServletResponse response,
234 String contentType, String output) throws IOException {
235 response.setContentType(contentType);
236 final ServletOutputStream out = response.getOutputStream();
237
238 final PrintWriter outWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, "UTF-8")));
239 outWriter.print(output);
240 outWriter.flush();
241 outWriter.close();
242 out.flush();
243 }
244
245 @Override
246 protected VaadinServletService createServletService(DeploymentConfiguration deploymentConfiguration) throws ServiceException {
247 VaadinServletService service = new VaadinServletService(this, deploymentConfiguration) {
248
249 @Override
250 protected List<RequestHandler> createRequestHandlers() throws ServiceException {
251 List<RequestHandler> handlers = super.createRequestHandlers();
252 for (int i = 0; i < handlers.size(); i++) {
253 RequestHandler handler = handlers.get(i);
254 if (handler instanceof ServletBootstrapHandler) {
255 handlers.set(i, new ServletBootstrapHandler() {
256
257 @Override
258 protected String getServiceUrl(BootstrapContext context) {
259
260
261
262
263
264
265
266
267
268
269
270 return ServletUtil.getOriginalRequestURI(((VaadinServletRequest)context.getRequest()).getHttpServletRequest());
271 }
272 });
273 break;
274 }
275 }
276 return handlers;
277 }
278 };
279 service.init();
280 return service;
281 }
282 }