You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

VaadinPortletService.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. /*
  2. * Copyright 2000-2018 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 static com.vaadin.shared.util.SharedUtil.trimTrailingSlashes;
  18. import java.io.File;
  19. import java.io.InputStream;
  20. import java.net.URL;
  21. import java.util.List;
  22. import java.util.concurrent.locks.Lock;
  23. import java.util.concurrent.locks.ReentrantLock;
  24. import java.util.logging.Level;
  25. import java.util.logging.Logger;
  26. import javax.portlet.EventRequest;
  27. import javax.portlet.PortletContext;
  28. import javax.portlet.PortletRequest;
  29. import javax.portlet.PortletSession;
  30. import javax.portlet.RenderRequest;
  31. import com.vaadin.server.VaadinPortlet.RequestType;
  32. import com.vaadin.server.communication.PortletBootstrapHandler;
  33. import com.vaadin.server.communication.PortletDummyRequestHandler;
  34. import com.vaadin.server.communication.PortletListenerNotifier;
  35. import com.vaadin.server.communication.PortletStateAwareRequestHandler;
  36. import com.vaadin.server.communication.PortletUIInitHandler;
  37. import com.vaadin.ui.UI;
  38. public class VaadinPortletService extends VaadinService {
  39. private final VaadinPortlet portlet;
  40. public VaadinPortletService(VaadinPortlet portlet,
  41. DeploymentConfiguration deploymentConfiguration)
  42. throws ServiceException {
  43. super(deploymentConfiguration);
  44. this.portlet = portlet;
  45. }
  46. @Override
  47. protected List<RequestHandler> createRequestHandlers()
  48. throws ServiceException {
  49. List<RequestHandler> handlers = super.createRequestHandlers();
  50. handlers.add(new PortletUIInitHandler());
  51. handlers.add(new PortletListenerNotifier());
  52. handlers.add(0, new PortletDummyRequestHandler());
  53. handlers.add(0, new PortletBootstrapHandler());
  54. handlers.add(0, new PortletStateAwareRequestHandler());
  55. return handlers;
  56. }
  57. /**
  58. * Retrieves a reference to the portlet associated with this service.
  59. *
  60. * @return A reference to the VaadinPortlet this service is using
  61. */
  62. public VaadinPortlet getPortlet() {
  63. return portlet;
  64. }
  65. private String getParameter(VaadinRequest request, String name,
  66. String defaultValue) {
  67. VaadinPortletRequest portletRequest = (VaadinPortletRequest) request;
  68. String preference = portletRequest.getPortletPreference(name);
  69. if (preference != null) {
  70. return preference;
  71. }
  72. String appOrSystemProperty = getAppOrSystemProperty(name, null);
  73. if (appOrSystemProperty != null) {
  74. return appOrSystemProperty;
  75. }
  76. String portalProperty = portletRequest.getPortalProperty(name);
  77. if (portalProperty != null) {
  78. // For backwards compatibility - automatically map old portal
  79. // default widget set to default widget set
  80. if (name.equals(Constants.PORTAL_PARAMETER_VAADIN_WIDGETSET)) {
  81. return mapDefaultWidgetset(portalProperty);
  82. }
  83. return portalProperty;
  84. }
  85. return defaultValue;
  86. }
  87. private String getAppOrSystemProperty(String name, String defaultValue) {
  88. DeploymentConfiguration deploymentConfiguration = getDeploymentConfiguration();
  89. return deploymentConfiguration.getApplicationOrSystemProperty(name,
  90. defaultValue);
  91. }
  92. @Override
  93. public String getConfiguredWidgetset(VaadinRequest request) {
  94. String widgetset = getDeploymentConfiguration().getWidgetset(null);
  95. if (widgetset == null) {
  96. widgetset = getParameter(request,
  97. Constants.PORTAL_PARAMETER_VAADIN_WIDGETSET,
  98. Constants.DEFAULT_WIDGETSET);
  99. }
  100. return widgetset;
  101. }
  102. private String mapDefaultWidgetset(String widgetset) {
  103. if ("com.vaadin.portal.gwt.PortalDefaultWidgetSet".equals(widgetset)) {
  104. return Constants.DEFAULT_WIDGETSET;
  105. }
  106. return widgetset;
  107. }
  108. @Override
  109. public String getConfiguredTheme(VaadinRequest request) {
  110. return getParameter(request, Constants.PORTAL_PARAMETER_VAADIN_THEME,
  111. Constants.DEFAULT_THEME_NAME);
  112. }
  113. @Override
  114. public boolean isStandalone(VaadinRequest request) {
  115. return false;
  116. }
  117. @Override
  118. public String getStaticFileLocation(VaadinRequest request) {
  119. // /html is default for Liferay
  120. String staticFileLocation = getParameter(request,
  121. Constants.PORTAL_PARAMETER_VAADIN_RESOURCE_PATH, "/html");
  122. if (Constants.PORTLET_CONTEXT.equals(staticFileLocation)) {
  123. return request.getContextPath();
  124. } else {
  125. return trimTrailingSlashes(staticFileLocation);
  126. }
  127. }
  128. private PortletContext getPortletContext() {
  129. return getPortlet().getPortletContext();
  130. }
  131. @Override
  132. public String getMimeType(String resourceName) {
  133. return getPortletContext().getMimeType(resourceName);
  134. }
  135. @Override
  136. public File getBaseDirectory() {
  137. PortletContext context = getPortletContext();
  138. String resultPath = context.getRealPath("/");
  139. if (resultPath != null) {
  140. return new File(resultPath);
  141. } else {
  142. try {
  143. final URL url = context.getResource("/");
  144. return new File(url.getFile());
  145. } catch (final Exception e) {
  146. // FIXME: Handle exception
  147. getLogger().log(Level.INFO,
  148. "Cannot access base directory, possible security issue "
  149. + "with Application Server or Servlet Container",
  150. e);
  151. }
  152. }
  153. return null;
  154. }
  155. private static final Logger getLogger() {
  156. return Logger.getLogger(VaadinPortletService.class.getName());
  157. }
  158. @Override
  159. protected boolean requestCanCreateSession(VaadinRequest request) {
  160. if (!(request instanceof VaadinPortletRequest)) {
  161. throw new IllegalArgumentException(
  162. "Request is not a VaadinPortletRequest");
  163. }
  164. PortletRequest portletRequest = ((VaadinPortletRequest) request)
  165. .getPortletRequest();
  166. if (portletRequest instanceof RenderRequest) {
  167. // In most cases the first request is a render request that
  168. // renders the HTML fragment. This should create a Vaadin
  169. // session unless there is already one.
  170. return true;
  171. } else if (portletRequest instanceof EventRequest) {
  172. // A portlet can also be sent an event even though it has not
  173. // been rendered, e.g. portlet on one page sends an event to a
  174. // portlet on another page and then moves the user to that page.
  175. return true;
  176. } else if (PortletUIInitHandler.isUIInitRequest(request)) {
  177. // In some cases, the RenderRequest seems to be cached, causing the
  178. // first request be the one triggered by vaadinBootstrap.js.
  179. return true;
  180. }
  181. return false;
  182. }
  183. /**
  184. * Gets the request type for the request.
  185. *
  186. * @param request
  187. * the request to get a request type for
  188. * @return the request type
  189. *
  190. * @deprecated As of 7.0. Will likely change or be removed in a future
  191. * version
  192. */
  193. @Deprecated
  194. protected RequestType getRequestType(VaadinRequest request) {
  195. RequestType type = (RequestType) request
  196. .getAttribute(RequestType.class.getName());
  197. if (type == null) {
  198. type = getPortlet().getRequestType((VaadinPortletRequest) request);
  199. request.setAttribute(RequestType.class.getName(), type);
  200. }
  201. return type;
  202. }
  203. /**
  204. * Gets the currently processed portlet request. The current portlet request
  205. * is automatically defined when the request is started. The current portlet
  206. * request can not be used in e.g. background threads because of the way
  207. * server implementations reuse request instances.
  208. *
  209. * @return the current portlet request instance if available, otherwise
  210. * <code>null</code>
  211. *
  212. */
  213. public static PortletRequest getCurrentPortletRequest() {
  214. VaadinPortletRequest currentRequest = getCurrentRequest();
  215. if (currentRequest != null) {
  216. return currentRequest.getPortletRequest();
  217. } else {
  218. return null;
  219. }
  220. }
  221. /**
  222. * Gets the currently processed Vaadin portlet request. The current request
  223. * is automatically defined when the request is started. The current request
  224. * can not be used in e.g. background threads because of the way server
  225. * implementations reuse request instances.
  226. *
  227. * @return the current Vaadin portlet request instance if available,
  228. * otherwise <code>null</code>
  229. *
  230. */
  231. public static VaadinPortletRequest getCurrentRequest() {
  232. return (VaadinPortletRequest) VaadinService.getCurrentRequest();
  233. }
  234. /**
  235. * Gets the currently processed Vaadin portlet response. The current
  236. * response is automatically defined when the request is started. The
  237. * current response can not be used in e.g. background threads because of
  238. * the way server implementations reuse response instances.
  239. *
  240. * @return the current Vaadin portlet response instance if available,
  241. * otherwise <code>null</code>
  242. *
  243. */
  244. public static VaadinPortletResponse getCurrentResponse() {
  245. return (VaadinPortletResponse) VaadinService.getCurrentResponse();
  246. }
  247. @Override
  248. protected VaadinSession createVaadinSession(VaadinRequest request)
  249. throws ServiceException {
  250. return new VaadinPortletSession(this);
  251. }
  252. @Override
  253. public String getServiceName() {
  254. return getPortlet().getPortletName();
  255. }
  256. /**
  257. * Always preserve UIs in portlets to make portlet actions work.
  258. */
  259. @Override
  260. public boolean preserveUIOnRefresh(UIProvider provider,
  261. UICreateEvent event) {
  262. return true;
  263. }
  264. @Override
  265. public InputStream getThemeResourceAsStream(UI uI, String themeName,
  266. String resource) {
  267. VaadinPortletSession session = (VaadinPortletSession) uI.getSession();
  268. PortletContext portletContext = session.getPortletSession()
  269. .getPortletContext();
  270. return portletContext
  271. .getResourceAsStream("/" + VaadinPortlet.THEME_DIR_PATH + '/'
  272. + themeName + "/" + resource);
  273. }
  274. @Override
  275. public String getMainDivId(VaadinSession session, VaadinRequest request,
  276. Class<? extends UI> uiClass) {
  277. PortletRequest portletRequest = ((VaadinPortletRequest) request)
  278. .getPortletRequest();
  279. /*
  280. * We need to generate a unique ID because some portals already create a
  281. * DIV with the portlet's Window ID as the DOM ID.
  282. */
  283. return "v-" + portletRequest.getWindowID();
  284. }
  285. /*
  286. * (non-Javadoc)
  287. *
  288. * @see
  289. * com.vaadin.server.VaadinService#handleSessionExpired(com.vaadin.server
  290. * .VaadinRequest, com.vaadin.server.VaadinResponse)
  291. */
  292. @Override
  293. protected void handleSessionExpired(VaadinRequest request,
  294. VaadinResponse response) {
  295. // TODO Figure out a better way to deal with
  296. // SessionExpiredExceptions
  297. getLogger().finest("A user session has expired");
  298. }
  299. private WrappedPortletSession getWrappedPortletSession(
  300. WrappedSession wrappedSession) {
  301. return (WrappedPortletSession) wrappedSession;
  302. }
  303. @Override
  304. protected void writeToHttpSession(WrappedSession wrappedSession,
  305. VaadinSession session) {
  306. getWrappedPortletSession(wrappedSession).setAttribute(
  307. getSessionAttributeName(), session,
  308. PortletSession.APPLICATION_SCOPE);
  309. }
  310. @Override
  311. protected VaadinSession readFromHttpSession(WrappedSession wrappedSession) {
  312. return (VaadinSession) getWrappedPortletSession(wrappedSession)
  313. .getAttribute(getSessionAttributeName(),
  314. PortletSession.APPLICATION_SCOPE);
  315. }
  316. @Override
  317. protected void removeFromHttpSession(WrappedSession wrappedSession) {
  318. getWrappedPortletSession(wrappedSession).removeAttribute(
  319. getSessionAttributeName(), PortletSession.APPLICATION_SCOPE);
  320. }
  321. @Override
  322. protected void setSessionLock(WrappedSession wrappedSession, Lock lock) {
  323. if (wrappedSession == null) {
  324. throw new IllegalArgumentException(
  325. "Can't set a lock for a null session");
  326. }
  327. Object currentSessionLock = getWrappedPortletSession(wrappedSession)
  328. .getAttribute(getLockAttributeName(),
  329. PortletSession.APPLICATION_SCOPE);
  330. assert (currentSessionLock == null
  331. || currentSessionLock == lock) : "Changing the lock for a session is not allowed";
  332. getWrappedPortletSession(wrappedSession).setAttribute(
  333. getLockAttributeName(), lock,
  334. PortletSession.APPLICATION_SCOPE);
  335. }
  336. @Override
  337. protected Lock getSessionLock(WrappedSession wrappedSession) {
  338. Object lock = getWrappedPortletSession(wrappedSession)
  339. .getAttribute(getLockAttributeName(),
  340. PortletSession.APPLICATION_SCOPE);
  341. if (lock instanceof ReentrantLock) {
  342. return (ReentrantLock) lock;
  343. }
  344. if (lock == null) {
  345. return null;
  346. }
  347. throw new RuntimeException(
  348. "Something else than a ReentrantLock was stored in the "
  349. + getLockAttributeName() + " in the session");
  350. }
  351. }