]> source.dussan.org Git - vaadin-framework.git/commitdiff
Making the gwt adapter even more simple - removed variable map alltogether
authorJoonas Lehtinen <joonas.lehtinen@itmill.com>
Wed, 18 Jul 2007 12:59:08 +0000 (12:59 +0000)
committerJoonas Lehtinen <joonas.lehtinen@itmill.com>
Wed, 18 Jul 2007 12:59:08 +0000 (12:59 +0000)
svn changeset:1882/svn branch:trunk

src/com/itmill/toolkit/terminal/gwt/client/ApplicationConnection.java
src/com/itmill/toolkit/terminal/gwt/server/AjaxHttpUploadStream.java [deleted file]
src/com/itmill/toolkit/terminal/gwt/server/AjaxVariableMap.java [deleted file]
src/com/itmill/toolkit/terminal/gwt/server/ApplicationManager.java [deleted file]
src/com/itmill/toolkit/terminal/gwt/server/ApplicationServlet.java
src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java [new file with mode: 0644]
src/com/itmill/toolkit/terminal/gwt/server/HttpUploadStream.java [new file with mode: 0644]
src/com/itmill/toolkit/terminal/gwt/server/JsonPaintTarget.java
src/com/itmill/toolkit/terminal/gwt/server/Log.java
src/com/itmill/toolkit/terminal/gwt/server/MultipartRequest.java [deleted file]
src/com/itmill/toolkit/terminal/gwt/server/ServletMultipartRequest.java [deleted file]

index e1c490f4de7fbdba760107a32f2f0ea5eca9b81a..06824e5541d24c1a19b56bca2cf62da85556fb64 100755 (executable)
@@ -185,8 +185,8 @@ public class ApplicationConnection implements EntryPoint {
        }
 
        private void addVariableToQueue(String paintableId, String variableName,
-                       String encodedValue, boolean immediate) {
-               String id = paintableId + "_" + variableName;
+                       String encodedValue, boolean immediate, char type) {
+               String id = paintableId + "_" + variableName + "_" + type;
                for (int i = 0; i < pendingVariables.size(); i += 2)
                        if ((pendingVariables.get(i)).equals(id)) {
                                pendingVariables.remove(i);
@@ -202,37 +202,35 @@ public class ApplicationConnection implements EntryPoint {
        public void sendPendingVariableChanges() {
                StringBuffer req = new StringBuffer();
 
+               req.append("changes=");
                for (int i = 0; i < pendingVariables.size(); i++) {
-                       req.append(pendingVariables.get(i++));
-                       req.append("=");
+                       if (i>0) req.append("\u0001");
                        req.append(pendingVariables.get(i));
-                       req.append("&");
                }
 
                pendingVariables.clear();
                makeUidlRequest(req.toString());
        }
 
-       private String escapeString(String value) {
-               // TODO
-               return value;
-       }
+       private static native String escapeString(String value) /*-{
+               return encodeURIComponent(value);
+       }-*/;
 
        public void updateVariable(String paintableId, String variableName,
                        String newValue, boolean immediate) {
                addVariableToQueue(paintableId, variableName, escapeString(newValue),
-                               immediate);
+                               immediate, 's');
        }
 
        public void updateVariable(String paintableId, String variableName,
                        int newValue, boolean immediate) {
-               addVariableToQueue(paintableId, variableName, "" + newValue, immediate);
+               addVariableToQueue(paintableId, variableName, "" + newValue, immediate, 'i');
        }
 
        public void updateVariable(String paintableId, String variableName,
                        boolean newValue, boolean immediate) {
                addVariableToQueue(paintableId, variableName, newValue ? "true"
-                               : "false", immediate);
+                               : "false", immediate, 'b');
        }
 
        public void updateVariable(String paintableId, String variableName,
@@ -243,8 +241,8 @@ public class ApplicationConnection implements EntryPoint {
                                buf.append(",");
                        buf.append(escapeString(values[i].toString()));
                }
-               addVariableToQueue("array:" + paintableId, variableName,
-                               buf.toString(), immediate);
+               addVariableToQueue(paintableId, variableName,
+                               buf.toString(), immediate, 'a');
        }
 
        public WidgetFactory getWidgetFactory() {
diff --git a/src/com/itmill/toolkit/terminal/gwt/server/AjaxHttpUploadStream.java b/src/com/itmill/toolkit/terminal/gwt/server/AjaxHttpUploadStream.java
deleted file mode 100644 (file)
index e431d51..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/* *************************************************************************
- IT Mill Toolkit 
-
- Development of Browser User Interfaces Made Easy
-
- Copyright (C) 2000-2006 IT Mill Ltd
- *************************************************************************
-
- This product is distributed under commercial license that can be found
- from the product package on license.pdf. Use of this product might 
- require purchasing a commercial license from IT Mill Ltd. For guidelines 
- on usage, see licensing-guidelines.html
-
- *************************************************************************
- For more information, contact:
- IT Mill Ltd                           phone: +358 2 4802 7180
- Ruukinkatu 2-4                        fax:   +358 2 4802 7181
- 20540, Turku                          email:  info@itmill.com
- Finland                               company www: www.itmill.com
- Primary source for information and releases: www.itmill.com
-
- ********************************************************************** */
-
-package com.itmill.toolkit.terminal.gwt.server;
-
-import java.io.InputStream;
-
-/**
- * AjaxAdapter implementation of the UploadStream interface.
- * 
- * @author IT Mill Ltd.
- * @version
- * @VERSION@
- * @since 5.0
- */
-public class AjaxHttpUploadStream implements
-               com.itmill.toolkit.terminal.UploadStream {
-
-       /**
-        * Holds value of property variableName.
-        */
-       private String streamName;
-
-       private String contentName;
-
-       private String contentType;
-
-       /**
-        * Holds value of property variableValue.
-        */
-       private InputStream stream;
-
-       /**
-        * Creates a new instance of UploadStreamImpl.
-        * 
-        * @param name
-        *            the name of the stream.
-        * @param stream
-        *            the input stream.
-        * @param contentName
-        *            the name of the content.
-        * @param contentType
-        *            the type of the content.
-        */
-       public AjaxHttpUploadStream(String name, InputStream stream,
-                       String contentName, String contentType) {
-               this.streamName = name;
-               this.stream = stream;
-               this.contentName = contentName;
-               this.contentType = contentType;
-       }
-
-       /**
-        * Gets the name of the stream.
-        * 
-        * @return the name of the stream.
-        */
-       public String getStreamName() {
-               return this.streamName;
-       }
-
-       /**
-        * Gets the input stream.
-        * 
-        * @return the Input stream.
-        */
-       public InputStream getStream() {
-               return this.stream;
-       }
-
-       /**
-        * Gets the input stream content type.
-        * 
-        * @return the content type of the input stream.
-        */
-       public String getContentType() {
-               return this.contentType;
-       }
-
-       /**
-        * Gets the stream content name. Stream content name usually differs from
-        * the actual stream name. It is used to identify the content of the stream.
-        * 
-        * @return the Name of the stream content.
-        */
-       public String getContentName() {
-               return this.contentName;
-       }
-}
diff --git a/src/com/itmill/toolkit/terminal/gwt/server/AjaxVariableMap.java b/src/com/itmill/toolkit/terminal/gwt/server/AjaxVariableMap.java
deleted file mode 100644 (file)
index 54c0013..0000000
+++ /dev/null
@@ -1,803 +0,0 @@
-/* *************************************************************************
- IT Mill Toolkit 
-
- Development of Browser User Interfaces Made Easy
-
- Copyright (C) 2000-2006 IT Mill Ltd
- *************************************************************************
-
- This product is distributed under commercial license that can be found
- from the product package on license.pdf. Use of this product might 
- require purchasing a commercial license from IT Mill Ltd. For guidelines 
- on usage, see licensing-guidelines.html
-
- *************************************************************************
- For more information, contact:
- IT Mill Ltd                           phone: +358 2 4802 7180
- Ruukinkatu 2-4                        fax:   +358 2 4802 7181
- 20540, Turku                          email:  info@itmill.com
- Finland                               company www: www.itmill.com
- Primary source for information and releases: www.itmill.com
-
- ********************************************************************** */
-
-package com.itmill.toolkit.terminal.gwt.server;
-
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.WeakHashMap;
-
-import javax.servlet.http.HttpServletRequest;
-
-import com.itmill.toolkit.terminal.SystemError;
-import com.itmill.toolkit.terminal.Terminal;
-import com.itmill.toolkit.terminal.UploadStream;
-import com.itmill.toolkit.terminal.VariableOwner;
-
-/**
- * Variable map for ajax applications.
- * 
- * @author IT Mill Ltd.
- * @version
- * @VERSION@
- * @since 5.0
- */
-public class AjaxVariableMap {
-
-       // Id <-> (Owner,Name) mapping
-       private Map idToNameMap = new HashMap();
-
-       private Map idToTypeMap = new HashMap();
-
-       private Map idToOwnerMap = new HashMap();
-
-       private Map idToValueMap = new HashMap();
-
-       private Map ownerToNameToIdMap = new WeakHashMap();
-
-       private Object mapLock = new Object();
-
-       // Id generator
-       private long lastId = 0;
-
-       /**
-        * Converts the string to a supported class.
-        * 
-        * @param type
-        * @param value
-        * @return
-        * @throws java.lang.ClassCastException
-        *             if the code has attempted to cast an object to a subclass of
-        *             which it is not an instance
-        */
-       private static Object convert(Class type, String value)
-                       throws java.lang.ClassCastException {
-               try {
-
-                       // Boolean typed variables
-                       if (type.equals(Boolean.class))
-                               return new Boolean(!(value.equals("") || value.equals("false")));
-
-                       // Integer typed variables
-                       if (type.equals(Integer.class))
-                               return new Integer(value.trim());
-
-                       // String typed variables
-                       if (type.equals(String.class))
-                               return value;
-
-                       throw new ClassCastException("Unsupported type: " + type.getName());
-               } catch (NumberFormatException e) {
-                       return null;
-               }
-       }
-
-       /**
-        * Registers a new variable.
-        * 
-        * @param name
-        *            the Variable name.
-        * @param type
-        * @param value
-        * @param owner
-        *            the Listener for variable changes.
-        * @return id to assigned for this variable.
-        */
-       public String registerVariable(String name, Class type, Object value,
-                       VariableOwner owner) {
-
-               // Checks that the type of the class is supported
-               if (!(type.equals(Boolean.class) || type.equals(Integer.class)
-                               || type.equals(String.class) || type.equals(String[].class) || type
-                               .equals(UploadStream.class)))
-                       throw new SystemError("Unsupported variable type: "
-                                       + type.getClass());
-
-               synchronized (mapLock) {
-
-                       // Checks if the variable is already mapped
-                       HashMap nameToIdMap = (HashMap) ownerToNameToIdMap.get(owner);
-                       if (nameToIdMap == null) {
-                               nameToIdMap = new HashMap();
-                               ownerToNameToIdMap.put(owner, nameToIdMap);
-                       }
-                       String id = (String) nameToIdMap.get(name);
-
-                       if (id == null) {
-                               // Generates new id and register it
-
-// ----------
-// TODO This HACK is only included for testing GWT integration                         
-//Original                             id = "v" + String.valueOf(++lastId);
-                               Object pid = ApplicationManager.paintableIdMap.get(owner);
-                               id = pid + "_"+name;
-// ----------
-                               
-                               
-                               nameToIdMap.put(name, id);
-                               idToOwnerMap.put(id, new WeakReference(owner));
-                               idToNameMap.put(id, name);
-                               idToTypeMap.put(id, type);
-                       }
-
-                       idToValueMap.put(id, value);
-
-                       return id;
-               }
-       }
-
-       /**
-        * Unregisters the variable.
-        * 
-        * @param name
-        *            the Variable name.
-        * @param owner
-        *            the Listener for variable changes.
-        */
-       public void unregisterVariable(String name, VariableOwner owner) {
-
-               synchronized (mapLock) {
-
-                       // Get the id
-                       HashMap nameToIdMap = (HashMap) ownerToNameToIdMap.get(owner);
-                       if (nameToIdMap == null)
-                               return;
-                       String id = (String) nameToIdMap.get(name);
-                       if (id != null)
-                               return;
-
-                       // Remove all the mappings
-                       nameToIdMap.remove(name);
-                       if (nameToIdMap.isEmpty())
-                               ownerToNameToIdMap.remove(owner);
-                       idToNameMap.remove(id);
-                       idToTypeMap.remove(id);
-                       idToValueMap.remove(id);
-                       idToOwnerMap.remove(id);
-
-               }
-       }
-
-       /**
-        * @author IT Mill Ltd.
-        * @version
-        * @VERSION@
-        * @since 3.0
-        */
-       private class ParameterContainer {
-
-               /**
-                * Constructs the mapping: listener to set of listened parameter names.
-                */
-               private HashMap parameters = new HashMap();
-
-               /**
-                * Parameter values.
-                */
-               private HashMap values = new HashMap();
-
-               /**
-                * Multipart parser used for parsing the request.
-                */
-               private ServletMultipartRequest parser = null;
-
-               /**
-                * Name - Value mapping of parameters that are not variables.
-                */
-               private HashMap nonVariables = new HashMap();
-
-               /**
-                * Creates a new parameter container and parse the parameters from the
-                * request using GET, POST and POST/MULTIPART parsing
-                * 
-                * @param req
-                *            the Http request to handle.
-                * @throws IOException
-                *             if the writing failed due to input/output error.
-                */
-               public ParameterContainer(HttpServletRequest req) throws IOException {
-                       // Parse GET / POST parameters
-                       for (Enumeration e = req.getParameterNames(); e.hasMoreElements();) {
-                               String paramName = (String) e.nextElement();
-                               String[] paramValues = req.getParameterValues(paramName);
-                               addParam(paramName, paramValues);
-                       }
-
-                       // Parse multipart variables
-                       try {
-                               parser = new ServletMultipartRequest(req,
-                                               MultipartRequest.MAX_READ_BYTES);
-                       } catch (IllegalArgumentException ignored) {
-                               parser = null;
-                       }
-
-                       if (parser != null) {
-                               for (Enumeration e = parser.getFileParameterNames(); e
-                                               .hasMoreElements();) {
-                                       String paramName = (String) e.nextElement();
-                                       addParam(paramName, null);
-                               }
-                               for (Enumeration e = parser.getParameterNames(); e
-                                               .hasMoreElements();) {
-                                       String paramName = (String) e.nextElement();
-                                       Enumeration val = parser.getURLParameters(paramName);
-
-                                       // Create a linked list from enumeration to calculate
-                                       // elements
-                                       LinkedList l = new LinkedList();
-                                       while (val.hasMoreElements())
-                                               l.addLast(val.nextElement());
-
-                                       // String array event constructor
-                                       String[] s = new String[l.size()];
-                                       Iterator i = l.iterator();
-                                       for (int j = 0; j < s.length; j++)
-                                               s[j] = (String) i.next();
-
-                                       addParam(paramName, s);
-                               }
-                       }
-
-               }
-
-               /**
-                * Adds the parameter to container.
-                * 
-                * @param name
-                *            the Parameter name.
-                * @param value
-                *            the Parameter value.
-                */
-               private void addParam(String name, String[] value) {
-
-                       // Support name="set:name=value" value="ignored" notation
-                       if (name.startsWith("set:")) {
-                               int equalsIndex = name.indexOf('=');
-                               value[0] = name.substring(equalsIndex + 1, name.length());
-                               name = name.substring(4, equalsIndex);
-                               String[] curVal = (String[]) values.get(name);
-                               if (curVal != null) {
-                                       String[] newVal = new String[1 + curVal.length];
-                                       newVal[curVal.length] = value[0];
-                                       for (int i = 0; i < curVal.length; i++)
-                                               newVal[i] = curVal[i];
-                                       value = newVal;
-
-                                       // Special case - if the set:-method is used for
-                                       // declaring array of length 2, where either of the
-                                       // following conditions are true:
-                                       // - the both items are the same
-                                       // - the both items have the same length and
-                                       // - the items only differ on last character
-                                       // - second last character is '.'
-                                       // - last char of one string is 'x' and other is 'y'
-                                       // Browser is unporposely modifying the name.
-                                       if (value.length == 2
-                                                       && value[0].length() == value[1].length()) {
-                                               boolean same = true;
-                                               for (int i = 0; i < value[0].length() - 1 && same; i++)
-                                                       if (value[0].charAt(i) != value[1].charAt(i))
-                                                               same = false;
-                                               if (same
-                                                               && ((value[0].charAt(value[0].length() - 1) == 'x' && value[1]
-                                                                               .charAt(value[1].length() - 1) == 'y') || (value[0]
-                                                                               .charAt(value[0].length() - 1) == 'y' && value[1]
-                                                                               .charAt(value[1].length() - 1) == 'x'))) {
-                                                       value = new String[] { value[0].substring(0,
-                                                                       value[1].length() - 2) };
-                                               } else if (same && value[0].equals(value[1]))
-                                                       value = new String[] { value[0] };
-                                       }
-
-                                       // Special case - if the set:-method is used for
-                                       // declaring array of length 3, where all of the
-                                       // following conditions are true:
-                                       // - two last items have the same length
-                                       // - the first item is 2 chars shorter
-                                       // - the longer items only differ on last character
-                                       // - the shortest item is a prefix of the longer ones
-                                       // - second last character of longer ones is '.'
-                                       // - last char of one long string is 'x' and other is 'y'
-                                       // Browser is unporposely modifying the name. (Mozilla,
-                                       // Firefox, ..)
-                                       if (value.length == 3
-                                                       && value[1].length() == value[2].length()
-                                                       && value[0].length() + 2 == value[1].length()) {
-                                               boolean same = true;
-                                               for (int i = 0; i < value[1].length() - 1 && same; i++)
-                                                       if (value[2].charAt(i) != value[1].charAt(i))
-                                                               same = false;
-                                               for (int i = 0; i < value[0].length() && same; i++)
-                                                       if (value[0].charAt(i) != value[1].charAt(i))
-                                                               same = false;
-                                               if (same
-                                                               && (value[2].charAt(value[2].length() - 1) == 'x' && value[1]
-                                                                               .charAt(value[1].length() - 1) == 'y')
-                                                               || (value[2].charAt(value[2].length() - 1) == 'y' && value[1]
-                                                                               .charAt(value[1].length() - 1) == 'x')) {
-                                                       value = new String[] { value[0] };
-                                               }
-                                       }
-
-                               }
-                       }
-
-                       // Support for setting arrays in format
-                       // set-array:name=value1,value2,value3,...
-                       else if (name.startsWith("set-array:")) {
-                               int equalsIndex = name.indexOf('=');
-                               if (equalsIndex < 0)
-                                       return;
-
-                               StringTokenizer commalist = new StringTokenizer(name
-                                               .substring(equalsIndex + 1), ",");
-                               name = name.substring(10, equalsIndex);
-                               String[] curVal = (String[]) values.get(name);
-                               ArrayList elems = new ArrayList();
-
-                               // Add old values if present.
-                               if (curVal != null) {
-                                       for (int i = 0; i < curVal.length; i++)
-                                               elems.add(curVal[i]);
-                               }
-                               while (commalist.hasMoreTokens()) {
-                                       String token = commalist.nextToken();
-                                       if (token != null && token.length() > 0)
-                                               elems.add(token);
-                               }
-                               value = new String[elems.size()];
-                               for (int i = 0; i < value.length; i++)
-                                       value[i] = (String) elems.get(i);
-
-                       }
-
-                       // Support name="array:name" value="val1,val2,val3" notation
-                       // All the empty elements are ignored
-                       else if (name.startsWith("array:")) {
-
-                               name = name.substring(6);
-                               StringTokenizer commalist = new StringTokenizer(value[0], ",");
-                               String[] curVal = (String[]) values.get(name);
-                               ArrayList elems = new ArrayList();
-
-                               // Add old values if present.
-                               if (curVal != null) {
-                                       for (int i = 0; i < curVal.length; i++)
-                                               elems.add(curVal[i]);
-                               }
-                               while (commalist.hasMoreTokens()) {
-                                       String token = commalist.nextToken();
-                                       if (token != null && token.length() > 0)
-                                               elems.add(token);
-                               }
-                               value = new String[elems.size()];
-                               for (int i = 0; i < value.length; i++)
-                                       value[i] = (String) elems.get(i);
-                       }
-
-                       // Support declaring variables with name="declare:name"
-                       else if (name.startsWith("declare:")) {
-                               name = name.substring(8);
-                               value = (String[]) values.get(name);
-                               if (value == null)
-                                       value = new String[0];
-                       }
-
-                       // Gets the owner
-                       WeakReference ref = (WeakReference) idToOwnerMap.get(name);
-                       VariableOwner owner = null;
-                       if (ref != null)
-                               owner = (VariableOwner) ref.get();
-
-                       // Adds the parameter to mapping only if they have owners
-                       if (owner != null) {
-                               Set p = (Set) parameters.get(owner);
-                               if (p == null)
-                                       parameters.put(owner, p = new HashSet());
-                               p.add(name);
-                               if (value != null)
-                                       values.put(name, value);
-                       }
-
-                       // If the owner can not be found
-                       else {
-
-                               // If parameter has been mapped before, remove the old owner
-                               // mapping
-                               if (ref != null) {
-
-                                       // The owner has been destroyed, so we remove the mappings
-                                       idToNameMap.remove(name);
-                                       idToOwnerMap.remove(name);
-                                       idToTypeMap.remove(name);
-                                       idToValueMap.remove(name);
-                               }
-
-                               // Adds the parameter to set of non-variables
-                               nonVariables.put(name, value);
-                       }
-
-               }
-
-               /**
-                * Gets the set of all parameters connected to given variable owner.
-                * 
-                * @param owner
-                *            the Listener for variable changes.
-                * @return the set of all the parameters.
-                */
-               public Set getParameters(VariableOwner owner) {
-                       if (owner == null)
-                               return null;
-                       return (Set) parameters.get(owner);
-               }
-
-               /**
-                * Gets the set of all variable owners owning parameters in this
-                * request.
-                * 
-                * @return the set of all varaible owners.
-                */
-               public Set getOwners() {
-                       return parameters.keySet();
-               }
-
-               /**
-                * Gets the value of a parameter.
-                * 
-                * @param parameterName
-                *            the name of the parameter.
-                * @return the value of the parameter.
-                */
-               public String[] getValue(String parameterName) {
-                       return (String[]) values.get(parameterName);
-               }
-
-               /**
-                * Gets the servlet multipart parser.
-                * 
-                * @return the parser.
-                */
-               public ServletMultipartRequest getParser() {
-                       return parser;
-               }
-
-               /**
-                * Gets the name - value[] mapping of non variable parameters.
-                * 
-                * @return the mapping of non variable parameters.
-                */
-               public Map getNonVariables() {
-                       return nonVariables;
-               }
-       }
-
-       /**
-        * Handles all variable changes in this request.
-        * 
-        * @param req
-        *            the Http request to handle.
-        * @param errorListener
-        *            the listeners If the list is non null, only the listed
-        *            listeners are served. Otherwise all the listeners are served.
-        * @return Name to Value[] mapping of unhandled variables.
-        * @throws IOException
-        *             if the writing failed due to input/output error.
-        */
-       public Map handleVariables(HttpServletRequest req,
-                       Terminal.ErrorListener errorListener) throws IOException {
-
-               // Gets the parameters
-               ParameterContainer parcon = new ParameterContainer(req);
-
-               // Sorts listeners to dependency order
-               List listeners = getDependencySortedListenerList(parcon.getOwners());
-
-               // Handles all parameters for all listeners
-               while (!listeners.isEmpty()) {
-                       VariableOwner listener = (VariableOwner) listeners.remove(0);
-                       boolean changed = false; // Has any of this owners variabes
-                                                                               // changed
-                       // Handles all parameters for listener
-                       Set params = parcon.getParameters(listener);
-                       if (params != null) { // Name value mapping
-                               Map variables = new HashMap();
-                               for (Iterator pi = params.iterator(); pi.hasNext();) {
-                                       // Gets the name of the parameter
-                                       String param = (String) pi.next();
-                                       // Extracts more information about the parameter
-                                       String varName = (String) idToNameMap.get(param);
-                                       Class varType = (Class) idToTypeMap.get(param);
-                                       Object varOldValue = idToValueMap.get(param);
-                                       if (varName == null || varType == null)
-                                               // TODO Remove this?
-                                               System.err
-                                                               .println("VariableMap: No variable found for parameter "
-                                                                               + param
-                                                                               + " ("
-                                                                               + varName
-                                                                               + ","
-                                                                               + listener + ")");
-                                       else {
-
-                                               ServletMultipartRequest parser = parcon.getParser();
-
-                                               // Uploads events
-                                               if (varType.equals(UploadStream.class)) {
-                                                       if (parser != null
-                                                                       && parser.getFileParameter(param,
-                                                                                       MultipartRequest.FILENAME) != null) {
-                                                               String filename = (String) parser
-                                                                               .getFileParameter(param,
-                                                                                               MultipartRequest.FILENAME);
-                                                               String contentType = (String) parser
-                                                                               .getFileParameter(param,
-                                                                                               MultipartRequest.CONTENT_TYPE);
-                                                               UploadStream upload = new AjaxHttpUploadStream(
-                                                                               varName, parser.getFileContents(param),
-                                                                               filename, contentType);
-                                                               variables.put(varName, upload);
-                                                               changed = true;
-                                                       }
-                                               }
-
-                                               // Normal variable change events
-                                               else {
-                                                       // First try to parse the event without multipart
-                                                       String[] values = parcon.getValue(param);
-                                                       if (values != null) {
-
-                                                               if (varType.equals(String[].class)) {
-                                                                       variables.put(varName, values);
-                                                                       changed |= (!Arrays.equals(values,
-                                                                                       (String[]) varOldValue));
-                                                               } else {
-                                                                       try {
-                                                                               if (values.length == 1) {
-                                                                                       Object val = convert(varType,
-                                                                                                       values[0]);
-                                                                                       variables.put(varName, val);
-                                                                                       changed |= ((val == null && varOldValue != null) || (val != null && !val
-                                                                                                       .equals(varOldValue)));
-                                                                               } else if (values.length == 0
-                                                                                               && varType
-                                                                                                               .equals(Boolean.class)) {
-                                                                                       Object val = new Boolean(false);
-                                                                                       variables.put(varName, val);
-                                                                                       changed |= (!val
-                                                                                                       .equals(varOldValue));
-                                                                               } else {
-                                                                                       // TODO Remove this?
-                                                                                       System.err
-                                                                                                       .println("Empty variable '"
-                                                                                                                       + varName
-                                                                                                                       + "' of type "
-                                                                                                                       + varType
-                                                                                                                                       .toString());
-                                                                               }
-
-                                                                       } catch (java.lang.ClassCastException e) {
-                                                                               // TODO Remove this?
-                                                                               System.err
-                                                                                               .println("WebVariableMap conversion exception");
-                                                                               e.printStackTrace(System.err);
-                                                                               errorListener
-                                                                                               .terminalError(new TerminalErrorImpl(
-                                                                                                               e));
-                                                                       }
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-
-                               // Do the valuechange if the listener is enabled
-                               if (listener.isEnabled() && changed) {
-                                       try {
-                                               listener.changeVariables(req, variables);
-                                       } catch (Throwable t) {
-                                               // Notify the error listener
-                                               errorListener.terminalError(new VariableOwnerErrorImpl(
-                                                               listener, t));
-                                       }
-                               }
-                       }
-               }
-
-               return parcon.getNonVariables();
-       }
-
-       /**
-        * Implementation of VariableOwner.Error interface.
-        */
-       public class TerminalErrorImpl implements Terminal.ErrorEvent {
-               private Throwable throwable;
-
-               /**
-                * 
-                * @param throwable
-                */
-               private TerminalErrorImpl(Throwable throwable) {
-                       this.throwable = throwable;
-               }
-
-               /**
-                * @see com.itmill.toolkit.terminal.Terminal.ErrorEvent#getThrowable()
-                */
-               public Throwable getThrowable() {
-                       return this.throwable;
-               }
-
-       }
-
-       /**
-        * Implementation of VariableOwner.Error interface.
-        */
-       public class VariableOwnerErrorImpl extends TerminalErrorImpl implements
-                       VariableOwner.ErrorEvent {
-
-               private VariableOwner owner;
-
-               /**
-                * 
-                * @param owner
-                *            the Listener for variable changes.
-                * @param throwable
-                */
-               private VariableOwnerErrorImpl(VariableOwner owner, Throwable throwable) {
-                       super(throwable);
-                       this.owner = owner;
-               }
-
-               /**
-                * @see com.itmill.toolkit.terminal.VariableOwner.ErrorEvent#getVariableOwner()
-                */
-               public VariableOwner getVariableOwner() {
-                       return this.owner;
-               }
-
-       }
-
-       /**
-        * Resolves the VariableOwners needed from the request and sort them to
-        * assure that the dependencies are met (as well as possible).
-        * 
-        * @param listeners
-        * @return List of variable list changers, that are needed for handling all
-        *         the variables in the request
-        */
-       private List getDependencySortedListenerList(Set listeners) {
-
-               LinkedList resultNormal = new LinkedList();
-               LinkedList resultImmediate = new LinkedList();
-
-               // Go trough the listeners and either add them to result or resolve
-               // their dependencies
-               HashMap deepdeps = new HashMap();
-               LinkedList unresolved = new LinkedList();
-               for (Iterator li = listeners.iterator(); li.hasNext();) {
-
-                       VariableOwner listener = (VariableOwner) li.next();
-                       if (listener != null) {
-                               Set dependencies = listener.getDirectDependencies();
-
-                               // The listeners with no dependencies are added to the front of
-                               // the
-                               // list directly
-                               if (dependencies == null || dependencies.isEmpty()) {
-                                       if (listener.isImmediate())
-                                               resultImmediate.addFirst(listener);
-                                       else
-                                               resultNormal.addFirst(listener);
-                               }
-
-                               // Resolve deep dependencies for the listeners with dependencies
-                               // (the listeners will be added to the end of results in correct
-                               // dependency order later). Also the dependencies of all the
-                               // depended listeners are resolved.
-                               else if (deepdeps.get(listener) == null) {
-
-                                       // Set the fifo for unresolved parents to contain only the
-                                       // listener to be resolved
-                                       unresolved.clear();
-                                       unresolved.add(listener);
-
-                                       // Resolve dependencies
-                                       HashSet tmpdeepdeps = new HashSet();
-                                       while (!unresolved.isEmpty()) {
-
-                                               VariableOwner l = (VariableOwner) unresolved
-                                                               .removeFirst();
-                                               if (!tmpdeepdeps.contains(l)) {
-                                                       tmpdeepdeps.add(l);
-                                                       if (deepdeps.containsKey(l)) {
-                                                               tmpdeepdeps.addAll((Set) deepdeps.get(l));
-                                                       } else {
-                                                               Set deps = l.getDirectDependencies();
-                                                               if (deps != null && !deps.isEmpty())
-                                                                       for (Iterator di = deps.iterator(); di
-                                                                                       .hasNext();) {
-                                                                               Object d = di.next();
-                                                                               if (d != null
-                                                                                               && !tmpdeepdeps.contains(d))
-                                                                                       unresolved.addLast(d);
-                                                                       }
-                                                       }
-                                               }
-                                       }
-
-                                       tmpdeepdeps.remove(listener);
-                                       deepdeps.put(listener, tmpdeepdeps);
-                               }
-                       }
-               }
-
-               // Adds the listeners with dependencies in sane order to the result
-               for (Iterator li = deepdeps.keySet().iterator(); li.hasNext();) {
-                       VariableOwner l = (VariableOwner) li.next();
-                       boolean immediate = l.isImmediate();
-
-                       // Adds each listener after the last depended listener already in
-                       // the list
-                       int index = -1;
-                       for (Iterator di = ((Set) deepdeps.get(l)).iterator(); di.hasNext();) {
-                               int k;
-                               Object depended = di.next();
-                               if (immediate) {
-                                       k = resultImmediate.lastIndexOf(depended);
-                               } else {
-                                       k = resultNormal.lastIndexOf(depended);
-                               }
-                               if (k > index)
-                                       index = k;
-                       }
-                       if (immediate) {
-                               resultImmediate.add(index + 1, l);
-                       } else {
-                               resultNormal.add(index + 1, l);
-                       }
-               }
-
-               // Appends immediate listeners to normal listeners
-               // This way the normal handlers are always called before
-               // immediate ones
-               resultNormal.addAll(resultImmediate);
-               return resultNormal;
-       }
-}
diff --git a/src/com/itmill/toolkit/terminal/gwt/server/ApplicationManager.java b/src/com/itmill/toolkit/terminal/gwt/server/ApplicationManager.java
deleted file mode 100644 (file)
index 3a3c27a..0000000
+++ /dev/null
@@ -1,929 +0,0 @@
-/* *************************************************************************
- IT Mill Toolkit 
-
- Development of Browser User Interfaces Made Easy
-
- Copyright (C) 2000-2006 IT Mill Ltd
- *************************************************************************
-
- This product is distributed under commercial license that can be found
- from the product package on license.pdf. Use of this product might 
- require purchasing a commercial license from IT Mill Ltd. For guidelines 
- on usage, see licensing-guidelines.html
-
- *************************************************************************
- For more information, contact:
- IT Mill Ltd                           phone: +358 2 4802 7180
- Ruukinkatu 2-4                        fax:   +358 2 4802 7181
- 20540, Turku                          email:  info@itmill.com
- Finland                               company www: www.itmill.com
- Primary source for information and releases: www.itmill.com
-
- ********************************************************************** */
-
-package com.itmill.toolkit.terminal.gwt.server;
-
-import java.io.BufferedWriter;
-import java.io.FileInputStream;
-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.text.DateFormatSymbols;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.GregorianCalendar;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.WeakHashMap;
-
-import javax.servlet.ServletException;
-import javax.servlet.ServletOutputStream;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.itmill.toolkit.Application;
-import com.itmill.toolkit.Application.WindowAttachEvent;
-import com.itmill.toolkit.Application.WindowDetachEvent;
-import com.itmill.toolkit.terminal.DownloadStream;
-import com.itmill.toolkit.terminal.PaintTarget;
-import com.itmill.toolkit.terminal.Paintable;
-import com.itmill.toolkit.terminal.URIHandler;
-import com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent;
-import com.itmill.toolkit.ui.Component;
-import com.itmill.toolkit.ui.FrameWindow;
-import com.itmill.toolkit.ui.Window;
-
-/**
- * Application manager processes changes and paints for single application
- * instance.
- * 
- * @author IT Mill Ltd.
- * @version
- * @VERSION@
- * @since 5.0
- */
-public class ApplicationManager implements
-               Paintable.RepaintRequestListener, Application.WindowAttachListener,
-               Application.WindowDetachListener {
-
-       private static String GET_PARAM_REPAINT_ALL = "repaintAll";
-
-       private static int DEFAULT_BUFFER_SIZE = 32 * 1024;
-
-       private static int MAX_BUFFER_SIZE = 64 * 1024;
-
-       private WeakHashMap applicationToVariableMapMap = new WeakHashMap();
-
-       private HashSet dirtyPaintabletSet = new HashSet();
-
-
-       // TODO THIS TEMPORARY HACK IS ONLY HERE TO MAKE GWT DEVEL EASIER
-    static WeakHashMap paintableIdMap = new WeakHashMap();
-
-       private int idSequence = 0;
-
-       private Application application;
-
-       private Set removedWindows = new HashSet();
-
-       private JsonPaintTarget paintTarget;
-       
-       private List locales;
-       
-       private int pendingLocalesIndex;
-       
-       private ApplicationServlet applicationServlet;
-
-       public ApplicationManager(Application application, ApplicationServlet applicationServlet) {
-               this.application = application;
-               this.applicationServlet = applicationServlet;
-               requireLocale(application.getLocale().toString());
-       }
-
-       /**
-        * 
-        * @return
-        */
-       private AjaxVariableMap getVariableMap() {
-               AjaxVariableMap vm = (AjaxVariableMap) applicationToVariableMapMap
-                               .get(application);
-               if (vm == null) {
-                       vm = new AjaxVariableMap();
-                       applicationToVariableMapMap.put(application, vm);
-               }
-               return vm;
-       }
-
-       /**
-        * 
-        * 
-        */
-       public void takeControl() {
-               application.addListener((Application.WindowAttachListener) this);
-               application.addListener((Application.WindowDetachListener) this);
-
-       }
-
-       /**
-        * 
-        * 
-        */
-       public void releaseControl() {
-               application.removeListener((Application.WindowAttachListener) this);
-               application.removeListener((Application.WindowDetachListener) this);
-       }
-
-       
-       public void handleUidlRequest(HttpServletRequest request,
-                       HttpServletResponse response) throws IOException {
-
-               // repaint requested or sesssion has timed out and new one is created
-               boolean repaintAll = (request.getParameter(GET_PARAM_REPAINT_ALL) != null)
-                               || request.getSession().isNew();
-
-               OutputStream out = response.getOutputStream();
-               PrintWriter outWriter = new PrintWriter(new BufferedWriter(
-                               new OutputStreamWriter(out, "UTF-8")));
-               
-               outWriter.print(")/*{"); // some dirt to prevent cross site scripting vulnerabilities
-
-               try {
-
-                       // Is this a download request from application
-                       DownloadStream download = null;
-
-                       // The rest of the process is synchronized with the application
-                       // in order to guarantee that no parallel variable handling is
-                       // made
-                       synchronized (application) {
-
-                               // Change all variables based on request parameters
-                               Map unhandledParameters = getVariableMap().handleVariables(
-                                               request, application);
-
-                               // Handles the URI if the application is still running
-                               if (application.isRunning())
-                                       download = handleURI(application, request, response);
-
-                               // If this is not a download request
-                               if (download == null) {
-
-                                       // Finds the window within the application
-                                       Window window = null;
-                                       if (application.isRunning())
-                                               window = getApplicationWindow(request, application);
-
-                                       // Handles the unhandled parameters if the application is
-                                       // still running
-                                       if (window != null && unhandledParameters != null
-                                                       && !unhandledParameters.isEmpty())
-                                               window.handleParameters(unhandledParameters);
-
-                                       // Removes application if it has stopped
-                                       if (!application.isRunning()) {
-                                               endApplication(request, response, application);
-                                               return;
-                                       }
-
-                                       // Returns if no window found
-                                       if (window == null)
-                                               return;
-
-                                       // Sets the response type
-                                       response.setContentType("application/json; charset=UTF-8");
-                                       outWriter.print("\"changes\":[");
-                                       
-                                       paintTarget = new JsonPaintTarget(getVariableMap(), 
-                                                       this, outWriter);
-
-                                       // Paints components
-                                       Set paintables;
-                                       if (repaintAll) {
-                                               paintables = new LinkedHashSet();
-                                               paintables.add(window);
-                                               
-                                               // Reset sent locales
-                                               locales = null;
-                                               requireLocale(application.getLocale().toString());
-
-                                               // Adds all non-native windows
-                                               for (Iterator i = window.getApplication().getWindows()
-                                                               .iterator(); i.hasNext();) {
-                                                       Window w = (Window) i.next();
-                                                       if (!"native".equals(w.getStyle()) && w != window)
-                                                               paintables.add(w);
-                                               }
-                                       } else
-                                               paintables = getDirtyComponents();
-                                       if (paintables != null) {
-
-                                               // Creates "working copy" of the current state.
-                                               List currentPaintables = new ArrayList(paintables);
-
-                                               // Sorts the paintable so that parent windows
-                                               // are always painted before child windows
-                                               Collections.sort(currentPaintables, new Comparator() {
-
-                                                       public int compare(Object o1, Object o2) {
-
-                                                               // If first argumement is now window
-                                                               // the second is "smaller" if it is.
-                                                               if (!(o1 instanceof Window)) {
-                                                                       return (o2 instanceof Window) ? 1 : 0;
-                                                               }
-
-                                                               // Now, if second is not window the
-                                                               // first is smaller.
-                                                               if (!(o2 instanceof Window)) {
-                                                                       return -1;
-                                                               }
-
-                                                               // Both are windows.
-                                                               String n1 = ((Window) o1).getName();
-                                                               String n2 = ((Window) o2).getName();
-                                                               if (o1 instanceof FrameWindow) {
-                                                                       if (((FrameWindow) o1).getFrameset()
-                                                                                       .getFrame(n2) != null) {
-                                                                               return -1;
-                                                                       } else if (!(o2 instanceof FrameWindow)) {
-                                                                               return -1;
-                                                                       }
-                                                               }
-                                                               if (o2 instanceof FrameWindow) {
-                                                                       if (((FrameWindow) o2).getFrameset()
-                                                                                       .getFrame(n1) != null) {
-                                                                               return 1;
-                                                                       } else if (!(o1 instanceof FrameWindow)) {
-                                                                               return 1;
-                                                                       }
-                                                               }
-
-                                                               return 0;
-                                                       }
-                                               });
-
-                                               for (Iterator i = currentPaintables.iterator(); i
-                                                               .hasNext();) {
-                                                       Paintable p = (Paintable) i.next();
-
-                                                       // TODO CLEAN
-                                                       if (p instanceof Window) {
-                                                               Window w = (Window) p;
-                                                               if (w.getTerminal() == null)
-                                                                       w.setTerminal(application.getMainWindow()
-                                                                                       .getTerminal());
-                                                       }
-
-                                                       paintTarget.startTag("change");
-                                                       paintTarget.addAttribute("format", "uidl");
-                                                       String pid = getPaintableId(p);
-                                                       paintTarget.addAttribute("pid", pid);
-
-                                                       // Track paints to identify empty paints
-                                                       paintTarget.setTrackPaints(true);
-                                                       p.paint(paintTarget);
-
-                                                       // If no paints add attribute empty
-                                                       if (paintTarget.getNumberOfPaints() <= 0) {
-                                                               paintTarget.addAttribute("visible", false);
-                                                       }
-                                                       paintTarget.endTag("change");
-                                                       paintablePainted(p);
-                                               }
-                                       }
-
-                                       
-                                                       paintTarget.close();
-                                       outWriter.print("]"); // close changes
-
-
-                                       // Render the removed windows
-                                       // TODO refactor commented area to send some meta instructions to close window
-//                                     Set removed = new HashSet(getRemovedWindows());
-//                                     if (removed.size() > 0) {
-//                                             for (Iterator i = removed.iterator(); i.hasNext();) {
-//                                                     Window w = (Window) i.next();
-//                                                     paintTarget.startTag("change");
-//                                                     paintTarget.addAttribute("format", "uidl");
-//                                                     String pid = getPaintableId(w);
-//                                                     paintTarget.addAttribute("pid", pid);
-//                                                     paintTarget.addAttribute("windowname", w.getName());
-//                                                     paintTarget.addAttribute("visible", false);
-//                                                     paintTarget.endTag("change");
-//                                                     removedWindowNotified(w);
-//
-//                                             }
-//                                     }
-
-
-                                       
-                       outWriter.print(", \"meta\" : {");
-                       boolean metaOpen = false;
-
-                                       
-                    // .. or initializion (first uidl-request)
-                    if(application.ajaxInit()) {
-                       outWriter.print("\"appInit\":true");
-                    }
-                    // add meta instruction for client to set focus if it is set
-                    Paintable f = (Paintable) application.consumeFocus();
-                    if(f != null) {
-                       if(metaOpen)
-                               outWriter.append(",");
-                       outWriter.write("\"focus\":\""+ getPaintableId(f) +"\"");
-                    }
-
-                       outWriter.print("}, \"resources\" : {");
-
-                    // Precache custom layouts
-                    // TODO Does not support theme-get param or different themes in different windows -> Allways preload layouts with the theme specified by the applications
-                    String themeName = application.getTheme() != null ? application.getTheme() : ApplicationServlet.DEFAULT_THEME;
-                    // TODO We should only precache the layouts that are not cached already
-                       int resourceIndex = 0;
-                    for (Iterator i=paintTarget.getPreCachedResources().iterator(); i.hasNext();) {
-                       String resource = (String) i.next();
-                       InputStream is = null;
-                       try {
-                               is = applicationServlet.getServletContext().getResourceAsStream(ApplicationServlet.THEME_DIRECTORY_PATH + themeName + "/" +  resource);
-                               } catch (Exception e) {
-                                       Log.info(e.getMessage());
-                               }
-                       if (is != null) {
-                               
-                               outWriter.print((resourceIndex++ > 0 ? ", " : "") + "\""+resource + "\" : ");
-                               StringBuffer layout = new StringBuffer();
-
-                               try {
-                                       InputStreamReader r = new InputStreamReader(is);
-                                               char[] buffer = new char[20000];
-                                               int charsRead = 0;
-                                               while ((charsRead = r.read(buffer)) > 0)
-                                                       layout.append(buffer, 0, charsRead);
-                                               r.close();
-                               } catch (java.io.IOException e) {
-                                       Log.info("Resource transfer failed:  " + request.getRequestURI()
-                                                       + ". (" + e.getMessage() + ")");
-                               }
-                               outWriter.print("\"" + JsonPaintTarget.escapeJSON(layout.toString()) + "\"");
-                       }
-                    }
-                       outWriter.print("}");
-                       
-                       
-                       /* -----------------------------
-                        * Sending Locale sensitive date
-                        * -----------------------------
-                        */
-                       
-                       // Store JVM default locale for later restoration
-                       // (we'll have to change the default locale for a while)
-                       Locale jvmDefault = Locale.getDefault();
-                       
-                    // Send locale informations to client
-                       outWriter.print(", \"locales\":[");
-                       for(;pendingLocalesIndex < locales.size(); pendingLocalesIndex++) {
-                               
-                               Locale l = generateLocale((String) locales.get(pendingLocalesIndex));
-                               // Locale name
-                               outWriter.print("{\"name\":\"" + l.toString() + "\",");
-                               
-                               /*
-                                * Month names (both short and full)
-                                */
-                               DateFormatSymbols dfs = new DateFormatSymbols(l);
-                               String[] short_months = dfs.getShortMonths();
-                               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)
-                            */
-                               String[] short_days = dfs.getShortWeekdays();
-                               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)
-                                */
-                               Calendar cal = new GregorianCalendar(l);
-                               outWriter.print("\"fdow\":" + (cal.getFirstDayOfWeek() - 1) + ",");
-                               
-                               /*
-                                * Date formatting (MM/DD/YYYY etc.)
-                                */
-                               // Force our locale as JVM default for a while (SimpleDateFormat uses JVM default)
-                               Locale.setDefault(l);
-                               String df = new SimpleDateFormat().toPattern();
-                               int timeStart = df.indexOf("H");
-                               if(timeStart < 0)
-                                       timeStart = df.indexOf("h");
-                               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;
-                               String dateformat = df.substring(0, timeStart-1);
-                               
-                               outWriter.print("\"df\":\"" + dateformat.trim() + "\",");
-                               
-                               /*
-                                * Time formatting (24 or 12 hour clock and AM/PM suffixes)
-                                */
-                               String timeformat = df.substring(timeStart, df.length()); // Doesn't return second or milliseconds
-                               // We use timeformat to determine 12/24-hour clock
-                               boolean twelve_hour_clock = timeformat.contains("a");
-                               // TODO there are other possibilities as well, like 'h' in french (ignore them, too complicated)
-                               String hour_min_delimiter = timeformat.contains(".")? "." : ":";
-                               //outWriter.print("\"tf\":\"" + timeformat + "\",");
-                               outWriter.print("\"thc\":" + twelve_hour_clock + ",");
-                               outWriter.print("\"hmd\":\"" + hour_min_delimiter + "\"");
-                               if(twelve_hour_clock) {
-                                       String[] ampm = dfs.getAmPmStrings();
-                                       outWriter.print(",\"ampm\":[\""+ampm[0]+"\",\""+ampm[1]+"\"]");
-                               }
-                               outWriter.print("}");
-                               if(pendingLocalesIndex < locales.size()-1)
-                                       outWriter.print(",");
-                       }
-                       outWriter.print("]"); // Close locales
-                       
-                       // Restore JVM default locale
-                       Locale.setDefault(jvmDefault);
-                
-                       outWriter.flush();
-                    outWriter.close();
-                                       out.flush();
-                               } else {
-
-                                       // For download request, transfer the downloaded data
-                                       handleDownload(download, request, response);
-                               }
-                       }
-
-                       out.flush();
-                       out.close();
-
-               } catch (Throwable e) {
-                       // Writes the error report to client
-                       OutputStreamWriter w = new OutputStreamWriter(out);
-                       PrintWriter err = new PrintWriter(w);
-                       err
-                                       .write("<html><head><title>Application Internal Error</title></head><body>");
-                       err.write("<h1>" + e.toString() + "</h1><pre>\n");
-                       e.printStackTrace(new PrintWriter(err));
-                       err.write("\n</pre></body></html>");
-                       err.close();
-               } finally {
-
-               }
-
-       }
-
-       /**
-        * 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.
-        * @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 Window getApplicationWindow(HttpServletRequest request,
-                       Application application) throws ServletException {
-
-               Window window = null;
-
-               // Find the window where the request is handled
-               String path = request.getPathInfo();
-
-               // Main window as the URI is empty
-               if (path == null || path.length() == 0 || path.equals("/"))
-                       window = application.getMainWindow();
-
-               // Try to search by window name
-               else {
-                       String windowName = null;
-                       if (path.charAt(0) == '/')
-                               path = path.substring(1);
-                       int index = path.indexOf('/');
-                       if (index < 0) {
-                               windowName = path;
-                               path = "";
-                       } else {
-                               windowName = path.substring(0, index);
-                               path = path.substring(index + 1);
-                       }
-                       window = application.getWindow(windowName);
-
-                       // By default, we use main window
-                       if (window == null)
-                               window = application.getMainWindow();
-               }
-
-               return window;
-       }
-
-       /**
-        * 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.
-        * 
-        * @param application
-        *            the Application owning the URI.
-        * @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, otherwise
-        *         <code>false</code>.
-        * @see com.itmill.toolkit.terminal.URIHandler
-        */
-       private DownloadStream handleURI(Application application,
-                       HttpServletRequest request, HttpServletResponse response) {
-
-               String uri = request.getPathInfo();
-
-               // If no URI is available
-               if (uri == null || uri.length() == 0 || uri.equals("/"))
-                       return null;
-
-               // Remove the leading /
-               while (uri.startsWith("/") && uri.length() > 0)
-                       uri = uri.substring(1);
-
-               // Handle the uri
-               DownloadStream stream = null;
-               try {
-                       stream = application.handleURI(application.getURL(), uri);
-               } catch (Throwable t) {
-                       application.terminalError(new URIHandlerErrorImpl(application, t));
-               }
-
-               return stream;
-       }
-
-       /**
-        * 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.
-        * 
-        * @param stream
-        *            the downloadable stream.
-        * 
-        * @param request
-        *            the HTTP request instance.
-        * @param response
-        *            the HTTP response to write to.
-        * 
-        * @see com.itmill.toolkit.terminal.URIHandler
-        */
-       private void handleDownload(DownloadStream stream,
-                       HttpServletRequest request, HttpServletResponse response) {
-
-               // Download from given stream
-               InputStream data = stream.getStream();
-               if (data != null) {
-
-                       // Sets content type
-                       response.setContentType(stream.getContentType());
-
-                       // Sets cache headers
-                       long cacheTime = stream.getCacheTime();
-                       if (cacheTime <= 0) {
-                               response.setHeader("Cache-Control", "no-cache");
-                               response.setHeader("Pragma", "no-cache");
-                               response.setDateHeader("Expires", 0);
-                       } else {
-                               response.setHeader("Cache-Control", "max-age=" + cacheTime
-                                               / 1000);
-                               response.setDateHeader("Expires", System.currentTimeMillis()
-                                               + cacheTime);
-                               response.setHeader("Pragma", "cache"); // Required to apply
-                               // caching in some
-                               // Tomcats
-                       }
-
-                       // Copy download stream parameters directly
-                       // to HTTP headers.
-                       Iterator i = stream.getParameterNames();
-                       if (i != null) {
-                               while (i.hasNext()) {
-                                       String param = (String) i.next();
-                                       response.setHeader((String) param, stream
-                                                       .getParameter(param));
-                               }
-                       }
-
-                       int bufferSize = stream.getBufferSize();
-                       if (bufferSize <= 0 || bufferSize > MAX_BUFFER_SIZE)
-                               bufferSize = DEFAULT_BUFFER_SIZE;
-                       byte[] buffer = new byte[bufferSize];
-                       int bytesRead = 0;
-
-                       try {
-                               OutputStream out = response.getOutputStream();
-
-                               while ((bytesRead = data.read(buffer)) > 0) {
-                                       out.write(buffer, 0, bytesRead);
-                                       out.flush();
-                               }
-                               out.close();
-                       } catch (IOException ignored) {
-                       }
-
-               }
-
-       }
-
-       /**
-        * Ends the Application.
-        * 
-        * @param request
-        *            the HTTP request instance.
-        * @param response
-        *            the HTTP response to write to.
-        * @param application
-        *            the Application to end.
-        * @throws IOException
-        *             if the writing failed due to input/output error.
-        */
-       private void endApplication(HttpServletRequest request,
-                       HttpServletResponse 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 xml file to
-               // tell client that application is quit and where to point browser now
-               // Set the response type
-               response.setContentType("application/xml; charset=UTF-8");
-               ServletOutputStream out = response.getOutputStream();
-               out.println("<redirect url=\"" + logoutUrl + "\">");
-               out.println("</redirect>");
-       }
-
-       /**
-        * Gets the Paintable Id.
-        * 
-        * @param paintable
-        * @return the paintable Id.
-        */
-       public synchronized String getPaintableId(Paintable paintable) {
-
-               String id = (String) paintableIdMap.get(paintable);
-               if (id == null) {
-                       id = "PID" + Integer.toString(idSequence++);
-                       paintableIdMap.put(paintable, id);
-               }
-
-               return id;
-       }
-
-       /**
-        * 
-        * @return
-        */
-       public synchronized Set getDirtyComponents() {
-
-               // Remove unnecessary repaints from the list
-               Object[] paintables = dirtyPaintabletSet.toArray();
-               for (int i = 0; i < paintables.length; i++) {
-                       if (paintables[i] instanceof Component) {
-                               Component c = (Component) paintables[i];
-
-                               // Check if any of the parents of c already exist in the list
-                               Component p = c.getParent();
-                               while (p != null) {
-                                       if (dirtyPaintabletSet.contains(p)) {
-
-                                               // Remove component c from the dirty paintables as its
-                                               // parent is also dirty
-                                               dirtyPaintabletSet.remove(c);
-                                               p = null;
-                                       } else
-                                               p = p.getParent();
-                               }
-                       }
-               }
-
-               return Collections.unmodifiableSet(dirtyPaintabletSet);
-       }
-
-       /**
-        * Clears the Dirty Components.
-        * 
-        */
-       public synchronized void clearDirtyComponents() {
-               dirtyPaintabletSet.clear();
-       }
-
-       /**
-        * @see com.itmill.toolkit.terminal.Paintable.RepaintRequestListener#repaintRequested(com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent)
-        */
-       public void repaintRequested(RepaintRequestEvent event) {
-               Paintable p = event.getPaintable();
-               dirtyPaintabletSet.add(p);
-
-               // For FrameWindows we mark all frames (windows) dirty
-               if (p instanceof FrameWindow) {
-                       FrameWindow fw = (FrameWindow) p;
-                       repaintFrameset(fw.getFrameset());
-               }
-       }
-
-       /**
-        * Recursively request repaint for all frames in frameset.
-        * 
-        * @param fs
-        *            the Framewindow.Frameset.
-        */
-       private void repaintFrameset(FrameWindow.Frameset fs) {
-               List frames = fs.getFrames();
-               for (Iterator i = frames.iterator(); i.hasNext();) {
-                       FrameWindow.Frame f = (FrameWindow.Frame) i.next();
-                       if (f instanceof FrameWindow.Frameset) {
-                               repaintFrameset((FrameWindow.Frameset) f);
-                       } else {
-                               Window w = f.getWindow();
-                               if (w != null) {
-                                       w.requestRepaint();
-                               }
-                       }
-               }
-       }
-
-       /**
-        * 
-        * @param p
-        */
-       public void paintablePainted(Paintable p) {
-               dirtyPaintabletSet.remove(p);
-               p.requestRepaintRequests();
-       }
-
-       /**
-        * 
-        * @param paintable
-        * @return
-        */
-       public boolean isDirty(Paintable paintable) {
-               return (dirtyPaintabletSet.contains(paintable));
-       }
-
-       /**
-        * @see com.itmill.toolkit.Application.WindowAttachListener#windowAttached(com.itmill.toolkit.Application.WindowAttachEvent)
-        */
-       public void windowAttached(WindowAttachEvent event) {
-               event.getWindow().addListener(this);
-               dirtyPaintabletSet.add(event.getWindow());
-       }
-
-       /**
-        * @see com.itmill.toolkit.Application.WindowDetachListener#windowDetached(com.itmill.toolkit.Application.WindowDetachEvent)
-        */
-       public void windowDetached(WindowDetachEvent event) {
-               event.getWindow().removeListener(this);
-               // Notify client of the close operation
-               removedWindows.add(event.getWindow());
-       }
-
-       /**
-        * 
-        * @return
-        */
-       public synchronized Set getRemovedWindows() {
-               return Collections.unmodifiableSet(removedWindows);
-
-       }
-
-       /**
-        * 
-        * @param w
-        */
-       private void removedWindowNotified(Window w) {
-               this.removedWindows.remove(w);
-       }
-
-       /**
-        * Implementation of URIHandler.ErrorEvent interface.
-        */
-       public class URIHandlerErrorImpl implements URIHandler.ErrorEvent {
-
-               private URIHandler owner;
-
-               private Throwable throwable;
-
-               /**
-                * 
-                * @param owner
-                * @param throwable
-                */
-               private URIHandlerErrorImpl(URIHandler owner, Throwable throwable) {
-                       this.owner = owner;
-                       this.throwable = throwable;
-               }
-
-               /**
-                * @see com.itmill.toolkit.terminal.Terminal.ErrorEvent#getThrowable()
-                */
-               public Throwable getThrowable() {
-                       return this.throwable;
-               }
-
-               /**
-                * @see com.itmill.toolkit.terminal.URIHandler.ErrorEvent#getURIHandler()
-                */
-               public URIHandler getURIHandler() {
-                       return this.owner;
-               }
-       }
-
-       public void requireLocale(String value) {
-               if(locales == null) {
-                       locales = new ArrayList();
-                       locales.add(application.getLocale().toString());
-                       pendingLocalesIndex = 0;
-               }
-               if(!locales.contains(value))
-                               locales.add(value);
-       }
-       
-       private Locale generateLocale(String value) {
-               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]);
-       }
-}
index 5ba33b7778090b33282ea8799335b7d35f95d542..324cd6cc1234f1bdb3baf9df3641df418ed242a5 100644 (file)
@@ -1242,14 +1242,14 @@ public class ApplicationServlet extends HttpServlet {
         * @param application
         * @return AJAX Application Manager
         */
-       private ApplicationManager getApplicationManager(Application application) {
-               ApplicationManager mgr = (ApplicationManager) applicationToAjaxAppMgrMap
+       private CommunicationManager getApplicationManager(Application application) {
+               CommunicationManager mgr = (CommunicationManager) applicationToAjaxAppMgrMap
                                .get(application);
 
                // This application is going from Web to AJAX mode, create new manager
                if (mgr == null) {
                        // Creates new manager
-                       mgr = new ApplicationManager(application, this);
+                       mgr = new CommunicationManager(application, this);
                        applicationToAjaxAppMgrMap.put(application, mgr);
 
                        // Manager takes control over the application
diff --git a/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java b/src/com/itmill/toolkit/terminal/gwt/server/CommunicationManager.java
new file mode 100644 (file)
index 0000000..b2bcc68
--- /dev/null
@@ -0,0 +1,1053 @@
+/* *************************************************************************
+ IT Mill Toolkit 
+
+ Development of Browser User Interfaces Made Easy
+
+ Copyright (C) 2000-2006 IT Mill Ltd
+ *************************************************************************
+
+ This product is distributed under commercial license that can be found
+ from the product package on license.pdf. Use of this product might 
+ require purchasing a commercial license from IT Mill Ltd. For guidelines 
+ on usage, see licensing-guidelines.html
+
+ *************************************************************************
+ For more information, contact:
+ IT Mill Ltd                           phone: +358 2 4802 7180
+ Ruukinkatu 2-4                        fax:   +358 2 4802 7181
+ 20540, Turku                          email:  info@itmill.com
+ Finland                               company www: www.itmill.com
+ Primary source for information and releases: www.itmill.com
+
+ ********************************************************************** */
+
+package com.itmill.toolkit.terminal.gwt.server;
+
+import java.io.BufferedWriter;
+import java.io.FileInputStream;
+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.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.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.itmill.toolkit.Application;
+import com.itmill.toolkit.Application.WindowAttachEvent;
+import com.itmill.toolkit.Application.WindowDetachEvent;
+import com.itmill.toolkit.terminal.DownloadStream;
+import com.itmill.toolkit.terminal.PaintTarget;
+import com.itmill.toolkit.terminal.Paintable;
+import com.itmill.toolkit.terminal.URIHandler;
+import com.itmill.toolkit.terminal.VariableOwner;
+import com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent;
+import com.itmill.toolkit.ui.Component;
+import com.itmill.toolkit.ui.FrameWindow;
+import com.itmill.toolkit.ui.Window;
+
+/**
+ * Application manager processes changes and paints for single application
+ * instance.
+ * 
+ * @author IT Mill Ltd.
+ * @version
+ * @VERSION@
+ * @since 5.0
+ */
+public class CommunicationManager implements Paintable.RepaintRequestListener,
+               Application.WindowAttachListener, Application.WindowDetachListener {
+
+       private static String GET_PARAM_REPAINT_ALL = "repaintAll";
+
+       private static int DEFAULT_BUFFER_SIZE = 32 * 1024;
+
+       private static int MAX_BUFFER_SIZE = 64 * 1024;
+
+       private WeakHashMap applicationToVariableMapMap = new WeakHashMap();
+
+       private HashSet dirtyPaintabletSet = new HashSet();
+
+       private WeakHashMap paintableIdMap = new WeakHashMap();
+
+       private WeakHashMap idPaintableMap = new WeakHashMap();
+
+       private int idSequence = 0;
+
+       private Application application;
+
+       private Set removedWindows = new HashSet();
+
+       private JsonPaintTarget paintTarget;
+
+       private List locales;
+
+       private int pendingLocalesIndex;
+
+       private ApplicationServlet applicationServlet;
+
+       public CommunicationManager(Application application,
+                       ApplicationServlet applicationServlet) {
+               this.application = application;
+               this.applicationServlet = applicationServlet;
+               requireLocale(application.getLocale().toString());
+       }
+
+       /**
+        * 
+        * 
+        */
+       public void takeControl() {
+               application.addListener((Application.WindowAttachListener) this);
+               application.addListener((Application.WindowDetachListener) this);
+
+       }
+
+       /**
+        * 
+        * 
+        */
+       public void releaseControl() {
+               application.removeListener((Application.WindowAttachListener) this);
+               application.removeListener((Application.WindowDetachListener) this);
+       }
+
+       public void handleUidlRequest(HttpServletRequest request,
+                       HttpServletResponse response) throws IOException {
+
+               // repaint requested or sesssion has timed out and new one is created
+               boolean repaintAll = (request.getParameter(GET_PARAM_REPAINT_ALL) != null)
+                               || request.getSession().isNew();
+
+               OutputStream out = response.getOutputStream();
+               PrintWriter outWriter = new PrintWriter(new BufferedWriter(
+                               new OutputStreamWriter(out, "UTF-8")));
+
+               // TODO Move dirt elsewhere
+               outWriter.print(")/*{"); // some dirt to prevent cross site scripting
+               // vulnerabilities
+
+               try {
+
+                       // Is this a download request from application
+                       DownloadStream download = null;
+
+                       // The rest of the process is synchronized with the application
+                       // in order to guarantee that no parallel variable handling is
+                       // made
+                       synchronized (application) {
+
+                               // Change all variables based on request parameters
+                               Map unhandledParameters = handleVariables(request, application);
+
+                               // Handles the URI if the application is still running
+                               if (application.isRunning())
+                                       download = handleURI(application, request, response);
+
+                               // If this is not a download request
+                               if (download == null) {
+
+                                       // Finds the window within the application
+                                       Window window = null;
+                                       if (application.isRunning())
+                                               window = getApplicationWindow(request, application);
+
+                                       // Handles the unhandled parameters if the application is
+                                       // still running
+                                       if (window != null && unhandledParameters != null
+                                                       && !unhandledParameters.isEmpty())
+                                               window.handleParameters(unhandledParameters);
+
+                                       // Removes application if it has stopped
+                                       if (!application.isRunning()) {
+                                               endApplication(request, response, application);
+                                               return;
+                                       }
+
+                                       // Returns if no window found
+                                       if (window == null)
+                                               return;
+
+                                       // Sets the response type
+                                       response.setContentType("application/json; charset=UTF-8");
+                                       outWriter.print("\"changes\":[");
+
+                                       paintTarget = new JsonPaintTarget(this, outWriter);
+
+                                       // Paints components
+                                       Set paintables;
+                                       if (repaintAll) {
+                                               paintables = new LinkedHashSet();
+                                               paintables.add(window);
+
+                                               // Reset sent locales
+                                               locales = null;
+                                               requireLocale(application.getLocale().toString());
+
+                                               // Adds all non-native windows
+                                               for (Iterator i = window.getApplication().getWindows()
+                                                               .iterator(); i.hasNext();) {
+                                                       Window w = (Window) i.next();
+                                                       if (!"native".equals(w.getStyle()) && w != window)
+                                                               paintables.add(w);
+                                               }
+                                       } else
+                                               paintables = getDirtyComponents();
+                                       if (paintables != null) {
+
+                                               // Creates "working copy" of the current state.
+                                               List currentPaintables = new ArrayList(paintables);
+
+                                               // Sorts the paintable so that parent windows
+                                               // are always painted before child windows
+                                               Collections.sort(currentPaintables, new Comparator() {
+
+                                                       public int compare(Object o1, Object o2) {
+
+                                                               // If first argumement is now window
+                                                               // the second is "smaller" if it is.
+                                                               if (!(o1 instanceof Window)) {
+                                                                       return (o2 instanceof Window) ? 1 : 0;
+                                                               }
+
+                                                               // Now, if second is not window the
+                                                               // first is smaller.
+                                                               if (!(o2 instanceof Window)) {
+                                                                       return -1;
+                                                               }
+
+                                                               // Both are windows.
+                                                               String n1 = ((Window) o1).getName();
+                                                               String n2 = ((Window) o2).getName();
+                                                               if (o1 instanceof FrameWindow) {
+                                                                       if (((FrameWindow) o1).getFrameset()
+                                                                                       .getFrame(n2) != null) {
+                                                                               return -1;
+                                                                       } else if (!(o2 instanceof FrameWindow)) {
+                                                                               return -1;
+                                                                       }
+                                                               }
+                                                               if (o2 instanceof FrameWindow) {
+                                                                       if (((FrameWindow) o2).getFrameset()
+                                                                                       .getFrame(n1) != null) {
+                                                                               return 1;
+                                                                       } else if (!(o1 instanceof FrameWindow)) {
+                                                                               return 1;
+                                                                       }
+                                                               }
+
+                                                               return 0;
+                                                       }
+                                               });
+
+                                               for (Iterator i = currentPaintables.iterator(); i
+                                                               .hasNext();) {
+                                                       Paintable p = (Paintable) i.next();
+
+                                                       // TODO CLEAN
+                                                       if (p instanceof Window) {
+                                                               Window w = (Window) p;
+                                                               if (w.getTerminal() == null)
+                                                                       w.setTerminal(application.getMainWindow()
+                                                                                       .getTerminal());
+                                                       }
+
+                                                       paintTarget.startTag("change");
+                                                       paintTarget.addAttribute("format", "uidl");
+                                                       String pid = getPaintableId(p);
+                                                       paintTarget.addAttribute("pid", pid);
+
+                                                       // Track paints to identify empty paints
+                                                       paintTarget.setTrackPaints(true);
+                                                       p.paint(paintTarget);
+
+                                                       // If no paints add attribute empty
+                                                       if (paintTarget.getNumberOfPaints() <= 0) {
+                                                               paintTarget.addAttribute("visible", false);
+                                                       }
+                                                       paintTarget.endTag("change");
+                                                       paintablePainted(p);
+                                               }
+                                       }
+
+                                       paintTarget.close();
+                                       outWriter.print("]"); // close changes
+
+                                       outWriter.print(", \"meta\" : {");
+                                       boolean metaOpen = false;
+
+                                       // .. or initializion (first uidl-request)
+                                       if (application.ajaxInit()) {
+                                               outWriter.print("\"appInit\":true");
+                                       }
+                                       // add meta instruction for client to set focus if it is set
+                                       Paintable f = (Paintable) application.consumeFocus();
+                                       if (f != null) {
+                                               if (metaOpen)
+                                                       outWriter.append(",");
+                                               outWriter.write("\"focus\":\"" + getPaintableId(f)
+                                                               + "\"");
+                                       }
+
+                                       outWriter.print("}, \"resources\" : {");
+
+                                       // Precache custom layouts
+                                       // TODO Does not support theme-get param or different themes
+                                       // in different windows -> Allways preload layouts with the
+                                       // theme specified by the applications
+                                       String themeName = application.getTheme() != null ? application
+                                                       .getTheme()
+                                                       : ApplicationServlet.DEFAULT_THEME;
+                                       // TODO We should only precache the layouts that are not
+                                       // cached already
+                                       int resourceIndex = 0;
+                                       for (Iterator i = paintTarget.getPreCachedResources()
+                                                       .iterator(); i.hasNext();) {
+                                               String resource = (String) i.next();
+                                               InputStream is = null;
+                                               try {
+                                                       is = applicationServlet
+                                                                       .getServletContext()
+                                                                       .getResourceAsStream(
+                                                                                       ApplicationServlet.THEME_DIRECTORY_PATH
+                                                                                                       + themeName
+                                                                                                       + "/"
+                                                                                                       + resource);
+                                               } catch (Exception e) {
+                                                       Log.info(e.getMessage());
+                                               }
+                                               if (is != null) {
+
+                                                       outWriter.print((resourceIndex++ > 0 ? ", " : "")
+                                                                       + "\"" + resource + "\" : ");
+                                                       StringBuffer layout = new StringBuffer();
+
+                                                       try {
+                                                               InputStreamReader r = new InputStreamReader(is);
+                                                               char[] buffer = new char[20000];
+                                                               int charsRead = 0;
+                                                               while ((charsRead = r.read(buffer)) > 0)
+                                                                       layout.append(buffer, 0, charsRead);
+                                                               r.close();
+                                                       } catch (java.io.IOException e) {
+                                                               Log.info("Resource transfer failed:  "
+                                                                               + request.getRequestURI() + ". ("
+                                                                               + e.getMessage() + ")");
+                                                       }
+                                                       outWriter.print("\""
+                                                                       + JsonPaintTarget.escapeJSON(layout
+                                                                                       .toString()) + "\"");
+                                               }
+                                       }
+                                       outWriter.print("}");
+
+                                       printLocaleDeclarations(outWriter);
+
+                                       outWriter.flush();
+                                       outWriter.close();
+                                       out.flush();
+                               } else {
+
+                                       // For download request, transfer the downloaded data
+                                       handleDownload(download, request, response);
+                               }
+                       }
+
+                       out.flush();
+                       out.close();
+
+               } catch (Throwable e) {
+                       // Writes the error report to client
+                       OutputStreamWriter w = new OutputStreamWriter(out);
+                       PrintWriter err = new PrintWriter(w);
+                       err
+                                       .write("<html><head><title>Application Internal Error</title></head><body>");
+                       err.write("<h1>" + e.toString() + "</h1><pre>\n");
+                       e.printStackTrace(new PrintWriter(err));
+                       err.write("\n</pre></body></html>");
+                       err.close();
+               } finally {
+
+               }
+
+       }
+
+       private Map handleVariables(HttpServletRequest request,
+                       Application application2) {
+
+               Map params = new HashMap(request.getParameterMap());
+               String changes = (String) ((params.get("changes") instanceof String[]) ? ((String[]) params
+                               .get("changes"))[0]
+                               : params.get("changes"));
+               params.remove("changes");
+               if (changes != null) {
+                       String[] ca = changes.split("\u0001");
+                       System.out.println("Changes = " + changes);
+                       for (int i = 0; i < ca.length; i++) {
+                               String[] vid = ca[i].split("_");
+                               VariableOwner owner = (VariableOwner) idPaintableMap
+                                               .get(vid[0]);
+                               if (owner != null) {
+                                       Map m;
+                                       if (i + 2 >= ca.length
+                                                       || !vid[0].equals(ca[i + 2].split("_")[0]))
+                                               m = new SingleValueMap(vid[1], convertVariableValue(
+                                                               vid[2].charAt(0), ca[++i]));
+                                       else {
+                                               m = new HashMap();
+                                               m.put(vid[1], convertVariableValue(vid[2].charAt(0),
+                                                               ca[++i]));
+                                       }
+                                       while (i + 1 < ca.length
+                                                       && vid[0].equals(ca[i + 1].split("_")[0])) {
+                                               vid = ca[++i].split("_");
+                                               m.put(vid[1], convertVariableValue(vid[2].charAt(0),
+                                                               ca[++i]));
+                                       }
+                                       owner.changeVariables(request, m);
+                               }
+                       }
+               }
+
+               return params;
+       }
+
+       private Object convertVariableValue(char variableType, String strValue) {
+               Object val = null;
+               System.out.println("converting " + strValue + " of type "
+                               + variableType);
+               switch (variableType) {
+               case 'a':
+                       val = strValue.split(",");
+                       break;
+               case 's':
+                       val = strValue;
+                       break;
+               case 'i':
+                       val = Integer.valueOf(strValue);
+                       break;
+               case 'b':
+                       val = Boolean.valueOf(strValue);
+                       break;
+               }
+               
+               System.out.println("result: " + val + " of type " + (val == null ? "-" : val.getClass()));
+               return val;
+       }
+
+       private void printLocaleDeclarations(PrintWriter outWriter) {
+               /*
+                * ----------------------------- Sending Locale sensitive date
+                * -----------------------------
+                */
+
+               // Store JVM default locale for later restoration
+               // (we'll have to change the default locale for a while)
+               Locale jvmDefault = Locale.getDefault();
+
+               // Send locale informations to client
+               outWriter.print(", \"locales\":[");
+               for (; pendingLocalesIndex < locales.size(); pendingLocalesIndex++) {
+
+                       Locale l = generateLocale((String) locales.get(pendingLocalesIndex));
+                       // Locale name
+                       outWriter.print("{\"name\":\"" + l.toString() + "\",");
+
+                       /*
+                        * Month names (both short and full)
+                        */
+                       DateFormatSymbols dfs = new DateFormatSymbols(l);
+                       String[] short_months = dfs.getShortMonths();
+                       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)
+                        */
+                       String[] short_days = dfs.getShortWeekdays();
+                       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)
+                        */
+                       Calendar cal = new GregorianCalendar(l);
+                       outWriter.print("\"fdow\":" + (cal.getFirstDayOfWeek() - 1) + ",");
+
+                       /*
+                        * Date formatting (MM/DD/YYYY etc.)
+                        */
+                       // Force our locale as JVM default for a while (SimpleDateFormat
+                       // uses JVM default)
+                       Locale.setDefault(l);
+                       String df = new SimpleDateFormat().toPattern();
+                       int timeStart = df.indexOf("H");
+                       if (timeStart < 0)
+                               timeStart = df.indexOf("h");
+                       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;
+                       String dateformat = df.substring(0, timeStart - 1);
+
+                       outWriter.print("\"df\":\"" + dateformat.trim() + "\",");
+
+                       /*
+                        * Time formatting (24 or 12 hour clock and AM/PM suffixes)
+                        */
+                       String timeformat = df.substring(timeStart, df.length()); // Doesn't
+                       // return
+                       // second
+                       // or
+                       // milliseconds
+                       // We use timeformat to determine 12/24-hour clock
+                       boolean twelve_hour_clock = timeformat.contains("a");
+                       // TODO there are other possibilities as well, like 'h' in french
+                       // (ignore them, too complicated)
+                       String hour_min_delimiter = timeformat.contains(".") ? "." : ":";
+                       // outWriter.print("\"tf\":\"" + timeformat + "\",");
+                       outWriter.print("\"thc\":" + twelve_hour_clock + ",");
+                       outWriter.print("\"hmd\":\"" + hour_min_delimiter + "\"");
+                       if (twelve_hour_clock) {
+                               String[] ampm = dfs.getAmPmStrings();
+                               outWriter.print(",\"ampm\":[\"" + ampm[0] + "\",\"" + ampm[1]
+                                               + "\"]");
+                       }
+                       outWriter.print("}");
+                       if (pendingLocalesIndex < locales.size() - 1)
+                               outWriter.print(",");
+               }
+               outWriter.print("]"); // Close locales
+
+               // Restore JVM default locale
+               Locale.setDefault(jvmDefault);
+       }
+
+       /**
+        * 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.
+        * @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 Window getApplicationWindow(HttpServletRequest request,
+                       Application application) throws ServletException {
+
+               Window window = null;
+
+               // Find the window where the request is handled
+               String path = request.getPathInfo();
+
+               // Main window as the URI is empty
+               if (path == null || path.length() == 0 || path.equals("/"))
+                       window = application.getMainWindow();
+
+               // Try to search by window name
+               else {
+                       String windowName = null;
+                       if (path.charAt(0) == '/')
+                               path = path.substring(1);
+                       int index = path.indexOf('/');
+                       if (index < 0) {
+                               windowName = path;
+                               path = "";
+                       } else {
+                               windowName = path.substring(0, index);
+                               path = path.substring(index + 1);
+                       }
+                       window = application.getWindow(windowName);
+
+                       // By default, we use main window
+                       if (window == null)
+                               window = application.getMainWindow();
+               }
+
+               return window;
+       }
+
+       /**
+        * 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.
+        * 
+        * @param application
+        *            the Application owning the URI.
+        * @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, otherwise
+        *         <code>false</code>.
+        * @see com.itmill.toolkit.terminal.URIHandler
+        */
+       private DownloadStream handleURI(Application application,
+                       HttpServletRequest request, HttpServletResponse response) {
+
+               String uri = request.getPathInfo();
+
+               // If no URI is available
+               if (uri == null || uri.length() == 0 || uri.equals("/"))
+                       return null;
+
+               // Remove the leading /
+               while (uri.startsWith("/") && uri.length() > 0)
+                       uri = uri.substring(1);
+
+               // Handle the uri
+               DownloadStream stream = null;
+               try {
+                       stream = application.handleURI(application.getURL(), uri);
+               } catch (Throwable t) {
+                       application.terminalError(new URIHandlerErrorImpl(application, t));
+               }
+
+               return stream;
+       }
+
+       /**
+        * 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.
+        * 
+        * @param stream
+        *            the downloadable stream.
+        * 
+        * @param request
+        *            the HTTP request instance.
+        * @param response
+        *            the HTTP response to write to.
+        * 
+        * @see com.itmill.toolkit.terminal.URIHandler
+        */
+       private void handleDownload(DownloadStream stream,
+                       HttpServletRequest request, HttpServletResponse response) {
+
+               // Download from given stream
+               InputStream data = stream.getStream();
+               if (data != null) {
+
+                       // Sets content type
+                       response.setContentType(stream.getContentType());
+
+                       // Sets cache headers
+                       long cacheTime = stream.getCacheTime();
+                       if (cacheTime <= 0) {
+                               response.setHeader("Cache-Control", "no-cache");
+                               response.setHeader("Pragma", "no-cache");
+                               response.setDateHeader("Expires", 0);
+                       } else {
+                               response.setHeader("Cache-Control", "max-age=" + cacheTime
+                                               / 1000);
+                               response.setDateHeader("Expires", System.currentTimeMillis()
+                                               + cacheTime);
+                               response.setHeader("Pragma", "cache"); // Required to apply
+                               // caching in some
+                               // Tomcats
+                       }
+
+                       // Copy download stream parameters directly
+                       // to HTTP headers.
+                       Iterator i = stream.getParameterNames();
+                       if (i != null) {
+                               while (i.hasNext()) {
+                                       String param = (String) i.next();
+                                       response.setHeader((String) param, stream
+                                                       .getParameter(param));
+                               }
+                       }
+
+                       int bufferSize = stream.getBufferSize();
+                       if (bufferSize <= 0 || bufferSize > MAX_BUFFER_SIZE)
+                               bufferSize = DEFAULT_BUFFER_SIZE;
+                       byte[] buffer = new byte[bufferSize];
+                       int bytesRead = 0;
+
+                       try {
+                               OutputStream out = response.getOutputStream();
+
+                               while ((bytesRead = data.read(buffer)) > 0) {
+                                       out.write(buffer, 0, bytesRead);
+                                       out.flush();
+                               }
+                               out.close();
+                       } catch (IOException ignored) {
+                       }
+
+               }
+
+       }
+
+       /**
+        * Ends the Application.
+        * 
+        * @param request
+        *            the HTTP request instance.
+        * @param response
+        *            the HTTP response to write to.
+        * @param application
+        *            the Application to end.
+        * @throws IOException
+        *             if the writing failed due to input/output error.
+        */
+       private void endApplication(HttpServletRequest request,
+                       HttpServletResponse 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 xml file to
+               // tell client that application is quit and where to point browser now
+               // Set the response type
+               response.setContentType("application/xml; charset=UTF-8");
+               ServletOutputStream out = response.getOutputStream();
+               out.println("<redirect url=\"" + logoutUrl + "\">");
+               out.println("</redirect>");
+       }
+
+       /**
+        * Gets the Paintable Id.
+        * 
+        * @param paintable
+        * @return the paintable Id.
+        */
+       public synchronized String getPaintableId(Paintable paintable) {
+
+               String id = (String) paintableIdMap.get(paintable);
+               if (id == null) {
+                       id = "PID" + Integer.toString(idSequence++);
+                       paintableIdMap.put(paintable, id);
+                       idPaintableMap.put(id, paintable);
+               }
+
+               return id;
+       }
+
+       /**
+        * 
+        * @return
+        */
+       public synchronized Set getDirtyComponents() {
+
+               // Remove unnecessary repaints from the list
+               Object[] paintables = dirtyPaintabletSet.toArray();
+               for (int i = 0; i < paintables.length; i++) {
+                       if (paintables[i] instanceof Component) {
+                               Component c = (Component) paintables[i];
+
+                               // Check if any of the parents of c already exist in the list
+                               Component p = c.getParent();
+                               while (p != null) {
+                                       if (dirtyPaintabletSet.contains(p)) {
+
+                                               // Remove component c from the dirty paintables as its
+                                               // parent is also dirty
+                                               dirtyPaintabletSet.remove(c);
+                                               p = null;
+                                       } else
+                                               p = p.getParent();
+                               }
+                       }
+               }
+
+               return Collections.unmodifiableSet(dirtyPaintabletSet);
+       }
+
+       /**
+        * Clears the Dirty Components.
+        * 
+        */
+       public synchronized void clearDirtyComponents() {
+               dirtyPaintabletSet.clear();
+       }
+
+       /**
+        * @see com.itmill.toolkit.terminal.Paintable.RepaintRequestListener#repaintRequested(com.itmill.toolkit.terminal.Paintable.RepaintRequestEvent)
+        */
+       public void repaintRequested(RepaintRequestEvent event) {
+               Paintable p = event.getPaintable();
+               dirtyPaintabletSet.add(p);
+
+               // For FrameWindows we mark all frames (windows) dirty
+               if (p instanceof FrameWindow) {
+                       FrameWindow fw = (FrameWindow) p;
+                       repaintFrameset(fw.getFrameset());
+               }
+       }
+
+       /**
+        * Recursively request repaint for all frames in frameset.
+        * 
+        * @param fs
+        *            the Framewindow.Frameset.
+        */
+       private void repaintFrameset(FrameWindow.Frameset fs) {
+               List frames = fs.getFrames();
+               for (Iterator i = frames.iterator(); i.hasNext();) {
+                       FrameWindow.Frame f = (FrameWindow.Frame) i.next();
+                       if (f instanceof FrameWindow.Frameset) {
+                               repaintFrameset((FrameWindow.Frameset) f);
+                       } else {
+                               Window w = f.getWindow();
+                               if (w != null) {
+                                       w.requestRepaint();
+                               }
+                       }
+               }
+       }
+
+       /**
+        * 
+        * @param p
+        */
+       public void paintablePainted(Paintable p) {
+               dirtyPaintabletSet.remove(p);
+               p.requestRepaintRequests();
+       }
+
+       /**
+        * 
+        * @param paintable
+        * @return
+        */
+       public boolean isDirty(Paintable paintable) {
+               return (dirtyPaintabletSet.contains(paintable));
+       }
+
+       /**
+        * @see com.itmill.toolkit.Application.WindowAttachListener#windowAttached(com.itmill.toolkit.Application.WindowAttachEvent)
+        */
+       public void windowAttached(WindowAttachEvent event) {
+               event.getWindow().addListener(this);
+               dirtyPaintabletSet.add(event.getWindow());
+       }
+
+       /**
+        * @see com.itmill.toolkit.Application.WindowDetachListener#windowDetached(com.itmill.toolkit.Application.WindowDetachEvent)
+        */
+       public void windowDetached(WindowDetachEvent event) {
+               event.getWindow().removeListener(this);
+               // Notify client of the close operation
+               removedWindows.add(event.getWindow());
+       }
+
+       /**
+        * 
+        * @return
+        */
+       public synchronized Set getRemovedWindows() {
+               return Collections.unmodifiableSet(removedWindows);
+
+       }
+
+       /**
+        * 
+        * @param w
+        */
+       private void removedWindowNotified(Window w) {
+               this.removedWindows.remove(w);
+       }
+
+       private final class SingleValueMap implements Map {
+               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() {
+                       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() {
+                       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() {
+                       LinkedList s = new LinkedList();
+                       s.add(value);
+                       return s;
+
+               }
+       }
+
+       /**
+        * Implementation of URIHandler.ErrorEvent interface.
+        */
+       public class URIHandlerErrorImpl implements URIHandler.ErrorEvent {
+
+               private URIHandler owner;
+
+               private Throwable throwable;
+
+               /**
+                * 
+                * @param owner
+                * @param throwable
+                */
+               private URIHandlerErrorImpl(URIHandler owner, Throwable throwable) {
+                       this.owner = owner;
+                       this.throwable = throwable;
+               }
+
+               /**
+                * @see com.itmill.toolkit.terminal.Terminal.ErrorEvent#getThrowable()
+                */
+               public Throwable getThrowable() {
+                       return this.throwable;
+               }
+
+               /**
+                * @see com.itmill.toolkit.terminal.URIHandler.ErrorEvent#getURIHandler()
+                */
+               public URIHandler getURIHandler() {
+                       return this.owner;
+               }
+       }
+
+       public void requireLocale(String value) {
+               if (locales == null) {
+                       locales = new ArrayList();
+                       locales.add(application.getLocale().toString());
+                       pendingLocalesIndex = 0;
+               }
+               if (!locales.contains(value))
+                       locales.add(value);
+       }
+
+       private Locale generateLocale(String value) {
+               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]);
+       }
+}
diff --git a/src/com/itmill/toolkit/terminal/gwt/server/HttpUploadStream.java b/src/com/itmill/toolkit/terminal/gwt/server/HttpUploadStream.java
new file mode 100644 (file)
index 0000000..d6ee9b9
--- /dev/null
@@ -0,0 +1,114 @@
+/* *************************************************************************
+ IT Mill Toolkit 
+
+ Development of Browser User Interfaces Made Easy
+
+ Copyright (C) 2000-2006 IT Mill Ltd
+ *************************************************************************
+
+ This product is distributed under commercial license that can be found
+ from the product package on license.pdf. Use of this product might 
+ require purchasing a commercial license from IT Mill Ltd. For guidelines 
+ on usage, see licensing-guidelines.html
+
+ *************************************************************************
+ For more information, contact:
+ IT Mill Ltd                           phone: +358 2 4802 7180
+ Ruukinkatu 2-4                        fax:   +358 2 4802 7181
+ 20540, Turku                          email:  info@itmill.com
+ Finland                               company www: www.itmill.com
+ Primary source for information and releases: www.itmill.com
+
+ ********************************************************************** */
+
+package com.itmill.toolkit.terminal.gwt.server;
+
+import java.io.InputStream;
+
+/**
+ * AjaxAdapter implementation of the UploadStream interface.
+ * 
+ * @author IT Mill Ltd.
+ * @version
+ * @VERSION@
+ * @since 5.0
+ */
+public class HttpUploadStream implements
+               com.itmill.toolkit.terminal.UploadStream {
+
+       /**
+        * Holds value of property variableName.
+        */
+       private String streamName;
+
+       private String contentName;
+
+       private String contentType;
+
+       /**
+        * Holds value of property variableValue.
+        */
+       private InputStream stream;
+
+       /**
+        * Creates a new instance of UploadStreamImpl.
+        * 
+        * @param name
+        *            the name of the stream.
+        * @param stream
+        *            the input stream.
+        * @param contentName
+        *            the name of the content.
+        * @param contentType
+        *            the type of the content.
+        */
+       public HttpUploadStream(String name, InputStream stream,
+                       String contentName, String contentType) {
+               this.streamName = name;
+               this.stream = stream;
+               this.contentName = contentName;
+               this.contentType = contentType;
+       }
+
+       /**
+        * Gets the name of the stream.
+        * 
+        * @return the name of the stream.
+        */
+       public String getStreamName() {
+               return this.streamName;
+       }
+
+       /**
+        * Gets the input stream.
+        * 
+        * @return the Input stream.
+        */
+       public InputStream getStream() {
+               return this.stream;
+       }
+
+       /**
+        * Gets the input stream content type.
+        * 
+        * @return the content type of the input stream.
+        */
+       public String getContentType() {
+               return this.contentType;
+       }
+
+       /**
+        * Gets the stream content name. Stream content name usually differs from
+        * the actual stream name. It is used to identify the content of the stream.
+        * 
+        * @return the Name of the stream content.
+        */
+       public String getContentName() {
+               return this.contentName;
+       }
+}
index 6e4662e55711acb44d28c714ba89c8a4a90869fc..8095141895e4604e49040b4707fc926cc9b9a36c 100644 (file)
@@ -78,11 +78,9 @@ public class JsonPaintTarget implements PaintTarget {
 
        private PrintWriter uidlBuffer;
 
-       private AjaxVariableMap variableMap;
-
        private boolean closed = false;
 
-       private ApplicationManager manager;
+       private CommunicationManager manager;
 
        private boolean trackPaints = false;
 
@@ -106,13 +104,11 @@ public class JsonPaintTarget implements PaintTarget {
         * @throws PaintException
         *             if the paint operation failed.
         */
-       public JsonPaintTarget(AjaxVariableMap variableMap,
-                       ApplicationManager manager, PrintWriter outWriter)
+       public JsonPaintTarget(
+                       CommunicationManager manager, PrintWriter outWriter)
                        throws PaintException {
 
                this.manager = manager;
-               // Sets the variable map
-               this.variableMap = variableMap;
 
                // Sets the target for UIDL writing
                this.uidlBuffer = outWriter;
@@ -561,10 +557,7 @@ public class JsonPaintTarget implements PaintTarget {
         */
        public void addUploadStreamVariable(VariableOwner owner, String name)
                        throws PaintException {
-               String code = variableMap.registerVariable(name, UploadStream.class,
-                               null, owner);
                startTag("uploadstream");
-               addAttribute(UIDL_ARG_ID, code);
                addAttribute(UIDL_ARG_NAME, name);
                endTag("uploadstream");
        }
@@ -750,8 +743,6 @@ public class JsonPaintTarget implements PaintTarget {
 
                Vector attr = new Vector();
 
-               private HashMap childTagCounters = new HashMap();
-
                StringBuffer data = new StringBuffer();
 
                public boolean childrenArrayOpen = false;
@@ -891,21 +882,18 @@ public class JsonPaintTarget implements PaintTarget {
        }
 
        abstract class Variable {
-               String code;
 
                String name;
 
                public abstract String getJsonPresentation();
        }
-
+       
        class BooleanVariable extends Variable {
                boolean value;
 
                public BooleanVariable(VariableOwner owner, String name, boolean v) {
                        value = v;
                        this.name = name;
-                       code = variableMap.registerVariable(name, Boolean.class,
-                                       new Boolean(value), owner);
                }
 
                public String getJsonPresentation() {
@@ -920,8 +908,6 @@ public class JsonPaintTarget implements PaintTarget {
                public StringVariable(VariableOwner owner, String name, String v) {
                        value = v;
                        this.name = name;
-                       code = variableMap.registerVariable(name, String.class, value,
-                                       owner);
                }
 
                public String getJsonPresentation() {
@@ -936,8 +922,6 @@ public class JsonPaintTarget implements PaintTarget {
                public IntVariable(VariableOwner owner, String name, int v) {
                        value = v;
                        this.name = name;
-                       code = variableMap.registerVariable(name, Integer.class,
-                                       new Integer(value), owner);
                }
 
                public String getJsonPresentation() {
@@ -951,8 +935,6 @@ public class JsonPaintTarget implements PaintTarget {
                public ArrayVariable(VariableOwner owner, String name, String[] v) {
                        value = v;
                        this.name = name;
-                       code = variableMap.registerVariable(name, String[].class, value,
-                                       owner);
                }
 
                public String getJsonPresentation() {
index 7a84341543ade4f9df2a485512f8ebeaa3213fb3..27bd738c6277d36b356e98afe137d39bd1d7b497 100644 (file)
@@ -55,9 +55,9 @@ package com.itmill.toolkit.terminal.gwt.server;
  * @author IT Mill Ltd.
  * @version
  * @VERSION@
- * @since 3.0
+ * @since 5.0
  */
-public class Log {
+class Log {
 
        private static boolean useStdOut = true;
 
diff --git a/src/com/itmill/toolkit/terminal/gwt/server/MultipartRequest.java b/src/com/itmill/toolkit/terminal/gwt/server/MultipartRequest.java
deleted file mode 100644 (file)
index ae22f5b..0000000
+++ /dev/null
@@ -1,1332 +0,0 @@
-/* *************************************************************************
- IT Mill Toolkit 
-
- Development of Browser User Interfaces Made Easy
-
- Copyright (C) 2000-2006 IT Mill Ltd
- *************************************************************************
-
- This product is distributed under commercial license that can be found
- from the product package on license.pdf. Use of this product might 
- require purchasing a commercial license from IT Mill Ltd. For guidelines 
- on usage, see licensing-guidelines.html
-
- *************************************************************************
- For more information, contact:
- IT Mill Ltd                           phone: +358 2 4802 7180
- Ruukinkatu 2-4                        fax:   +358 2 4802 7181
- 20540, Turku                          email:  info@itmill.com
- Finland                               company www: www.itmill.com
- Primary source for information and releases: www.itmill.com
-
- ********************************************************************** */
-
-package com.itmill.toolkit.terminal.gwt.server;
-
-import java.util.Hashtable;
-import java.io.BufferedOutputStream;
-import java.io.BufferedInputStream;
-import java.io.OutputStream;
-import java.io.InputStream;
-import java.io.PrintWriter;
-import java.io.ByteArrayOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.FileOutputStream;
-import java.io.UnsupportedEncodingException;
-import java.io.IOException;
-import java.util.Enumeration;
-import java.util.Vector;
-import java.io.File;
-
-/**
- * A Multipart form data parser. Parses an input stream and writes out any files
- * found, making available a hashtable of other url parameters. As of version
- * 1.17 the files can be saved to memory, and optionally written to a database,
- * etc.
- * 
- * <BR>
- * <BR>
- * Copyright (C)2001 Jason Pell. <BR>
- * 
- * <PRE>
- * 
- * This library is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation; either version 2.1 of the License, or (at your option)
- * any later version. <BR>
- * This library is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details. <BR>
- * You should have received a copy of the GNU Lesser General Public License
- * along with this library; if not, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA <BR>
- * Email: jasonpell@hotmail.com Url: http://www.geocities.com/jasonpell
- * 
- * </PRE>
- * 
- * @author Jason Pell
- * 
- * @version 1.18 Fixed some serious bugs. A new method readAndWrite(InputStream
- *          in, OutputStream out) which now does the generic processing in
- *          common for readAndWriteFile and readFile. The differences are that
- *          now the two extra bytes at the end of a file upload are processed
- *          once, instead of after each line. Also if an empty file is
- *          encountered, an outputstream is opened, but then deleted if no data
- *          written to it. The <code>getCharArray</code> method has been
- *          removed. Replaced by the new String(bytes, encoding) method using a
- *          specific encoding (Defaults to ISO-8859-1) to ensure that extended
- *          characters are supported. All strings are processed using this
- *          encoding. The addition of static methods setEncoding(String) and
- *          <code>getEncoding</code> method to allow the use of
- *          <code>MultipartRequest</code> with a specific encoding type. All
- *          instances of MultipartRequest will utilise the static charEncoding
- *          variable value, that the <code>setEncoding</code> method can be
- *          used to set. Started to introduce support for multiple file uploads
- *          with the same form field name, but not completed for v1.18.
- *          26/06/2001
- * 
- * @version 1.17 A few _very_ minor fixes. Plus a cool new feature added. The
- *          ability to save files into memory. <b>Thanks to Mark Latham for the
- *          idea and some of the code.</b> 11/04/2001
- * @version 1.16 Added support for multiple parameter values. Also fixed
- *          getCharArray(...) method to support parameters with non-english
- *          ascii values (ascii above 127). Thanks to Stefan Schmidt & Michael
- *          Elvers for this. (No fix yet for reported problems with Tomcat 3.2
- *          or a single extra byte appended to uploads of certain files). By
- *          1.17 hopefully will have a resolution for the second problem.
- *          14/03/2001
- * @version 1.15 A new parameter added, intMaxReadBytes, to allow arbitrary
- *          length files. Released under the LGPL (Lesser General Public
- *          License). 03/02/2001
- * @version 1.14 Fix for IE problem with filename being empty. This is because
- *          IE includes a default Content-Type even when no file is uploaded.
- *          16/02/2001
- * @version 1.13 If an upload directory is not specified, then all file contents
- *          are sent into oblivion, but the rest of the parsing works as normal.
- * @version 1.12 Fix, was allowing zero length files. Will not even create the
- *          output file until there is something to write. getFile(String) now
- *          returns null, if a zero length file was specified. 06/11/2000
- * @version 1.11 Fix, in case Content-type is not specified.
- * @version 1.1 Removed dependence on Servlets. Now passes in a generic
- *          InputStream instead. "Borrowed" readLine from Tomcat 3.1
- *          ServletInputStream class, so we can remove some of the dependencies
- *          on ServletInputStream. Fixed bug where a empty INPUT TYPE="FILE"
- *          value, would cause an exception.
- * @version 1.0 Initial Release.
- */
-
-public class MultipartRequest {
-       /**
-        * Defines Character Encoding method here.
-        */
-       private String charEncoding = "UTF-8";
-
-       // If not null, send debugging out here.
-       private PrintWriter debug = null;
-
-       private Hashtable htParameters = null;
-
-       private Hashtable htFiles = null;
-
-       private String strBoundary = null;
-
-       // If this Directory spec remains null, writing of files will be disabled...
-       private File fileOutPutDirectory = null;
-
-       private boolean loadIntoMemory = false;
-
-       private long intContentLength = -1;
-
-       private long intTotalRead = -1;
-
-       /**
-        * Prevent a denial of service by defining this, will never read more data.
-        * If Content-Length is specified to be more than this, will throw an
-        * exception.
-        * 
-        * This limits the maximum number of bytes to the value of an int, which is
-        * 2 Gigabytes.
-        */
-       public static final int MAX_READ_BYTES = Integer.MAX_VALUE;
-
-       /**
-        * Defines the number of bytes to read per readLine call. 128K
-        */
-       public static final int READ_LINE_BLOCK = 1024 * 128;
-
-       /**
-        * Store a read from the input stream here. Global so we do not keep
-        * creating new arrays each read.
-        */
-       private byte[] blockOfBytes = null;
-
-       /**
-        * Type constant for File FILENAME.
-        */
-       public static final int FILENAME = 0;
-
-       /**
-        * Type constant for the File CONTENT_TYPE.
-        */
-       public static final int CONTENT_TYPE = 1;
-
-       /**
-        * Type constant for the File SIZE.
-        */
-       public static final int SIZE = 2;
-
-       /**
-        * Type constant for the File CONTENTS.
-        * 
-        * <b>Note: </b>Only used for file upload to memory.
-        */
-       public static final int CONTENTS = 3;
-
-       /**
-        * This method should be called on the <code>MultipartRequest</code>
-        * itself, not on any instances of <code>MultipartRequest</code>, because
-        * this sets up the encoding for all instances of multipartrequest. You can
-        * set the encoding to null, in which case the default encoding will be
-        * applied. The default encoding if this method is not called has been set
-        * to ISO-8859-1, which seems to offer the best hope of support for
-        * international characters, such as german "Umlaut" characters.
-        * 
-        * <p>
-        * <b>Warning:</b> In multithreaded environments it is the responsibility
-        * of the implementer to make sure that this method is not called while
-        * another instance is being constructed. When an instance of
-        * MultipartRequest is constructed, it parses the input data, and uses the
-        * result of <code>getEncoding</code> method to convert between bytes and
-        * strings. If <code>setEncoding</code> method is called by another
-        * thread, while the private <code>parse</code> method is executing, the
-        * method will utilise this new encoding, which may cause serious problems.
-        * </p>
-        */
-       public void setEncoding(String enc) throws UnsupportedEncodingException {
-               if (enc == null || enc.trim() == "")
-                       charEncoding = System.getProperty("file.encoding");
-               else {
-                       // This will test the encoding for validity.
-                       new String(new byte[] { '\n' }, enc);
-
-                       charEncoding = enc;
-               }
-       }
-
-       /**
-        * Gets the current encoding method.
-        * 
-        * @return the encoding method.
-        */
-       public String getEncoding() {
-               return charEncoding;
-       }
-
-       /**
-        * Constructor.
-        * 
-        * @param strContentTypeText
-        *            the &quot;Content-Type&quot; HTTP header value.
-        * @param intContentLength
-        *            the &quot;Content-Length&quot; HTTP header value.
-        * @param in
-        *            the InputStream to read and parse.
-        * @param strSaveDirectory
-        *            the temporary directory to save the file from where they can
-        *            then be moved to wherever by the calling process. <b>If you
-        *            specify <u>null</u> for this parameter, then any files
-        *            uploaded will be silently ignored.</b>
-        * 
-        * @exception IllegalArgumentException
-        *                If the strContentTypeText does not contain a Content-Type
-        *                of "multipart/form-data" or the boundary is not found.
-        * @exception IOException
-        *                If the intContentLength is higher than MAX_READ_BYTES or
-        *                strSaveDirectory is invalid or cannot be written to.
-        * 
-        * @see #MAX_READ_BYTES
-        */
-       public MultipartRequest(String strContentTypeText, int intContentLength,
-                       InputStream in, String strSaveDirectory)
-                       throws IllegalArgumentException, IOException {
-               this(null, strContentTypeText, intContentLength, in, strSaveDirectory,
-                               MAX_READ_BYTES);
-       }
-
-       /**
-        * Constructor.
-        * 
-        * @param strContentTypeText
-        *            the &quot;Content-Type&quot; HTTP header value.
-        * @param intContentLength
-        *            the &quot;Content-Length&quot; HTTP header value.
-        * @param in
-        *            the InputStream to read and parse.
-        * @param strSaveDirectory
-        *            the temporary directory to save the file from where they can
-        *            then be moved to wherever by the calling process. <b>If you
-        *            specify <u>null</u> for this parameter, then any files
-        *            uploaded will be silently ignored.</B>
-        * @param intMaxReadBytes
-        *            Overrides the MAX_BYTES_READ value, to allow arbitrarily long
-        *            files.
-        * 
-        * @exception IllegalArgumentException
-        *                If the strContentTypeText does not contain a Content-Type
-        *                of "multipart/form-data" or the boundary is not found.
-        * @exception IOException
-        *                If the intContentLength is higher than MAX_READ_BYTES or
-        *                strSaveDirectory is invalid or cannot be written to.
-        * 
-        * @see #MAX_READ_BYTES
-        */
-       public MultipartRequest(String strContentTypeText, int intContentLength,
-                       InputStream in, String strSaveDirectory, int intMaxReadBytes)
-                       throws IllegalArgumentException, IOException {
-               this(null, strContentTypeText, intContentLength, in, strSaveDirectory,
-                               intMaxReadBytes);
-       }
-
-       /**
-        * Constructor.
-        * 
-        * @param debug
-        *            A PrintWriter that can be used for debugging.
-        * @param strContentTypeText
-        *            the &quot;Content-Type&quot; HTTP header value.
-        * @param intContentLength
-        *            the &quot;Content-Length&quot; HTTP header value.
-        * @param in
-        *            the InputStream to read and parse.
-        * @param strSaveDirectory
-        *            the temporary directory to save the file from where they can
-        *            then be moved to wherever by the calling process. <b>If you
-        *            specify <u>null</u> for this parameter, then any files
-        *            uploaded will be silently ignored.</B>
-        * 
-        * @exception IllegalArgumentException
-        *                If the strContentTypeText does not contain a Content-Type
-        *                of "multipart/form-data" or the boundary is not found.
-        * @exception IOException
-        *                If the intContentLength is higher than MAX_READ_BYTES or
-        *                strSaveDirectory is invalid or cannot be written to.
-        * 
-        * @see #MAX_READ_BYTES
-        * @deprecated Replaced by MultipartRequest(PrintWriter, String, int,
-        *             InputStream, int) You can specify
-        *             MultipartRequest.MAX_READ_BYTES for the intMaxReadBytes
-        *             parameter
-        */
-       public MultipartRequest(PrintWriter debug, String strContentTypeText,
-                       int intContentLength, InputStream in, String strSaveDirectory)
-                       throws IllegalArgumentException, IOException {
-               this(debug, strContentTypeText, intContentLength, in, strSaveDirectory,
-                               MAX_READ_BYTES);
-
-       }
-
-       /**
-        * Constructor - load into memory constructor
-        * 
-        * @param debug
-        *            A PrintWriter that can be used for debugging.
-        * @param strContentTypeText
-        *            the &quot;Content-Type&quot; HTTP header value.
-        * @param intContentLength
-        *            the &quot;Content-Length&quot; HTTP header value.
-        * @param in
-        *            the InputStream to read and parse.
-        * @param intMaxReadBytes
-        *            Overrides the MAX_BYTES_READ value, to allow arbitrarily long
-        *            files.
-        * 
-        * @exception IllegalArgumentException
-        *                If the strContentTypeText does not contain a Content-Type
-        *                of "multipart/form-data" or the boundary is not found.
-        * @exception IOException
-        *                If the intContentLength is higher than MAX_READ_BYTES or
-        *                strSaveDirectory is invalid or cannot be written to.
-        * 
-        * @see #MAX_READ_BYTES
-        */
-       public MultipartRequest(PrintWriter debug, String strContentTypeText,
-                       int intContentLength, InputStream in, int intMaxReadBytes)
-                       throws IllegalArgumentException, IOException {
-               this.loadIntoMemory = true;
-
-               // Now initialise the object, which will actually call the parse method
-               // to parse multipart stream.
-               init(debug, strContentTypeText, intContentLength, in, intMaxReadBytes);
-       }
-
-       /**
-        * Constructor.
-        * 
-        * @param debug
-        *            A PrintWriter that can be used for debugging.
-        * @param strContentTypeText
-        *            the &quot;Content-Type&quot; HTTP header value.
-        * @param intContentLength
-        *            the &quot;Content-Length&quot; HTTP header value.
-        * @param in
-        *            the InputStream to read and parse.
-        * @param strSaveDirectory
-        *            the temporary directory to save the file from where they can
-        *            then be moved to wherever by the calling process. <b>If you
-        *            specify <u>null</u> for this parameter, then any files
-        *            uploaded will be silently ignored.</B>
-        * @param intMaxReadBytes
-        *            Overrides the MAX_BYTES_READ value, to allow arbitrarily long
-        *            files.
-        * 
-        * @exception IllegalArgumentException
-        *                If the strContentTypeText does not contain a Content-Type
-        *                of "multipart/form-data" or the boundary is not found.
-        * @exception IOException
-        *                If the intContentLength is higher than MAX_READ_BYTES or
-        *                strSaveDirectory is invalid or cannot be written to.
-        * 
-        * @see #MAX_READ_BYTES
-        */
-       public MultipartRequest(PrintWriter debug, String strContentTypeText,
-                       int intContentLength, InputStream in, String strSaveDirectory,
-                       int intMaxReadBytes) throws IllegalArgumentException, IOException {
-               // IF strSaveDirectory == NULL, then we should ignore any files
-               // uploaded.
-               if (strSaveDirectory != null) {
-                       fileOutPutDirectory = new File(strSaveDirectory);
-                       if (!fileOutPutDirectory.exists())
-                               throw new IOException("Directory [" + strSaveDirectory
-                                               + "] is invalid.");
-                       else if (!fileOutPutDirectory.canWrite())
-                               throw new IOException("Directory [" + strSaveDirectory
-                                               + "] is readonly.");
-               }
-
-               // Now initialise the object, which will actually call the parse method
-               // to parse multipart stream.
-               init(debug, strContentTypeText, intContentLength, in, intMaxReadBytes);
-       }
-
-       /**
-        * Initialise the parser.
-        * 
-        * @param debug
-        *            A PrintWriter that can be used for debugging.
-        * @param strContentTypeText
-        *            the &quot;Content-Type&quot; HTTP header value.
-        * @param intContentLength
-        *            the &quot;Content-Length&quot; HTTP header value.
-        * @param in
-        *            the InputStream to read and parse.
-        * @param strSaveDirectory
-        *            the temporary directory to save the file from where they can
-        *            then be moved to wherever by the calling process. <b>If you
-        *            specify <u>null</u> for this parameter, then any files
-        *            uploaded will be silently ignored.</B>
-        * @param intMaxReadBytes
-        *            Overrides the MAX_BYTES_READ value, to allow arbitrarily long
-        *            files.
-        * 
-        * @exception IllegalArgumentException
-        *                If the strContentTypeText does not contain a Content-Type
-        *                of "multipart/form-data" or the boundary is not found.
-        * @exception IOException
-        *                If the intContentLength is higher than MAX_READ_BYTES or
-        *                strSaveDirectory is invalid or cannot be written to.
-        * 
-        * @see #MAX_READ_BYTES
-        */
-       private void init(PrintWriter debug, String strContentTypeText,
-                       int intContentLength, InputStream in, int intMaxReadBytes)
-                       throws IllegalArgumentException, IOException {
-               // saves reference to debug stream for later.
-               this.debug = debug;
-
-               if (strContentTypeText != null
-                               && strContentTypeText.startsWith("multipart/form-data")
-                               && strContentTypeText.indexOf("boundary=") != -1)
-                       strBoundary = strContentTypeText.substring(
-                                       strContentTypeText.indexOf("boundary=")
-                                                       + "boundary=".length()).trim();
-               else {
-                       // <mtl,jpell>
-                       debug("ContentType = " + strContentTypeText);
-                       throw new IllegalArgumentException("Invalid Content Type.");
-               }
-
-               this.intContentLength = intContentLength;
-               // FIX: 115
-               if (intContentLength > intMaxReadBytes)
-                       throw new IOException("Content Length Error (" + intContentLength
-                                       + " > " + intMaxReadBytes + ")");
-
-               // Instantiate the hashtable...
-               htParameters = new Hashtable();
-               htFiles = new Hashtable();
-               blockOfBytes = new byte[READ_LINE_BLOCK];
-
-               // Now parse the data.
-               parse(new BufferedInputStream(in));
-
-               // No need for this once parse is complete.
-               this.blockOfBytes = null;
-               this.debug = null;
-               this.strBoundary = null;
-       }
-
-       /**
-        * Gets the value of the strName URLParameter. If more than one value for a
-        * particular Parameter, will return the first. If an error occurs will
-        * return null.
-        * 
-        * @param strName
-        *            the form field name, used to upload the file. This identifies
-        *            the formfield location in the storage facility.
-        * @return the value of the URL Parameter.
-        */
-       public String getURLParameter(String strName) {
-               Object value = htParameters.get(strName);
-               if (value instanceof Vector)
-                       return (String) ((Vector) value).firstElement();
-               else
-                       return (String) htParameters.get(strName);
-       }
-
-       /**
-        * Gets an enumeration of all values for the strName parameter. Even if a
-        * single value for, will always return an enumeration, although it may
-        * actually be empty if no value was encountered for strName or it is an
-        * invalid parameter name.
-        * 
-        * @param strName
-        *            the form field name, used to upload the file. This identifies
-        *            the formfield location in the storage facility.
-        * @return the enumeration of all values.
-        */
-       public Enumeration getURLParameters(String strName) {
-               Object value = htParameters.get(strName);
-               if (value instanceof Vector)
-                       return ((Vector) value).elements();
-               else {
-                       Vector vector = new Vector();
-                       if (value != null)
-                               vector.addElement(value);
-                       return vector.elements();
-               }
-       }
-
-       /**
-        * Gets the enumeration of all URL Parameters for the current HTTP Request.
-        * 
-        * @return the enumeration of URl Parameters.
-        */
-       public Enumeration getParameterNames() {
-               return htParameters.keys();
-       }
-
-       /**
-        * Gets the enumeration of all INPUT TYPE=FILE parameter NAMES as
-        * encountered during the upload.
-        * 
-        * @return
-        */
-       public Enumeration getFileParameterNames() {
-               return htFiles.keys();
-       }
-
-       /**
-        * Returns the Content-Type of a file.
-        * 
-        * @see #getFileParameter(java.lang.String, int)
-        */
-       public String getContentType(String strName) {
-               // Can cast null, it will be ignored.
-               return (String) getFileParameter(strName, CONTENT_TYPE);
-       }
-
-       /**
-        * If files were uploaded into memory, this method will retrieve the
-        * contents of the file as a InputStream.
-        * 
-        * @param strName
-        *            the form field name, used to upload the file. This identifies
-        *            the formfield location in the storage facility.
-        * @return the contents of the file as a InputStream, or null if not file
-        *         uploaded, or file uploaded to file system directory.
-        * @see #getFileParameter(java.lang.String, int)
-        */
-       public InputStream getFileContents(String strName) {
-               Object obj = getFileParameter(strName, CONTENTS);
-               if (obj != null)
-                       return new ByteArrayInputStream((byte[]) obj);
-               else
-                       return null;
-       }
-
-       /**
-        * Returns a File reference to the uploaded file. This reference is to the
-        * files uploaded location, and allows you to read/move/delete the file.
-        * This method is only of use, if files were uploaded to the file system.
-        * Will return null if uploaded to memory, in which case you should use
-        * getFileContents(strName) instead.
-        * 
-        * @param strName
-        *            the form field name, used to upload the file. This identifies
-        *            the formfield location in the storage facility.
-        * @return a null file reference if a call to getFileSize(strName) returns
-        *         zero or files were uploaded to memory.
-        * @see #getFileSize(java.lang.String)
-        * @see #getFileContents(java.lang.String)
-        * @see #getFileSystemName(java.lang.String)
-        */
-       public File getFile(String strName) {
-               String filename = getFileSystemName(strName);
-               // Fix: If fileOutPutDirectory is null, then we are ignoring any file
-               // contents, so we must return null.
-               if (filename != null && getFileSize(strName) > 0
-                               && fileOutPutDirectory != null)
-                       return new File(fileOutPutDirectory, filename);
-               else
-                       return null;
-       }
-
-       /**
-        * Gets the file system basename of an uploaded file.
-        * 
-        * @param strName
-        *            the form field name, used to upload the file. This identifies
-        *            the formfield location in the storage facility.
-        * @return null if strName not found.
-        * 
-        * @see #getFileParameter(java.lang.String, int)
-        */
-       public String getFileSystemName(String strName) {
-               // Can cast null, it will be ignored.
-               return (String) getFileParameter(strName, FILENAME);
-       }
-
-       /**
-        * Returns the File Size of a uploaded file.
-        * 
-        * @param strName
-        *            the form field name, used to upload the file. This identifies
-        *            the formfield location in the storage facility.
-        * @return -1 if file size not defined.
-        * 
-        * @see #getFileParameter(java.lang.String, int)
-        */
-       public long getFileSize(String strName) {
-               Object obj = getFileParameter(strName, SIZE);
-               if (obj != null)
-                       return ((Long) obj).longValue();
-               else
-                       return (long) -1;
-       }
-
-       /**
-        * Access an attribute of a file upload parameter record.
-        * <p>
-        * The getFileSystemName(String strName),getFileSize(String
-        * strName),getContentType(String strName), getContents(String strName)
-        * methods all use this method passing in a different type argument.
-        * </p>
-        * 
-        * <p>
-        * <b>Note: </b>This class has been changed to provide for future
-        * functionality where you will be able to access all files uploaded, even
-        * if they are uploaded using the same form field name. At this point
-        * however, only the first file uploaded via a form field name is
-        * accessible.
-        * </p>
-        * 
-        * @param strName
-        *            the form field name, used to upload the file. This identifies
-        *            the formfield location in the storage facility.
-        * 
-        * @param type
-        *            What attribute you want from the File Parameter. The following
-        *            types are supported: MultipartRequest.FILENAME,
-        *            MultipartRequest.CONTENT_TYPE, MultipartRequest.SIZE,
-        *            MultipartRequest.CONTENTS
-        * 
-        * @see #getContentType(java.lang.String)
-        * @see #getFileSize(java.lang.String)
-        * @see #getFileContents(java.lang.String)
-        * @see #getFileSystemName(java.lang.String)
-        */
-       public Object getFileParameter(String strName, int type) {
-               Object[] objArray = null;
-               Object value = htFiles.get(strName);
-               if (value instanceof Vector)
-                       objArray = (Object[]) ((Vector) value).firstElement();
-               else
-                       objArray = (Object[]) htFiles.get(strName);
-
-               // Now ensure valid value.
-               if (objArray != null && type >= FILENAME && type <= CONTENTS)
-                       return objArray[type];
-               else
-                       return null;
-       }
-
-       /**
-        * This is the main parse method.
-        * 
-        * @param in
-        *            the InputStream to read and parse.
-        * @throws IOException
-        *             If the intContentLength is higher than MAX_READ_BYTES or
-        *             strSaveDirectory is invalid or cannot be written to.
-        */
-       private void parse(InputStream in) throws IOException {
-               String strContentType = null;
-               String strName = null;
-               String strFilename = null;
-               String strLine = null;
-               int read = -1;
-
-               // First run through, check that the first line is a boundary, otherwise
-               // throw a exception as format incorrect.
-               read = readLine(in, blockOfBytes);
-               strLine = read > 0 ? new String(blockOfBytes, 0, read, charEncoding)
-                               : null;
-
-               // Must be boundary at top of loop, otherwise we have finished.
-               if (strLine == null || strLine.indexOf(this.strBoundary) == -1)
-                       // Just exit. Exception would be overkill
-                       return;
-               // throw new IOException("Invalid Form Data, no boundary encountered.");
-
-               // At the top of loop, we assume that the Content-Disposition line is
-               // next, otherwise we are at the end.
-               while (true) {
-                       // Get Content-Disposition line.
-                       read = readLine(in, blockOfBytes);
-                       if (read <= 0)
-                               break; // Nothing to do.
-                       else {
-                               strLine = new String(blockOfBytes, 0, read, charEncoding);
-
-                               // Mac IE4 adds extra line after last boundary - 1.21
-                               if (strLine == null || strLine.length() == 0
-                                               || strLine.trim().length() == 0)
-                                       break;
-
-                               strName = trimQuotes(getValue("name", strLine));
-                               // If this is not null, it indicates that we are processing a
-                               // filename.
-                               strFilename = trimQuotes(getValue("filename", strLine));
-                               // Now if not null, strip it of any directory information.
-
-                               if (strFilename != null) {
-                                       // Fix: did not check whether filename was empty string
-                                       // indicating FILE contents were not passed.
-                                       if (strFilename.length() > 0) {
-                                               // Need to get the content type.
-                                               read = readLine(in, blockOfBytes);
-                                               strLine = read > 0 ? new String(blockOfBytes, 0, read,
-                                                               charEncoding) : null;
-
-                                               strContentType = "application/octet-stream";
-                                               // Fix 1.11: If not null AND strLine.length() is long
-                                               // enough.
-                                               if (strLine != null
-                                                               && strLine.length() > "Content-Type: ".length())
-                                                       strContentType = strLine.substring("Content-Type: "
-                                                                       .length());// Changed 1.13
-                                       } else {
-                                               // FIX 1.14: IE problem with empty filename.
-                                               read = readLine(in, blockOfBytes);
-                                               strLine = read > 0 ? new String(blockOfBytes, 0, read,
-                                                               charEncoding) : null;
-
-                                               if (strLine != null
-                                                               && strLine.startsWith("Content-Type:"))
-                                                       readLine(in, blockOfBytes);
-                                       }
-                               }
-
-                               // Ignore next line, as it should be blank.
-                               readLine(in, blockOfBytes);
-
-                               // No filename specified at all.
-                               if (strFilename == null) {
-                                       String param = readParameter(in);
-                                       addParameter(strName, param);
-                               } else {
-                                       if (strFilename.length() > 0) {
-                                               long filesize = -1;
-                                               // Will remain null for read onto file system uploads.
-                                               byte[] contentsOfFile = null;
-
-                                               // Get the BASENAME version of strFilename.
-                                               strFilename = getBasename(strFilename);
-
-                                               // Are we loading files into memory instead of the
-                                               // filesystem?
-                                               if (loadIntoMemory) {
-                                                       contentsOfFile = readFile(in);
-                                                       if (contentsOfFile != null)
-                                                               filesize = contentsOfFile.length;
-                                               } else
-                                                       // Read the file onto file system.
-                                                       filesize = readAndWriteFile(in, strFilename);
-
-                                               // Fix 1.18 for multiple FILE parameter values.
-                                               if (filesize > 0)
-                                                       addFileParameter(strName, new Object[] {
-                                                                       strFilename, strContentType,
-                                                                       new Long(filesize), contentsOfFile });
-                                               else
-                                                       // Zero length file.
-                                                       addFileParameter(strName, new Object[] {
-                                                                       strFilename, null, new Long(0), null });
-                                       } else // Fix: FILE INPUT TYPE, but no file passed as
-                                                       // input...
-                                       {
-                                               addFileParameter(strName, new Object[] { null, null,
-                                                               null, null });
-                                               readLine(in, blockOfBytes);
-                                       }
-                               }
-                       }
-               }// while
-       }
-
-       /**
-        * So we can put the logic for supporting multiple parameters with the same
-        * form field name in the one location.
-        * 
-        * @param strName
-        *            the form field name, used to upload the file. This identifies
-        *            the formfield location in the storage facility.
-        * @param value
-        *            the form field value.
-        */
-       private void addParameter(String strName, String value) {
-               // Fix NPE in case of null name
-               if (strName == null)
-                       return;
-
-               // Fix 1.16: for multiple parameter values.
-               Object objParms = htParameters.get(strName);
-
-               // Adds an new entry to the param vector.
-               if (objParms instanceof Vector)
-                       ((Vector) objParms).addElement(value);
-               else if (objParms instanceof String)// There is only one entry, so we
-                                                                                       // create a vector!
-               {
-                       Vector vecParms = new Vector();
-                       vecParms.addElement(objParms);
-                       vecParms.addElement(value);
-
-                       htParameters.put(strName, vecParms);
-               } else
-                       // first entry for strName.
-                       htParameters.put(strName, value);
-       }
-
-       /**
-        * So we can put the logic for supporting multiple files with the same form
-        * field name in the one location.
-        * 
-        * Assumes that this method will never be called with a null fileObj or
-        * strFilename.
-        * 
-        * @param strName
-        *            the form field name, used to upload the file. This identifies
-        *            the formfield location in the storage facility.
-        * @param fileObj
-        */
-       private void addFileParameter(String strName, Object[] fileObj) {
-               Object objParms = htFiles.get(strName);
-
-               // Add an new entry to the param vector.
-               if (objParms instanceof Vector)
-                       ((Vector) objParms).addElement(fileObj);
-               else if (objParms instanceof Object[])// There is only one entry, so
-                                                                                               // we create a vector!
-               {
-                       Vector vecParms = new Vector();
-                       vecParms.addElement(objParms);
-                       vecParms.addElement(fileObj);
-
-                       htFiles.put(strName, vecParms);
-               } else
-                       // first entry for strName.
-                       htFiles.put(strName, fileObj);
-       }
-
-       /**
-        * Reads the parameters, assume already passed Content-Disposition and blank
-        * line.
-        * 
-        * @param in
-        *            the InputStream to read and parse.
-        * @return the value read in.
-        * @throws IOException
-        *             if an error occurs writing the file.
-        */
-       private String readParameter(InputStream in) throws IOException {
-               StringBuffer buf = new StringBuffer();
-               int read = -1;
-
-               String line = null;
-               while (true) {
-                       read = readLine(in, blockOfBytes);
-                       if (read < 0)
-                               throw new IOException("Stream ended prematurely.");
-
-                       // Change v1.18: Only instantiate string once for performance
-                       // reasons.
-                       line = new String(blockOfBytes, 0, read, charEncoding);
-                       if (read < blockOfBytes.length
-                                       && line.indexOf(this.strBoundary) != -1)
-                               break; // Boundary found, we need to finish up.
-                       else
-                               buf.append(line);
-               }
-
-               if (buf.length() > 0)
-                       buf.setLength(getLengthMinusEnding(buf));
-               return buf.toString();
-       }
-
-       /**
-        * Read from in, write to out, minus last two line ending bytes.
-        * 
-        * @param in
-        *            the InputStream to read and parse.
-        * @param out
-        *            the OutputStream.
-        * @throws IOException
-        *             if an error occurs writing the file.
-        */
-       private long readAndWrite(InputStream in, OutputStream out)
-                       throws IOException {
-               long fileSize = 0;
-               int read = -1;
-
-               // This variable will be assigned the bytes actually read.
-               byte[] secondLineOfBytes = new byte[blockOfBytes.length];
-               // So we do not have to keep creating the second array.
-               int sizeOfSecondArray = 0;
-
-               while (true) {
-                       read = readLine(in, blockOfBytes);
-                       if (read < 0)
-                               throw new IOException("Stream ended prematurely.");
-
-                       // Found boundary.
-                       if (read < blockOfBytes.length
-                                       && new String(blockOfBytes, 0, read, charEncoding)
-                                                       .indexOf(this.strBoundary) != -1) {
-                               // Writes the line, minus any line ending bytes.
-                               // The secondLineOfBytes will NEVER BE NON-NULL if out==null, so
-                               // there is no need to included this in the test
-                               if (sizeOfSecondArray != 0) {
-                                       // Only used once, so declare here.
-                                       int actualLength = getLengthMinusEnding(secondLineOfBytes,
-                                                       sizeOfSecondArray);
-                                       if (actualLength > 0 && out != null) {
-                                               out.write(secondLineOfBytes, 0, actualLength);
-                                               // Updates the file size.
-                                               fileSize += actualLength;
-                                       }
-                               }
-                               break;
-                       } else {
-                               // Writes the out previous line.
-                               // The sizeOfSecondArray will NEVER BE ZERO if out==null, so
-                               // there is no need to included this in the test
-                               if (sizeOfSecondArray != 0) {
-                                       out.write(secondLineOfBytes, 0, sizeOfSecondArray);
-                                       // Updates the file size.
-                                       fileSize += sizeOfSecondArray;
-                               }
-
-                               // out will always be null, so there is no need to reset
-                               // sizeOfSecondArray to zero each time.
-                               if (out != null) {
-                                       // Copy the read bytes into the array.
-                                       System.arraycopy(blockOfBytes, 0, secondLineOfBytes, 0,
-                                                       read);
-                                       // That is how many bytes to read from the secondLineOfBytes
-                                       sizeOfSecondArray = read;
-                               }
-                       }
-               }
-
-               // Returns the number of bytes written to outstream.
-               return fileSize;
-       }
-
-       /**
-        * Reads a Multipart section that is a file type. Assumes that the
-        * Content-Disposition/Content-Type and blank line have already been
-        * processed. So we read until we hit a boundary, then close file and
-        * return.
-        * 
-        * @param in
-        *            the InputStream to read and parse.
-        * @param strFilename
-        *            the FileSystemName of the file.
-        * @return the number of bytes read.
-        * @throws IOException
-        *             if an error occurs writing the file.
-        */
-       private long readAndWriteFile(InputStream in, String strFilename)
-                       throws IOException {
-               // Stores a reference to this, as we may need to delete it later.
-               File outFile = new File(fileOutPutDirectory, strFilename);
-
-               BufferedOutputStream out = null;
-               // Do not bother opening a OutputStream, if we cannot even write the
-               // file.
-               if (fileOutPutDirectory != null)
-                       out = new BufferedOutputStream(new FileOutputStream(outFile));
-
-               long count = readAndWrite(in, out);
-               // Count would NOT be larger than zero if out was null.
-               if (count > 0) {
-                       out.flush();
-                       out.close();
-               } else {
-                       out.close();
-                       // Deletes the file as empty. We should be able to delete it, if we
-                       // can open it!
-                       outFile.delete();
-               }
-               return count;
-       }
-
-       /**
-        * If the fileOutPutDirectory wasn't specified, just read the file to
-        * memory.
-        * 
-        * @param in
-        *            the InputStream to read and parse.
-        * @return contents of file, from which you can garner the size as well.
-        * @throws IOException
-        *             if the writing failed due to input/output error.
-        */
-       private byte[] readFile(InputStream in) throws IOException {
-               // In this case, we do not need to worry about a outputdirectory.
-               ByteArrayOutputStream out = new ByteArrayOutputStream();
-
-               long count = readAndWrite(in, out);
-               // Count would NOT be larger than zero if out was null.
-               if (count > 0) {
-                       // Return contents of file to parse method for inclusion in htFiles
-                       // object.
-                       return out.toByteArray();
-               } else
-                       return null;
-       }
-
-       /**
-        * Gets the length of the line minus line ending.
-        * 
-        * @param byteLine
-        * @param endOfArray
-        *            This is because in many cases the byteLine will have garbage
-        *            data at the end, so we act as though the actual end of the
-        *            array is this parameter. If you want to process the complete
-        *            byteLine, specify byteLine.length as the endOfArray parameter.
-        * @return the length.
-        */
-       private static final int getLengthMinusEnding(byte byteLine[],
-                       int endOfArray) {
-               if (byteLine == null)
-                       return 0;
-
-               if (endOfArray >= 2 && byteLine[endOfArray - 2] == '\r'
-                               && byteLine[endOfArray - 1] == '\n')
-                       return endOfArray - 2;
-               else if (endOfArray >= 1 && byteLine[endOfArray - 1] == '\n'
-                               || byteLine[endOfArray - 1] == '\r')
-                       return endOfArray - 1;
-               else
-                       return endOfArray;
-       }
-
-       /**
-        * 
-        * @param buf
-        * @return
-        */
-       private static final int getLengthMinusEnding(StringBuffer buf) {
-               if (buf.length() >= 2 && buf.charAt(buf.length() - 2) == '\r'
-                               && buf.charAt(buf.length() - 1) == '\n')
-                       return buf.length() - 2;
-               else if (buf.length() >= 1 && buf.charAt(buf.length() - 1) == '\n'
-                               || buf.charAt(buf.length() - 1) == '\r')
-                       return buf.length() - 1;
-               else
-                       return buf.length();
-       }
-
-       /**
-        * Reads at most READ_BLOCK blocks of data, or a single line whichever is
-        * smaller. Returns -1, if nothing to read, or we have reached the specified
-        * content-length.
-        * 
-        * Assumes that bytToBeRead.length indicates the block size to read.
-        * 
-        * @param in
-        *            the InputStream to read and parse.
-        * @param bytesToBeRead
-        *            the bytes to be read.
-        * @return -1 if stream has ended, before a newline encountered (should
-        *         never happen) OR we have read past the Content-Length specified.
-        *         (Should also not happen). Otherwise return the number of
-        *         characters read. You can test whether the number returned is less
-        *         than bytesToBeRead.length, which indicates that we have read the
-        *         last line of a file or parameter or a border line, or some other
-        *         formatting stuff.
-        * @throws IOException
-        *             if the writing failed due to input/output error.
-        */
-       private int readLine(InputStream in, byte[] bytesToBeRead)
-                       throws IOException {
-               // Ensure that there is still stuff to read...
-               if (intTotalRead >= intContentLength)
-                       return -1;
-
-               // Get the length of what we are wanting to read.
-               int length = bytesToBeRead.length;
-
-               // End of content, but some servers (apparently) may not realise this
-               // and end the InputStream, so
-               // we cover ourselves this way.
-               if (length > (intContentLength - intTotalRead))
-                       length = (int) (intContentLength - intTotalRead); // So we only
-                                                                                                                               // read the data
-                                                                                                                               // that is left.
-
-               int result = readLine(in, bytesToBeRead, 0, length);
-               // Only if we get actually read something, otherwise something weird has
-               // happened, such as the end of stream.
-               if (result > 0)
-                       intTotalRead += result;
-
-               return result;
-       }
-
-       /**
-        * This needs to support the possibility of a / or a \ separator.
-        * 
-        * @param strFilename
-        *            the FileSystemName of the file.
-        * @return the strFilename after removing all characters before the last
-        *         occurence of / or \.
-        */
-       private static final String getBasename(String strFilename) {
-               if (strFilename == null)
-                       return strFilename;
-
-               int intIndex = strFilename.lastIndexOf("/");
-               if (intIndex == -1 || strFilename.lastIndexOf("\\") > intIndex)
-                       intIndex = strFilename.lastIndexOf("\\");
-
-               if (intIndex != -1)
-                       return strFilename.substring(intIndex + 1);
-               else
-                       return strFilename;
-       }
-
-       /**
-        * Trims any quotes from the start and end of a string.
-        * 
-        * @param strItem
-        * @return the trimmed string.
-        */
-       private static final String trimQuotes(String strItem) {
-               // Saves having to go any further....
-               if (strItem == null || strItem.indexOf("\"") == -1)
-                       return strItem;
-
-               // Gets the rid of any whitespace..
-               strItem = strItem.trim();
-
-               if (strItem.charAt(0) == '\"')
-                       strItem = strItem.substring(1);
-
-               if (strItem.charAt(strItem.length() - 1) == '\"')
-                       strItem = strItem.substring(0, strItem.length() - 1);
-
-               return strItem;
-       }
-
-       /**
-        * Format of string name=value; name=value; If not found, will return null.
-        * 
-        * @param strName
-        *            the form field name, used to upload the file. This identifies
-        *            the formfield location in the storage facility.
-        * @param strToDecode
-        * 
-        */
-       private static final String getValue(String strName, String strToDecode) {
-               strName = strName + "=";
-
-               int startIndexOf = 0;
-               while (startIndexOf < strToDecode.length()) {
-                       int indexOf = strToDecode.indexOf(strName, startIndexOf);
-                       // Ensure either first name, or a space or ; precedes it.
-                       if (indexOf != -1) {
-                               if (indexOf == 0
-                                               || Character.isWhitespace(strToDecode
-                                                               .charAt(indexOf - 1))
-                                               || strToDecode.charAt(indexOf - 1) == ';') {
-                                       int endIndexOf = strToDecode.indexOf(";", indexOf
-                                                       + strName.length());
-                                       if (endIndexOf == -1) // May return an empty string...
-                                               return strToDecode
-                                                               .substring(indexOf + strName.length());
-                                       else
-                                               return strToDecode.substring(
-                                                               indexOf + strName.length(), endIndexOf);
-                               } else
-                                       startIndexOf = indexOf + strName.length();
-                       } else
-                               return null;
-               }
-               return null;
-       }
-
-       /**
-        * <I>Tomcat's ServletInputStream.readLine(byte[],int,int) Slightly Modified
-        * to utilise in.read()</I> <BR>
-        * Reads the input stream, one line at a time. Starting at an offset, reads
-        * bytes into an array, until it reads a certain number of bytes or reaches
-        * a newline character, which it reads into the array as well.
-        * 
-        * <p>
-        * This method <u><b>does not</b></u> returns -1 if it reaches the end of
-        * the input stream before reading the maximum number of bytes, it returns
-        * -1, if no bytes read.
-        * 
-        * @param in
-        *            the InputStream to read and parse.
-        * @param b
-        *            an array of bytes into which data is read.
-        * 
-        * @param off
-        *            an integer specifying the character at which this method
-        *            begins reading.
-        * 
-        * @param len
-        *            an integer specifying the maximum number of bytes to read.
-        * 
-        * @return an integer specifying the actual number of bytes read, or -1 if
-        *         the end of the stream is reached.
-        * 
-        * @throws IOException
-        *             if an input or output exception has occurred
-        * 
-        * 
-        * Note: We have a problem with Tomcat reporting an erroneous number of
-        * bytes, so we need to check this. This is the method where we get an
-        * infinite loop, but only with binary files.
-        */
-       private int readLine(InputStream in, byte[] b, int off, int len)
-                       throws IOException {
-               if (len <= 0)
-                       return 0;
-
-               int count = 0, c;
-
-               while ((c = in.read()) != -1) {
-                       b[off++] = (byte) c;
-                       count++;
-                       if (c == '\n' || count == len)
-                               break;
-               }
-
-               return count > 0 ? count : -1;
-       }
-
-       /**
-        * Prints the given debugging message.
-        * 
-        * @param x
-        *            the message to print.
-        */
-       protected void debug(String x) {
-               if (debug != null) {
-                       debug.println(x);
-                       debug.flush();
-               }
-       }
-
-       /**
-        * Gets the Html Table.For debugging.
-        */
-       public String getHtmlTable() {
-               StringBuffer sbReturn = new StringBuffer();
-
-               sbReturn.append("<h2>Parameters</h2>");
-               sbReturn
-                               .append("\n<table border=3><tr><td><b>Name</b></td><td><b>Value</b></td></tr>");
-               for (Enumeration e = getParameterNames(); e.hasMoreElements();) {
-                       String strName = (String) e.nextElement();
-                       sbReturn.append("\n<tr>" + "<td>" + strName + "</td>");
-
-                       sbReturn.append("<td><table border=1><tr>");
-                       for (Enumeration f = getURLParameters(strName); f.hasMoreElements();) {
-                               String value = (String) f.nextElement();
-                               sbReturn.append("<td>" + value + "</td>");
-                       }
-                       sbReturn.append("</tr></table></td></tr>");
-               }
-               sbReturn.append("</table>");
-
-               sbReturn.append("<h2>File Parameters</h2>");
-
-               sbReturn
-                               .append("\n<table border=2><tr><td><b>Name</b></td><td><b>Filename</b></td><td><b>Path</b></td><td><b>Content Type</b></td><td><b>Size</b></td></tr>");
-               for (Enumeration e = getFileParameterNames(); e.hasMoreElements();) {
-                       String strName = (String) e.nextElement();
-
-                       sbReturn
-                                       .append("\n<tr>"
-                                                       + "<td>"
-                                                       + strName
-                                                       + "</td>"
-                                                       + "<td>"
-                                                       + (getFileSystemName(strName) != null ? getFileSystemName(strName)
-                                                                       : "") + "</td>");
-
-                       if (loadIntoMemory)
-                               sbReturn.append("<td>"
-                                               + (getFileSize(strName) > 0 ? "<i>in memory</i>" : "")
-                                               + "</td>");
-                       else
-                               sbReturn.append("<td>"
-                                               + (getFile(strName) != null ? getFile(strName)
-                                                               .getAbsolutePath() : "") + "</td>");
-
-                       sbReturn
-                                       .append("<td>"
-                                                       + (getContentType(strName) != null ? getContentType(strName)
-                                                                       : "")
-                                                       + "</td>"
-                                                       + "<td>"
-                                                       + (getFileSize(strName) != -1 ? getFileSize(strName)
-                                                                       + ""
-                                                                       : "") + "</td>" + "</tr>");
-               }
-               sbReturn.append("</table>");
-
-               return sbReturn.toString();
-       }
-}
diff --git a/src/com/itmill/toolkit/terminal/gwt/server/ServletMultipartRequest.java b/src/com/itmill/toolkit/terminal/gwt/server/ServletMultipartRequest.java
deleted file mode 100644 (file)
index a0352e5..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/* *************************************************************************
- IT Mill Toolkit 
-
- Development of Browser User Interfaces Made Easy
-
- Copyright (C) 2000-2006 IT Mill Ltd
- *************************************************************************
-
- This product is distributed under commercial license that can be found
- from the product package on license.pdf. Use of this product might 
- require purchasing a commercial license from IT Mill Ltd. For guidelines 
- on usage, see licensing-guidelines.html
-
- *************************************************************************
- For more information, contact:
- IT Mill Ltd                           phone: +358 2 4802 7180
- Ruukinkatu 2-4                        fax:   +358 2 4802 7181
- 20540, Turku                          email:  info@itmill.com
- Finland                               company www: www.itmill.com
- Primary source for information and releases: www.itmill.com
-
- ********************************************************************** */
-
-package com.itmill.toolkit.terminal.gwt.server;
-
-import java.io.IOException;
-
-import javax.servlet.http.HttpServletRequest;
-
-/**
- * This class wraps the MultipartRequest class by Jason Pell for the Servlet
- * environment.
- * 
- * @author IT Mill Ltd
- * @version
- * @VERSION@
- * @since 3.0
- */
-public class ServletMultipartRequest extends MultipartRequest {
-       /**
-        * Constructor wrapper, unwraps the InputStream, content type and content
-        * length from the servlet request object.
-        * 
-        * @param request
-        *            the HttpServletRequest will be used to initialise the
-        *            MultipartRequest super class.
-        * @param strSaveDirectory
-        *            the temporary directory to save the file from where they can
-        *            then be moved to wherever by the calling process. <b>If you
-        *            specify <u>null</u> for this parameter, then any files
-        *            uploaded will be silently ignored.</B>
-        * 
-        * @throws IllegalArgumentException
-        *             If the request.getContentType() does not contain a
-        *             Content-Type of "multipart/form-data" or the boundary is not
-        *             found.
-        * @throws IOException
-        *             If the request.getContentLength() is higher than
-        *             MAX_READ_BYTES or strSaveDirectory is invalid or cannot be
-        *             written to.
-        * 
-        * @see MultipartRequest#MAX_READ_BYTES
-        */
-       public ServletMultipartRequest(HttpServletRequest request,
-                       String strSaveDirectory) throws IllegalArgumentException,
-                       IOException {
-               super(null, request.getContentType(), request.getContentLength(),
-                               request.getInputStream(), strSaveDirectory,
-                               MultipartRequest.MAX_READ_BYTES);
-       }
-
-       /**
-        * Constructor wrapper, unwraps the InputStream, content type and content
-        * lenght from the servlet request object. Also allow to explicitly set the
-        * max permissable length of the request.
-        * 
-        * @param request
-        *            the HttpServletRequest will be used to initialise the
-        *            MultipartRequest super class.
-        * @param strSaveDirectory
-        *            the temporary directory to save the file from where they can
-        *            then be moved to wherever by the calling process. <b>If you
-        *            specify <u>null</u> for this parameter, then any files
-        *            uploaded will be silently ignored.</B>
-        * @param intMaxReadBytes
-        *            Overrides the MAX_BYTES_READ value, to allow arbitrarily long
-        *            files.
-        * 
-        * @throws IllegalArgumentException
-        *             If the request.getContentType() does not contain a
-        *             Content-Type of "multipart/form-data" or the boundary is not
-        *             found.
-        * @throws IOException
-        *             If the request.getContentLength() is higher than
-        *             MAX_READ_BYTES or strSaveDirectory is invalid or cannot be
-        *             written to.
-        * 
-        * @see MultipartRequest#MAX_READ_BYTES
-        */
-       public ServletMultipartRequest(HttpServletRequest request,
-                       String strSaveDirectory, int intMaxReadBytes)
-                       throws IllegalArgumentException, IOException {
-               super(null, request.getContentType(), request.getContentLength(),
-                               request.getInputStream(), strSaveDirectory, intMaxReadBytes);
-       }
-
-       /**
-        * Constructor wrapper for loading the request into memory rather than
-        * temp-file.
-        * 
-        * @param request
-        *            the HttpServletRequest will be used to initialise the
-        *            MultipartRequest super class.
-        * @param intMaxReadBytes
-        *            Overrides the MAX_BYTES_READ value, to allow arbitrarily long
-        *            files.
-        * 
-        * @throws IllegalArgumentException
-        *             If the request.getContentType() does not contain a
-        *             Content-Type of "multipart/form-data" or the boundary is not
-        *             found.
-        * @throws IOException
-        *             If the request.getContentLength() is higher than
-        *             MAX_READ_BYTES or strSaveDirectory is invalid or cannot be
-        *             written to.
-        * 
-        * @see MultipartRequest#MAX_READ_BYTES
-        */
-       public ServletMultipartRequest(HttpServletRequest request,
-                       int intMaxReadBytes) throws IllegalArgumentException, IOException {
-               super(null, request.getContentType(), request.getContentLength(),
-                               request.getInputStream(), intMaxReadBytes);
-       }
-}