diff options
Diffstat (limited to 'src')
20 files changed, 125 insertions, 1874 deletions
diff --git a/src/com/itmill/toolkit/terminal/ajax/AjaxAdapterServlet.java b/src/com/itmill/toolkit/terminal/ajax/AjaxAdapterServlet.java deleted file mode 100644 index e001d74468..0000000000 --- a/src/com/itmill/toolkit/terminal/ajax/AjaxAdapterServlet.java +++ /dev/null @@ -1,271 +0,0 @@ -/* ************************************************************************* - - IT Mill Toolkit - - Development of Browser User Intarfaces 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/license.txt. Use of this product might - require purchasing a commercial license from IT Mill Ltd. For guidelines - on usage, see license/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.ajax; - -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpSessionBindingEvent; -import javax.servlet.http.HttpSessionBindingListener; - -import com.itmill.toolkit.Application; - -/** - * Servlet implementing connection between a web-browser and Millstone - * Application. - * - * (stage drafting and planning) - * - * <h1>Paintable update format</h1> - * - * <changes><change pid="271987">... UIDL XML FRAGMENT HERE ... </change> - * <change pid="271987">... UIDL XML FRAGMENT HERE ... </change> <change - * pid="271987">... UIDL XML FRAGMENT HERE ... </change> <change format="HTML" - * paintableId="271987">. <![CDATA[... SERVER SIDE TRANSFORMED HTML HERE ...]]> - * </change> </changes> - * - * In the first phase, no server side-transforms are supported, so the format - * attribute is omitted and only UIDL supported. - * - * <h1>Request parameters</h1> - * - * TBD - * - * @author IT Mill Ltd, Joonas Lehtinen, Sami Ekblad - * @version @VERSION@ - * @since 3.1 - */ -public class AjaxAdapterServlet extends HttpServlet { - - /** - * Session attribute, where to find servlet context to - * AjaxApplicationContext mapping - */ - private static String SESSION_ATTR_APPLICATION_CONTEXT = "org.millstone.ajaxadapter.AjaxApplicationContext"; - - private static String SESSION_BINDING_LISTENER = "bindinglistener"; - - private Class applicationClass; - - private Properties applicationProperties; - - - - /** - * Called by the servlet container to indicate to a servlet that the servlet - * is being placed into service. - * - * @param servletConfig - * object containing the servlet's configuration and - * initialization parameters - * @throws ServletException - * if an exception has occurred that interferes with the - * servlet's normal operation. - */ - public void init(javax.servlet.ServletConfig servletConfig) - throws javax.servlet.ServletException { - super.init(servletConfig); - - // Get the application class name - String applicationClassName = servletConfig - .getInitParameter("application"); - if (applicationClassName == null) { - Log.error("Application not specified in servlet parameters"); - } - - // Store the application parameters into Properties object - this.applicationProperties = new Properties(); - for (Enumeration e = servletConfig.getInitParameterNames(); e - .hasMoreElements();) { - String name = (String) e.nextElement(); - this.applicationProperties.setProperty(name, servletConfig - .getInitParameter(name)); - } - - // Override with server.xml parameters - ServletContext context = servletConfig.getServletContext(); - for (Enumeration e = context.getInitParameterNames(); e - .hasMoreElements();) { - String name = (String) e.nextElement(); - this.applicationProperties.setProperty(name, context - .getInitParameter(name)); - } - - // Load the application class using the same class loader - // as the servlet itself - ClassLoader loader = this.getClass().getClassLoader(); - try { - this.applicationClass = loader.loadClass(applicationClassName); - } catch (ClassNotFoundException e) { - throw new ServletException("Failed to load application class: " - + applicationClassName); - } - } - - private AjaxApplicationContext getAjaxApplicationContext( - HttpServletRequest request) { - - // Get the session - HttpSession session = request.getSession(true); - - // Get the Map - Map acmap = (Map) session - .getAttribute(SESSION_ATTR_APPLICATION_CONTEXT); - if (acmap == null) { - acmap = new HashMap(); - session.setAttribute(SESSION_ATTR_APPLICATION_CONTEXT, acmap); - HttpSessionBindingListener sessionBindingListener = new SessionBindingListener( - acmap); - session.setAttribute(SESSION_BINDING_LISTENER, - sessionBindingListener); - - } - - // Get the application context - AjaxApplicationContext ac = (AjaxApplicationContext) acmap - .get(getServletContext()); - if (ac == null) { - ac = new AjaxApplicationContext(getServletContext()); - acmap.put(getServletContext(), ac); - } - - return ac; - } - - protected void service(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - - // Get the context - AjaxApplicationContext context = getAjaxApplicationContext(request); - - try { - - // Get the application - Application application = context.getApplication( - getApplicationUrl(request), request.getContextPath() - + request.getServletPath()); - - // Create application if it doesn't exist - if (application == null) - application = context.createApplication(applicationClass, - getApplicationUrl(request), request.getLocale(), - applicationProperties); - - // Notify transaction start - if (context != null) { - context.startTransaction(application, request); - } - - // Uidl - context.getApplicationManager(application).handleXmlHttpRequest( - request, response); - - // Notify transaction end - if (context != null) { - context.endTransaction(application, request); - } - - } catch (InstantiationException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } catch (IllegalAccessException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - /** Get the current application URL from request */ - private URL getApplicationUrl(HttpServletRequest request) { - - URL applicationUrl; - try { - URL reqURL = new URL((request.isSecure() ? "https://" : "http://") - + request.getServerName() + ":" + request.getServerPort() - + request.getRequestURI()); - String servletPath = request.getContextPath() - + request.getServletPath(); - if (servletPath.length() == 0 - || servletPath.charAt(servletPath.length() - 1) != '/') - servletPath = servletPath + "/"; - applicationUrl = new URL(reqURL, servletPath); - } catch (MalformedURLException e) { - Log.error("Error constructing application url " - + request.getRequestURI() + " (" + e + ")"); - throw new RuntimeException("Error constructing application url", e); - } - - return applicationUrl; - } - - - private class SessionBindingListener implements HttpSessionBindingListener { - private Map acmap; - protected SessionBindingListener(Map acmap) { - this.acmap = acmap; - } - - /** - * @see javax.servlet.http.HttpSessionBindingListener#valueBound(HttpSessionBindingEvent) - */ - public void valueBound(HttpSessionBindingEvent arg0) { - // We are not interested in bindings - } - - /** - * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(HttpSessionBindingEvent) - */ - public void valueUnbound(HttpSessionBindingEvent event) { - - // If the binding listener is unbound from the session, the - // session must be closing - if (event.getName().equals(SESSION_BINDING_LISTENER)) { - - // Close all applications - for (Iterator i = acmap.values().iterator(); i.hasNext();) { - AjaxApplicationContext actx = (AjaxApplicationContext) i.next(); - actx.close(); - } - } - } - - } - -} diff --git a/src/com/itmill/toolkit/terminal/ajax/AjaxApplicationContext.java b/src/com/itmill/toolkit/terminal/ajax/AjaxApplicationContext.java deleted file mode 100644 index 26e6565fff..0000000000 --- a/src/com/itmill/toolkit/terminal/ajax/AjaxApplicationContext.java +++ /dev/null @@ -1,204 +0,0 @@ -/* ************************************************************************* - - IT Mill Toolkit - - Development of Browser User Intarfaces 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/license.txt. Use of this product might - require purchasing a commercial license from IT Mill Ltd. For guidelines - on usage, see license/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.ajax; - -import java.io.File; -import java.net.URL; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Locale; -import java.util.Properties; -import java.util.WeakHashMap; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; - -import com.itmill.toolkit.Application; -import com.itmill.toolkit.service.ApplicationContext; - -/** Application context for ajax applications. - * - * @author IT Mill Ltd, Joonas Lehtinen - * @version @VERSION@ - * @since 3.1 - */ -public class AjaxApplicationContext implements ApplicationContext { - - private LinkedList applications = new LinkedList(); - - private ServletContext servletContext; - - private LinkedList transactionListeners = new LinkedList(); - - private WeakHashMap applicationToManagerMap = new WeakHashMap(); - - AjaxApplicationContext(ServletContext servletContext) { - this.servletContext = servletContext; - } - - ApplicationManager getApplicationManager(Application application) { - ApplicationManager vm = (ApplicationManager) applicationToManagerMap - .get(application); - if (vm == null) { - vm = new ApplicationManager(application); - applicationToManagerMap.put(application, vm); - } - return vm; - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.service.ApplicationContext#getBaseDirectory() - */ - public File getBaseDirectory() { - - String path = servletContext.getRealPath("/"); - if (path == null) - return null; - return new File(path); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.service.ApplicationContext#getApplications() - */ - public Collection getApplications() { - return Collections.unmodifiableCollection(applications); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.service.ApplicationContext#addTransactionListener(com.itmill.toolkit.service.ApplicationContext.TransactionListener) - */ - public void addTransactionListener(TransactionListener listener) { - transactionListeners.add(listener); - } - - /* - * (non-Javadoc) - * - * @see com.itmill.toolkit.service.ApplicationContext#removeTransactionListener(com.itmill.toolkit.service.ApplicationContext.TransactionListener) - */ - public void removeTransactionListener(TransactionListener listener) { - transactionListeners.remove(listener); - } - - /** - * Create a new application. - * - * @return New application instance - */ - Application createApplication(Class applicationClass, URL applicationUrl, - Locale locale, Properties applicationStartProperties) - throws InstantiationException, IllegalAccessException { - - Application application = null; - - // Create new application and start it - try { - application = (Application) applicationClass.newInstance(); - applications.add(application); - application.setLocale(locale); - - getApplicationManager(application).takeControl(); - - application.start(applicationUrl, applicationStartProperties, this); - - } catch (IllegalAccessException e) { - Log.error("Illegal access to application class " - + applicationClass.getName()); - throw e; - } catch (InstantiationException e) { - Log.error("Failed to instantiate application class: " - + applicationClass.getName()); - throw e; - } - - return application; - } - - void removeApplication(Application application) { - applications.remove(application); - } - - Application getApplication(URL applicationUrl, String servletPath) { - // Search for the application (using the application URI) from the list - Application application = null; - for (Iterator i = applications.iterator(); i.hasNext() - && application == null;) { - Application a = (Application) i.next(); - String aPath = a.getURL().getPath(); - if (servletPath.length() < aPath.length()) - servletPath += "/"; - if (servletPath.equals(aPath)) - application = a; - } - - // Remove stopped application from the list - if (application != null && !application.isRunning()) { - applications.remove(application); - application = null; - } - - return application; - } - - /** Notify transaction start */ - protected void startTransaction(Application application, HttpServletRequest request) { - if (this.transactionListeners == null) return; - for (Iterator i = this.transactionListeners.iterator(); i.hasNext();) { - ((ApplicationContext.TransactionListener)i.next()).transactionStart(application,request); - } - } - - /** Notify transaction end */ - protected void endTransaction(Application application, HttpServletRequest request) { - if (this.transactionListeners == null) return; - for (Iterator i = this.transactionListeners.iterator(); i.hasNext();) { - ((ApplicationContext.TransactionListener)i.next()).transactionEnd(application,request); - } - } - - /** Closes this application context and all applications bound to it. - * - */ - public void close() { - for (Iterator i = this.applications.iterator(); i.hasNext();) { - Application app = (Application) i.next(); - app.close(); - } - - } - -} diff --git a/src/com/itmill/toolkit/terminal/ajax/Log.java b/src/com/itmill/toolkit/terminal/ajax/Log.java deleted file mode 100644 index 890dd04d5a..0000000000 --- a/src/com/itmill/toolkit/terminal/ajax/Log.java +++ /dev/null @@ -1,107 +0,0 @@ -/* ************************************************************************* - - IT Mill Toolkit - - Development of Browser User Intarfaces 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/license.txt. Use of this product might - require purchasing a commercial license from IT Mill Ltd. For guidelines - on usage, see license/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.ajax; - -/** <p>Class providing centralized logging services. The logger defines - * five message types, and provides methods to create messages of those - * types. These types are:</p> - * - * <ul> - * <li> <code>info</code> - Useful information generated during normal - * operation of the application - * <li> <code>warning</code> - An error situation has occurred, but the - * operation was able to finish succesfully - * <li> <code>error</code> - An error situation which prevented the - * operation from finishing succesfully - * <li> <code>debug</code> - Internal information from the application meant - * for developers - * <li> <code>exception</code> - A Java exception reported using the logger. - * Includes the exception stack trace and a possible free-form message - * </ul> - * - * <p>Currently the class offers logging only to the standard output</p> - * - * @author IT Mill Ltd. - * @version @VERSION@ - * @since 3.1 - */ -public class Log { - - private static String logFilename; - private static boolean useStdOut = true; - - private static String LOG_MSG_INFO = "[INFO]"; - private static String LOG_MSG_ERROR = "[ERROR]"; - private static String LOG_MSG_WARN = "[WARNING]"; - private static String LOG_MSG_DEBUG = "[DEBUG]"; - private static String LOG_MSG_EXCEPT = "[EXCEPTION]"; - - /** Logs a <code>warning</code> message. - * - * @param message Message <code>String</code> to be logged. - */ - protected static synchronized void warn(java.lang.String message) { - if (Log.useStdOut) System.out.println(LOG_MSG_WARN+ " "+message); - } - /** Logs a <code>debug</code> message. - * - * @param message Message <code>String</code> to be logged. - */ - protected static synchronized void debug(java.lang.String message) { - if (Log.useStdOut) System.out.println(LOG_MSG_DEBUG+ " "+message); - } - - /** Logs an <code>info</code> message. - * - * @param message Message <code>String</code> to be logged. - */ - protected static synchronized void info(java.lang.String message) { - if (Log.useStdOut) System.out.println(LOG_MSG_INFO+ " "+message); - } - - /** Logs a Java exception and an accompanying error message. - * - * @param message Message <code>String</code> to be logged. - * @param e Exception to be logged. - */ - protected static synchronized void except(java.lang.String message, Exception e) { - if (Log.useStdOut) { - System.out.println(LOG_MSG_EXCEPT+ " "+message); - e.printStackTrace(); - } - } - - /** Logs an <code>error</code> message. - * - * @param message Message <code>String</code> to be logged. - */ - protected static synchronized void error(java.lang.String message) { - if (Log.useStdOut) System.out.println(LOG_MSG_ERROR+ " "+message); - } -} diff --git a/src/com/itmill/toolkit/terminal/ajax/MultipartRequest.java b/src/com/itmill/toolkit/terminal/ajax/MultipartRequest.java deleted file mode 100644 index 48f86606c2..0000000000 --- a/src/com/itmill/toolkit/terminal/ajax/MultipartRequest.java +++ /dev/null @@ -1,1107 +0,0 @@ -package com.itmill.toolkit.terminal.ajax; - -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 getCharArray() 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 getEncoding() to allow the use of MultipartRequest with a specific encoding type. All instances - of MultipartRequest will utilise the static charEncoding variable value, that the setEncoding() 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 -{ - /** - Define 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 MultipartRequest itself, not on any - instances of MultipartRequest, 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 getEncoding() to convert between bytes and - strings. If setEncoding() is called by another thread, while the private parse() 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; - } - } - - /** - Returns the current encoding method. - */ - public String getEncoding() - { - return charEncoding; - } - - /** - * Constructor. - * - * @param strContentTypeText The "Content-Type" HTTP header value. - * @param intContentLength The "Content-Length" 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 "Content-Type" HTTP header value. - * @param intContentLength The "Content-Length" 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 "Content-Type" HTTP header value. - * @param intContentLength The "Content-Length" 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 "Content-Type" HTTP header value. - * @param intContentLength The "Content-Length" 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 "Content-Type" HTTP header value. - * @param intContentLength The "Content-Length" 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 "Content-Type" HTTP header value. - * @param intContentLength The "Content-Length" 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 - { - // save 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; - } - - /** - Return 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. - */ - 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); - } - - /** - Return 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. - */ - 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(); - } - } - - /** - An enumeration of all URL Parameters for the current HTTP Request. - */ - public Enumeration getParameterNames() - { - return htParameters.keys(); - } - - /** - This enumeration will return all INPUT TYPE=FILE parameter NAMES as encountered - during the upload. - */ - 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. - - @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. - - @return Returns 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; - } - - /** - Get the file system basename of an uploaded file. - - @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. - - @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. - - @param strName is the form field name, used to upload the file. This identifies - the formfield location in the storage facility. - - @param strFilename This is the FileSystemName of the file - @param type What attribute you want from the File Parameter. - The following types are supported: - MultipartRequest.FILENAME, - MultipartRequest.CONTENT_TYPE, - MultipartRequest.SIZE, - MultipartRequest.CONTENTS - - <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> - - @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. - */ - 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); - 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. - */ - 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); - - // Add 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. - */ - 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); - } - - /** - Read parameters, assume already passed Content-Disposition and blank line. - - @return the value read in. - */ - 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. - */ - 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) - { - // Write 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); - // Update file size. - fileSize+=actualLength; - } - } - break; - } - else - { - // Write 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); - // Update 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; - } - } - } - - //Return the number of bytes written to outstream. - return fileSize; - } - - /** - Read 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. - - @exception IOException if an error occurs writing the file. - - @return the number of bytes read. - */ - private long readAndWriteFile(InputStream in, String strFilename) throws IOException - { - // Store 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(); - // Delete 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 strName - Url parameter this file was loaded under. - * @return contents of file, from which you can garner the size as well. - */ - 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; - } - - /** - Returns the length of the line minus line ending. - - @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. - */ - 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; - } - - 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. - - @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. - */ - 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. - - Returns 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; - } - - /** - trimQuotes trims any quotes from the start and end of a string and returns the trimmed string... - */ - private static final String trimQuotes (String strItem) - { - // Saves having to go any further.... - if (strItem==null || strItem.indexOf("\"")==-1) - return strItem; - - // Get 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. - */ - 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 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 - * - * @exception 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; - } - - /** - Use when debugging this object. - */ - protected void debug(String x) - { - if (debug!=null) - { - debug.println(x); - debug.flush(); - } - } - - /** - 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/ajax/ServletMultipartRequest.java b/src/com/itmill/toolkit/terminal/ajax/ServletMultipartRequest.java deleted file mode 100644 index 54dc518ffd..0000000000 --- a/src/com/itmill/toolkit/terminal/ajax/ServletMultipartRequest.java +++ /dev/null @@ -1,113 +0,0 @@ -/* ************************************************************************* - - IT Mill Toolkit - - Development of Browser User Intarfaces 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/license.txt. Use of this product might - require purchasing a commercial license from IT Mill Ltd. For guidelines - on usage, see license/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.ajax; - -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 lenght 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> - * - * @exception IllegalArgumentException If the request.getContentType() does not contain a Content-Type of "multipart/form-data" or the boundary is not found. - * @exception 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 lenght 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. - * - * @exception IllegalArgumentException If the request.getContentType() does not contain a Content-Type of "multipart/form-data" or the boundary is not found. - * @exception 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. - * - * @exception IllegalArgumentException If the request.getContentType() does not contain a Content-Type of "multipart/form-data" or the boundary is not found. - * @exception 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); - } -} diff --git a/src/com/itmill/toolkit/terminal/ajax/ApplicationManager.java b/src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java index 403d6721eb..d54a824e80 100644 --- a/src/com/itmill/toolkit/terminal/ajax/ApplicationManager.java +++ b/src/com/itmill/toolkit/terminal/web/AjaxApplicationManager.java @@ -26,7 +26,7 @@ ********************************************************************** */ -package com.itmill.toolkit.terminal.ajax; +package com.itmill.toolkit.terminal.web; import java.io.IOException; import java.io.InputStream; @@ -66,7 +66,7 @@ import com.itmill.toolkit.ui.Window; * @version @VERSION@ * @since 3.1 */ -public class ApplicationManager implements Paintable.RepaintRequestListener, +public class AjaxApplicationManager implements Paintable.RepaintRequestListener, Application.WindowAttachListener, Application.WindowDetachListener { private static String GET_PARAM_VARIABLE_CHANGES = "changeVariables"; @@ -91,17 +91,17 @@ public class ApplicationManager implements Paintable.RepaintRequestListener, private Set removedWindows = new HashSet(); - private UIDLPaintTarget paintTarget; + private AjaxPaintTarget paintTarget; - public ApplicationManager(Application application) { + public AjaxApplicationManager(Application application) { this.application = application; } - private VariableMap getVariableMap() { - VariableMap vm = (VariableMap) applicationToVariableMapMap + private AjaxVariableMap getVariableMap() { + AjaxVariableMap vm = (AjaxVariableMap) applicationToVariableMapMap .get(application); if (vm == null) { - vm = new VariableMap(); + vm = new AjaxVariableMap(); applicationToVariableMapMap.put(application, vm); } return vm; @@ -169,7 +169,7 @@ public class ApplicationManager implements Paintable.RepaintRequestListener, // Set the response type response.setContentType("application/xml; charset=UTF-8"); - paintTarget = new UIDLPaintTarget( + paintTarget = new AjaxPaintTarget( getVariableMap(), this, out); // Render the removed windows @@ -464,11 +464,6 @@ public class ApplicationManager implements Paintable.RepaintRequestListener, if (logoutUrl == null) logoutUrl = application.getURL().toString(); - AjaxApplicationContext context = (AjaxApplicationContext) application - .getContext(); - if (context != null) - context.removeApplication(application); - response.sendRedirect(response.encodeRedirectURL(logoutUrl)); } diff --git a/src/com/itmill/toolkit/terminal/ajax/HttpUploadStream.java b/src/com/itmill/toolkit/terminal/web/AjaxHttpUploadStream.java index e76179d5c2..c798002ba9 100644 --- a/src/com/itmill/toolkit/terminal/ajax/HttpUploadStream.java +++ b/src/com/itmill/toolkit/terminal/web/AjaxHttpUploadStream.java @@ -26,7 +26,7 @@ ********************************************************************** */ -package com.itmill.toolkit.terminal.ajax; +package com.itmill.toolkit.terminal.web; import java.io.InputStream; @@ -36,7 +36,7 @@ import java.io.InputStream; * @version @VERSION@ * @since 3.1 */ -public class HttpUploadStream +public class AjaxHttpUploadStream implements com.itmill.toolkit.terminal.UploadStream { /** Holds value of property variableName. */ @@ -56,7 +56,7 @@ public class HttpUploadStream * (for parallel events (for example in * same http request), times are equal) */ - public HttpUploadStream( + public AjaxHttpUploadStream( String name, InputStream stream, String contentName, diff --git a/src/com/itmill/toolkit/terminal/ajax/UIDLPaintTarget.java b/src/com/itmill/toolkit/terminal/web/AjaxPaintTarget.java index 69fc162b01..5d5598bb40 100644 --- a/src/com/itmill/toolkit/terminal/ajax/UIDLPaintTarget.java +++ b/src/com/itmill/toolkit/terminal/web/AjaxPaintTarget.java @@ -26,7 +26,7 @@ ********************************************************************** */ -package com.itmill.toolkit.terminal.ajax; +package com.itmill.toolkit.terminal.web; import com.itmill.toolkit.Application; import com.itmill.toolkit.terminal.ApplicationResource; @@ -54,7 +54,7 @@ import java.util.Stack; * @VERSION@ * @since 3.1 */ -public class UIDLPaintTarget implements PaintTarget { +public class AjaxPaintTarget implements PaintTarget { /* Document type declarations */ private final static String UIDL_XML_DECL = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; @@ -78,13 +78,13 @@ public class UIDLPaintTarget implements PaintTarget { private PrintWriter uidlBuffer; - private VariableMap variableMap; + private AjaxVariableMap variableMap; private boolean closed = false; private OutputStream output; - private ApplicationManager manager; + private AjaxApplicationManager manager; private String paintableId; @@ -99,7 +99,7 @@ public class UIDLPaintTarget implements PaintTarget { * @param out * A character-output stream. */ - public UIDLPaintTarget(VariableMap variableMap, ApplicationManager manager, + public AjaxPaintTarget(AjaxVariableMap variableMap, AjaxApplicationManager manager, OutputStream output) throws PaintException { // Set the cache diff --git a/src/com/itmill/toolkit/terminal/ajax/VariableMap.java b/src/com/itmill/toolkit/terminal/web/AjaxVariableMap.java index 54027ef703..2751c9b2bf 100644 --- a/src/com/itmill/toolkit/terminal/ajax/VariableMap.java +++ b/src/com/itmill/toolkit/terminal/web/AjaxVariableMap.java @@ -26,7 +26,7 @@ ********************************************************************** */ -package com.itmill.toolkit.terminal.ajax; +package com.itmill.toolkit.terminal.web; import java.io.IOException; import java.lang.ref.WeakReference; @@ -56,7 +56,7 @@ import com.itmill.toolkit.terminal.VariableOwner; * @version @VERSION@ * @since 3.1 */ -public class VariableMap { +public class AjaxVariableMap { // Id <-> (Owner,Name) mapping @@ -474,7 +474,8 @@ public class VariableMap { Class varType = (Class) idToTypeMap.get(param); Object varOldValue = idToValueMap.get(param); if (varName == null || varType == null) - Log.warn( + // TODO Remove this? + System.err.println( "VariableMap: No variable found for parameter " + param + " (" @@ -502,7 +503,7 @@ public class VariableMap { param, MultipartRequest.CONTENT_TYPE); UploadStream upload = - new HttpUploadStream( + new AjaxHttpUploadStream( varName, parser.getFileContents(param), filename, @@ -546,7 +547,8 @@ public class VariableMap { changed |= (!val.equals(varOldValue)); } else { - Log.warn( + // TODO Remove this? + System.err.println( "Empty variable '" + varName + "' of type " @@ -554,9 +556,10 @@ public class VariableMap { } } catch (java.lang.ClassCastException e) { - Log.except( - "WebVariableMap conversion exception", - e); + // TODO Remove this? + System.err.println( + "WebVariableMap conversion exception"); + e.printStackTrace(System.err); errorListener.terminalError( new TerminalErrorImpl(e)); } diff --git a/src/com/itmill/toolkit/terminal/web/WebAdapterServlet.java b/src/com/itmill/toolkit/terminal/web/ApplicationServlet.java index 890bd63b43..15ce3f10f0 100644 --- a/src/com/itmill/toolkit/terminal/web/WebAdapterServlet.java +++ b/src/com/itmill/toolkit/terminal/web/ApplicationServlet.java @@ -89,16 +89,17 @@ import com.itmill.toolkit.ui.Window; * @since 3.0 */ -public class WebAdapterServlet extends HttpServlet +public class ApplicationServlet extends HttpServlet implements Application.WindowAttachListener, Application.WindowDetachListener, Paintable.RepaintRequestListener { // Versions - private static final int VERSION_MAJOR = 3; - private static final int VERSION_MINOR = 1; - private static final int VERSION_BUILD = 1; + // TODO AUTOUPDATE VERSION NUMBER + private static final int VERSION_MAJOR = 4; + private static final int VERSION_MINOR = 0; + private static final int VERSION_BUILD = 0; private static final String VERSION = "" + VERSION_MAJOR + "." + VERSION_MINOR + "." + VERSION_BUILD; @@ -114,22 +115,23 @@ public class WebAdapterServlet extends HttpServlet private static int DEFAULT_BUFFER_SIZE = 32 * 1024; private static int DEFAULT_MAX_TRANSFORMERS = 1; private static int MAX_BUFFER_SIZE = 64 * 1024; - private static String SESSION_ATTR_VARMAP = "varmap"; - static String SESSION_ATTR_CONTEXT = "millstone_context"; - static String SESSION_ATTR_APPS = "apps"; - private static String SESSION_BINDING_LISTENER = "bindinglistener"; - private static String SESSION_DEFAULT_THEME = "default"; + private static String SESSION_ATTR_VARMAP = "itmill-toolkit-varmap"; + static String SESSION_ATTR_CONTEXT = "itmill-toolkit-context"; + static String SESSION_ATTR_APPS = "itmill-toolkit-apps"; + private static String SESSION_BINDING_LISTENER = "itmill-toolkit-bindinglistener"; + private static String DEFAULT_THEME = "default"; private static String RESOURCE_URI = "/RES/"; + private static String AJAX_UIDL_URI = "/UIDL/"; private static String THEME_DIRECTORY_PATH = "WEB-INF/lib/themes/"; private static String THEME_LISTING_FILE = THEME_DIRECTORY_PATH + "themes.txt"; - private static String DEFAULT_THEME_JAR_PREFIX = "millstone-web-themes"; + private static String DEFAULT_THEME_JAR_PREFIX = "itmill-toolkit-web-themes"; private static String DEFAULT_THEME_JAR = "WEB-INF/lib/" + DEFAULT_THEME_JAR_PREFIX + "-" + VERSION + ".jar"; private static String DEFAULT_THEME_SNAPSHOT_JAR = "WEB-INF/lib/" + DEFAULT_THEME_JAR_PREFIX + "-" + VERSION_MAJOR + "." + VERSION_MINOR + "-SNAPSHOT.jar"; - private static String DEFAULT_THEME_TEMP_FILE_PREFIX = "WA_TMP_"; + private static String DEFAULT_THEME_TEMP_FILE_PREFIX = "ITMILL_TMP_"; private static String SERVER_COMMAND_PARAM = "SERVER_COMMANDS"; private static int SERVER_COMMAND_STREAM_MAINTAIN_PERIOD = 15000; private static int SERVER_COMMAND_HEADER_PADDING = 2000; @@ -140,7 +142,6 @@ public class WebAdapterServlet extends HttpServlet private UIDLTransformerFactory transformerFactory; private CollectionThemeSource themeSource; private String resourcePath = null; - //private boolean enableBrowserProbe = false; private boolean debugMode = false; private int maxConcurrentTransformers; private long transformerCacheTime; @@ -149,6 +150,9 @@ public class WebAdapterServlet extends HttpServlet private WeakHashMap applicationToServerCommandStreamLock = new WeakHashMap(); private WeakHashMap applicationToLastRequestDate = new WeakHashMap(); private List allWindows = new LinkedList(); + private WeakHashMap applicationToAjaxAppMgrMap = new WeakHashMap(); + + /** * Called by the servlet container to indicate to a servlet that the servlet @@ -472,14 +476,29 @@ public class WebAdapterServlet extends HttpServlet appContext.startTransaction(application, request); } + // Set the last application request date + applicationToLastRequestDate.put(application, new Date()); + // The rest of the process is synchronized with the application // in order to guarantee that no parallel variable handling is // made synchronized (application) { - // Set the last application request date - applicationToLastRequestDate.put(application, new Date()); + // Handle UIDL requests? + String resourceId = request.getPathInfo(); + if (resourceId != null && resourceId.startsWith(AJAX_UIDL_URI)) { + + getApplicationManager(application).handleXmlHttpRequest( + request, response); + // Notify transaction end + if (appContext != null) { + appContext.endTransaction(application, request); + } + + return; + } + // Get the variable map variableMap = getVariableMap(application, request); if (variableMap == null) @@ -581,7 +600,7 @@ public class WebAdapterServlet extends HttpServlet // Use default theme if selected theme was not found. if (transformerType == null) { Theme defaultTheme = this.themeSource - .getThemeByName(WebAdapterServlet.SESSION_DEFAULT_THEME); + .getThemeByName(ApplicationServlet.DEFAULT_THEME); if (defaultTheme == null) { throw new ServletException( "Default theme not found in the specified theme source(s)."); @@ -1098,8 +1117,12 @@ public class WebAdapterServlet extends HttpServlet try { application = (Application) this.applicationClass.newInstance(); applications.add(application); + + // Listen to window add/removes (for web mode) application.addListener((Application.WindowAttachListener) this); application.addListener((Application.WindowDetachListener) this); + + // Set localte application.setLocale(request.getLocale()); // Get application context for this session @@ -1555,4 +1578,34 @@ public class WebAdapterServlet extends HttpServlet return this.owner; } } + + /** Get AJAX application manager for an application. + * + * If this application has not been running in ajax mode before, new manager + * is created and web adapter stops listening to changes. + * + * @param application + * @return AJAX Application Manager + */ + private AjaxApplicationManager getApplicationManager(Application application) { + AjaxApplicationManager mgr = (AjaxApplicationManager) applicationToAjaxAppMgrMap + .get(application); + + // This application is going from Web to AJAX mode, create new manager + if (mgr == null) { + + // Create new manager + mgr = new AjaxApplicationManager(application); + applicationToAjaxAppMgrMap.put(application, mgr); + + // Stop sending changes to this servlet because manager will take + // control + application.removeListener((Application.WindowAttachListener) this); + application.removeListener((Application.WindowDetachListener) this); + + // Manager takes control over the application + mgr.takeControl(); + } + return mgr; + } } diff --git a/src/com/itmill/toolkit/terminal/web/DebugWindow.java b/src/com/itmill/toolkit/terminal/web/DebugWindow.java index ee760476bc..0be33ccd7b 100644 --- a/src/com/itmill/toolkit/terminal/web/DebugWindow.java +++ b/src/com/itmill/toolkit/terminal/web/DebugWindow.java @@ -66,7 +66,7 @@ public class DebugWindow extends Window { private Application debuggedApplication; private HashMap rawUIDL = new HashMap(); - private WebAdapterServlet servlet; + private ApplicationServlet servlet; private HttpSession session; private TabSheet tabs = new TabSheet(); @@ -81,7 +81,7 @@ public class DebugWindow extends Window { protected DebugWindow( Application debuggedApplication, HttpSession session, - WebAdapterServlet servlet) { + ApplicationServlet servlet) { super("Debug window"); setName(WINDOW_NAME); @@ -385,7 +385,7 @@ public class DebugWindow extends Window { * Returns the servlet. * @return WebAdapterServlet */ - protected WebAdapterServlet getServlet() { + protected ApplicationServlet getServlet() { return servlet; } @@ -401,7 +401,7 @@ public class DebugWindow extends Window { * Sets the servlet. * @param servlet The servlet to set */ - protected void setServlet(WebAdapterServlet servlet) { + protected void setServlet(ApplicationServlet servlet) { this.servlet = servlet; } diff --git a/src/com/itmill/toolkit/terminal/web/DirectoryThemeSource.java b/src/com/itmill/toolkit/terminal/web/DirectoryThemeSource.java index b4628f1e18..f2d26e1465 100644 --- a/src/com/itmill/toolkit/terminal/web/DirectoryThemeSource.java +++ b/src/com/itmill/toolkit/terminal/web/DirectoryThemeSource.java @@ -47,7 +47,7 @@ public class DirectoryThemeSource implements ThemeSource { private File path; private Theme theme; - private WebAdapterServlet webAdapterServlet; + private ApplicationServlet webAdapterServlet; /** Collection of subdirectory entries */ private Collection subdirs = new LinkedList(); @@ -58,7 +58,7 @@ public class DirectoryThemeSource implements ThemeSource { * @param url External URL of the repository * @throws FileNotFoundException if no theme files are found */ - public DirectoryThemeSource(File path, WebAdapterServlet webAdapterServlet) + public DirectoryThemeSource(File path, ApplicationServlet webAdapterServlet) throws ThemeException, FileNotFoundException, IOException { this.path = path; diff --git a/src/com/itmill/toolkit/terminal/web/JarThemeSource.java b/src/com/itmill/toolkit/terminal/web/JarThemeSource.java index 9c6f403180..05b47f077b 100644 --- a/src/com/itmill/toolkit/terminal/web/JarThemeSource.java +++ b/src/com/itmill/toolkit/terminal/web/JarThemeSource.java @@ -58,7 +58,7 @@ public class JarThemeSource implements ThemeSource { private Theme theme; private String path; private String name; - private WebAdapterServlet webAdapterServlet; + private ApplicationServlet webAdapterServlet; private Cache resourceCache = new Cache(); /** Collection of subdirectory entries */ @@ -72,7 +72,7 @@ public class JarThemeSource implements ThemeSource { */ public JarThemeSource( File file, - WebAdapterServlet webAdapterServlet, + ApplicationServlet webAdapterServlet, String path) throws ThemeException, FileNotFoundException, IOException { diff --git a/src/com/itmill/toolkit/terminal/web/ServletThemeSource.java b/src/com/itmill/toolkit/terminal/web/ServletThemeSource.java index c2db9c92bd..efbadea862 100644 --- a/src/com/itmill/toolkit/terminal/web/ServletThemeSource.java +++ b/src/com/itmill/toolkit/terminal/web/ServletThemeSource.java @@ -56,7 +56,7 @@ public class ServletThemeSource implements ThemeSource { private ServletContext context; private Theme theme; private String path; - private WebAdapterServlet webAdapterServlet; + private ApplicationServlet webAdapterServlet; private Cache resourceCache = new Cache(); /** Collection of subdirectory entries */ @@ -71,7 +71,7 @@ public class ServletThemeSource implements ThemeSource { */ public ServletThemeSource( ServletContext context, - WebAdapterServlet webAdapterServlet, + ApplicationServlet webAdapterServlet, String path) throws IOException, ThemeException { diff --git a/src/com/itmill/toolkit/terminal/web/ThemeFunctionLibrary.java b/src/com/itmill/toolkit/terminal/web/ThemeFunctionLibrary.java index 51472578c3..cca9191a34 100644 --- a/src/com/itmill/toolkit/terminal/web/ThemeFunctionLibrary.java +++ b/src/com/itmill/toolkit/terminal/web/ThemeFunctionLibrary.java @@ -68,7 +68,7 @@ public class ThemeFunctionLibrary { Window window, WebBrowser webBrowser, HttpSession session, - WebAdapterServlet webAdapterServlet, + ApplicationServlet webAdapterServlet, String theme) { state.set( new Object[] { @@ -144,7 +144,7 @@ public class ThemeFunctionLibrary { static public String resource(String resource, String theme) { try { return ( - (WebAdapterServlet) + (ApplicationServlet) ( (Object[]) state .get())[WEBADAPTERSERVLET]) @@ -161,7 +161,7 @@ public class ThemeFunctionLibrary { static public String resource(String resource) { try { return ( - (WebAdapterServlet) + (ApplicationServlet) ( (Object[]) state .get())[WEBADAPTERSERVLET]) @@ -198,14 +198,14 @@ public class ThemeFunctionLibrary { return generateWindowScript( window(), application(), - (WebAdapterServlet) ((Object[]) state.get())[WEBADAPTERSERVLET], + (ApplicationServlet) ((Object[]) state.get())[WEBADAPTERSERVLET], browser()); } static protected String generateWindowScript( Window window, Application app, - WebAdapterServlet wa, + ApplicationServlet wa, WebBrowser browser) { StringBuffer script = new StringBuffer(); diff --git a/src/com/itmill/toolkit/terminal/web/UIDLTransformer.java b/src/com/itmill/toolkit/terminal/web/UIDLTransformer.java index 3588555e0e..2796cc3190 100644 --- a/src/com/itmill/toolkit/terminal/web/UIDLTransformer.java +++ b/src/com/itmill/toolkit/terminal/web/UIDLTransformer.java @@ -92,7 +92,7 @@ public class UIDLTransformer { /** Theme repository used for late error reporting */ private ThemeSource themeSource; - private WebAdapterServlet webAdapterServlet; + private ApplicationServlet webAdapterServlet; /** UIDLTransformer constructor. * @param type Type of the transformer @@ -103,7 +103,7 @@ public class UIDLTransformer { public UIDLTransformer( UIDLTransformerType type, ThemeSource themes, - WebAdapterServlet webAdapterServlet) + ApplicationServlet webAdapterServlet) throws UIDLTransformerException { this.transformerType = type; this.themeSource = themes; diff --git a/src/com/itmill/toolkit/terminal/web/UIDLTransformerFactory.java b/src/com/itmill/toolkit/terminal/web/UIDLTransformerFactory.java index fc57b71a84..557b42e4e4 100644 --- a/src/com/itmill/toolkit/terminal/web/UIDLTransformerFactory.java +++ b/src/com/itmill/toolkit/terminal/web/UIDLTransformerFactory.java @@ -69,7 +69,7 @@ public class UIDLTransformerFactory { private Map transformerSpool = new HashMap(); private ThemeSource themeSource; - private WebAdapterServlet webAdapterServlet; + private ApplicationServlet webAdapterServlet; private int transformerCount = 0; private int transformersInUse = 0; @@ -82,7 +82,7 @@ public class UIDLTransformerFactory { */ public UIDLTransformerFactory( ThemeSource themeSource, - WebAdapterServlet webAdapterServlet, + ApplicationServlet webAdapterServlet, int maxConcurrentTransformers, long cacheTime) { this.webAdapterServlet = webAdapterServlet; diff --git a/src/com/itmill/toolkit/terminal/web/WebApplicationContext.java b/src/com/itmill/toolkit/terminal/web/WebApplicationContext.java index 8fc19cfbca..84bc60a610 100644 --- a/src/com/itmill/toolkit/terminal/web/WebApplicationContext.java +++ b/src/com/itmill/toolkit/terminal/web/WebApplicationContext.java @@ -97,6 +97,7 @@ public class WebApplicationContext implements ApplicationContext { */ public File getBaseDirectory() { String realPath = session.getServletContext().getRealPath("/"); + if (realPath == null) return null; return new File(realPath); } @@ -114,7 +115,7 @@ public class WebApplicationContext implements ApplicationContext { public Collection getApplications() { LinkedList applications = (LinkedList) session.getAttribute( - WebAdapterServlet.SESSION_ATTR_APPS); + ApplicationServlet.SESSION_ATTR_APPS); return Collections.unmodifiableCollection( applications == null ? (new LinkedList()) : applications); @@ -175,4 +176,5 @@ public class WebApplicationContext implements ApplicationContext { ((ApplicationContext.TransactionListener)i.next()).transactionEnd(application,request); } } + } diff --git a/src/com/itmill/toolkit/terminal/web/WebPaintTarget.java b/src/com/itmill/toolkit/terminal/web/WebPaintTarget.java index 8f1b6672cb..7d0450ab0b 100644 --- a/src/com/itmill/toolkit/terminal/web/WebPaintTarget.java +++ b/src/com/itmill/toolkit/terminal/web/WebPaintTarget.java @@ -65,7 +65,7 @@ public class WebPaintTarget implements PaintTarget { private StringBuffer tagBuffer; private HttpVariableMap variableMap; private boolean closed = false; - private WebAdapterServlet webAdapterServlet; + private ApplicationServlet webAdapterServlet; private Theme theme; private static final int TAG_BUFFER_DEFAULT_SIZE = 20; private boolean mSuppressOutput = false; @@ -79,7 +79,7 @@ public class WebPaintTarget implements PaintTarget { public WebPaintTarget( HttpVariableMap variableMap, UIDLTransformerType type, - WebAdapterServlet webAdapterServlet, + ApplicationServlet webAdapterServlet, Theme theme) throws PaintException { diff --git a/src/com/itmill/toolkit/terminal/web/XSLReader.java b/src/com/itmill/toolkit/terminal/web/XSLReader.java index fecb08a2b1..f3d4b63548 100644 --- a/src/com/itmill/toolkit/terminal/web/XSLReader.java +++ b/src/com/itmill/toolkit/terminal/web/XSLReader.java @@ -101,7 +101,7 @@ public class XSLReader implements XMLReader, ContentHandler { } } - private static final String MILLSTONE_PREFIX = "millstone://"; + private static final String JAVA_PREFIX = "java://"; private Collection streams; private boolean startTagHandled = false; private String xslNamespace = ""; @@ -422,29 +422,29 @@ public class XSLReader implements XMLReader, ContentHandler { String uri = original.getURI(index); // Map millstone:// namespaces to transformer specific namespaces - if (uri != null && uri.startsWith(MILLSTONE_PREFIX)) { + if (uri != null && uri.startsWith(JAVA_PREFIX)) { System.out.print("DEBUG " + uri + " --> "); switch (xsltProcessor) { case XSLT_SAXON6 : uri = "saxon://" - + uri.substring(MILLSTONE_PREFIX.length()); + + uri.substring(JAVA_PREFIX.length()); break; case XSLT_SAXON7 : uri = "saxon://" - + uri.substring(MILLSTONE_PREFIX.length()); + + uri.substring(JAVA_PREFIX.length()); break; case XSLT_XALAN : uri = "xalan://" - + uri.substring(MILLSTONE_PREFIX.length()); + + uri.substring(JAVA_PREFIX.length()); break; default : uri = "xalan://" - + uri.substring(MILLSTONE_PREFIX.length()); + + uri.substring(JAVA_PREFIX.length()); break; } System.out.println(uri); |