*/
private URL applicationUrl;
- /**
- * The ID of the portlet window that this application runs in.
- */
- private String portletWindowId;
-
/**
* Name of the theme currently used by the application.
*/
*/
private Terminal.ErrorListener errorHandler = this;
- // TODO Document me!
- public String getPortletWindowId() {
- return portletWindowId;
- }
-
- // TODO Document me!
- public void setPortletWindowId(String portletWindowId) {
- this.portletWindowId = portletWindowId;
- }
-
- // TODO Document me!
- @Deprecated
- public static interface ResourceURLGenerator extends Serializable {
-
- public String generateResourceURL(ApplicationResource resource,
- String mapKey);
-
- public boolean isResourceURL(URL context, String relativeUri);
-
- public String getMapKey(URL context, String relativeUri);
-
- }
-
- /*
- * Default resource URL generator for servlets
- */
- @Deprecated
- private static ResourceURLGenerator defaultResourceURLGenerator = new ResourceURLGenerator() {
- public String generateResourceURL(ApplicationResource resource,
- String mapKey) {
-
- final String filename = resource.getFilename();
- if (filename == null) {
- return "APP/" + mapKey + "/";
- } else {
- return "APP/" + mapKey + "/" + filename;
- }
-
- }
-
- public boolean isResourceURL(URL context, String relativeUri) {
- // If the relative uri is null, we are ready
- if (relativeUri == null) {
- return false;
- }
-
- // Resolves the prefix
- String prefix = relativeUri;
- final int index = relativeUri.indexOf('/');
- if (index >= 0) {
- prefix = relativeUri.substring(0, index);
- }
-
- // Handles the resource requests
- return (prefix.equals("APP"));
- }
-
- public String getMapKey(URL context, String relativeUri) {
- final int index = relativeUri.indexOf('/');
- final int next = relativeUri.indexOf('/', index + 1);
- if (next < 0) {
- return null;
- }
- return relativeUri.substring(index + 1, next);
- };
-
- };
-
- @Deprecated
- private ResourceURLGenerator resourceURLGenerator = defaultResourceURLGenerator;
-
- @Deprecated
- public ResourceURLGenerator getResourceURLGenerator() {
- return resourceURLGenerator;
- }
-
- @Deprecated
- public void setResourceURLGenerator(
- ResourceURLGenerator resourceURLGenerator) {
- if (resourceURLGenerator == null) {
- this.resourceURLGenerator = defaultResourceURLGenerator;
- } else {
- this.resourceURLGenerator = resourceURLGenerator;
- }
- }
-
/**
* <p>
* Gets a window by name. Returns <code>null</code> if the application is
@Deprecated
public String getRelativeLocation(ApplicationResource resource) {
- // FIXME Move to ApplicationContext
+ // FIXME Move to ApplicationContext?
// Gets the key
final String key = resourceKeyMap.get(resource);
return null;
}
- return resourceURLGenerator.generateResourceURL(resource, key);
+ return context.generateApplicationResourceURL(resource, key);
}
/**
@Deprecated
public DownloadStream handleURI(URL context, String relativeUri) {
- // FIXME Move to ApplicationContext
+ // FIXME Move to ApplicationContext? - public API, need to leave hook
+ // here
- if (resourceURLGenerator.isResourceURL(context, relativeUri)) {
+ if (this.context.isApplicationResourceURL(context, relativeUri)) {
// Handles the resource request
- final String key = resourceURLGenerator.getMapKey(context,
+ final String key = this.context.getURLKey(context,
relativeUri);
final ApplicationResource resource = keyResourceMap
.get(key);
-/*
+/*
@ITMillApache2LicenseForJavaFiles@
*/
import java.io.File;
import java.io.Serializable;
+import java.net.URL;
import java.util.Collection;
import com.vaadin.Application;
* context of the application. Each context is shared by all applications that
* are open for one user. In a web-environment this corresponds to a
* HttpSession.
- *
+ *
* @author IT Mill Ltd.
* @version
* @VERSION@
/**
* Returns application context base directory.
- *
+ *
* Typically an application is deployed in a such way that is has an
* application directory. For web applications this directory is the root
* directory of the web applications. In some cases applications might not
* have an application directory (for example web applications running
* inside a war).
- *
+ *
* @return The application base directory or null if the application has no
* base directory.
*/
/**
* Returns a collection of all the applications in this context.
- *
+ *
* Each application context contains all active applications for one user.
- *
+ *
* @return A collection containing all the applications in this context.
*/
public Collection<Application> getApplications();
-
+
/**
- * Adds a transaction listener to this context.
- *
- * @param listener
- * the listener to be added.
- * @see TransactionListener
+ * Adds a transaction listener to this context. The transaction listener is
+ * called before and after each each request related to this session except
+ * when serving static resources.
+ *
+ *
+ * @see com.vaadin.service.ApplicationContext#addTransactionListener(com.vaadin.service.ApplicationContext.TransactionListener)
*/
public void addTransactionListener(TransactionListener listener);
/**
* Removes a transaction listener from this context.
- *
+ *
* @param listener
* the listener to be removed.
* @see TransactionListener
*/
public void removeTransactionListener(TransactionListener listener);
+ /**
+ * Generate a URL that can be used as the relative location of e.g. an
+ * {@link ApplicationResource}.
+ *
+ * @deprecated this is subject to change/removal from the interface
+ *
+ * @param resource
+ * @param urlKey
+ * a key for the resource that can later be extracted from a URL
+ * with {@link #getURLKey(URL, String)}
+ */
+ @Deprecated
+ public String generateApplicationResourceURL(ApplicationResource resource,
+ String urlKey);
+
+ /**
+ * Tests if a URL is for an application resource (APP/...).
+ *
+ * @deprecated this is subject to change/removal from the interface
+ *
+ * @param context
+ * @param relativeUri
+ * @return
+ */
+ @Deprecated
+ public boolean isApplicationResourceURL(URL context, String relativeUri);
+
+ /**
+ * Gets the identifier (key) from an application resource URL. This key is
+ * 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
+ * @param relativeUri
+ * @return
+ */
+ @Deprecated
+ public String getURLKey(URL context, String relativeUri);
+
/**
* Interface for listening to transaction events. Implement this interface
* to listen to all transactions between the client and the application.
- *
+ *
*/
public interface TransactionListener extends Serializable {
/**
* Invoked at the beginning of every transaction.
- *
+ *
* The transaction is linked to the context, not the application so if
* you have multiple applications running in the same context you need
* to check that the request is associated with the application you are
* interested in. This can be done looking at the application parameter.
- *
+ *
* @param application
* the Application object.
* @param transactionData
/**
* Invoked at the end of every transaction.
- *
+ *
* The transaction is linked to the context, not the application so if
* you have multiple applications running in the same context you need
* to check that the request is associated with the application you are
* interested in. This can be done looking at the application parameter.
- *
+ *
* @param applcation
* the Application object.
* @param transactionData
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
-import java.net.URL;
import java.security.GeneralSecurityException;
-import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;
import com.vaadin.Application;
import com.vaadin.Application.SystemMessages;
import com.vaadin.external.org.apache.commons.fileupload.portlet.PortletFileUpload;
-import com.vaadin.terminal.ApplicationResource;
import com.vaadin.terminal.DownloadStream;
import com.vaadin.terminal.Terminal;
import com.vaadin.ui.Window;
private static final String PORTAL_PARAMETER_VAADIN_THEME = "vaadin.theme";
- /*
- * TODO Big parts of this class are directly copy-pasted from
- * AbstractApplicationServlet. On the long term, it would probably be wise
- * to try to integrate the common parts into a shared super class.
- */
+ // TODO some parts could be shared with AbstractApplicationServlet
// TODO Can we close the application when the portlet is removed? Do we know
// when the portlet is removed?
private boolean productionMode = false;
- private static class PortletResourceURLGenerator implements
- Application.ResourceURLGenerator {
-
- private final MimeResponse response;
-
- public PortletResourceURLGenerator(MimeResponse response) {
- this.response = response;
- }
-
- public boolean isResourceURL(URL context, String relativeUri) {
- // If the relative uri is null, we are ready
- if (relativeUri == null) {
- return false;
- }
-
- // Resolves the prefix
- String prefix = relativeUri;
- final int index = relativeUri.indexOf('/');
- if (index >= 0) {
- prefix = relativeUri.substring(0, index);
- }
-
- // Handles the resource requests
- return (prefix.equals("APP"));
- }
-
- public String getMapKey(URL context, String relativeUri) {
- final int index = relativeUri.indexOf('/');
- final int next = relativeUri.indexOf('/', index + 1);
- if (next < 0) {
- return null;
- }
- return relativeUri.substring(index + 1, next);
- }
-
- public String generateResourceURL(ApplicationResource resource,
- String mapKey) {
- ResourceURL resourceURL = response.createResourceURL();
- final String filename = resource.getFilename();
- if (filename == null) {
- resourceURL.setResourceID("APP/" + mapKey + "/");
- } else {
- resourceURL.setResourceID("APP/" + mapKey + "/" + filename);
- }
- return resourceURL.toString();
- }
- };
-
@SuppressWarnings("unchecked")
@Override
public void init(PortletConfig config) throws PortletException {
if (application == null) {
return;
}
- if (response instanceof MimeResponse) {
- application
- .setResourceURLGenerator(new PortletResourceURLGenerator(
- (MimeResponse) response));
- }
/*
* Get or create an application context and an application
*/
PortletApplicationContext2 applicationContext = PortletApplicationContext2
.getApplicationContext(request.getPortletSession());
+ if (response instanceof MimeResponse) {
+ applicationContext.setMimeResponse((MimeResponse) response);
+ }
+
PortletCommunicationManager applicationManager = applicationContext
.getApplicationManager(application);
private Application createApplication(PortletRequest request)
throws PortletException, MalformedURLException {
Application newApplication = getNewApplication(request);
- newApplication.setPortletWindowId(request.getWindowID());
final PortletApplicationContext2 context = PortletApplicationContext2
.getApplicationContext(request.getPortletSession());
- context.addApplication(newApplication);
+ context.addApplication(newApplication, request.getWindowID());
return newApplication;
}
PortletApplicationContext2 context = PortletApplicationContext2
.getApplicationContext(session);
-
- final Collection<Application> applications = context.getApplications();
- for (Application sessionApplication : applications) {
- if (request.getWindowID().equals(
- sessionApplication.getPortletWindowId())) {
- if (sessionApplication.isRunning()) {
- return sessionApplication;
- }
- PortletApplicationContext2.getApplicationContext(session)
- .removeApplication(sessionApplication);
- break;
- }
+ Application application = context.getApplicationForWindowId(request
+ .getWindowID());
+ if (application == null) {
+ return null;
+ }
+ if (application.isRunning()) {
+ return application;
}
+ // application found but not running
+ PortletApplicationContext2.getApplicationContext(session)
+ .removeApplication(application);
return null;
}
systemMessages = getSystemMessages();
} catch (SystemMessageException e) {
// failing to get the system messages is always a problem
- throw new PortletException("CommunicationError!", e);
+ throw new PortletException("Failed to obtain system messages!", e);
}
page.write("<script type=\"text/javascript\">\n");
*/
public static final String VERSION;
/**
- * Major version number. For example 5 in 6.2.0.
+ * Major version number. For example 6 in 6.2.0.
*/
public static final int VERSION_MAJOR;
/**
- * Minor version number. For example 1 in 6.2.0.
+ * Minor version number. For example 2 in 6.2.0.
*/
public static final int VERSION_MINOR;
/**
* This request attribute forces widgetsets to be loaded from under the
* specified base path; e.g shared widgetset for all portlets in a portal.
- *
+ *
* It is set by the {@link ApplicationPortlet} (Portlet 1.0) based on
* {@link Constants.PORTAL_PARAMETER_VAADIN_RESOURCE_PATH} and read by
* {@link AbstractApplicationServlet}.
--- /dev/null
+package com.vaadin.terminal.gwt.server;\r
+\r
+import java.io.PrintWriter;\r
+import java.io.Serializable;\r
+import java.io.StringWriter;\r
+import java.net.URL;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.LinkedList;\r
+\r
+import javax.servlet.http.HttpSessionBindingEvent;\r
+import javax.servlet.http.HttpSessionBindingListener;\r
+\r
+import com.vaadin.Application;\r
+import com.vaadin.service.ApplicationContext;\r
+import com.vaadin.terminal.ApplicationResource;\r
+\r
+/**\r
+ * Base class for web application contexts (including portlet contexts) that\r
+ * handles the common tasks.\r
+ */\r
+public abstract class AbstractWebApplicationContext implements\r
+ ApplicationContext, HttpSessionBindingListener, Serializable {\r
+\r
+ protected Collection<TransactionListener> listeners = Collections\r
+ .synchronizedList(new LinkedList<TransactionListener>());\r
+\r
+ protected final HashSet<Application> applications = new HashSet<Application>();\r
+\r
+ protected WebBrowser browser = new WebBrowser();\r
+\r
+ protected HashMap<Application, AbstractCommunicationManager> applicationToAjaxAppMgrMap = new HashMap<Application, AbstractCommunicationManager>();\r
+\r
+ public void addTransactionListener(TransactionListener listener) {\r
+ listeners.add(listener);\r
+ }\r
+\r
+ public void removeTransactionListener(TransactionListener listener) {\r
+ listeners.remove(listener);\r
+ }\r
+\r
+ /**\r
+ * Sends a notification that a transaction is starting.\r
+ *\r
+ * @param application\r
+ * The application associated with the transaction.\r
+ * @param request\r
+ * the HTTP or portlet request that triggered the transaction.\r
+ */\r
+ protected void startTransaction(Application application, Object request) {\r
+ synchronized (listeners) {\r
+ for (TransactionListener listener : listeners) {\r
+ listener.transactionStart(application, request);\r
+ }\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Sends a notification that a transaction has ended.\r
+ *\r
+ * @param application\r
+ * The application associated with the transaction.\r
+ * @param request\r
+ * the HTTP or portlet request that triggered the transaction.\r
+ */\r
+ protected void endTransaction(Application application, Object request) {\r
+ LinkedList<Exception> exceptions = null;\r
+\r
+ synchronized (listeners) {\r
+ for (TransactionListener listener : listeners) {\r
+ try {\r
+ listener.transactionEnd(application, request);\r
+ } catch (final RuntimeException t) {\r
+ if (exceptions == null) {\r
+ exceptions = new LinkedList<Exception>();\r
+ }\r
+ exceptions.add(t);\r
+ }\r
+ }\r
+ }\r
+\r
+ // If any runtime exceptions occurred, throw a combined exception\r
+ if (exceptions != null) {\r
+ final StringBuffer msg = new StringBuffer();\r
+ for (Exception e : exceptions) {\r
+ if (msg.length() == 0) {\r
+ msg.append("\n\n--------------------------\n\n");\r
+ }\r
+ msg.append(e.getMessage() + "\n");\r
+ final StringWriter trace = new StringWriter();\r
+ e.printStackTrace(new PrintWriter(trace, true));\r
+ msg.append(trace.toString());\r
+ }\r
+ throw new RuntimeException(msg.toString());\r
+ }\r
+ }\r
+\r
+ /**\r
+ * @see javax.servlet.http.HttpSessionBindingListener#valueBound(HttpSessionBindingEvent)\r
+ */\r
+ public void valueBound(HttpSessionBindingEvent arg0) {\r
+ // We are not interested in bindings\r
+ }\r
+\r
+ /**\r
+ * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(HttpSessionBindingEvent)\r
+ */\r
+ public void valueUnbound(HttpSessionBindingEvent event) {\r
+ // If we are going to be unbound from the session, the session must be\r
+ // closing\r
+ try {\r
+ while (!applications.isEmpty()) {\r
+ final Application app = applications.iterator().next();\r
+ app.close();\r
+ removeApplication(app);\r
+ }\r
+ } catch (Exception e) {\r
+ // This should never happen but is possible with rare\r
+ // configurations (e.g. robustness tests). If you have one\r
+ // thread doing HTTP socket write and another thread trying to\r
+ // remove same application here. Possible if you got e.g. session\r
+ // lifetime 1 min but socket write may take longer than 1 min.\r
+ // FIXME: Handle exception\r
+ System.err.println("Could not remove application, leaking memory.");\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Get the web browser associated with this application context.\r
+ *\r
+ * Because application context is related to the http session and server\r
+ * maintains one session per browser-instance, each context has exactly one\r
+ * web browser associated with it.\r
+ *\r
+ * @return\r
+ */\r
+ public WebBrowser getBrowser() {\r
+ return browser;\r
+ }\r
+\r
+ public Collection<Application> getApplications() {\r
+ return Collections.unmodifiableCollection(applications);\r
+ }\r
+\r
+ protected void removeApplication(Application application) {\r
+ applications.remove(application);\r
+ applicationToAjaxAppMgrMap.remove(application);\r
+ }\r
+\r
+ public String generateApplicationResourceURL(\r
+ ApplicationResource resource, String mapKey) {\r
+\r
+ final String filename = resource.getFilename();\r
+ if (filename == null) {\r
+ return "APP/" + mapKey + "/";\r
+ } else {\r
+ return "APP/" + mapKey + "/" + filename;\r
+ }\r
+\r
+ }\r
+\r
+ public boolean isApplicationResourceURL(URL context, String relativeUri) {\r
+ // If the relative uri is null, we are ready\r
+ if (relativeUri == null) {\r
+ return false;\r
+ }\r
+\r
+ // Resolves the prefix\r
+ String prefix = relativeUri;\r
+ final int index = relativeUri.indexOf('/');\r
+ if (index >= 0) {\r
+ prefix = relativeUri.substring(0, index);\r
+ }\r
+\r
+ // Handles the resource requests\r
+ return (prefix.equals("APP"));\r
+ }\r
+\r
+ public String getURLKey(URL context, String relativeUri) {\r
+ final int index = relativeUri.indexOf('/');\r
+ final int next = relativeUri.indexOf('/', index + 1);\r
+ if (next < 0) {\r
+ return null;\r
+ }\r
+ return relativeUri.substring(index + 1, next);\r
+ }\r
+\r
+}
\ No newline at end of file
package com.vaadin.terminal.gwt.server;
import java.io.File;
-import java.io.PrintWriter;
import java.io.Serializable;
-import java.io.StringWriter;
import java.net.URL;
-import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.LinkedHashSet;
-import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import javax.portlet.ActionResponse;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
-import javax.portlet.PortletRequest;
+import javax.portlet.MimeResponse;
import javax.portlet.PortletSession;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
-import javax.servlet.http.HttpSessionBindingEvent;
+import javax.portlet.ResourceURL;
import javax.servlet.http.HttpSessionBindingListener;
import com.vaadin.Application;
-import com.vaadin.service.ApplicationContext;
+import com.vaadin.terminal.ApplicationResource;
/**
* TODO Write documentation, fix JavaDoc tags.
* @author peholmst
*/
@SuppressWarnings("serial")
-public class PortletApplicationContext2 implements ApplicationContext,
- HttpSessionBindingListener, Serializable {
-
- protected LinkedList<TransactionListener> listeners;
+public class PortletApplicationContext2 extends AbstractWebApplicationContext {
protected Map<Application, Set<PortletListener>> portletListeners = new HashMap<Application, Set<PortletListener>>();
protected transient PortletSession session;
- protected final HashSet<Application> applications = new HashSet<Application>();
-
- protected WebBrowser browser = new WebBrowser();
+ protected HashMap<String, Application> portletWindowIdToApplicationMap = new HashMap<String, Application>();
- protected HashMap<Application, PortletCommunicationManager> applicationToAjaxAppMgrMap = new HashMap<Application, PortletCommunicationManager>();
-
- public Collection<Application> getApplications() {
- return Collections.unmodifiableCollection(applications);
- }
+ private MimeResponse mimeResponse;
public File getBaseDirectory() {
String resultPath = session.getPortletContext().getRealPath("/");
return null;
}
- public void addTransactionListener(TransactionListener listener) {
- if (listeners == null) {
- listeners = new LinkedList<TransactionListener>();
- }
- listeners.add(listener);
- }
-
- public void removeTransactionListener(TransactionListener listener) {
- if (listeners != null) {
- listeners.remove(listener);
- }
- }
-
protected PortletCommunicationManager getApplicationManager(
Application application) {
- PortletCommunicationManager mgr = applicationToAjaxAppMgrMap
+ PortletCommunicationManager mgr = (PortletCommunicationManager) applicationToAjaxAppMgrMap
.get(application);
if (mgr == null) {
return cx;
}
- public WebBrowser getBrowser() {
- return browser;
- }
-
- @SuppressWarnings("unchecked")
- protected void startTransaction(Application application,
- PortletRequest request) {
- if (listeners == null) {
- return;
- }
- for (TransactionListener listener : (LinkedList<TransactionListener>) listeners
- .clone()) {
- listener.transactionStart(application, request);
- }
- }
-
- @SuppressWarnings("unchecked")
- protected void endTransaction(Application application,
- PortletRequest request) {
- if (listeners == null) {
- return;
- }
-
- LinkedList<Exception> exceptions = null;
- for (TransactionListener listener : (LinkedList<TransactionListener>) listeners
- .clone()) {
- try {
- listener.transactionEnd(application, request);
- } catch (final RuntimeException e) {
- if (exceptions == null) {
- exceptions = new LinkedList<Exception>();
- }
- exceptions.add(e);
- }
- }
-
- // If any runtime exceptions occurred, throw a combined exception
- if (exceptions != null) {
- final StringBuffer msg = new StringBuffer();
- for (Exception e : exceptions) {
- if (msg.length() == 0) {
- msg.append("\n\n--------------------------\n\n");
- }
- msg.append(e.getMessage() + "\n");
- final StringWriter trace = new StringWriter();
- e.printStackTrace(new PrintWriter(trace, true));
- msg.append(trace.toString());
- }
- throw new RuntimeException(msg.toString());
- }
- }
-
+ @Override
protected void removeApplication(Application application) {
- applications.remove(application);
- applicationToAjaxAppMgrMap.remove(application);
+ super.removeApplication(application);
+ // values() is backed by map, removes the key-value pair from the map
+ portletWindowIdToApplicationMap.values().remove(application);
}
- protected void addApplication(Application application) {
+ protected void addApplication(Application application,
+ String portletWindowId) {
applications.add(application);
+ portletWindowIdToApplicationMap.put(portletWindowId, application);
}
- public PortletSession getPortletSession() {
- return session;
+ public Application getApplicationForWindowId(String portletWindowId) {
+ return portletWindowIdToApplicationMap.get(portletWindowId);
}
- public void valueBound(HttpSessionBindingEvent event) {
- // We are not interested in bindings
- }
-
- public void valueUnbound(HttpSessionBindingEvent event) {
- // If we are going to be unbound from the session, the session must be
- // closing
- try {
- while (!applications.isEmpty()) {
- final Application app = applications.iterator().next();
- app.close();
- applicationToAjaxAppMgrMap.remove(app);
- removeApplication(app);
- }
- } catch (Exception e) {
- // FIXME: Handle exception
- System.err.println("Could not remove application, leaking memory.");
- e.printStackTrace();
- }
+ public PortletSession getPortletSession() {
+ return session;
}
public void addPortletListener(Application app, PortletListener listener) {
ResourceResponse response);
}
+ /**
+ * This is for use by {@link AbstractApplicationPortlet} only.
+ *
+ * TODO cleaner implementation, now "semi-static"!
+ *
+ * @param mimeResponse
+ */
+ void setMimeResponse(MimeResponse mimeResponse) {
+ this.mimeResponse = mimeResponse;
+ }
+
+ @Override
+ public String generateApplicationResourceURL(
+ ApplicationResource resource,
+ String mapKey) {
+ ResourceURL resourceURL = mimeResponse.createResourceURL();
+ final String filename = resource.getFilename();
+ if (filename == null) {
+ resourceURL.setResourceID("APP/" + mapKey + "/");
+ } else {
+ resourceURL.setResourceID("APP/" + mapKey + "/" + filename);
+ }
+ return resourceURL.toString();
+ }
+
}
package com.vaadin.terminal.gwt.server;
import java.io.File;
-import java.io.PrintWriter;
-import java.io.Serializable;
-import java.io.StringWriter;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import com.vaadin.Application;
-import com.vaadin.service.ApplicationContext;
/**
* Web application context for Vaadin applications.
- *
+ *
* This is automatically added as a {@link HttpSessionBindingListener} when
* added to a {@link HttpSession}.
*
* @since 3.1
*/
@SuppressWarnings("serial")
-public class WebApplicationContext implements ApplicationContext,
- HttpSessionBindingListener, Serializable {
-
- protected List<TransactionListener> listeners = Collections
- .synchronizedList(new LinkedList<TransactionListener>());
+public class WebApplicationContext extends AbstractWebApplicationContext {
protected transient HttpSession session;
- protected final HashSet<Application> applications = new HashSet<Application>();
-
- protected WebBrowser browser = new WebBrowser();
-
- protected HashMap<Application, CommunicationManager> applicationToAjaxAppMgrMap = new HashMap<Application, CommunicationManager>();
-
/**
* Creates a new Web Application Context.
*
return session;
}
- /**
- * Gets the applications in this context.
- *
- * @see com.vaadin.service.ApplicationContext#getApplications()
- */
- public Collection<Application> getApplications() {
- return Collections.unmodifiableCollection(applications);
- }
-
/**
* Gets the application context for an HttpSession.
*
return cx;
}
- /**
- * Adds a transaction listener to this context. The transaction listener is
- * called before and after each each HTTP request related to this session
- * except when serving static resources.
- *
- *
- * @see com.vaadin.service.ApplicationContext#addTransactionListener(com.vaadin.service.ApplicationContext.TransactionListener)
- */
- public void addTransactionListener(TransactionListener listener) {
- listeners.add(listener);
- }
-
- /**
- * Removes a transaction listener from this context. The transaction
- * listener is called before and after each each HTTP request related to
- * this session except when serving static resources.
- *
- * @see com.vaadin.service.ApplicationContext#removeTransactionListener(com.vaadin.service.ApplicationContext.TransactionListener)
- */
- public void removeTransactionListener(TransactionListener listener) {
- listeners.remove(listener);
-
- }
-
- /**
- * Sends a notification that a transaction is starting.
- *
- * @param application
- * The application associated with the transaction.
- * @param request
- * the HTTP request that triggered the transaction.
- */
- protected void startTransaction(Application application,
- HttpServletRequest request) {
- synchronized (listeners) {
- for (TransactionListener listener : listeners) {
- listener.transactionStart(application, request);
- }
- }
- }
-
- /**
- * Sends a notification that a transaction has ended.
- *
- * @param application
- * The application associated with the transaction.
- * @param request
- * the HTTP request that triggered the transaction.
- */
- protected void endTransaction(Application application,
- HttpServletRequest request) {
- LinkedList<Exception> exceptions = null;
-
- synchronized (listeners) {
- for (TransactionListener listener : listeners) {
- try {
- listener.transactionEnd(application, request);
- } catch (final RuntimeException t) {
- if (exceptions == null) {
- exceptions = new LinkedList<Exception>();
- }
- exceptions.add(t);
- }
- }
- }
-
- // If any runtime exceptions occurred, throw a combined exception
- if (exceptions != null) {
- final StringBuffer msg = new StringBuffer();
- for (final Iterator i = exceptions.iterator(); i.hasNext();) {
- final RuntimeException e = (RuntimeException) i.next();
- if (msg.length() == 0) {
- msg.append("\n\n--------------------------\n\n");
- }
- msg.append(e.getMessage() + "\n");
- final StringWriter trace = new StringWriter();
- e.printStackTrace(new PrintWriter(trace, true));
- msg.append(trace.toString());
- }
- throw new RuntimeException(msg.toString());
- }
- }
-
- protected void removeApplication(Application application) {
- applications.remove(application);
- applicationToAjaxAppMgrMap.remove(application);
- }
-
protected void addApplication(Application application) {
applications.add(application);
}
- /**
- * @see javax.servlet.http.HttpSessionBindingListener#valueBound(HttpSessionBindingEvent)
- */
- public void valueBound(HttpSessionBindingEvent arg0) {
- // We are not interested in bindings
- }
-
- /**
- * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(HttpSessionBindingEvent)
- */
- public void valueUnbound(HttpSessionBindingEvent event) {
- // If we are going to be unbound from the session, the session must be
- // closing
- try {
- while (!applications.isEmpty()) {
- final Application app = applications.iterator().next();
- app.close();
- removeApplication(app);
- }
- } catch (Exception e) {
- // This should never happen but is possible with rare
- // configurations (e.g. robustness tests). If you have one
- // thread doing HTTP socket write and another thread trying to
- // remove same application here. Possible if you got e.g. session
- // lifetime 1 min but socket write may take longer than 1 min.
- // FIXME: Handle exception
- System.err.println("Could not remove application, leaking memory.");
- e.printStackTrace();
- }
- }
-
- /**
- * Get the web browser associated with this application context.
- *
- * Because application context is related to the http session and server
- * maintains one session per browser-instance, each context has exactly one
- * web browser associated with it.
- *
- * @return
- */
- public WebBrowser getBrowser() {
- return browser;
- }
-
/**
* Gets communication manager for an application.
*
*/
protected CommunicationManager getApplicationManager(
Application application, AbstractApplicationServlet servlet) {
- CommunicationManager mgr = applicationToAjaxAppMgrMap.get(application);
+ CommunicationManager mgr = (CommunicationManager) applicationToAjaxAppMgrMap
+ .get(application);
if (mgr == null) {
// Creates new manager