Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

VaadinPortlet.java 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. /*
  2. * Copyright 2011 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.server;
  17. import java.io.BufferedWriter;
  18. import java.io.IOException;
  19. import java.io.InputStream;
  20. import java.io.OutputStream;
  21. import java.io.OutputStreamWriter;
  22. import java.io.PrintWriter;
  23. import java.lang.reflect.Method;
  24. import java.net.MalformedURLException;
  25. import java.security.GeneralSecurityException;
  26. import java.util.Enumeration;
  27. import java.util.Map;
  28. import java.util.Properties;
  29. import java.util.logging.Logger;
  30. import javax.portlet.ActionRequest;
  31. import javax.portlet.ActionResponse;
  32. import javax.portlet.EventRequest;
  33. import javax.portlet.EventResponse;
  34. import javax.portlet.GenericPortlet;
  35. import javax.portlet.PortletConfig;
  36. import javax.portlet.PortletContext;
  37. import javax.portlet.PortletException;
  38. import javax.portlet.PortletRequest;
  39. import javax.portlet.PortletResponse;
  40. import javax.portlet.RenderRequest;
  41. import javax.portlet.RenderResponse;
  42. import javax.portlet.ResourceRequest;
  43. import javax.portlet.ResourceResponse;
  44. import javax.servlet.http.HttpServletRequest;
  45. import javax.servlet.http.HttpServletRequestWrapper;
  46. import javax.servlet.http.HttpServletResponse;
  47. import com.liferay.portal.kernel.util.PortalClassInvoker;
  48. import com.liferay.portal.kernel.util.PropsUtil;
  49. import com.vaadin.server.AbstractCommunicationManager.Callback;
  50. import com.vaadin.ui.UI;
  51. import com.vaadin.util.CurrentInstance;
  52. /**
  53. * Portlet 2.0 base class. This replaces the servlet in servlet/portlet 1.0
  54. * deployments and handles various portlet requests from the browser.
  55. *
  56. * TODO Document me!
  57. *
  58. * @author peholmst
  59. */
  60. public class VaadinPortlet extends GenericPortlet implements Constants {
  61. /**
  62. * @deprecated As of 7.0. Will likely change or be removed in a future version
  63. */
  64. @Deprecated
  65. public static final String RESOURCE_URL_ID = "APP";
  66. public static class VaadinHttpAndPortletRequest extends
  67. VaadinPortletRequest {
  68. public VaadinHttpAndPortletRequest(PortletRequest request,
  69. HttpServletRequest originalRequest,
  70. VaadinPortletService vaadinService) {
  71. super(request, vaadinService);
  72. this.originalRequest = originalRequest;
  73. }
  74. private final HttpServletRequest originalRequest;
  75. @Override
  76. public String getParameter(String name) {
  77. String parameter = super.getParameter(name);
  78. if (parameter == null) {
  79. parameter = originalRequest.getParameter(name);
  80. }
  81. return parameter;
  82. }
  83. @Override
  84. public String getRemoteAddr() {
  85. return originalRequest.getRemoteAddr();
  86. }
  87. @Override
  88. public String getRemoteHost() {
  89. return originalRequest.getRemoteHost();
  90. }
  91. @Override
  92. public int getRemotePort() {
  93. return originalRequest.getRemotePort();
  94. }
  95. @Override
  96. public String getHeader(String name) {
  97. String header = super.getHeader(name);
  98. if (header == null) {
  99. header = originalRequest.getHeader(name);
  100. }
  101. return header;
  102. }
  103. @Override
  104. public Enumeration<String> getHeaderNames() {
  105. Enumeration<String> headerNames = super.getHeaderNames();
  106. if (headerNames == null) {
  107. headerNames = originalRequest.getHeaderNames();
  108. }
  109. return headerNames;
  110. }
  111. @Override
  112. public Enumeration<String> getHeaders(String name) {
  113. Enumeration<String> headers = super.getHeaders(name);
  114. if (headers == null) {
  115. headers = originalRequest.getHeaders(name);
  116. }
  117. return headers;
  118. }
  119. @Override
  120. public Map<String, String[]> getParameterMap() {
  121. Map<String, String[]> parameterMap = super.getParameterMap();
  122. if (parameterMap == null) {
  123. parameterMap = originalRequest.getParameterMap();
  124. }
  125. return parameterMap;
  126. }
  127. }
  128. public static class VaadinGateinRequest extends VaadinHttpAndPortletRequest {
  129. public VaadinGateinRequest(PortletRequest request,
  130. VaadinPortletService vaadinService) {
  131. super(request, getOriginalRequest(request), vaadinService);
  132. }
  133. private static final HttpServletRequest getOriginalRequest(
  134. PortletRequest request) {
  135. try {
  136. Method getRealReq = request.getClass().getMethod(
  137. "getRealRequest");
  138. HttpServletRequestWrapper origRequest = (HttpServletRequestWrapper) getRealReq
  139. .invoke(request);
  140. return origRequest;
  141. } catch (Exception e) {
  142. throw new IllegalStateException("GateIn request not detected",
  143. e);
  144. }
  145. }
  146. }
  147. public static class VaadinLiferayRequest extends
  148. VaadinHttpAndPortletRequest {
  149. public VaadinLiferayRequest(PortletRequest request,
  150. VaadinPortletService vaadinService) {
  151. super(request, getOriginalRequest(request), vaadinService);
  152. }
  153. @Override
  154. public String getPortalProperty(String name) {
  155. return PropsUtil.get(name);
  156. }
  157. private static HttpServletRequest getOriginalRequest(
  158. PortletRequest request) {
  159. try {
  160. // httpRequest = PortalUtil.getHttpServletRequest(request);
  161. HttpServletRequest httpRequest = (HttpServletRequest) PortalClassInvoker
  162. .invoke("com.liferay.portal.util.PortalUtil",
  163. "getHttpServletRequest", request);
  164. // httpRequest =
  165. // PortalUtil.getOriginalServletRequest(httpRequest);
  166. httpRequest = (HttpServletRequest) PortalClassInvoker.invoke(
  167. "com.liferay.portal.util.PortalUtil",
  168. "getOriginalServletRequest", httpRequest);
  169. return httpRequest;
  170. } catch (Exception e) {
  171. throw new IllegalStateException("Liferay request not detected",
  172. e);
  173. }
  174. }
  175. }
  176. public static class AbstractApplicationPortletWrapper implements Callback {
  177. private final VaadinPortlet portlet;
  178. public AbstractApplicationPortletWrapper(VaadinPortlet portlet) {
  179. this.portlet = portlet;
  180. }
  181. @Override
  182. public void criticalNotification(VaadinRequest request,
  183. VaadinResponse response, String cap, String msg,
  184. String details, String outOfSyncURL) throws IOException {
  185. portlet.criticalNotification((VaadinPortletRequest) request,
  186. (VaadinPortletResponse) response, cap, msg, details,
  187. outOfSyncURL);
  188. }
  189. }
  190. /**
  191. * This portlet parameter is used to add styles to the main element. E.g
  192. * "height:500px" generates a style="height:500px" to the main element.
  193. *
  194. * @deprecated As of 7.0. Will likely change or be removed in a future version
  195. */
  196. @Deprecated
  197. public static final String PORTLET_PARAMETER_STYLE = "style";
  198. /**
  199. * This portal parameter is used to define the name of the Vaadin theme that
  200. * is used for all Vaadin applications in the portal.
  201. *
  202. * @deprecated As of 7.0. Will likely change or be removed in a future version
  203. */
  204. @Deprecated
  205. public static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme";
  206. /**
  207. * @deprecated As of 7.0. Will likely change or be removed in a future version
  208. */
  209. @Deprecated
  210. public static final String WRITE_AJAX_PAGE_SCRIPT_WIDGETSET_SHOULD_WRITE = "writeAjaxPageScriptWidgetsetShouldWrite";
  211. // TODO some parts could be shared with AbstractApplicationServlet
  212. // TODO Can we close the application when the portlet is removed? Do we know
  213. // when the portlet is removed?
  214. private VaadinPortletService vaadinService;
  215. @Override
  216. public void init(PortletConfig config) throws PortletException {
  217. CurrentInstance.clearAll();
  218. setCurrent(this);
  219. super.init(config);
  220. Properties initParameters = new Properties();
  221. // Read default parameters from the context
  222. final PortletContext context = config.getPortletContext();
  223. for (final Enumeration<String> e = context.getInitParameterNames(); e
  224. .hasMoreElements();) {
  225. final String name = e.nextElement();
  226. initParameters.setProperty(name, context.getInitParameter(name));
  227. }
  228. // Override with application settings from portlet.xml
  229. for (final Enumeration<String> e = config.getInitParameterNames(); e
  230. .hasMoreElements();) {
  231. final String name = e.nextElement();
  232. initParameters.setProperty(name, config.getInitParameter(name));
  233. }
  234. DeploymentConfiguration deploymentConfiguration = createDeploymentConfiguration(initParameters);
  235. vaadinService = createPortletService(deploymentConfiguration);
  236. // Sets current service even though there are no request and response
  237. vaadinService.setCurrentInstances(null, null);
  238. portletInitialized();
  239. CurrentInstance.clearAll();
  240. }
  241. protected void portletInitialized() throws PortletException {
  242. }
  243. protected DeploymentConfiguration createDeploymentConfiguration(
  244. Properties initParameters) {
  245. return new DefaultDeploymentConfiguration(getClass(), initParameters);
  246. }
  247. protected VaadinPortletService createPortletService(
  248. DeploymentConfiguration deploymentConfiguration) {
  249. return new VaadinPortletService(this, deploymentConfiguration);
  250. }
  251. /**
  252. * @author Vaadin Ltd
  253. *
  254. * @deprecated As of 7.0. Will likely change or be removed in a future version
  255. */
  256. @Deprecated
  257. protected enum RequestType {
  258. FILE_UPLOAD, UIDL, RENDER, STATIC_FILE, APP, DUMMY, EVENT, ACTION, UNKNOWN, BROWSER_DETAILS, PUBLISHED_FILE, HEARTBEAT;
  259. }
  260. /**
  261. * @param vaadinRequest
  262. * @return
  263. *
  264. * @deprecated As of 7.0. Will likely change or be removed in a future version
  265. */
  266. @Deprecated
  267. protected RequestType getRequestType(VaadinPortletRequest vaadinRequest) {
  268. PortletRequest request = vaadinRequest.getPortletRequest();
  269. if (request instanceof RenderRequest) {
  270. return RequestType.RENDER;
  271. } else if (request instanceof ResourceRequest) {
  272. ResourceRequest resourceRequest = (ResourceRequest) request;
  273. if (ServletPortletHelper.isUIDLRequest(vaadinRequest)) {
  274. return RequestType.UIDL;
  275. } else if (isBrowserDetailsRequest(resourceRequest)) {
  276. return RequestType.BROWSER_DETAILS;
  277. } else if (ServletPortletHelper.isFileUploadRequest(vaadinRequest)) {
  278. return RequestType.FILE_UPLOAD;
  279. } else if (ServletPortletHelper
  280. .isPublishedFileRequest(vaadinRequest)) {
  281. return RequestType.PUBLISHED_FILE;
  282. } else if (ServletPortletHelper.isAppRequest(vaadinRequest)) {
  283. return RequestType.APP;
  284. } else if (ServletPortletHelper.isHeartbeatRequest(vaadinRequest)) {
  285. return RequestType.HEARTBEAT;
  286. } else if (isDummyRequest(resourceRequest)) {
  287. return RequestType.DUMMY;
  288. } else {
  289. return RequestType.STATIC_FILE;
  290. }
  291. } else if (request instanceof ActionRequest) {
  292. return RequestType.ACTION;
  293. } else if (request instanceof EventRequest) {
  294. return RequestType.EVENT;
  295. }
  296. return RequestType.UNKNOWN;
  297. }
  298. private boolean isBrowserDetailsRequest(ResourceRequest request) {
  299. return request.getResourceID() != null
  300. && request.getResourceID().equals("browserDetails");
  301. }
  302. private boolean isDummyRequest(ResourceRequest request) {
  303. return request.getResourceID() != null
  304. && request.getResourceID().equals("DUMMY");
  305. }
  306. /**
  307. * @param request
  308. * @param response
  309. * @throws PortletException
  310. * @throws IOException
  311. *
  312. * @deprecated As of 7.0. Will likely change or be removed in a future version
  313. */
  314. @Deprecated
  315. protected void handleRequest(PortletRequest request,
  316. PortletResponse response) throws PortletException, IOException {
  317. RequestTimer requestTimer = new RequestTimer();
  318. requestTimer.start();
  319. CurrentInstance.clearAll();
  320. setCurrent(this);
  321. try {
  322. AbstractApplicationPortletWrapper portletWrapper = new AbstractApplicationPortletWrapper(
  323. this);
  324. VaadinPortletRequest vaadinRequest = createVaadinRequest(request);
  325. VaadinPortletResponse vaadinResponse = new VaadinPortletResponse(
  326. response, getService());
  327. getService().setCurrentInstances(vaadinRequest, vaadinResponse);
  328. RequestType requestType = getRequestType(vaadinRequest);
  329. if (requestType == RequestType.UNKNOWN) {
  330. handleUnknownRequest(request, response);
  331. } else if (requestType == RequestType.DUMMY) {
  332. /*
  333. * This dummy page is used by action responses to redirect to,
  334. * in order to prevent the boot strap code from being rendered
  335. * into strange places such as iframes.
  336. */
  337. ((ResourceResponse) response).setContentType("text/html");
  338. final OutputStream out = ((ResourceResponse) response)
  339. .getPortletOutputStream();
  340. final PrintWriter outWriter = new PrintWriter(
  341. new BufferedWriter(new OutputStreamWriter(out, "UTF-8")));
  342. outWriter.print("<html><body>dummy page</body></html>");
  343. outWriter.close();
  344. } else if (requestType == RequestType.STATIC_FILE) {
  345. serveStaticResources((ResourceRequest) request,
  346. (ResourceResponse) response);
  347. } else {
  348. VaadinPortletSession vaadinSession = null;
  349. try {
  350. // TODO What about PARAM_UNLOADBURST &
  351. // redirectToApplication??
  352. vaadinSession = (VaadinPortletSession) getService()
  353. .findVaadinSession(vaadinRequest);
  354. if (vaadinSession == null) {
  355. return;
  356. }
  357. PortletCommunicationManager communicationManager = (PortletCommunicationManager) vaadinSession
  358. .getCommunicationManager();
  359. if (requestType == RequestType.PUBLISHED_FILE) {
  360. communicationManager.servePublishedFile(vaadinRequest,
  361. vaadinResponse);
  362. return;
  363. } else if (requestType == RequestType.HEARTBEAT) {
  364. communicationManager.handleHeartbeatRequest(
  365. vaadinRequest, vaadinResponse, vaadinSession);
  366. return;
  367. }
  368. /* Update browser information from request */
  369. vaadinSession.getBrowser().updateRequestDetails(
  370. vaadinRequest);
  371. /* Notify listeners */
  372. // Finds the right UI
  373. UI uI = null;
  374. if (requestType == RequestType.UIDL) {
  375. uI = getService().findUI(vaadinRequest);
  376. }
  377. // TODO Should this happen before or after the transaction
  378. // starts?
  379. if (request instanceof RenderRequest) {
  380. vaadinSession.firePortletRenderRequest(uI,
  381. (RenderRequest) request,
  382. (RenderResponse) response);
  383. } else if (request instanceof ActionRequest) {
  384. vaadinSession.firePortletActionRequest(uI,
  385. (ActionRequest) request,
  386. (ActionResponse) response);
  387. } else if (request instanceof EventRequest) {
  388. vaadinSession.firePortletEventRequest(uI,
  389. (EventRequest) request,
  390. (EventResponse) response);
  391. } else if (request instanceof ResourceRequest) {
  392. vaadinSession.firePortletResourceRequest(uI,
  393. (ResourceRequest) request,
  394. (ResourceResponse) response);
  395. }
  396. /* Handle the request */
  397. if (requestType == RequestType.FILE_UPLOAD) {
  398. // UI is resolved in handleFileUpload by
  399. // PortletCommunicationManager
  400. communicationManager.handleFileUpload(vaadinSession,
  401. vaadinRequest, vaadinResponse);
  402. return;
  403. } else if (requestType == RequestType.BROWSER_DETAILS) {
  404. communicationManager.handleBrowserDetailsRequest(
  405. vaadinRequest, vaadinResponse, vaadinSession);
  406. return;
  407. } else if (requestType == RequestType.UIDL) {
  408. // Handles AJAX UIDL requests
  409. communicationManager.handleUidlRequest(vaadinRequest,
  410. vaadinResponse, portletWrapper, uI);
  411. return;
  412. } else {
  413. handleOtherRequest(vaadinRequest, vaadinResponse,
  414. requestType, vaadinSession,
  415. communicationManager);
  416. }
  417. } catch (final SessionExpiredException e) {
  418. // TODO Figure out a better way to deal with
  419. // SessionExpiredExceptions
  420. getLogger().finest("A user session has expired");
  421. } catch (final GeneralSecurityException e) {
  422. // TODO Figure out a better way to deal with
  423. // GeneralSecurityExceptions
  424. getLogger()
  425. .fine("General security exception, the security key was probably incorrect.");
  426. } catch (final Throwable e) {
  427. handleServiceException(vaadinRequest, vaadinResponse,
  428. vaadinSession, e);
  429. } finally {
  430. if (vaadinSession != null) {
  431. vaadinSession.cleanupInactiveUIs();
  432. requestTimer.stop(vaadinSession);
  433. }
  434. }
  435. }
  436. } finally {
  437. CurrentInstance.clearAll();
  438. }
  439. }
  440. /**
  441. * Wraps the request in a (possibly portal specific) Vaadin portlet request.
  442. *
  443. * @param request
  444. * The original PortletRequest
  445. * @return A wrapped version of the PorletRequest
  446. */
  447. protected VaadinPortletRequest createVaadinRequest(PortletRequest request) {
  448. String portalInfo = request.getPortalContext().getPortalInfo()
  449. .toLowerCase();
  450. if (portalInfo.contains("liferay")) {
  451. return new VaadinLiferayRequest(request, getService());
  452. } else if (portalInfo.contains("gatein")) {
  453. return new VaadinGateinRequest(request, getService());
  454. } else {
  455. return new VaadinPortletRequest(request, getService());
  456. }
  457. }
  458. protected VaadinPortletService getService() {
  459. return vaadinService;
  460. }
  461. private void handleUnknownRequest(PortletRequest request,
  462. PortletResponse response) {
  463. getLogger().warning("Unknown request type");
  464. }
  465. /**
  466. * Handle a portlet request that is not for static files, UIDL or upload.
  467. * Also render requests are handled here.
  468. *
  469. * This method is called after starting the application and calling portlet
  470. * and transaction listeners.
  471. *
  472. * @param request
  473. * @param response
  474. * @param requestType
  475. * @param vaadinSession
  476. * @param vaadinSession
  477. * @param communicationManager
  478. * @throws PortletException
  479. * @throws IOException
  480. * @throws MalformedURLException
  481. */
  482. private void handleOtherRequest(VaadinPortletRequest request,
  483. VaadinResponse response, RequestType requestType,
  484. VaadinSession vaadinSession,
  485. PortletCommunicationManager communicationManager)
  486. throws PortletException, IOException, MalformedURLException {
  487. if (requestType == RequestType.APP || requestType == RequestType.RENDER) {
  488. if (!communicationManager.handleOtherRequest(request, response)) {
  489. response.sendError(HttpServletResponse.SC_NOT_FOUND,
  490. "Not found");
  491. }
  492. } else if (requestType == RequestType.EVENT) {
  493. // nothing to do, listeners do all the work
  494. } else if (requestType == RequestType.ACTION) {
  495. // nothing to do, listeners do all the work
  496. } else {
  497. throw new IllegalStateException(
  498. "handleRequest() without anything to do - should never happen!");
  499. }
  500. }
  501. @Override
  502. public void processEvent(EventRequest request, EventResponse response)
  503. throws PortletException, IOException {
  504. handleRequest(request, response);
  505. }
  506. private void serveStaticResources(ResourceRequest request,
  507. ResourceResponse response) throws IOException, PortletException {
  508. final String resourceID = request.getResourceID();
  509. final PortletContext pc = getPortletContext();
  510. InputStream is = pc.getResourceAsStream(resourceID);
  511. if (is != null) {
  512. final String mimetype = pc.getMimeType(resourceID);
  513. if (mimetype != null) {
  514. response.setContentType(mimetype);
  515. }
  516. final OutputStream os = response.getPortletOutputStream();
  517. final byte buffer[] = new byte[DEFAULT_BUFFER_SIZE];
  518. int bytes;
  519. while ((bytes = is.read(buffer)) >= 0) {
  520. os.write(buffer, 0, bytes);
  521. }
  522. } else {
  523. getLogger().info(
  524. "Requested resource [" + resourceID
  525. + "] could not be found");
  526. response.setProperty(ResourceResponse.HTTP_STATUS_CODE,
  527. Integer.toString(HttpServletResponse.SC_NOT_FOUND));
  528. }
  529. }
  530. @Override
  531. public void processAction(ActionRequest request, ActionResponse response)
  532. throws PortletException, IOException {
  533. handleRequest(request, response);
  534. }
  535. @Override
  536. protected void doDispatch(RenderRequest request, RenderResponse response)
  537. throws PortletException, IOException {
  538. try {
  539. // try to let super handle - it'll call methods annotated for
  540. // handling, the default doXYZ(), or throw if a handler for the mode
  541. // is not found
  542. super.doDispatch(request, response);
  543. } catch (PortletException e) {
  544. if (e.getCause() == null) {
  545. // No cause interpreted as 'unknown mode' - pass that trough
  546. // so that the application can handle
  547. handleRequest(request, response);
  548. } else {
  549. // Something else failed, pass on
  550. throw e;
  551. }
  552. }
  553. }
  554. @Override
  555. public void serveResource(ResourceRequest request, ResourceResponse response)
  556. throws PortletException, IOException {
  557. handleRequest(request, response);
  558. }
  559. private void handleServiceException(VaadinPortletRequest request,
  560. VaadinPortletResponse response, VaadinSession vaadinSession,
  561. Throwable e) throws IOException, PortletException {
  562. // TODO Check that this error handler is working when running inside a
  563. // portlet
  564. // if this was an UIDL request, response UIDL back to client
  565. ErrorHandler errorHandler = ErrorEvent.findErrorHandler(vaadinSession);
  566. if (getRequestType(request) == RequestType.UIDL) {
  567. SystemMessages ci = getService().getSystemMessages(
  568. ServletPortletHelper.findLocale(null, vaadinSession,
  569. request), request);
  570. criticalNotification(request, response,
  571. ci.getInternalErrorCaption(), ci.getInternalErrorMessage(),
  572. null, ci.getInternalErrorURL());
  573. if (errorHandler != null) {
  574. errorHandler.error(new ErrorEvent(e));
  575. }
  576. } else {
  577. if (errorHandler != null) {
  578. errorHandler.error(new ErrorEvent(e));
  579. } else {
  580. // Re-throw other exceptions
  581. throw new PortletException(e);
  582. }
  583. }
  584. }
  585. /**
  586. * Send notification to client's application. Used to notify client of
  587. * critical errors and session expiration due to long inactivity. Server has
  588. * no knowledge of what application client refers to.
  589. *
  590. * @param request
  591. * the Portlet request instance.
  592. * @param response
  593. * the Portlet response to write to.
  594. * @param caption
  595. * for the notification
  596. * @param message
  597. * for the notification
  598. * @param details
  599. * a detail message to show in addition to the passed message.
  600. * Currently shown directly but could be hidden behind a details
  601. * drop down.
  602. * @param url
  603. * url to load after message, null for current page
  604. * @throws IOException
  605. * if the writing failed due to input/output error.
  606. *
  607. * @deprecated As of 7.0. Will likely change or be removed in a future version
  608. */
  609. @Deprecated
  610. void criticalNotification(VaadinPortletRequest request,
  611. VaadinPortletResponse response, String caption, String message,
  612. String details, String url) throws IOException {
  613. // clients JS app is still running, but server application either
  614. // no longer exists or it might fail to perform reasonably.
  615. // send a notification to client's application and link how
  616. // to "restart" application.
  617. if (caption != null) {
  618. caption = "\"" + caption + "\"";
  619. }
  620. if (details != null) {
  621. if (message == null) {
  622. message = details;
  623. } else {
  624. message += "<br/><br/>" + details;
  625. }
  626. }
  627. if (message != null) {
  628. message = "\"" + message + "\"";
  629. }
  630. if (url != null) {
  631. url = "\"" + url + "\"";
  632. }
  633. // Set the response type
  634. response.setContentType("application/json; charset=UTF-8");
  635. final OutputStream out = response.getOutputStream();
  636. final PrintWriter outWriter = new PrintWriter(new BufferedWriter(
  637. new OutputStreamWriter(out, "UTF-8")));
  638. outWriter.print("for(;;);[{\"changes\":[], \"meta\" : {"
  639. + "\"appError\": {" + "\"caption\":" + caption + ","
  640. + "\"message\" : " + message + "," + "\"url\" : " + url
  641. + "}}, \"resources\": {}, \"locales\":[]}]");
  642. outWriter.close();
  643. }
  644. private static final Logger getLogger() {
  645. return Logger.getLogger(VaadinPortlet.class.getName());
  646. }
  647. /**
  648. * Gets the currently used Vaadin portlet. The current portlet is
  649. * automatically defined when initializing the portlet and when processing
  650. * requests to the server and in threads started at a point when the current
  651. * portlet is defined (see {@link InheritableThreadLocal}). In other cases,
  652. * (e.g. from background threads started in some other way), the current
  653. * portlet is not automatically defined.
  654. *
  655. * @return the current vaadin portlet instance if available, otherwise
  656. * <code>null</code>
  657. *
  658. * @see #setCurrent(VaadinPortlet)
  659. *
  660. * @since 7.0
  661. */
  662. public static VaadinPortlet getCurrent() {
  663. return CurrentInstance.get(VaadinPortlet.class);
  664. }
  665. /**
  666. * Sets the current Vaadin portlet. This method is used by the framework to
  667. * set the current portlet whenever a new request is processed and it is
  668. * cleared when the request has been processed.
  669. * <p>
  670. * The application developer can also use this method to define the current
  671. * portlet outside the normal request handling, e.g. when initiating custom
  672. * background threads.
  673. * </p>
  674. *
  675. * @param portlet
  676. * the Vaadin portlet to register as the current portlet
  677. *
  678. * @see #getCurrent()
  679. * @see InheritableThreadLocal
  680. */
  681. public static void setCurrent(VaadinPortlet portlet) {
  682. CurrentInstance.setInheritable(VaadinPortlet.class, portlet);
  683. }
  684. }