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