diff options
author | Petter Holmström <petter.holmstrom@itmill.com> | 2009-11-03 11:59:16 +0000 |
---|---|---|
committer | Petter Holmström <petter.holmstrom@itmill.com> | 2009-11-03 11:59:16 +0000 |
commit | 712d4c7b79f5d4c740c8f7166f9684d9ad6007fd (patch) | |
tree | 8d928ef4a25c11d1b963d1d2f3ee9032f234e162 /src/com/vaadin/terminal/gwt/server/CommunicationManager.java | |
parent | 1101a2f9e45bdacb51425950c05b805f54586375 (diff) | |
download | vaadin-framework-712d4c7b79f5d4c740c8f7166f9684d9ad6007fd.tar.gz vaadin-framework-712d4c7b79f5d4c740c8f7166f9684d9ad6007fd.zip |
CommunicationManager is no longer dependent on the Portlet API. The refactored API seems to work using portlets, I have no idea whether it works using servlets.
svn changeset:9601/svn branch:portlet_2.0
Diffstat (limited to 'src/com/vaadin/terminal/gwt/server/CommunicationManager.java')
-rw-r--r-- | src/com/vaadin/terminal/gwt/server/CommunicationManager.java | 1855 |
1 files changed, 138 insertions, 1717 deletions
diff --git a/src/com/vaadin/terminal/gwt/server/CommunicationManager.java b/src/com/vaadin/terminal/gwt/server/CommunicationManager.java index dd7de4b2b7..5a467c35f7 100644 --- a/src/com/vaadin/terminal/gwt/server/CommunicationManager.java +++ b/src/com/vaadin/terminal/gwt/server/CommunicationManager.java @@ -4,68 +4,22 @@ package com.vaadin.terminal.gwt.server; -import java.io.BufferedWriter; -import java.io.CharArrayWriter; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.Serializable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.security.GeneralSecurityException; -import java.text.DateFormat; -import java.text.DateFormatSymbols; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import javax.portlet.ActionRequest; -import javax.portlet.ActionResponse; -import javax.portlet.PortletException; -import javax.portlet.ResourceRequest; -import javax.portlet.ResourceResponse; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; import com.vaadin.Application; -import com.vaadin.Application.SystemMessages; import com.vaadin.external.org.apache.commons.fileupload.FileItemIterator; -import com.vaadin.external.org.apache.commons.fileupload.FileItemStream; +import com.vaadin.external.org.apache.commons.fileupload.FileUpload; import com.vaadin.external.org.apache.commons.fileupload.FileUploadException; -import com.vaadin.external.org.apache.commons.fileupload.ProgressListener; import com.vaadin.external.org.apache.commons.fileupload.servlet.ServletFileUpload; import com.vaadin.terminal.DownloadStream; -import com.vaadin.terminal.PaintException; -import com.vaadin.terminal.Paintable; -import com.vaadin.terminal.URIHandler; -import com.vaadin.terminal.UploadStream; -import com.vaadin.terminal.VariableOwner; -import com.vaadin.terminal.Paintable.RepaintRequestEvent; -import com.vaadin.terminal.Terminal.ErrorEvent; -import com.vaadin.terminal.gwt.client.ApplicationConnection; -import com.vaadin.terminal.gwt.server.ComponentSizeValidator.InvalidLayout; -import com.vaadin.ui.AbstractField; -import com.vaadin.ui.Component; -import com.vaadin.ui.Upload; import com.vaadin.ui.Window; -import com.vaadin.ui.Upload.UploadException; /** * Application manager processes changes and paints for single application @@ -77,1774 +31,241 @@ import com.vaadin.ui.Upload.UploadException; * @since 5.0 */ @SuppressWarnings("serial") -public class CommunicationManager implements Paintable.RepaintRequestListener, - Serializable { - - // FIXME Create an abstract class with custom Request/Response/Session interfaces, then create - // subclasses for servlets and portlets. +public class CommunicationManager extends AbstractCommunicationManager { - private static String GET_PARAM_REPAINT_ALL = "repaintAll"; + private static class HttpServletRequestWrapper implements Request { - // flag used in the request to indicate that the security token should be - // written to the response - private static final String WRITE_SECURITY_TOKEN_FLAG = "writeSecurityToken"; + private final HttpServletRequest request; - /* Variable records indexes */ - private static final int VAR_PID = 1; - private static final int VAR_NAME = 2; - private static final int VAR_TYPE = 3; - private static final int VAR_VALUE = 0; - - private static final String VAR_RECORD_SEPARATOR = "\u001e"; - - private static final String VAR_FIELD_SEPARATOR = "\u001f"; - - public static final String VAR_BURST_SEPARATOR = "\u001d"; - - public static final String VAR_ARRAYITEM_SEPARATOR = "\u001c"; - - private final HashMap<String, OpenWindowCache> currentlyOpenWindowsInClient = new HashMap<String, OpenWindowCache>(); - - private static final int MAX_BUFFER_SIZE = 64 * 1024; - - private static final String GET_PARAM_ANALYZE_LAYOUTS = "analyzeLayouts"; - - private final ArrayList<Paintable> dirtyPaintabletSet = new ArrayList<Paintable>(); - - private final HashMap<Paintable, String> paintableIdMap = new HashMap<Paintable, String>(); - - private final HashMap<String, Paintable> idPaintableMap = new HashMap<String, Paintable>(); - - private int idSequence = 0; - - private final Application application; - - // Note that this is only accessed from synchronized block and - // thus should be thread-safe. - private String closingWindowName = null; - - private List<String> locales; - - private int pendingLocalesIndex; - - private int timeoutInterval = -1; - - /** - * @deprecated use {@link #CommunicationManager(Application)} instead - * @param application - * @param applicationServlet - */ - @Deprecated - public CommunicationManager(Application application, - AbstractApplicationServlet applicationServlet) { - this.application = application; - requireLocale(application.getLocale().toString()); - } - - /** - * TODO New constructor - document me! - * - * @param application - */ - public CommunicationManager(Application application) { - this.application = application; - requireLocale(application.getLocale().toString()); - } - - /** - * TODO New method - document me! - * - * @param reuqest - * @param response - * @throws IOException - * @throws FileUploadException - */ - public void handleFileUpload(ActionRequest reuqest, ActionResponse response) - throws IOException, FileUploadException { - // FIXME Implement me! - throw new UnsupportedOperationException("Not implemented!"); - } - - /** - * Handles file upload request submitted via Upload component. - * - * @param request - * @param response - * @throws IOException - * @throws FileUploadException - */ - public void handleFileUpload(HttpServletRequest request, - HttpServletResponse response) throws IOException, - FileUploadException { - // Create a new file upload handler - final ServletFileUpload upload = new ServletFileUpload(); - - final UploadProgressListener pl = new UploadProgressListener(); - - upload.setProgressListener(pl); - - // Parse the request - FileItemIterator iter; - - try { - iter = upload.getItemIterator(request); - /* - * ATM this loop is run only once as we are uploading one file per - * request. - */ - while (iter.hasNext()) { - final FileItemStream item = iter.next(); - final String name = item.getFieldName(); - final String filename = item.getName(); - final String mimeType = item.getContentType(); - final InputStream stream = item.openStream(); - if (item.isFormField()) { - // ignored, upload requests contains only files - } else { - final String pid = name.split("_")[0]; - final Upload uploadComponent = (Upload) idPaintableMap - .get(pid); - if (uploadComponent == null) { - throw new FileUploadException( - "Upload component not found"); - } - if (uploadComponent.isReadOnly()) { - throw new FileUploadException( - "Warning: ignored file upload because upload component is set as read-only"); - } - synchronized (application) { - // put upload component into receiving state - uploadComponent.startUpload(); - } - final UploadStream upstream = new UploadStream() { - - public String getContentName() { - return filename; - } - - public String getContentType() { - return mimeType; - } - - public InputStream getStream() { - return stream; - } - - public String getStreamName() { - return "stream"; - } - - }; - - // tell UploadProgressListener which component is receiving - // file - pl.setUpload(uploadComponent); - - try { - uploadComponent.receiveUpload(upstream); - } catch (UploadException e) { - // error happened while receiving file. Handle the - // error in the same manner as it would have happened in - // variable change. - synchronized (application) { - handleChangeVariablesError(application, - uploadComponent, e, - new HashMap<String, Object>()); - } - } - } - } - } catch (final FileUploadException e) { - throw e; + public HttpServletRequestWrapper(HttpServletRequest request) { + this.request = request; } - // Send short response to acknowledge client that request was done - response.setContentType("text/html"); - final OutputStream out = response.getOutputStream(); - final PrintWriter outWriter = new PrintWriter(new BufferedWriter( - new OutputStreamWriter(out, "UTF-8"))); - outWriter.print("<html><body>download handled</body></html>"); - outWriter.flush(); - out.close(); - } - - /** - * TODO New method - document me! - * - * @param request - * @param response - * @throws IOException - * @throws PortletException - * @throws InvalidUIDLSecurityKeyException - */ - public void handleUidlRequest(ResourceRequest request, - ResourceResponse response) throws IOException, PortletException, - InvalidUIDLSecurityKeyException { - try { - doHandleUidlRequest(request, response, null); - } catch (ServletException e) { - throw new PortletException(e.getMessage(), e.getCause()); + public Object getAttribute(String name) { + return request.getAttribute(name); } - } - - /** - * Handles UIDL request - * - * @param request - * @param response - * @throws IOException - * @throws ServletException - */ - public void handleUidlRequest(HttpServletRequest request, - HttpServletResponse response, - AbstractApplicationServlet applicationServlet) throws IOException, - ServletException, InvalidUIDLSecurityKeyException { - doHandleUidlRequest(request, response, applicationServlet); - } - - private void doHandleUidlRequest(Object request, Object response, - AbstractApplicationServlet applicationServlet) throws IOException, - ServletException, InvalidUIDLSecurityKeyException { - - // repaint requested or session has timed out and new one is created - boolean repaintAll; - final OutputStream out; - if (request instanceof ResourceRequest) { - repaintAll = (((ResourceRequest) request) - .getParameter(GET_PARAM_REPAINT_ALL) != null) - || ((ResourceRequest) request).getPortletSession().isNew(); - // Assume the response is a ResourceResponse - out = ((ResourceResponse) response).getPortletOutputStream(); - } else { - repaintAll = (((HttpServletRequest) request) - .getParameter(GET_PARAM_REPAINT_ALL) != null) - || ((HttpServletRequest) request).getSession().isNew(); - // Assume the response is a HttpServletResponse - out = ((HttpServletResponse) response).getOutputStream(); - } - boolean analyzeLayouts = false; - if (repaintAll) { - // analyzing can be done only with repaintAll - if (request instanceof ResourceRequest) { - analyzeLayouts = (((ResourceRequest) request) - .getParameter(GET_PARAM_ANALYZE_LAYOUTS) != null); - } else { - analyzeLayouts = (((HttpServletRequest) request) - .getParameter(GET_PARAM_ANALYZE_LAYOUTS) != null); - } + public int getContentLength() { + return request.getContentLength(); } - final PrintWriter outWriter = new PrintWriter(new BufferedWriter( - new OutputStreamWriter(out, "UTF-8"))); - - // The rest of the process is synchronized with the application - // in order to guarantee that no parallel variable handling is - // made - synchronized (application) { - - // Finds the window within the application - Window window = null; - if (application.isRunning()) { - window = doGetApplicationWindow(request, applicationServlet, - application, null); - // Returns if no window found - if (window == null) { - // This should not happen, no windows exists but - // application is still open. - if (request instanceof ResourceRequest) { - System.err - .println("Warning, could not get window for application with resource ID " - + ((ResourceRequest) request) - .getResourceID()); - } else { - System.err - .println("Warning, could not get window for application with request URI " - + ((HttpServletRequest) request) - .getRequestURI()); - } - return; - } - } else { - // application has been closed - endApplication(request, response, application); - return; - } - - // Change all variables based on request parameters - if (!handleVariables(request, response, applicationServlet, - application, window)) { - - // var inconsistency; the client is probably out-of-sync - SystemMessages ci = null; - try { - Method m = application.getClass().getMethod( - "getSystemMessages", (Class[]) null); - ci = (Application.SystemMessages) m.invoke(null, - (Object[]) null); - } catch (Exception e2) { - // FIXME: Handle exception - // Not critical, but something is still wrong; print - // stacktrace - e2.printStackTrace(); - } - if (ci != null) { - String msg = ci.getOutOfSyncMessage(); - String cap = ci.getOutOfSyncCaption(); - if (msg != null || cap != null) { - if (request instanceof HttpServletRequest) { - applicationServlet.criticalNotification( - (HttpServletRequest) request, - (HttpServletResponse) response, cap, msg, - null, ci.getOutOfSyncURL()); - } - // FIXME What about Portlets? - // will reload page after this - return; - } - } - // No message to show, let's just repaint all. - repaintAll = true; - - } - - paintAfterVariablechanges(request, response, applicationServlet, - repaintAll, outWriter, window, analyzeLayouts); - - if (closingWindowName != null) { - currentlyOpenWindowsInClient.remove(closingWindowName); - closingWindowName = null; - } + public InputStream getInputStream() throws IOException { + return request.getInputStream(); } - out.flush(); - out.close(); - } - - private void paintAfterVariablechanges(Object request, Object response, - AbstractApplicationServlet applicationServlet, boolean repaintAll, - final PrintWriter outWriter, Window window, boolean analyzeLayouts) - throws IOException, ServletException, PaintException { - - if (repaintAll) { - // If repaint is requested, clean all ids in this root window - for (final Iterator<String> it = idPaintableMap.keySet().iterator(); it - .hasNext();) { - final Component c = (Component) idPaintableMap.get(it.next()); - if (isChildOf(window, c)) { - it.remove(); - paintableIdMap.remove(c); - } - } - // clean WindowCache - OpenWindowCache openWindowCache = currentlyOpenWindowsInClient - .get(window.getName()); - if (openWindowCache != null) { - openWindowCache.clear(); - } + public String getParameter(String name) { + return request.getParameter(name); } - // Removes application if it has stopped during variable changes - if (!application.isRunning()) { - endApplication(request, response, application); - return; + public String getRequestID() { + return "RequestURL:" + request.getRequestURI(); } - // Sets the response type - if (response instanceof ResourceResponse) { - ((ResourceResponse) response) - .setContentType("application/json; charset=UTF-8"); - } else { - ((HttpServletResponse) response) - .setContentType("application/json; charset=UTF-8"); + public Session getSession() { + return new HttpSessionWrapper(request.getSession()); } - // some dirt to prevent cross site scripting - outWriter.print("for(;;);[{"); - // security key - Object writeSecurityTokenFlag; - if (request instanceof ResourceRequest) { - writeSecurityTokenFlag = ((ResourceRequest) request) - .getAttribute(WRITE_SECURITY_TOKEN_FLAG); - } else { - writeSecurityTokenFlag = ((HttpServletRequest) request) - .getAttribute(WRITE_SECURITY_TOKEN_FLAG); + public Object getWrappedRequest() { + return request; } - if (writeSecurityTokenFlag != null) { - String seckey; - if (request instanceof ResourceRequest) { - seckey = (String) ((ResourceRequest) request) - .getPortletSession().getAttribute( - ApplicationConnection.UIDL_SECURITY_TOKEN_ID); - } else { - seckey = (String) ((HttpServletRequest) request).getSession() - .getAttribute( - ApplicationConnection.UIDL_SECURITY_TOKEN_ID); - } - if (seckey == null) { - seckey = "" + (int) (Math.random() * 1000000); - if (request instanceof ResourceRequest) { - ((ResourceRequest) request) - .getPortletSession() - .setAttribute( - ApplicationConnection.UIDL_SECURITY_TOKEN_ID, - seckey); - } else { - ((HttpServletRequest) request).getSession().setAttribute( - ApplicationConnection.UIDL_SECURITY_TOKEN_ID, - seckey); - } - } - outWriter.print("\"" + ApplicationConnection.UIDL_SECURITY_TOKEN_ID - + "\":\""); - outWriter.print(seckey); - outWriter.print("\","); + public boolean isRunningInPortlet() { + return false; } - outWriter.print("\"changes\":["); - - ArrayList<Paintable> paintables = null; - - // If the browser-window has been closed - we do not need to paint it at - // all - if (!window.getName().equals(closingWindowName)) { - - List<InvalidLayout> invalidComponentRelativeSizes = null; - - // re-get window - may have been changed - Window newWindow = doGetApplicationWindow(request, - applicationServlet, application, window); - if (newWindow != window) { - window = newWindow; - repaintAll = true; - } - - JsonPaintTarget paintTarget = new JsonPaintTarget(this, outWriter, - !repaintAll); - OpenWindowCache windowCache = currentlyOpenWindowsInClient - .get(window.getName()); - if (windowCache == null) { - windowCache = new OpenWindowCache(); - currentlyOpenWindowsInClient.put(window.getName(), windowCache); - } - - // Paints components - if (repaintAll) { - paintables = new ArrayList<Paintable>(); - paintables.add(window); - - // Reset sent locales - locales = null; - requireLocale(application.getLocale().toString()); - - } else { - // remove detached components from paintableIdMap so they - // can be GC'ed - for (Iterator<Paintable> it = paintableIdMap.keySet() - .iterator(); it.hasNext();) { - Component p = (Component) it.next(); - if (p.getApplication() == null) { - idPaintableMap.remove(paintableIdMap.get(p)); - it.remove(); - dirtyPaintabletSet.remove(p); - p.removeListener(this); - } - } - paintables = getDirtyVisibleComponents(window); - } - if (paintables != null) { - - // We need to avoid painting children before parent. - // This is ensured by ordering list by depth in component - // tree - Collections.sort(paintables, new Comparator<Paintable>() { - public int compare(Paintable o1, Paintable o2) { - Component c1 = (Component) o1; - Component c2 = (Component) o2; - int d1 = 0; - while (c1.getParent() != null) { - d1++; - c1 = c1.getParent(); - } - int d2 = 0; - while (c2.getParent() != null) { - d2++; - c2 = c2.getParent(); - } - if (d1 < d2) { - return -1; - } - if (d1 > d2) { - return 1; - } - return 0; - } - }); - - for (final Iterator i = paintables.iterator(); i.hasNext();) { - final Paintable p = (Paintable) i.next(); - - // TODO CLEAN - if (p instanceof Window) { - final Window w = (Window) p; - if (w.getTerminal() == null) { - w.setTerminal(application.getMainWindow() - .getTerminal()); - } - } - /* - * This does not seem to happen in tk5, but remember this - * case: else if (p instanceof Component) { if (((Component) - * p).getParent() == null || ((Component) - * p).getApplication() == null) { // Component requested - * repaint, but is no // longer attached: skip - * paintablePainted(p); continue; } } - */ - - // TODO we may still get changes that have been - // rendered already (changes with only cached flag) - if (paintTarget.needsToBePainted(p)) { - paintTarget.startTag("change"); - paintTarget.addAttribute("format", "uidl"); - final String pid = getPaintableId(p); - paintTarget.addAttribute("pid", pid); - - p.paint(paintTarget); - - paintTarget.endTag("change"); - } - paintablePainted(p); - - if (analyzeLayouts) { - Window w = (Window) p; - invalidComponentRelativeSizes = ComponentSizeValidator - .validateComponentRelativeSizes(w.getContent(), - null, null); - - // Also check any existing subwindows - if (w.getChildWindows() != null) { - for (Window subWindow : w.getChildWindows()) { - invalidComponentRelativeSizes = ComponentSizeValidator - .validateComponentRelativeSizes( - subWindow.getContent(), - invalidComponentRelativeSizes, - null); - } - } - } - } - } - - paintTarget.close(); - outWriter.print("]"); // close changes - - outWriter.print(", \"meta\" : {"); - boolean metaOpen = false; - - if (repaintAll) { - metaOpen = true; - outWriter.write("\"repaintAll\":true"); - if (analyzeLayouts) { - outWriter.write(", \"invalidLayouts\":"); - outWriter.write("["); - if (invalidComponentRelativeSizes != null) { - boolean first = true; - for (InvalidLayout invalidLayout : invalidComponentRelativeSizes) { - if (!first) { - outWriter.write(","); - } else { - first = false; - } - invalidLayout.reportErrors(outWriter, this, - System.err); - } - } - outWriter.write("]"); - } - } - - SystemMessages ci = null; - try { - Method m = application.getClass().getMethod( - "getSystemMessages", (Class[]) null); - ci = (Application.SystemMessages) m.invoke(null, - (Object[]) null); - } catch (NoSuchMethodException e1) { - e1.printStackTrace(); - } catch (IllegalArgumentException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - - // meta instruction for client to enable auto-forward to - // sessionExpiredURL after timer expires. - if (ci != null && ci.getSessionExpiredMessage() == null - && ci.getSessionExpiredCaption() == null - && ci.isSessionExpiredNotificationEnabled()) { - int newTimeoutInterval; - if (request instanceof ResourceRequest) { - newTimeoutInterval = ((ResourceRequest) request) - .getPortletSession().getMaxInactiveInterval(); - } else { - newTimeoutInterval = ((HttpServletRequest) request) - .getSession().getMaxInactiveInterval(); - } - if (repaintAll || (timeoutInterval != newTimeoutInterval)) { - String escapedURL = ci.getSessionExpiredURL() == null ? "" - : ci.getSessionExpiredURL().replace("/", "\\/"); - if (metaOpen) { - outWriter.write(","); - } - outWriter.write("\"timedRedirect\":{\"interval\":" - + (newTimeoutInterval + 15) + ",\"url\":\"" - + escapedURL + "\"}"); - metaOpen = true; - } - timeoutInterval = newTimeoutInterval; - } - - outWriter.print("}, \"resources\" : {"); - - // Precache custom layouts - String themeName = window.getTheme(); - String requestThemeName; - if (request instanceof ResourceRequest) { - requestThemeName = ((ResourceRequest) request) - .getParameter("theme"); - } else { - requestThemeName = ((HttpServletRequest) request) - .getParameter("theme"); - } - if (requestThemeName != null) { - themeName = requestThemeName; - } - if (themeName == null) { - themeName = AbstractApplicationServlet.getDefaultTheme(); - } - - // TODO We should only precache the layouts that are not - // cached already (plagiate from usedPaintableTypes) - int resourceIndex = 0; - for (final Iterator i = paintTarget.getUsedResources().iterator(); i - .hasNext();) { - final String resource = (String) i.next(); - InputStream is = null; - try { - is = applicationServlet - .getServletContext() - .getResourceAsStream( - "/" - + ApplicationServlet.THEME_DIRECTORY_PATH - + themeName + "/" + resource); - } catch (final Exception e) { - // FIXME: Handle exception - e.printStackTrace(); - } - if (is != null) { - - outWriter.print((resourceIndex++ > 0 ? ", " : "") + "\"" - + resource + "\" : "); - final StringBuffer layout = new StringBuffer(); - - try { - final InputStreamReader r = new InputStreamReader(is, - "UTF-8"); - final char[] buffer = new char[20000]; - int charsRead = 0; - while ((charsRead = r.read(buffer)) > 0) { - layout.append(buffer, 0, charsRead); - } - r.close(); - } catch (final java.io.IOException e) { - // FIXME: Handle exception - if (request instanceof ResourceRequest) { - System.err.println("Resource transfer failed: " - + ((ResourceRequest) request) - .getResourceID() + ". (" - + e.getMessage() + ")"); - } else { - System.err.println("Resource transfer failed: " - + ((HttpServletRequest) request) - .getRequestURI() + ". (" - + e.getMessage() + ")"); - } - } - outWriter.print("\"" - + JsonPaintTarget.escapeJSON(layout.toString()) - + "\""); - } else { - // FIXME: Handle exception - System.err.println("CustomLayout " + "/" - + ApplicationServlet.THEME_DIRECTORY_PATH - + themeName + "/" + resource + " not found!"); - } - } - outWriter.print("}"); - - Collection<Class<? extends Paintable>> usedPaintableTypes = paintTarget - .getUsedPaintableTypes(); - boolean typeMappingsOpen = false; - for (Class<? extends Paintable> class1 : usedPaintableTypes) { - if (windowCache.cache(class1)) { - // client does not know the mapping key for this type, send - // mapping to client - if (!typeMappingsOpen) { - typeMappingsOpen = true; - outWriter.print(", \"typeMappings\" : { "); - } else { - outWriter.print(" , "); - } - String canonicalName = class1.getCanonicalName(); - outWriter.print("\""); - outWriter.print(canonicalName); - outWriter.print("\" : "); - outWriter.print(getTagForType(class1)); - } - } - if (typeMappingsOpen) { - outWriter.print(" }"); - } - - printLocaleDeclarations(outWriter); - - outWriter.print("}]"); + public void setAttribute(String name, Object o) { + request.setAttribute(name, o); } - outWriter.flush(); - outWriter.close(); - } - /** - * If this method returns false, something was submitted that we did not - * expect; this is probably due to the client being out-of-sync and sending - * variable changes for non-existing pids - * - * @param request - * @param application2 - * @return true if successful, false if there was an inconsistency - * @throws IOException - */ - private boolean handleVariables(Object request, Object response, - AbstractApplicationServlet applicationServlet, - Application application2, Window window) throws IOException, - InvalidUIDLSecurityKeyException { - boolean success = true; - int contentLength; - if (request instanceof ResourceRequest) { - contentLength = ((ResourceRequest) request).getContentLength(); - } else { - contentLength = ((HttpServletRequest) request).getContentLength(); - } - - if (contentLength > 0) { - String changes = readRequest(request); - - // Manage bursts one by one - final String[] bursts = changes.split(VAR_BURST_SEPARATOR); - - // Security: double cookie submission pattern unless disabled by - // property - if (!"true" - .equals(application2 - .getProperty(AbstractApplicationServlet.SERVLET_PARAMETER_DISABLE_XSRF_PROTECTION))) { - if (bursts.length == 1 && "init".equals(bursts[0])) { - // init request; don't handle any variables, key sent in - // response. - if (request instanceof ResourceRequest) { - ((ResourceRequest) request).setAttribute( - WRITE_SECURITY_TOKEN_FLAG, true); - } else { - ((HttpServletRequest) request).setAttribute( - WRITE_SECURITY_TOKEN_FLAG, true); - } - return true; - } else { - // ApplicationServlet has stored the security token in the - // session; check that it matched the one sent in the UIDL - String sessId; - if (request instanceof ResourceRequest) { - sessId = (String) ((ResourceRequest) request) - .getPortletSession() - .getAttribute( - ApplicationConnection.UIDL_SECURITY_TOKEN_ID); - } else { - sessId = (String) ((HttpServletRequest) request) - .getSession() - .getAttribute( - ApplicationConnection.UIDL_SECURITY_TOKEN_ID); - } - if (sessId == null || !sessId.equals(bursts[0])) { - throw new InvalidUIDLSecurityKeyException( - "Security key mismatch"); - } - } + private static class HttpServletResponseWrapper implements Response { - } + private final HttpServletResponse response; - for (int bi = 1; bi < bursts.length; bi++) { - - // extract variables to two dim string array - final String[] tmp = bursts[bi].split(VAR_RECORD_SEPARATOR); - final String[][] variableRecords = new String[tmp.length][4]; - for (int i = 0; i < tmp.length; i++) { - variableRecords[i] = tmp[i].split(VAR_FIELD_SEPARATOR); - } - - for (int i = 0; i < variableRecords.length; i++) { - String[] variable = variableRecords[i]; - String[] nextVariable = null; - if (i + 1 < variableRecords.length) { - nextVariable = variableRecords[i + 1]; - } - final VariableOwner owner = (VariableOwner) idPaintableMap - .get(variable[VAR_PID]); - if (owner != null && owner.isEnabled()) { - Map m; - if (nextVariable != null - && variable[VAR_PID] - .equals(nextVariable[VAR_PID])) { - // we have more than one value changes in row for - // one variable owner, collect em in HashMap - m = new HashMap(); - m.put(variable[VAR_NAME], convertVariableValue( - variable[VAR_TYPE].charAt(0), - variable[VAR_VALUE])); - } else { - // use optimized single value map - m = new SingleValueMap(variable[VAR_NAME], - convertVariableValue(variable[VAR_TYPE] - .charAt(0), variable[VAR_VALUE])); - } - - // collect following variable changes for this owner - while (nextVariable != null - && variable[VAR_PID] - .equals(nextVariable[VAR_PID])) { - i++; - variable = nextVariable; - if (i + 1 < variableRecords.length) { - nextVariable = variableRecords[i + 1]; - } else { - nextVariable = null; - } - m.put(variable[VAR_NAME], convertVariableValue( - variable[VAR_TYPE].charAt(0), - variable[VAR_VALUE])); - } - try { - owner.changeVariables(request, m); - - // Special-case of closing browser-level windows: - // track browser-windows currently open in client - if (owner instanceof Window - && ((Window) owner).getParent() == null) { - final Boolean close = (Boolean) m.get("close"); - if (close != null && close.booleanValue()) { - closingWindowName = ((Window) owner) - .getName(); - } - } - } catch (Exception e) { - handleChangeVariablesError(application2, - (Component) owner, e, m); - } - } else { - - // Handle special case where window-close is called - // after the window has been removed from the - // application or the application has closed - if ("close".equals(variable[VAR_NAME]) - && "true".equals(variable[VAR_VALUE])) { - // Silently ignore this - continue; - } - - // Ignore variable change - String msg = "Warning: Ignoring variable change for "; - if (owner != null) { - msg += "disabled component " + owner.getClass(); - String caption = ((Component) owner).getCaption(); - if (caption != null) { - msg += ", caption=" + caption; - } - } else { - msg += "non-existent component, VAR_PID=" - + variable[VAR_PID]; - success = false; - } - System.err.println(msg); - continue; - } - } - - // In case that there were multiple bursts, we know that this is - // a special synchronous case for closing window. Thus we are - // not interested in sending any UIDL changes back to client. - // Still we must clear component tree between bursts to ensure - // that no removed components are updated. The painting after - // the last burst is handled normally by the calling method. - if (bi < bursts.length - 1) { - - // We will be discarding all changes - final PrintWriter outWriter = new PrintWriter( - new CharArrayWriter()); - try { - paintAfterVariablechanges(request, response, - applicationServlet, true, outWriter, window, - false); - - } catch (ServletException e) { - // We will ignore all servlet exceptions - } - } - - } + public HttpServletResponseWrapper(HttpServletResponse response) { + this.response = response; } - return success; - } - - /** - * Reads the request data from the HttpServletRequest or ResourceRequest and - * returns it converted to an UTF-8 string. - * - * @param request - * @return - * @throws IOException - */ - private static String readRequest(Object request) throws IOException { - int requestLength; - - if (request instanceof ResourceRequest) { - requestLength = ((ResourceRequest) request).getContentLength(); - } else { // Will throw ClassCastException if invalid request type - requestLength = ((HttpServletRequest) request).getContentLength(); + public OutputStream getOutputStream() throws IOException { + return response.getOutputStream(); } - byte[] buffer = new byte[requestLength]; - InputStream inputStream; - if (request instanceof ResourceRequest) { - inputStream = ((ResourceRequest) request).getPortletInputStream(); - } else { - inputStream = ((HttpServletRequest) request).getInputStream(); + public Object getWrappedResponse() { + return response; } - int bytesRemaining = requestLength; - while (bytesRemaining > 0) { - int bytesToRead = Math.min(bytesRemaining, MAX_BUFFER_SIZE); - int bytesRead = inputStream.read(buffer, requestLength - - bytesRemaining, bytesToRead); - if (bytesRead == -1) { - break; - } - - bytesRemaining -= bytesRead; + public void setContentType(String type) { + response.setContentType(type); } - String result = new String(buffer, "utf-8"); - - return result; } - public class ErrorHandlerErrorEvent implements ErrorEvent, Serializable { - private final Throwable throwable; + private static class HttpSessionWrapper implements Session { - public ErrorHandlerErrorEvent(Throwable throwable) { - this.throwable = throwable; - } + private final HttpSession session; - public Throwable getThrowable() { - return throwable; + public HttpSessionWrapper(HttpSession session) { + this.session = session; } - } - - private void handleChangeVariablesError(Application application, - Component owner, Exception e, Map m) { - boolean handled = false; - ChangeVariablesErrorEvent errorEvent = new ChangeVariablesErrorEvent( - owner, e, m); - - if (owner instanceof AbstractField) { - try { - handled = ((AbstractField) owner).handleError(errorEvent); - } catch (Exception handlerException) { - /* - * If there is an error in the component error handler we pass - * the that error to the application error handler and continue - * processing the actual error - */ - application.getErrorHandler().terminalError( - new ErrorHandlerErrorEvent(handlerException)); - handled = false; - } + public Object getAttribute(String name) { + return session.getAttribute(name); } - if (!handled) { - application.getErrorHandler().terminalError(errorEvent); + public int getMaxInactiveInterval() { + return session.getMaxInactiveInterval(); } - } - - private Object convertVariableValue(char variableType, String strValue) { - Object val = null; - switch (variableType) { - case 'a': - val = strValue.split(VAR_ARRAYITEM_SEPARATOR); - break; - case 's': - val = strValue; - break; - case 'i': - val = Integer.valueOf(strValue); - break; - case 'l': - val = Long.valueOf(strValue); - break; - case 'f': - val = Float.valueOf(strValue); - break; - case 'd': - val = Double.valueOf(strValue); - break; - case 'b': - val = Boolean.valueOf(strValue); - break; - case 'p': - val = idPaintableMap.get(strValue); - break; + public Object getWrappedSession() { + return session; } - return val; - } - - private void printLocaleDeclarations(PrintWriter outWriter) { - /* - * ----------------------------- Sending Locale sensitive date - * ----------------------------- - */ - - // Send locale informations to client - outWriter.print(", \"locales\":["); - for (; pendingLocalesIndex < locales.size(); pendingLocalesIndex++) { - - final Locale l = generateLocale(locales.get(pendingLocalesIndex)); - // Locale name - outWriter.print("{\"name\":\"" + l.toString() + "\","); - - /* - * Month names (both short and full) - */ - final DateFormatSymbols dfs = new DateFormatSymbols(l); - final String[] short_months = dfs.getShortMonths(); - final String[] months = dfs.getMonths(); - outWriter.print("\"smn\":[\"" - + // ShortMonthNames - short_months[0] + "\",\"" + short_months[1] + "\",\"" - + short_months[2] + "\",\"" + short_months[3] + "\",\"" - + short_months[4] + "\",\"" + short_months[5] + "\",\"" - + short_months[6] + "\",\"" + short_months[7] + "\",\"" - + short_months[8] + "\",\"" + short_months[9] + "\",\"" - + short_months[10] + "\",\"" + short_months[11] + "\"" - + "],"); - outWriter.print("\"mn\":[\"" - + // MonthNames - months[0] + "\",\"" + months[1] + "\",\"" + months[2] - + "\",\"" + months[3] + "\",\"" + months[4] + "\",\"" - + months[5] + "\",\"" + months[6] + "\",\"" + months[7] - + "\",\"" + months[8] + "\",\"" + months[9] + "\",\"" - + months[10] + "\",\"" + months[11] + "\"" + "],"); - - /* - * Weekday names (both short and full) - */ - final String[] short_days = dfs.getShortWeekdays(); - final String[] days = dfs.getWeekdays(); - outWriter.print("\"sdn\":[\"" - + // ShortDayNames - short_days[1] + "\",\"" + short_days[2] + "\",\"" - + short_days[3] + "\",\"" + short_days[4] + "\",\"" - + short_days[5] + "\",\"" + short_days[6] + "\",\"" - + short_days[7] + "\"" + "],"); - outWriter.print("\"dn\":[\"" - + // DayNames - days[1] + "\",\"" + days[2] + "\",\"" + days[3] + "\",\"" - + days[4] + "\",\"" + days[5] + "\",\"" + days[6] + "\",\"" - + days[7] + "\"" + "],"); - - /* - * First day of week (0 = sunday, 1 = monday) - */ - final Calendar cal = new GregorianCalendar(l); - outWriter.print("\"fdow\":" + (cal.getFirstDayOfWeek() - 1) + ","); - - /* - * Date formatting (MM/DD/YYYY etc.) - */ - - DateFormat dateFormat = DateFormat.getDateTimeInstance( - DateFormat.SHORT, DateFormat.SHORT, l); - if (!(dateFormat instanceof SimpleDateFormat)) { - System.err - .println("Unable to get default date pattern for locale " - + l.toString()); - dateFormat = new SimpleDateFormat(); - } - final String df = ((SimpleDateFormat) dateFormat).toPattern(); - - int timeStart = df.indexOf("H"); - if (timeStart < 0) { - timeStart = df.indexOf("h"); - } - final int ampm_first = df.indexOf("a"); - // E.g. in Korean locale AM/PM is before h:mm - // TODO should take that into consideration on client-side as well, - // now always h:mm a - if (ampm_first > 0 && ampm_first < timeStart) { - timeStart = ampm_first; - } - // Hebrew locale has time before the date - final boolean timeFirst = timeStart == 0; - String dateformat; - if (timeFirst) { - int dateStart = df.indexOf(' '); - if (ampm_first > dateStart) { - dateStart = df.indexOf(' ', ampm_first); - } - dateformat = df.substring(dateStart + 1); - } else { - dateformat = df.substring(0, timeStart - 1); - } - - outWriter.print("\"df\":\"" + dateformat.trim() + "\","); - - /* - * Time formatting (24 or 12 hour clock and AM/PM suffixes) - */ - final String timeformat = df.substring(timeStart, df.length()); - /* - * Doesn't return second or milliseconds. - * - * We use timeformat to determine 12/24-hour clock - */ - final boolean twelve_hour_clock = timeformat.indexOf("a") > -1; - // TODO there are other possibilities as well, like 'h' in french - // (ignore them, too complicated) - final String hour_min_delimiter = timeformat.indexOf(".") > -1 ? "." - : ":"; - // outWriter.print("\"tf\":\"" + timeformat + "\","); - outWriter.print("\"thc\":" + twelve_hour_clock + ","); - outWriter.print("\"hmd\":\"" + hour_min_delimiter + "\""); - if (twelve_hour_clock) { - final String[] ampm = dfs.getAmPmStrings(); - outWriter.print(",\"ampm\":[\"" + ampm[0] + "\",\"" + ampm[1] - + "\"]"); - } - outWriter.print("}"); - if (pendingLocalesIndex < locales.size() - 1) { - outWriter.print(","); - } + public boolean isNew() { + return session.isNew(); } - outWriter.print("]"); // Close locales - } - /** - * Gets the existing application or create a new one. Get a window within an - * application based on the requested URI. - * - * @param request - * the HTTP Request. - * @param application - * the Application to query for window. - * @param assumedWindow - * if the window has been already resolved once, this parameter - * must contain the window. - * @return Window mathing the given URI or null if not found. - * @throws ServletException - * if an exception has occurred that interferes with the - * servlet's normal operation. - */ - Window getApplicationWindow(HttpServletRequest request, - AbstractApplicationServlet applicationServlet, - Application application, Window assumedWindow) - throws ServletException { - return doGetApplicationWindow((Object) request, applicationServlet, - application, assumedWindow); - } - - /** - * TODO New method - document me! - * - * @param request - * @param application - * @param assumedWindow - * @return - * @throws PortletException - */ - Window getApplicationWindow(ResourceRequest request, - Application application, Window assumedWindow) - throws PortletException { - try { - return doGetApplicationWindow((Object) request, null, application, - assumedWindow); - } catch (ServletException e) { - throw new PortletException(e.getMessage(), e.getCause()); + public void setAttribute(String name, Object o) { + session.setAttribute(name, o); } - } - private Window doGetApplicationWindow(Object request, - AbstractApplicationServlet applicationServlet, - Application application, Window assumedWindow) - throws ServletException { + } - Window window = null; + private static class AbstractApplicationServletWrapper implements Callback { - // If the client knows which window to use, use it if possible - String windowClientRequestedName; - if (request instanceof ResourceRequest) { - windowClientRequestedName = ((ResourceRequest) request) - .getParameter("windowName"); - } else { - windowClientRequestedName = ((HttpServletRequest) request) - .getParameter("windowName"); - } + private final AbstractApplicationServlet servlet; - if (assumedWindow != null - && application.getWindows().contains(assumedWindow)) { - windowClientRequestedName = assumedWindow.getName(); - } - if (windowClientRequestedName != null) { - window = application.getWindow(windowClientRequestedName); - if (window != null) { - return window; - } + public AbstractApplicationServletWrapper( + AbstractApplicationServlet servlet) { + this.servlet = servlet; } - // If client does not know what window it wants - if (window == null && request instanceof HttpServletRequest) { - // This is only supported if the application is running inside a - // servlet - - // Get the path from URL - String path = applicationServlet - .getRequestPathInfo((HttpServletRequest) request); - if (path != null && path.startsWith("/UIDL")) { - path = path.substring("/UIDL".length()); - } - - // If the path is specified, create name from it - if (path != null && path.length() > 0 && !path.equals("/")) { - String windowUrlName = null; - if (path.charAt(0) == '/') { - path = path.substring(1); - } - final int index = path.indexOf('/'); - if (index < 0) { - windowUrlName = path; - path = ""; - } else { - windowUrlName = path.substring(0, index); - path = path.substring(index + 1); - } - - window = application.getWindow(windowUrlName); - } + public void criticalNotification(Request request, Response response, + String cap, String msg, String details, String outOfSyncURL) + throws IOException { + servlet.criticalNotification((HttpServletRequest) request + .getWrappedRequest(), (HttpServletResponse) response + .getWrappedResponse(), cap, msg, details, outOfSyncURL); } - // By default, use mainwindow - if (window == null) { - window = application.getMainWindow(); - // Return null if no main window was found - if (window == null) { - return null; - } + public String getRequestPathInfo(Request request) { + return servlet.getRequestPathInfo((HttpServletRequest) request + .getWrappedRequest()); } - // If the requested window is already open, resolve conflict - if (currentlyOpenWindowsInClient.containsKey(window.getName())) { - String newWindowName = window.getName(); - while (currentlyOpenWindowsInClient.containsKey(newWindowName)) { - newWindowName = window.getName() + "_" - + ((int) (Math.random() * 100000000)); - } - - window = application.getWindow(newWindowName); - - // If everything else fails, use main window even in case of - // conflicts - if (window == null) { - window = application.getMainWindow(); - } + public InputStream getThemeResourceAsStream(String themeName, + String resource) throws IOException { + return servlet.getServletContext().getResourceAsStream( + "/" + AbstractApplicationServlet.THEME_DIRECTORY_PATH + + themeName + "/" + resource); } - return window; } /** - * Ends the Application. - * - * @param request - * the HTTP/Resource request instance. - * @param response - * the HTTP/Resource response to write to. + * @deprecated use {@link #CommunicationManager(Application)} instead * @param application - * the Application to end. - * @throws IOException - * if the writing failed due to input/output error. + * @param applicationServlet */ - private void endApplication(Object request, Object response, - Application application) throws IOException { - - String logoutUrl = application.getLogoutURL(); - if (logoutUrl == null) { - logoutUrl = application.getURL().toString(); - } - // clients JS app is still running, send a special json file to tell - // client that application has quit and where to point browser now - // Set the response type - final OutputStream out; - if (response instanceof ResourceResponse) { - ((ResourceResponse) response) - .setContentType("application/json; charset=UTF-8"); - out = ((ResourceResponse) response).getPortletOutputStream(); - } else { // Will throw ClassCastException if invalid response - ((HttpServletResponse) response) - .setContentType("application/json; charset=UTF-8"); - out = ((HttpServletResponse) response).getOutputStream(); - } - final PrintWriter outWriter = new PrintWriter(new BufferedWriter( - new OutputStreamWriter(out, "UTF-8"))); - outWriter.print("for(;;);[{"); - outWriter.print("\"redirect\":{"); - outWriter.write("\"url\":\"" + logoutUrl + "\"}}]"); - outWriter.flush(); - outWriter.close(); - out.flush(); + @Deprecated + public CommunicationManager(Application application, + AbstractApplicationServlet applicationServlet) { + super(application); } /** - * Gets the Paintable Id. If Paintable has debug id set it will be used - * prefixed with "PID_S". Otherwise a sequenced ID is created. + * TODO New constructor - document me! * - * @param paintable - * @return the paintable Id. + * @param application */ - public String getPaintableId(Paintable paintable) { - - String id = paintableIdMap.get(paintable); - if (id == null) { - // use testing identifier as id if set - id = paintable.getDebugId(); - if (id == null) { - id = "PID" + Integer.toString(idSequence++); - } else { - id = "PID_S" + id; - } - Paintable old = idPaintableMap.put(id, paintable); - if (old != null && old != paintable) { - /* - * Two paintables have the same id. We still make sure the old - * one is a component which is still attached to the - * application. This is just a precaution and should not be - * absolutely necessary. - */ - - if (old instanceof Component - && ((Component) old).getApplication() != null) { - throw new IllegalStateException("Two paintables (" - + paintable.getClass().getSimpleName() + "," - + old.getClass().getSimpleName() - + ") have been assigned the same id: " - + paintable.getDebugId()); - } - } - paintableIdMap.put(paintable, id); - } - - return id; - } - - public boolean hasPaintableId(Paintable paintable) { - return paintableIdMap.containsKey(paintable); + public CommunicationManager(Application application) { + super(application); } - /** - * Returns dirty components which are in given window. Components in an - * invisible subtrees are omitted. - * - * @param w - * root window for which dirty components is to be fetched - * @return - */ - private ArrayList<Paintable> getDirtyVisibleComponents(Window w) { - final ArrayList<Paintable> resultset = new ArrayList<Paintable>( - dirtyPaintabletSet); - - // The following algorithm removes any components that would be painted - // as a direct descendant of other components from the dirty components - // list. The result is that each component should be painted exactly - // once and any unmodified components will be painted as "cached=true". - - for (final Iterator<Paintable> i = dirtyPaintabletSet.iterator(); i - .hasNext();) { - final Paintable p = i.next(); - if (p instanceof Component) { - final Component component = (Component) p; - if (component.getApplication() == null) { - // component is detached after requestRepaint is called - resultset.remove(p); - i.remove(); - } else { - Window componentsRoot = component.getWindow(); - if (componentsRoot.getParent() != null) { - // this is a subwindow - componentsRoot = (Window) componentsRoot.getParent(); - } - if (componentsRoot != w) { - resultset.remove(p); - } else if (component.getParent() != null - && !component.getParent().isVisible()) { - /* - * Do not return components in an invisible subtree. - * - * Components that are invisible in visible subree, must - * be rendered (to let client know that they need to be - * hidden). - */ - resultset.remove(p); - } - } - } - } - - return resultset; + @Override + protected FileUpload createFileUpload() { + return new ServletFileUpload(); } - /** - * @see com.vaadin.terminal.Paintable.RepaintRequestListener#repaintRequested(com.vaadin.terminal.Paintable.RepaintRequestEvent) - */ - public void repaintRequested(RepaintRequestEvent event) { - final Paintable p = event.getPaintable(); - if (!dirtyPaintabletSet.contains(p)) { - dirtyPaintabletSet.add(p); - } + @Override + protected FileItemIterator getItemIterator(FileUpload upload, + Request request) throws IOException, FileUploadException { + return ((ServletFileUpload) upload) + .getItemIterator((HttpServletRequest) request + .getWrappedRequest()); } /** + * Handles file upload request submitted via Upload component. * - * @param p + * @param request + * @param response + * @throws IOException + * @throws FileUploadException */ - private void paintablePainted(Paintable p) { - dirtyPaintabletSet.remove(p); - p.requestRepaintRequests(); - } - - private final class SingleValueMap implements Map<Object, Object>, - Serializable { - - private final String name; - - private final Object value; - - private SingleValueMap(String name, Object value) { - this.name = name; - this.value = value; - } - - public void clear() { - throw new UnsupportedOperationException(); - } - - public boolean containsKey(Object key) { - if (name == null) { - return key == null; - } - return name.equals(key); - } - - public boolean containsValue(Object v) { - if (value == null) { - return v == null; - } - return value.equals(v); - } - - public Set entrySet() { - final Set s = new HashSet(); - s.add(new Map.Entry() { - - public Object getKey() { - return name; - } - - public Object getValue() { - return value; - } - - public Object setValue(Object value) { - throw new UnsupportedOperationException(); - } - }); - return s; - } - - public Object get(Object key) { - if (!name.equals(key)) { - return null; - } - return value; - } - - public boolean isEmpty() { - return false; - } - - public Set keySet() { - final Set s = new HashSet(); - s.add(name); - return s; - } - - public Object put(Object key, Object value) { - throw new UnsupportedOperationException(); - } - - public void putAll(Map t) { - throw new UnsupportedOperationException(); - } - - public Object remove(Object key) { - throw new UnsupportedOperationException(); - } - - public int size() { - return 1; - } - - public Collection values() { - final LinkedList s = new LinkedList(); - s.add(value); - return s; - - } + public void handleFileUpload(HttpServletRequest request, + HttpServletResponse response) throws IOException, + FileUploadException { + doHandleFileUpload(new HttpServletRequestWrapper(request), + new HttpServletResponseWrapper(response)); } /** - * Implementation of URIHandler.ErrorEvent interface. - */ - public class URIHandlerErrorImpl implements URIHandler.ErrorEvent, - Serializable { - - private final URIHandler owner; - - private final Throwable throwable; - - /** - * - * @param owner - * @param throwable - */ - private URIHandlerErrorImpl(URIHandler owner, Throwable throwable) { - this.owner = owner; - this.throwable = throwable; - } - - /** - * @see com.vaadin.terminal.Terminal.ErrorEvent#getThrowable() - */ - public Throwable getThrowable() { - return throwable; - } - - /** - * @see com.vaadin.terminal.URIHandler.ErrorEvent#getURIHandler() - */ - public URIHandler getURIHandler() { - return owner; - } - } - - public void requireLocale(String value) { - if (locales == null) { - locales = new ArrayList<String>(); - locales.add(application.getLocale().toString()); - pendingLocalesIndex = 0; - } - if (!locales.contains(value)) { - locales.add(value); - } - } - - private Locale generateLocale(String value) { - final String[] temp = value.split("_"); - if (temp.length == 1) { - return new Locale(temp[0]); - } else if (temp.length == 2) { - return new Locale(temp[0], temp[1]); - } else { - return new Locale(temp[0], temp[1], temp[2]); - } - } - - /* - * Upload progress listener notifies upload component once when Jakarta - * FileUpload can determine content length. Used to detect files total size, - * uploads progress can be tracked inside upload. + * Handles UIDL request + * + * @param request + * @param response + * @throws IOException + * @throws ServletException */ - private class UploadProgressListener implements ProgressListener, - Serializable { - - Upload uploadComponent; - - boolean updated = false; - - public void setUpload(Upload u) { - uploadComponent = u; - } - - public void update(long bytesRead, long contentLength, int items) { - if (!updated && uploadComponent != null) { - uploadComponent.setUploadSize(contentLength); - updated = true; - } - } + public void handleUidlRequest(HttpServletRequest request, + HttpServletResponse response, + AbstractApplicationServlet applicationServlet) throws IOException, + ServletException, InvalidUIDLSecurityKeyException { + doHandleUidlRequest(new HttpServletRequestWrapper(request), + new HttpServletResponseWrapper(response), + new AbstractApplicationServletWrapper(applicationServlet)); } /** - * Helper method to test if a component contains another + * Gets the existing application or create a new one. Get a window within an + * application based on the requested URI. * - * @param parent - * @param child + * @param request + * the HTTP Request. + * @param application + * the Application to query for window. + * @param assumedWindow + * if the window has been already resolved once, this parameter + * must contain the window. + * @return Window mathing the given URI or null if not found. + * @throws ServletException + * if an exception has occurred that interferes with the + * servlet's normal operation. */ - private static boolean isChildOf(Component parent, Component child) { - Component p = child.getParent(); - while (p != null) { - if (parent == p) { - return true; - } - p = p.getParent(); - } - return false; - } - - private class InvalidUIDLSecurityKeyException extends - GeneralSecurityException { - - InvalidUIDLSecurityKeyException(String message) { - super(message); - } - + Window getApplicationWindow(HttpServletRequest request, + AbstractApplicationServlet applicationServlet, + Application application, Window assumedWindow) + throws ServletException { + return doGetApplicationWindow(new HttpServletRequestWrapper(request), + new AbstractApplicationServletWrapper(applicationServlet), + application, assumedWindow); } /** - * Handles the requested URI. An application can add handlers to do special - * processing, when a certain URI is requested. The handlers are invoked - * before any windows URIs are processed and if a DownloadStream is returned - * it is sent to the client. + * TODO Document me! * - * @param application - * the Application owning the URI. + * @param window * @param request - * the HTTP request instance. * @param response - * the HTTP response to write to. - * @return boolean <code>true</code> if the request was handled and further - * processing should be suppressed, <code>false</code> otherwise. - * @see com.vaadin.terminal.URIHandler + * @param applicationServlet + * @return */ DownloadStream handleURI(Window window, HttpServletRequest request, HttpServletResponse response, AbstractApplicationServlet applicationServlet) { - - String uri = applicationServlet.getRequestPathInfo(request); - - // If no URI is available - if (uri == null) { - uri = ""; - } else { - // Removes the leading / - while (uri.startsWith("/") && uri.length() > 0) { - uri = uri.substring(1); - } - } - - // Handles the uri - try { - URL context = application.getURL(); - if (window == application.getMainWindow()) { - DownloadStream stream = null; - /* - * Application.handleURI run first. Handles possible - * ApplicationResources. - */ - stream = application.handleURI(context, uri); - if (stream == null) { - stream = window.handleURI(context, uri); - } - return stream; - } else { - // Resolve the prefix end inded - final int index = uri.indexOf('/'); - if (index > 0) { - String prefix = uri.substring(0, index); - URL windowContext; - windowContext = new URL(context, prefix + "/"); - final String windowUri = (uri.length() > prefix.length() + 1) ? uri - .substring(prefix.length() + 1) - : ""; - return window.handleURI(windowContext, windowUri); - } else { - return null; - } - } - - } catch (final Throwable t) { - application.getErrorHandler().terminalError( - new URIHandlerErrorImpl(application, t)); - return null; - } + return handleURI(window, new HttpServletRequestWrapper(request), + new HttpServletResponseWrapper(response), + new AbstractApplicationServletWrapper(applicationServlet)); } - private static HashMap<Class<? extends Paintable>, Integer> typeToKey = new HashMap<Class<? extends Paintable>, Integer>(); - private static int nextTypeKey = 0; - - static String getTagForType(Class<? extends Paintable> class1) { - synchronized (typeToKey) { - Integer object = typeToKey.get(class1); - if (object == null) { - object = nextTypeKey++; - typeToKey.put(class1, object); - } - return object.toString(); - } - } - - /** - * Helper class for terminal to keep track of data that client is expected - * to know. - * - * TODO make customlayout templates (from theme) to be cached here. - */ - class OpenWindowCache implements Serializable { - - private Set<Object> res = new HashSet<Object>(); - - /** - * - * @param paintable - * @return true if the given class was added to cache - */ - boolean cache(Object object) { - return res.add(object); - } - - public void clear() { - res.clear(); - } - - } } |