Index: Form.java
===================================================================
RCS file: /cvsroot/wicket/wicket/src/java/wicket/markup/html/form/Form.java,v
retrieving revision 1.85
diff -u -r1.85 Form.java
--- Form.java	25 Jul 2005 11:43:04 -0000	1.85
+++ Form.java	27 Jul 2005 15:00:59 -0000
@@ -17,6 +17,12 @@
  */
 package wicket.markup.html.form;
 
+import java.util.HashMap;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -29,8 +35,12 @@
 import wicket.markup.html.WebMarkupContainer;
 import wicket.markup.html.form.persistence.CookieValuePersister;
 import wicket.markup.html.form.persistence.IValuePersister;
+import wicket.markup.html.form.upload.MultipartWebRequest;
 import wicket.model.IModel;
+import wicket.model.Model;
+import wicket.protocol.http.WebRequest;
 import wicket.protocol.http.WebRequestCycle;
+import wicket.util.lang.Bytes;
 import wicket.util.string.Strings;
 
 /**
@@ -64,6 +74,16 @@
  * </li>
  * </li>
  * </p>
+ * 
+ * Form for handling (file) uploads with multipart requests is supported by callign setMultiPart(true).
+ * Use this with {@link wicket.markup.html.form.upload.FileUploadField} components. You can
+ * attach mutliple FileInput fields for muliple file uploads.
+ * <p>
+ * Using multipart forms causes a runtime dependency on 
+ * <a href="http://jakarta.apache.org/commons/fileupload/">Commons FileUpload</a>, version 1.0.
+ * </p>
+ * 
+
  * <p>
  * If you want to have multiple buttons which submit the same form, simply put two or more
  * button components somewhere in the hierarchy of components that are children of the
@@ -77,6 +97,7 @@
  * @author Jonathan Locke
  * @author Juergen Donnerstag
  * @author Eelco Hillenius
+ * @author Cameron Braid
  */
 public class Form extends WebMarkupContainer
 	implements IFormSubmitListener, IFeedbackBoundary
@@ -84,6 +105,18 @@
 	/** Log. */
 	private static Log log = LogFactory.getLog(Form.class);
 
+	/** Maximum size of an upload in bytes */
+	private Bytes maxSize = Bytes.MAX;
+
+	protected boolean multiPart = false;
+
+	/** set to true to use enctype='multipart/form-data', and to process file uplloads 
+	 * by default multiPart = false
+	 */
+	public void setMultiPart(boolean multiPart) {
+		this.multiPart = multiPart;
+	}
+	
 	/**
 	 * Constructs a form with no validation.
 	 * 
@@ -258,6 +291,55 @@
 	 */
 	protected void process()
 	{
+		if (multiPart) 
+		{
+			// Change the request to a multipart web request so parameters are
+			// parsed out correctly
+			final HttpServletRequest request = ((WebRequest)getRequest()).getHttpServletRequest();
+			try
+			{
+				final MultipartWebRequest multipartWebRequest = new MultipartWebRequest(this.maxSize, request);
+				getRequestCycle().setRequest(multipartWebRequest);
+			}
+			catch (FileUploadException e)
+			{
+				// Create model with exception and maximum size values
+				final HashMap model = new HashMap();
+				model.put("exception", e);
+				model.put("maxSize", maxSize);
+
+				if (e instanceof SizeLimitExceededException)
+				{
+					// Resource key should be <form-id>.uploadTooLarge to override default message
+					final String defaultValue = "Upload must be less than " + maxSize;
+					String msg = getString(getId() + ".uploadTooLarge", Model.valueOf(model), defaultValue);
+					error(msg);
+
+					if (log.isDebugEnabled())
+					{
+						log.error(msg, e);
+					}
+					else
+					{
+						log.error(msg);
+					}
+				}
+				else
+				{
+					// Resource key should be <form-id>.uploadFailed to override default message
+					final String defaultValue = "Upload failed: " + e.getLocalizedMessage();
+					String msg = getString(getId() + ".uploadFailed", Model.valueOf(model), defaultValue);
+					error(msg);
+
+					log.error(msg, e);
+				}
+				
+				// don't process the form if there is a FileUploadException
+				return;
+			}
+
+		}
+		
 		// first, see if the processing was triggered by a Wicket button
 		final Button submittingButton = findSubmittingButton();
 
@@ -299,6 +381,24 @@
 		}
 	}
 
+
+	/**
+	 * @param maxSize
+	 *            The maxSize for uploaded files
+	 */
+	public void setMaxSize(final Bytes maxSize)
+	{
+		this.maxSize = maxSize;
+	}
+	/**
+	 * @return the maxSize of uploaded files
+	 */
+	public Bytes getMaxSize()
+	{
+		return this.maxSize;
+	}
+
+
 	/**
 	 * Called (by the default implementation of 'process') when all fields validated,
 	 * the form was updated and it's data was allowed to be persisted. It is meant for delegating
@@ -444,6 +544,9 @@
 		super.onComponentTag(tag);
 		tag.put("method", "post");
 		tag.put("action", Strings.replaceAll(urlFor(IFormSubmitListener.class), "&", "&amp;"));
+		if (multiPart) {
+			tag.put("enctype", "multipart/form-data");
+		}
 	}
 
 	/**
Index: upload/FileUploadField.java
===================================================================
RCS file: /cvsroot/wicket/wicket/src/java/wicket/markup/html/form/upload/FileUploadField.java,v
retrieving revision 1.5
diff -u -r1.5 FileUploadField.java
--- upload/FileUploadField.java	3 Apr 2005 16:33:34 -0000	1.5
+++ upload/FileUploadField.java	27 Jul 2005 15:01:00 -0000
@@ -22,6 +22,9 @@
 import wicket.Request;
 import wicket.markup.ComponentTag;
 import wicket.markup.html.form.FormComponent;
+import wicket.model.IModel;
+import wicket.model.Model;
+import wicket.model.PropertyModel;
 
 /**
  * Form component that corresponds to a &lt;input type=&quot;file&quot;&gt;.
@@ -43,13 +46,39 @@
 	{
 		super(id);
 	}
+	
+	/**
+	 * 
+	 * @param id
+	 *            See Component
+	 * @param model
+	 *            See Component
+	 */
+	public FileUploadField(final String id, IModel model)
+	{
+		super(id, model);
+	}
 
 	/**
 	 * @return The uploaded file
 	 */
 	public FileUpload getFileUpload()
 	{
-		return fileUpload;
+		// Get request 
+		final Request request = getRequest();
+		// If we successfully installed a multipart request
+		if (request instanceof MultipartWebRequest)
+		{
+			// Get the item for the path
+			final FileItem item = ((MultipartWebRequest)request).getFile(getPath());
+	
+			// Only update the model when there is a file (larger than zero bytes)
+			if (item != null && item.getSize() > 0)
+			{
+				return new FileUpload(item);
+			}
+		}
+		return null;
 	}
 	
 	/**
@@ -82,20 +111,10 @@
 	 */
 	protected void updateModel()
 	{
-		// Get request 
-		final Request request = getRequest();
-		
-		// If we successfully installed a multipart request
-		if (request instanceof MultipartWebRequest)
-		{
-			// Get the item for the path
-			final FileItem item = ((MultipartWebRequest)request).getFile(getPath());
-	
-			// Only update the model when there is a file (larger than zero bytes)
-			if (item != null && item.getSize() > 0)
-			{
-				this.fileUpload = new FileUpload(item);
-			}
+		// only update the model if one exists
+		if (getModel() != null) {
+			setModelObject(getFileUpload());
 		}
+
 	}
 }
Index: upload/MultipartWebRequest.java
===================================================================
RCS file: /cvsroot/wicket/wicket/src/java/wicket/markup/html/form/upload/MultipartWebRequest.java,v
retrieving revision 1.9
diff -u -r1.9 MultipartWebRequest.java
--- upload/MultipartWebRequest.java	29 May 2005 11:21:08 -0000	1.9
+++ upload/MultipartWebRequest.java	27 Jul 2005 15:01:00 -0000
@@ -31,6 +31,7 @@
 
 import wicket.WicketRuntimeException;
 import wicket.protocol.http.WebRequest;
+import wicket.util.lang.Bytes;
 import wicket.util.value.ValueMap;
 
 /**
@@ -47,6 +48,18 @@
 	/** Map of parameters. */
 	private final ValueMap parameters = new ValueMap();
 
+
+	/**
+	 * @deprecated UploadForm is deprecated - @see MultipartWebRequest(Bytes maxSize, final HttpServletRequest httpServletRequest)
+	 * @param maxSize the maxSize for uploaded files
+	 * @param httpServletRequest
+	 * @throws FileUploadException
+	 */
+	public MultipartWebRequest(UploadForm uploadForm, final HttpServletRequest httpServletRequest) throws FileUploadException
+	{
+		this(uploadForm.getMaxSize(), httpServletRequest);
+	}
+	
 	/**
 	 * Constructor
 	 * 
@@ -56,7 +69,7 @@
 	 *            The servlet request
 	 * @throws FileUploadException Thrown if something goes wrong with upload
 	 */
-	MultipartWebRequest(final UploadForm uploadForm, final HttpServletRequest httpServletRequest) throws FileUploadException
+	public MultipartWebRequest(Bytes maxSize, final HttpServletRequest httpServletRequest) throws FileUploadException
 	{
 		super(httpServletRequest);
 
@@ -81,7 +94,7 @@
 			diskFileUpload.setHeaderEncoding(encoding);
 		}
 
-		diskFileUpload.setSizeMax(uploadForm.maxSize.bytes());
+		diskFileUpload.setSizeMax(maxSize.bytes());
 		final List items = diskFileUpload.parseRequest(httpServletRequest);
 
 		// Loop through items
Index: upload/UploadForm.java
===================================================================
RCS file: /cvsroot/wicket/wicket/src/java/wicket/markup/html/form/upload/UploadForm.java,v
retrieving revision 1.18
diff -u -r1.18 UploadForm.java
--- upload/UploadForm.java	16 Jul 2005 15:54:22 -0000	1.18
+++ upload/UploadForm.java	27 Jul 2005 15:01:00 -0000
@@ -17,22 +17,9 @@
  */
 package wicket.markup.html.form.upload;
 
-import java.util.HashMap;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.fileupload.FileUploadException;
-import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
 import wicket.IFeedback;
-import wicket.markup.ComponentTag;
 import wicket.markup.html.form.Form;
 import wicket.model.IModel;
-import wicket.model.Model;
-import wicket.protocol.http.WebRequest;
-import wicket.util.lang.Bytes;
 
 /**
  * Form for handling (file) uploads with multipart requests. Use this with
@@ -45,14 +32,11 @@
  * 
  * @author Eelco Hillenius
  * @author Jonathan Locke
+ * 
+ * @deprecated @see Form.setMultiPart(true)
  */
 public abstract class UploadForm extends Form
 {
-	/** log. */
-	private static Log log = LogFactory.getLog(UploadForm.class);
-
-	/** Maximum size of an upload in bytes */
-	Bytes maxSize = Bytes.MAX;
 
 	/**
 	 * @see wicket.Component#Component(String)
@@ -60,6 +44,7 @@
 	public UploadForm(String id)
 	{
 		super(id);
+		setMultiPart(true);
 	}
 
 	/**
@@ -68,6 +53,7 @@
 	public UploadForm(final String id, IFeedback validationFeedback)
 	{
 		super(id, validationFeedback);
+		setMultiPart(true);
 	}
 
 	/**
@@ -76,82 +62,7 @@
 	public UploadForm(final String id, IModel model, IFeedback feedback)
 	{
 		super(id, model, feedback);
+		setMultiPart(true);
 	}
-
-	/**
-	 * Wraps the servlet request in a multipart request and sets it as the
-	 * current request.
-	 * 
-	 * @see wicket.markup.html.form.Form#process()
-	 */
-	public void process()
-	{
-		// Change the request to a multipart web request so parameters are
-		// parsed out correctly
-		final HttpServletRequest request = ((WebRequest)getRequest()).getHttpServletRequest();
-		try
-		{
-			final MultipartWebRequest multipartWebRequest = new MultipartWebRequest(this, request);
-			getRequestCycle().setRequest(multipartWebRequest);
-
-			// Now do normal form submit validation processing
-			super.process();
-		}
-		catch (FileUploadException e)
-		{
-			// Create model with exception and maximum size values
-			final HashMap model = new HashMap();
-			model.put("exception", e);
-			model.put("maxSize", maxSize);
-
-			if (e instanceof SizeLimitExceededException)
-			{
-				// Resource key should be <form-id>.uploadTooLarge to override default message
-				final String defaultValue = "Upload must be less than " + maxSize;
-				String msg = getString(getId() + ".uploadTooLarge", Model.valueOf(model), defaultValue);
-				error(msg);
-
-				if (log.isDebugEnabled())
-				{
-					log.error(msg, e);
-				}
-				else
-				{
-					log.error(msg);
-				}
-			}
-			else
-			{
-				// Resource key should be <form-id>.uploadFailed to override default message
-				final String defaultValue = "Upload failed: " + e.getLocalizedMessage();
-				String msg = getString(getId() + ".uploadFailed", Model.valueOf(model), defaultValue);
-				error(msg);
-
-				log.error(msg, e);
-			}
-		}
-	}
-
-	/**
-	 * @param maxSize
-	 *            The maxSize to set.
-	 */
-	public void setMaxSize(final Bytes maxSize)
-	{
-		this.maxSize = maxSize;
-	}
-
-	/**
-	 * @see wicket.Component#onComponentTag(ComponentTag)
-	 */
-	protected final void onComponentTag(final ComponentTag tag)
-	{
-		super.onComponentTag(tag);
-		tag.put("enctype", "multipart/form-data");
-	}
-
-	/**
-	 * @see Form#onSubmit()
-	 */
-	protected abstract void onSubmit();
+	
 }
Index: HiddenField.java
===================================================================
RCS file: HiddenField.java
diff -N HiddenField.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ HiddenField.java	1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,67 @@
+/*
+ * $Id: TextField.java,v 1.31 2005/04/22 17:42:09 jonathanlocke Exp $ $Revision:
+ * 1.10 $ $Date: 2005/04/22 17:42:09 $
+ * 
+ * ==============================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package wicket.markup.html.form;
+
+import wicket.markup.ComponentTag;
+import wicket.model.IModel;
+
+/**
+ * TextField doesn't permit the html <input type='hidden'> so this is a simple subclass to allow this
+ * 
+ * A HiddenField is useful when you have a javascript based component that updates the form state.
+ * Either 
+ * 
+ * 1) add a AttributeModified to set the id attribute, then use document.getElementById(id), or
+ * 2) lookup the field name=getPath() within the form  
+ * 
+ * @author Cameron Braid
+ */
+public class HiddenField extends TextField
+{
+
+	public HiddenField(String id, Class type)
+	{
+		super(id, type);
+	}
+
+	public HiddenField(String id, IModel model, Class type)
+	{
+		super(id, model, type);
+	}
+
+	public HiddenField(String id, IModel object)
+	{
+		super(id, object);
+	}
+
+	public HiddenField(String id)
+	{
+		super(id);
+	}
+	
+	protected void onComponentTag(ComponentTag tag)
+	{
+		// Check for hidden type
+		checkComponentTagAttribute(tag, "type", "hidden");
+
+		// Default handling for component tag
+		super.onComponentTag(tag);
+	}
+
+	
+}
