diff options
-rw-r--r-- | WebContent/WEB-INF/liferay-display.xml | 5 | ||||
-rw-r--r-- | WebContent/WEB-INF/portlet.xml | 44 | ||||
-rw-r--r-- | WebContent/WEB-INF/web.xml | 2 | ||||
-rw-r--r-- | build/package/WebContent/WEB-INF/web.xml | 2 | ||||
-rw-r--r-- | src/com/vaadin/Application.java | 6 | ||||
-rw-r--r-- | src/com/vaadin/service/ApplicationContext.java | 8 | ||||
-rw-r--r-- | src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java | 31 | ||||
-rw-r--r-- | src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java | 115 |
8 files changed, 177 insertions, 36 deletions
diff --git a/WebContent/WEB-INF/liferay-display.xml b/WebContent/WEB-INF/liferay-display.xml index 2981e08fd4..302f9961dd 100644 --- a/WebContent/WEB-INF/liferay-display.xml +++ b/WebContent/WEB-INF/liferay-display.xml @@ -18,6 +18,9 @@ <portlet id="AddressBookPortlet" /> <portlet id="CalcPortlet"/> <portlet id="SamplerPortlet"/> - <portlet id="HelloWorldEventPortlet"/> + <!-- + <portlet id="InterPortletEventPortlet" /> + <portlet id="VaadinInterPortletEventPortlet" /> + --> </category> </display>
\ No newline at end of file diff --git a/WebContent/WEB-INF/portlet.xml b/WebContent/WEB-INF/portlet.xml index c91bac7589..b4a40e77aa 100644 --- a/WebContent/WEB-INF/portlet.xml +++ b/WebContent/WEB-INF/portlet.xml @@ -136,33 +136,69 @@ <title>HelloWorld</title> <short-title>HelloWorld</short-title> </portlet-info> + </portlet> + + <!-- + <portlet> + <portlet-name>VaadinInterPortletEventPortlet</portlet-name> + <display-name>Hello World Event</display-name> + <portlet-class>com.vaadin.terminal.gwt.server.ApplicationPortlet2</portlet-class> + <init-param> + <name>application</name> + <value>com.vaadin.demo.portlet.VaadinInterPortletEventPortlet</value> + </init-param> + <init-param> + <name>widgetset</name> + <value>com.vaadin.demo.sampler.gwt.SamplerWidgetSet</value> + </init-param> + <supports> + <mime-type>text/html</mime-type> + <portlet-mode>view</portlet-mode> + </supports> + <portlet-info> + <title>Inter-portlet events</title> + <short-title>Inter-portlet events</short-title> + </portlet-info> <supported-processing-event> <qname xmlns:vaadin="http://www.vaadin.com/hello">vaadin:Hello</qname> </supported-processing-event> + <supported-processing-event> + <qname xmlns:vaadin="http://www.vaadin.com/hello">vaadin:ReplyToVaadin</qname> + </supported-processing-event> <supported-publishing-event> <qname xmlns:vaadin="http://www.vaadin.com/hello">vaadin:Reply</qname> </supported-publishing-event> + <supported-publishing-event> + <qname xmlns:vaadin="http://www.vaadin.com/hello">vaadin:FromVaadin</qname> + </supported-publishing-event> </portlet> <portlet> - <portlet-name>HelloWorldEventPortlet</portlet-name> + <portlet-name>InterPortletEventPortlet</portlet-name> <display-name>Hello World Event (non-Vaadin)</display-name> - <portlet-class>com.vaadin.demo.HelloWorldEventPortlet</portlet-class> + <portlet-class>com.vaadin.demo.portlet.InterPortletEventPortlet</portlet-class> <supports> <mime-type>text/html</mime-type> <portlet-mode>view</portlet-mode> </supports> <portlet-info> - <title>HelloWorldEvent (non-Vaadin)</title> - <short-title>HelloWorldEvent (non-Vaadin)</short-title> + <title>Inter-portlet events (non-Vaadin)</title> + <short-title>Inter-portlet events (non-Vaadin)</short-title> </portlet-info> <supported-processing-event> <qname xmlns:vaadin="http://www.vaadin.com/hello">vaadin:Reply</qname> </supported-processing-event> + <supported-processing-event> + <qname xmlns:vaadin="http://www.vaadin.com/hello">vaadin:FromVaadin</qname> + </supported-processing-event> <supported-publishing-event> <qname xmlns:vaadin="http://www.vaadin.com/hello">vaadin:Hello</qname> </supported-publishing-event> + <supported-publishing-event> + <qname xmlns:vaadin="http://www.vaadin.com/hello">vaadin:ReplyToVaadin</qname> + </supported-publishing-event> </portlet> + --> <portlet> <portlet-name>AddressBookPortlet</portlet-name> diff --git a/WebContent/WEB-INF/web.xml b/WebContent/WEB-INF/web.xml index ce3c2bba13..2e2c1b680e 100644 --- a/WebContent/WEB-INF/web.xml +++ b/WebContent/WEB-INF/web.xml @@ -120,7 +120,7 @@ <servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class>
<init-param>
<param-name>application</param-name>
- <param-value>com.vaadin.demo.PortletDemo</param-value>
+ <param-value>com.vaadin.demo.portlet.PortletDemo</param-value>
</init-param>
</servlet>
diff --git a/build/package/WebContent/WEB-INF/web.xml b/build/package/WebContent/WEB-INF/web.xml index f80129b810..cfbe2b41bc 100644 --- a/build/package/WebContent/WEB-INF/web.xml +++ b/build/package/WebContent/WEB-INF/web.xml @@ -149,7 +149,7 @@ <servlet-class>com.vaadin.terminal.gwt.server.ApplicationServlet</servlet-class> <init-param> <param-name>application</param-name> - <param-value>com.vaadin.demo.PortletDemo</param-value> + <param-value>com.vaadin.demo.portlet.PortletDemo</param-value> </init-param> </servlet> diff --git a/src/com/vaadin/Application.java b/src/com/vaadin/Application.java index 2b132fee64..5d10b215e4 100644 --- a/src/com/vaadin/Application.java +++ b/src/com/vaadin/Application.java @@ -722,10 +722,14 @@ public abstract class Application implements URIHandler, /** * Gets the relative uri of the resource. + * + * This method can only be called from within the processing of a UIDL + * request, not from a background thread. * * @param resource * the resource to get relative location. - * @return the relative uri of the resource. + * @return the relative uri of the resource or null if called in a + * background thread */ @Deprecated public String getRelativeLocation(ApplicationResource resource) { diff --git a/src/com/vaadin/service/ApplicationContext.java b/src/com/vaadin/service/ApplicationContext.java index ab201a4bd4..3d2c76c8d0 100644 --- a/src/com/vaadin/service/ApplicationContext.java +++ b/src/com/vaadin/service/ApplicationContext.java @@ -71,6 +71,10 @@ public interface ApplicationContext extends Serializable { * Generate a URL that can be used as the relative location of e.g. an * {@link ApplicationResource}. * + * This method should only be called from the processing of a UIDL request, + * not from a background thread. The return value is null if used outside a + * suitable request. + * * @deprecated this is subject to change/removal from the interface * * @param resource @@ -84,7 +88,7 @@ public interface ApplicationContext extends Serializable { /** * Tests if a URL is for an application resource (APP/...). - * + * * @deprecated this is subject to change/removal from the interface * * @param context @@ -99,7 +103,7 @@ public interface ApplicationContext extends Serializable { * the one that was given to * {@link #generateApplicationResourceURL(ApplicationResource, String)} when * creating the URL. - * + * * @deprecated this is subject to change/removal from the interface * * @param context diff --git a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java index 5c1396b449..9a5f4f0fb0 100644 --- a/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java +++ b/src/com/vaadin/terminal/gwt/server/AbstractApplicationPortlet.java @@ -49,7 +49,7 @@ import com.vaadin.ui.Window; /** * TODO Document me! - * + * * @author peholmst */ public abstract class AbstractApplicationPortlet extends GenericPortlet @@ -128,7 +128,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet /** * Gets an application property value. - * + * * @param parameterName * the Name or the parameter. * @return String value or null if not found @@ -149,7 +149,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet /** * Gets an system property value. - * + * * @param parameterName * the Name or the parameter. * @return String value or null if not found @@ -178,7 +178,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet /** * Gets an application or system property value. - * + * * @param parameterName * the Name or the parameter. * @param defaultValue @@ -209,7 +209,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet * Return the URL from where static files, e.g. the widgetset and the theme, * are served. In a standard configuration the VAADIN folder inside the * returned folder is what is used for widgetsets and themes. - * + * * @param request * @return The location of static resources (inside which there should be a * VAADIN directory). Does not end with a slash (/). @@ -233,7 +233,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } enum RequestType { - FILE_UPLOAD, UIDL, RENDER, STATIC_FILE, APPLICATION_RESOURCE, DUMMY, EVENT, UNKNOWN; + FILE_UPLOAD, UIDL, RENDER, STATIC_FILE, APPLICATION_RESOURCE, DUMMY, EVENT, ACTION, UNKNOWN; } protected RequestType getRequestType(PortletRequest request) { @@ -252,6 +252,9 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } else if (request instanceof ActionRequest) { if (isFileUploadRequest((ActionRequest) request)) { return RequestType.FILE_UPLOAD; + } else { + // action other than upload + return RequestType.ACTION; } } else if (request instanceof EventRequest) { return RequestType.EVENT; @@ -281,7 +284,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet /** * Returns true if the servlet is running in production mode. Production * mode disables all debug facilities. - * + * * @return true if in production mode, false if in debug mode */ public boolean isProductionMode() { @@ -331,9 +334,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet */ PortletApplicationContext2 applicationContext = PortletApplicationContext2 .getApplicationContext(request.getPortletSession()); - if (response instanceof MimeResponse) { - applicationContext.setMimeResponse((MimeResponse) response); - } + applicationContext.setResponse(response); PortletCommunicationManager applicationManager = applicationContext .getApplicationManager(application); @@ -445,6 +446,10 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet } else if (requestType == RequestType.RENDER) { writeAjaxPage((RenderRequest) request, (RenderResponse) response, window, application); + } else if (requestType == RequestType.EVENT) { + // nothing to do, listeners do all the work + } else if (requestType == RequestType.ACTION) { + // nothing to do, listeners do all the work } else { throw new IllegalStateException( "handleRequest() without anything to do - should never happen!"); @@ -929,7 +934,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet /** * Returns the theme for given request/window - * + * * @param request * @param window * @return @@ -980,7 +985,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet /** * Get system messages from the current application class - * + * * @return */ protected SystemMessages getSystemMessages() { @@ -1053,7 +1058,7 @@ public abstract class AbstractApplicationPortlet extends GenericPortlet * Send notification to client's application. Used to notify client of * critical errors and session expiration due to long inactivity. Server has * no knowledge of what application client refers to. - * + * * @param request * the Portlet request instance. * @param response diff --git a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java index 3af45acfaf..f6217774e2 100644 --- a/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java +++ b/src/com/vaadin/terminal/gwt/server/PortletApplicationContext2.java @@ -13,16 +13,22 @@ import javax.portlet.ActionResponse; import javax.portlet.EventRequest; import javax.portlet.EventResponse; import javax.portlet.MimeResponse; +import javax.portlet.PortletResponse; import javax.portlet.PortletSession; +import javax.portlet.PortletURL; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; import javax.portlet.ResourceRequest; import javax.portlet.ResourceResponse; import javax.portlet.ResourceURL; +import javax.portlet.StateAwareResponse; import javax.servlet.http.HttpSessionBindingListener; +import javax.xml.namespace.QName; import com.vaadin.Application; import com.vaadin.terminal.ApplicationResource; +import com.vaadin.terminal.ExternalResource; +import com.vaadin.ui.Window; /** * TODO Write documentation, fix JavaDoc tags. @@ -41,7 +47,10 @@ public class PortletApplicationContext2 extends AbstractWebApplicationContext { protected HashMap<String, Application> portletWindowIdToApplicationMap = new HashMap<String, Application>(); - private MimeResponse mimeResponse; + private PortletResponse response; + + private Map<String, QName> eventActionDestinationMap = new HashMap<String, QName>(); + private Map<String, Serializable> eventActionValueMap = new HashMap<String, Serializable>(); public File getBaseDirectory() { String resultPath = session.getPortletContext().getRealPath("/"); @@ -137,10 +146,20 @@ public class PortletApplicationContext2 extends AbstractWebApplicationContext { public void firePortletActionRequest(Application app, ActionRequest request, ActionResponse response) { - Set<PortletListener> listeners = portletListeners.get(app); - if (listeners != null) { - for (PortletListener l : listeners) { - l.handleActionRequest(request, response); + String key = request.getParameter(ActionRequest.ACTION_NAME); + if (eventActionDestinationMap.containsKey(key)) { + // this action request is only to send queued portlet events + response.setEvent(eventActionDestinationMap.get(key), eventActionValueMap + .get(key)); + // cleanup + eventActionDestinationMap.remove(key); + eventActionValueMap.remove(key); + } else { + Set<PortletListener> listeners = portletListeners.get(app); + if (listeners != null) { + for (PortletListener l : listeners) { + l.handleActionRequest(request, response); + } } } } @@ -187,22 +206,92 @@ public class PortletApplicationContext2 extends AbstractWebApplicationContext { * * @param mimeResponse */ - void setMimeResponse(MimeResponse mimeResponse) { - this.mimeResponse = mimeResponse; + void setResponse(PortletResponse response) { + this.response = response; } @Override public String generateApplicationResourceURL( ApplicationResource resource, String mapKey) { - ResourceURL resourceURL = mimeResponse.createResourceURL(); - final String filename = resource.getFilename(); - if (filename == null) { - resourceURL.setResourceID("APP/" + mapKey + "/"); + if (response instanceof MimeResponse) { + ResourceURL resourceURL = ((MimeResponse) response) + .createResourceURL(); + final String filename = resource.getFilename(); + if (filename == null) { + resourceURL.setResourceID("APP/" + mapKey + "/"); + } else { + resourceURL.setResourceID("APP/" + mapKey + "/" + filename); + } + return resourceURL.toString(); + } else { + // in a background thread or otherwise outside a request + return null; + } + } + + /** + * Creates a new action URL. + * + * @param action + * @return action URL or null if called outside a MimeRequest (outside a + * UIDL request or similar) + */ + public PortletURL generateActionURL(String action) { + PortletURL url = null; + if (response instanceof MimeResponse) { + url = ((MimeResponse) response).createActionURL(); + url.setParameter("javax.portlet.action", action); } else { - resourceURL.setResourceID("APP/" + mapKey + "/" + filename); + return null; } - return resourceURL.toString(); + return url; } + /** + * Sends a portlet event to the indicated destination. + * + * Internally, an action may be created and opened, as an event cannot be + * sent directly from all types of requests. + * + * The event destinations and values need to be kept in the context until + * sent. Any memory leaks if the action fails are limited to the session. + * + * Event names for events sent and received by a portlet need to be declared + * in portlet.xml . + * + * @param window + * a window in which a temporary action URL can be opened if + * necessary + * @param name + * event name + * @param value + * event value object that is Serializable and, if appropriate, + * has a valid JAXB annotation + */ + public void sendPortletEvent(Window window, QName name, Serializable value) + throws IllegalStateException { + if (response instanceof MimeResponse) { + String actionKey = "" + System.currentTimeMillis(); + while (eventActionDestinationMap.containsKey(actionKey)) { + actionKey = actionKey + "."; + } + PortletURL actionUrl = generateActionURL(actionKey); + if (actionUrl != null) { + eventActionDestinationMap.put(actionKey, name); + eventActionValueMap.put(actionKey, value); + window.open(new ExternalResource(actionUrl.toString())); + } else { + // this should never happen as we already know the response is a + // MimeResponse + throw new IllegalStateException( + "Portlet events can only be sent from a portlet request"); + } + } else if (response instanceof StateAwareResponse) { + ((StateAwareResponse) response).setEvent(name, value); + } else { + throw new IllegalStateException( + "Portlet events can only be sent from a portlet request"); + } + } } |