Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

PortletApplicationContext2.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. package com.vaadin.terminal.gwt.server;
  2. import java.io.File;
  3. import java.io.Serializable;
  4. import java.net.URL;
  5. import java.util.HashMap;
  6. import java.util.LinkedHashSet;
  7. import java.util.Map;
  8. import java.util.Set;
  9. import javax.portlet.ActionRequest;
  10. import javax.portlet.ActionResponse;
  11. import javax.portlet.EventRequest;
  12. import javax.portlet.EventResponse;
  13. import javax.portlet.MimeResponse;
  14. import javax.portlet.PortletMode;
  15. import javax.portlet.PortletModeException;
  16. import javax.portlet.PortletResponse;
  17. import javax.portlet.PortletSession;
  18. import javax.portlet.PortletURL;
  19. import javax.portlet.RenderRequest;
  20. import javax.portlet.RenderResponse;
  21. import javax.portlet.ResourceRequest;
  22. import javax.portlet.ResourceResponse;
  23. import javax.portlet.ResourceURL;
  24. import javax.portlet.StateAwareResponse;
  25. import javax.servlet.http.HttpSessionBindingListener;
  26. import javax.xml.namespace.QName;
  27. import com.vaadin.Application;
  28. import com.vaadin.terminal.ApplicationResource;
  29. import com.vaadin.terminal.ExternalResource;
  30. import com.vaadin.ui.Window;
  31. /**
  32. * TODO Write documentation, fix JavaDoc tags.
  33. *
  34. * This is automatically registered as a {@link HttpSessionBindingListener} when
  35. * {@link PortletSession#setAttribute()} is called with the context as value.
  36. *
  37. * @author peholmst
  38. */
  39. @SuppressWarnings("serial")
  40. public class PortletApplicationContext2 extends AbstractWebApplicationContext {
  41. protected Map<Application, Set<PortletListener>> portletListeners = new HashMap<Application, Set<PortletListener>>();
  42. protected transient PortletSession session;
  43. protected HashMap<String, Application> portletWindowIdToApplicationMap = new HashMap<String, Application>();
  44. private PortletResponse response;
  45. private Map<String, QName> eventActionDestinationMap = new HashMap<String, QName>();
  46. private Map<String, Serializable> eventActionValueMap = new HashMap<String, Serializable>();
  47. private Map<String, String> sharedParameterActionNameMap = new HashMap<String, String>();
  48. private Map<String, String> sharedParameterActionValueMap = new HashMap<String, String>();
  49. public File getBaseDirectory() {
  50. String resultPath = session.getPortletContext().getRealPath("/");
  51. if (resultPath != null) {
  52. return new File(resultPath);
  53. } else {
  54. try {
  55. final URL url = session.getPortletContext().getResource("/");
  56. return new File(url.getFile());
  57. } catch (final Exception e) {
  58. // FIXME: Handle exception
  59. e.printStackTrace();
  60. }
  61. }
  62. return null;
  63. }
  64. protected PortletCommunicationManager getApplicationManager(
  65. Application application) {
  66. PortletCommunicationManager mgr = (PortletCommunicationManager) applicationToAjaxAppMgrMap
  67. .get(application);
  68. if (mgr == null) {
  69. // Creates a new manager
  70. mgr = new PortletCommunicationManager(application);
  71. applicationToAjaxAppMgrMap.put(application, mgr);
  72. }
  73. return mgr;
  74. }
  75. public static PortletApplicationContext2 getApplicationContext(
  76. PortletSession session) {
  77. PortletApplicationContext2 cx = (PortletApplicationContext2) session
  78. .getAttribute(PortletApplicationContext2.class.getName());
  79. if (cx == null) {
  80. cx = new PortletApplicationContext2();
  81. session
  82. .setAttribute(PortletApplicationContext2.class.getName(),
  83. cx);
  84. }
  85. if (cx.session == null) {
  86. cx.session = session;
  87. }
  88. return cx;
  89. }
  90. @Override
  91. protected void removeApplication(Application application) {
  92. super.removeApplication(application);
  93. // values() is backed by map, removes the key-value pair from the map
  94. portletWindowIdToApplicationMap.values().remove(application);
  95. }
  96. protected void addApplication(Application application,
  97. String portletWindowId) {
  98. applications.add(application);
  99. portletWindowIdToApplicationMap.put(portletWindowId, application);
  100. }
  101. public Application getApplicationForWindowId(String portletWindowId) {
  102. return portletWindowIdToApplicationMap.get(portletWindowId);
  103. }
  104. public PortletSession getPortletSession() {
  105. return session;
  106. }
  107. public void addPortletListener(Application app, PortletListener listener) {
  108. Set<PortletListener> l = portletListeners.get(app);
  109. if (l == null) {
  110. l = new LinkedHashSet<PortletListener>();
  111. portletListeners.put(app, l);
  112. }
  113. l.add(listener);
  114. }
  115. public void removePortletListener(Application app, PortletListener listener) {
  116. Set<PortletListener> l = portletListeners.get(app);
  117. if (l != null) {
  118. l.remove(listener);
  119. }
  120. }
  121. public void firePortletRenderRequest(Application app,
  122. RenderRequest request, RenderResponse response) {
  123. Set<PortletListener> listeners = portletListeners.get(app);
  124. if (listeners != null) {
  125. for (PortletListener l : listeners) {
  126. l.handleRenderRequest(request, new RestrictedRenderResponse(
  127. response));
  128. }
  129. }
  130. }
  131. public void firePortletActionRequest(Application app,
  132. ActionRequest request, ActionResponse response) {
  133. String key = request.getParameter(ActionRequest.ACTION_NAME);
  134. if (eventActionDestinationMap.containsKey(key)) {
  135. // this action request is only to send queued portlet events
  136. response.setEvent(eventActionDestinationMap.get(key),
  137. eventActionValueMap.get(key));
  138. // cleanup
  139. eventActionDestinationMap.remove(key);
  140. eventActionValueMap.remove(key);
  141. } else if (sharedParameterActionNameMap.containsKey(key)) {
  142. // this action request is only to set shared render parameters
  143. response.setRenderParameter(sharedParameterActionNameMap.get(key),
  144. sharedParameterActionValueMap.get(key));
  145. // cleanup
  146. sharedParameterActionNameMap.remove(key);
  147. sharedParameterActionValueMap.remove(key);
  148. } else {
  149. // normal action request, notify listeners
  150. Set<PortletListener> listeners = portletListeners.get(app);
  151. if (listeners != null) {
  152. for (PortletListener l : listeners) {
  153. l.handleActionRequest(request, response);
  154. }
  155. }
  156. }
  157. }
  158. public void firePortletEventRequest(Application app, EventRequest request,
  159. EventResponse response) {
  160. Set<PortletListener> listeners = portletListeners.get(app);
  161. if (listeners != null) {
  162. for (PortletListener l : listeners) {
  163. l.handleEventRequest(request, response);
  164. }
  165. }
  166. }
  167. public void firePortletResourceRequest(Application app,
  168. ResourceRequest request, ResourceResponse response) {
  169. Set<PortletListener> listeners = portletListeners.get(app);
  170. if (listeners != null) {
  171. for (PortletListener l : listeners) {
  172. l.handleResourceRequest(request, response);
  173. }
  174. }
  175. }
  176. public interface PortletListener extends Serializable {
  177. public void handleRenderRequest(RenderRequest request,
  178. RenderResponse response);
  179. public void handleActionRequest(ActionRequest request,
  180. ActionResponse response);
  181. public void handleEventRequest(EventRequest request,
  182. EventResponse response);
  183. public void handleResourceRequest(ResourceRequest request,
  184. ResourceResponse response);
  185. }
  186. /**
  187. * This is for use by {@link AbstractApplicationPortlet} only.
  188. *
  189. * TODO cleaner implementation, now "semi-static"!
  190. *
  191. * @param mimeResponse
  192. */
  193. void setResponse(PortletResponse response) {
  194. this.response = response;
  195. }
  196. @Override
  197. public String generateApplicationResourceURL(ApplicationResource resource,
  198. String mapKey) {
  199. if (response instanceof MimeResponse) {
  200. ResourceURL resourceURL = ((MimeResponse) response)
  201. .createResourceURL();
  202. final String filename = resource.getFilename();
  203. if (filename == null) {
  204. resourceURL.setResourceID("APP/" + mapKey + "/");
  205. } else {
  206. resourceURL.setResourceID("APP/" + mapKey + "/" + filename);
  207. }
  208. return resourceURL.toString();
  209. } else {
  210. // in a background thread or otherwise outside a request
  211. return null;
  212. }
  213. }
  214. /**
  215. * Creates a new action URL.
  216. *
  217. * @param action
  218. * @return action URL or null if called outside a MimeRequest (outside a
  219. * UIDL request or similar)
  220. */
  221. public PortletURL generateActionURL(String action) {
  222. PortletURL url = null;
  223. if (response instanceof MimeResponse) {
  224. url = ((MimeResponse) response).createActionURL();
  225. url.setParameter("javax.portlet.action", action);
  226. } else {
  227. return null;
  228. }
  229. return url;
  230. }
  231. /**
  232. * Sends a portlet event to the indicated destination.
  233. *
  234. * Internally, an action may be created and opened, as an event cannot be
  235. * sent directly from all types of requests.
  236. *
  237. * The event destinations and values need to be kept in the context until
  238. * sent. Any memory leaks if the action fails are limited to the session.
  239. *
  240. * Event names for events sent and received by a portlet need to be declared
  241. * in portlet.xml .
  242. *
  243. * @param window
  244. * a window in which a temporary action URL can be opened if
  245. * necessary
  246. * @param name
  247. * event name
  248. * @param value
  249. * event value object that is Serializable and, if appropriate,
  250. * has a valid JAXB annotation
  251. */
  252. public void sendPortletEvent(Window window, QName name, Serializable value)
  253. throws IllegalStateException {
  254. if (response instanceof MimeResponse) {
  255. String actionKey = "" + System.currentTimeMillis();
  256. while (eventActionDestinationMap.containsKey(actionKey)) {
  257. actionKey = actionKey + ".";
  258. }
  259. PortletURL actionUrl = generateActionURL(actionKey);
  260. if (actionUrl != null) {
  261. eventActionDestinationMap.put(actionKey, name);
  262. eventActionValueMap.put(actionKey, value);
  263. window.open(new ExternalResource(actionUrl.toString()));
  264. } else {
  265. // this should never happen as we already know the response is a
  266. // MimeResponse
  267. throw new IllegalStateException(
  268. "Portlet events can only be sent from a portlet request");
  269. }
  270. } else if (response instanceof StateAwareResponse) {
  271. ((StateAwareResponse) response).setEvent(name, value);
  272. } else {
  273. throw new IllegalStateException(
  274. "Portlet events can only be sent from a portlet request");
  275. }
  276. }
  277. /**
  278. * Sets a shared portlet parameter.
  279. *
  280. * Internally, an action may be created and opened, as shared parameters
  281. * cannot be set directly from all types of requests.
  282. *
  283. * The parameters and values need to be kept in the context until sent. Any
  284. * memory leaks if the action fails are limited to the session.
  285. *
  286. * Shared parameters set or read by a portlet need to be declared in
  287. * portlet.xml .
  288. *
  289. * @param window
  290. * a window in which a temporary action URL can be opened if
  291. * necessary
  292. * @param name
  293. * parameter identifier
  294. * @param value
  295. * parameter value
  296. */
  297. public void setSharedRenderParameter(Window window, String name,
  298. String value) throws IllegalStateException {
  299. if (response instanceof MimeResponse) {
  300. String actionKey = "" + System.currentTimeMillis();
  301. while (sharedParameterActionNameMap.containsKey(actionKey)) {
  302. actionKey = actionKey + ".";
  303. }
  304. PortletURL actionUrl = generateActionURL(actionKey);
  305. if (actionUrl != null) {
  306. sharedParameterActionNameMap.put(actionKey, name);
  307. sharedParameterActionValueMap.put(actionKey, value);
  308. window.open(new ExternalResource(actionUrl.toString()));
  309. } else {
  310. // this should never happen as we already know the response is a
  311. // MimeResponse
  312. throw new IllegalStateException(
  313. "Shared parameters can only be set from a portlet request");
  314. }
  315. } else if (response instanceof StateAwareResponse) {
  316. ((StateAwareResponse) response).setRenderParameter(name, value);
  317. } else {
  318. throw new IllegalStateException(
  319. "Shared parameters can only be set from a portlet request");
  320. }
  321. }
  322. /**
  323. * Sets the portlet mode. This may trigger a new render request.
  324. *
  325. * Portlet modes used by a portlet need to be declared in portlet.xml .
  326. *
  327. * @param window
  328. * a window in which the render URL can be opened if necessary
  329. * @param portletMode
  330. * the portlet mode to switch to
  331. * @throws PortletModeException
  332. * if the portlet mode is not allowed for some reason
  333. * (configuration, permissions etc.)
  334. */
  335. public void setPortletMode(Window window, PortletMode portletMode)
  336. throws IllegalStateException, PortletModeException {
  337. if (response instanceof MimeResponse) {
  338. PortletURL url = ((MimeResponse) response).createRenderURL();
  339. url.setPortletMode(portletMode);
  340. window.open(new ExternalResource(url.toString()));
  341. } else if (response instanceof StateAwareResponse) {
  342. ((StateAwareResponse) response).setPortletMode(portletMode);
  343. } else {
  344. throw new IllegalStateException(
  345. "Portlet mode can only be changed from a portlet request");
  346. }
  347. }
  348. }