This is an automated email from the ASF dual-hosted git repository.
solomax pushed a commit to branch wicket-8.x
in repository https://gitbox.apache.org/repos/asf/wicket.git
The following commit(s) were added to refs/heads/wicket-8.x by this push:
new bc7fd4d646 [WICKET-7035] fileCountMax is added
bc7fd4d646 is described below
commit bc7fd4d6464dfa984ecd8b34a32d4f632fbe4625
Author: Maxim Solodovnik <[email protected]>
AuthorDate: Sat Mar 25 10:33:40 2023 +0700
[WICKET-7035] fileCountMax is added
---
pom.xml | 2 +-
.../java/org/apache/wicket/Application.properties | 5 +-
.../apache/wicket/Application_ru.properties.xml | 8 +-
.../org/apache/wicket/markup/html/form/Form.java | 207 ++++++++++++---------
.../http/servlet/MultipartServletWebRequest.java | 22 ++-
.../servlet/MultipartServletWebRequestImpl.java | 24 +--
.../wicket/examples/upload/MultiUploadPage.java | 15 +-
.../apache/wicket/examples/upload/UploadPage.html | 1 +
.../apache/wicket/examples/upload/UploadPage.java | 13 +-
.../org/apache/wicket/examples/StartExamples.java | 2 +-
.../extensions/ajax/AjaxFileDropBehavior.java | 39 +++-
11 files changed, 214 insertions(+), 124 deletions(-)
diff --git a/pom.xml b/pom.xml
index cbb86d0b71..e8f9beea2b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -126,7 +126,7 @@
<cglib.version>3.2.12</cglib.version>
<commons-collections.version>3.2.2</commons-collections.version>
<commons-collections4.version>4.4</commons-collections4.version>
- <commons-fileupload.version>1.4</commons-fileupload.version>
+ <commons-fileupload.version>1.5</commons-fileupload.version>
<commons-lang3.version>3.9</commons-lang3.version>
<jacoco.version>0.8.2</jacoco.version>
<jackson.version>2.9.9</jackson.version>
diff --git a/wicket-core/src/main/java/org/apache/wicket/Application.properties
b/wicket-core/src/main/java/org/apache/wicket/Application.properties
index ca23a009af..ca12fef6cd 100644
--- a/wicket-core/src/main/java/org/apache/wicket/Application.properties
+++ b/wicket-core/src/main/java/org/apache/wicket/Application.properties
@@ -25,7 +25,7 @@ MinimumValidator=The value of '${label}' must be at least
${minimum}.
#deprecated, use RangeValidator.maximum
MaximumValidator=The value of '${label}' must be at most ${maximum}.
-#raplaced with RangeValidator
+#raplaced with RangeValidator
NumberValidator.positive=The value of '${label}' must be a positive number.
#replaced with RangeValidator
NumberValidator.negative=The value of '${label}' must be a negative number.
@@ -57,11 +57,12 @@ PagingNavigator.last=Go to last page
PagingNavigation.page=Go to page ${page}
org.apache.wicket.mfu.caption.unlimited=Files:
-org.apache.wicket.mfu.caption.limited=Files (maximum ${max}):
+org.apache.wicket.mfu.caption.limited=Files (maximum ${max}):
org.apache.wicket.mfu.delete=Delete
uploadTooLarge = File must be less than ${maxSize}.
uploadSingleFileTooLarge = Each of files must be less than ${fileMaxSize}.
+uploadTooManyFiles = There should be no more than ${fileCountMax} files.
uploadFailed = File failed to upload: ${exception.localizedMessage}
FeedbackMessage.CSS.undefined=feedbackPanelUNDEFINED
diff --git
a/wicket-core/src/main/java/org/apache/wicket/Application_ru.properties.xml
b/wicket-core/src/main/java/org/apache/wicket/Application_ru.properties.xml
index f3f9b4a823..8f2e414b15 100644
--- a/wicket-core/src/main/java/org/apache/wicket/Application_ru.properties.xml
+++ b/wicket-core/src/main/java/org/apache/wicket/Application_ru.properties.xml
@@ -48,16 +48,18 @@
<entry key="null">Выберите значение</entry>
<entry key="nullValid"></entry>
-
+
<entry key="PagingNavigator.first">Перейти на первую страницу</entry>
<entry key="PagingNavigator.previous">Перейти на предыдущую
страницу</entry>
<entry key="PagingNavigator.next">Перейти на следующую страницу</entry>
<entry key="PagingNavigator.last">Перейти на последнюю страницу</entry>
<entry key="PagingNavigation.page">Перейти на страницу ${page}</entry>
-
+
<entry key="org.apache.wicket.mfu.caption.unlimited">Файлы:</entry>
<entry key="org.apache.wicket.mfu.caption.limited">Файлы (всего не
больше ${max}): </entry>
-
+
<entry key="uploadTooLarge">Размер файла не должен превышать
${maxSize}.</entry>
+ <entry key="uploadTooManyFiles">Количество загружаемых файлов не должно
превышать ${fileCountMax}.</entry>
+
<entry key="uploadFailed">Ошибка загрузки файла на сервер:
${exception.localizedMessage}.</entry>
</properties>
\ No newline at end of file
diff --git
a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
index 1416697e37..fc64c33364 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/form/Form.java
@@ -26,6 +26,7 @@ import java.util.Map;
import javax.servlet.http.HttpServletRequest;
+import org.apache.commons.fileupload.FileCountLimitExceededException;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.wicket.Component;
@@ -106,7 +107,7 @@ import org.slf4j.LoggerFactory;
* </ul>
* </li>
* </ul>
- *
+ *
* A Form can be configured for handling uploads with multipart requests (e.g.
files) by calling
* {@link #setMultiPart(boolean)} (although Wicket will try to automatically
detect this for you).
* Use this with {@link FileUploadField} components. You can attach multiple
{@link FileUploadField}
@@ -115,11 +116,11 @@ import org.slf4j.LoggerFactory;
* In case of an upload error two resource keys are available to specify error
messages:
* {@code uploadTooLarge} and {@code uploadFailed}, i.e. for a form with id
{@code myform} in
* {@code MyPage.properties}:
- *
+ *
* <pre>
* myform.uploadTooLarge=You have uploaded a file that is over the allowed
limit of 2Mb
* </pre>
- *
+ *
* Forms can be nested. You can put a form in another form. Since HTML doesn't
allow nested
* <form> tags, the inner forms will be rendered using the <div>
tag. You have to submit
* the inner forms using explicit components (like {@link Button} or {@link
SubmitLink}), you can't
@@ -128,7 +129,7 @@ import org.slf4j.LoggerFactory;
* <p>
* When a nested form is submitted, the user entered values in outer (parent)
forms are preserved
* and only the fields in the submitted form are validated. </b>
- *
+ *
* @author Jonathan Locke
* @author Juergen Donnerstag
* @author Eelco Hillenius
@@ -136,7 +137,7 @@ import org.slf4j.LoggerFactory;
* @author Johan Compagner
* @author Igor Vaynberg (ivaynberg)
* @author David Leangen
- *
+ *
* @param <T>
* The model object type
*/
@@ -149,7 +150,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Visitor used for validation
- *
+ *
* @author Igor Vaynberg (ivaynberg)
*/
public abstract static class ValidationVisitor implements
IVisitor<FormComponent<?>, Void>
@@ -178,7 +179,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Callback that should be used to validate form component
- *
+ *
* @param formComponent
*/
public abstract void validate(FormComponent<?> formComponent);
@@ -187,7 +188,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Visitor used to update component models
- *
+ *
* @author Igor Vaynberg (ivaynberg)
*/
private static class FormModelUpdateVisitor implements
IVisitor<Component, Void>
@@ -196,7 +197,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Constructor
- *
+ *
* @param formFilter
*/
public FormModelUpdateVisitor(Form<?> formFilter)
@@ -251,6 +252,7 @@ public class Form<T> extends WebMarkupContainer
private static final String UPLOAD_TOO_LARGE_RESOURCE_KEY =
"uploadTooLarge";
private static final String UPLOAD_SINGLE_FILE_TOO_LARGE_RESOURCE_KEY =
"uploadSingleFileTooLarge";
+ private static final String UPLOAD_TOO_MANY_FILES_RESOURCE_KEY =
"uploadTooManyFiles";
/**
* Any default IFormSubmittingComponent. If set, a hidden submit
component will be rendered
@@ -276,6 +278,12 @@ public class Form<T> extends WebMarkupContainer
*/
private Bytes fileMaxSize;
+ /**
+ * Maximum amount of files in request.
+ * A value of -1 indicates no maximum.
+ */
+ private long fileCountMax = -1L;
+
/** True if the form has enctype of multipart/form-data */
private short multiPart = 0;
@@ -299,7 +307,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Constructs a form with no validation.
- *
+ *
* @param id
* See Component
*/
@@ -323,7 +331,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Adds a form validator to the form.
- *
+ *
* @param validator
* validator
* @throws IllegalArgumentException
@@ -346,7 +354,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Removes a form validator from the form.
- *
+ *
* @param validator
* validator
* @throws IllegalArgumentException
@@ -411,7 +419,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Registers an error feedback message for this component
- *
+ *
* @param error
* error message
* @param args
@@ -426,7 +434,7 @@ public class Form<T> extends WebMarkupContainer
* THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
* <p>
* Gets the IFormSubmittingComponent which submitted this form.
- *
+ *
* @return The component which submitted this form, or null if the
processing was not triggered
* by a registered IFormSubmittingComponent
*/
@@ -471,7 +479,7 @@ public class Form<T> extends WebMarkupContainer
* </p>
* There can be only one default submit component per form hierarchy.
So if you want to get the
* default component on a nested form, it will actually delegate the
call to root form. </b>
- *
+ *
* @return The submit component to set as the default
IFormSubmittingComponent, or null when you
* want to 'unset' any previously set default
IFormSubmittingComponent
*/
@@ -489,7 +497,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Gets all {@link IFormValidator}s added to this form
- *
+ *
* @return unmodifiable collection of {@link IFormValidator}s
*/
public final Collection<IFormValidator> getFormValidators()
@@ -516,10 +524,10 @@ public class Form<T> extends WebMarkupContainer
/**
* Generate a piece of JavaScript that submits the form to the given
URL of an {@link IRequestListener}.
- *
+ *
* Warning: This code should only be called in the rendering phase for
form components inside
* the form because it uses the css/javascript id of the form which can
be stored in the markup.
- *
+ *
* @param url
* The listener url to be submitted to
* @return the javascript code that submits the form.
@@ -529,20 +537,20 @@ public class Form<T> extends WebMarkupContainer
Form<?> root = getRootForm();
AppendingStringBuffer buffer = new AppendingStringBuffer();
-
+
String action = url.toString();
if (root.encodeUrlInHiddenFields()) {
buffer.append(String.format("document.getElementById('%s').innerHTML = '",
root.getHiddenFieldsId()));
-
+
// parameter must be sent as hidden field, as it would
be ignored in the action URL
int i = action.indexOf('?');
if (i != -1)
{
writeParamsAsHiddenFields(Strings.split(action.substring(i + 1), '&'), buffer);
-
+
action = action.substring(0, i);
}
-
+
buffer.append("';");
}
buffer.append(String.format("var f =
document.getElementById('%s');", root.getMarkupId()));
@@ -553,11 +561,11 @@ public class Form<T> extends WebMarkupContainer
/**
* Generate a piece of JavaScript that submits the form with the given
{@link IFormSubmittingComponent}.
- *
+ *
* @param submitter
* the submitter
* @return the javascript code that submits the form.
- *
+ *
* @see #findSubmittingButton()
*/
public final CharSequence getJsForSubmitter(IFormSubmittingComponent
submitter)
@@ -571,9 +579,9 @@ public class Form<T> extends WebMarkupContainer
if (root.encodeUrlInHiddenFields())
{
buffer.append(String.format("document.getElementById('%s').innerHTML += '",
root.getHiddenFieldsId()));
-
+
writeParamsAsHiddenFields(new String[] {param}, buffer);
-
+
buffer.append("';");
}
else
@@ -588,8 +596,8 @@ public class Form<T> extends WebMarkupContainer
/**
* Gets the maximum size for uploads. If null, the setting
* {@link
org.apache.wicket.settings.ApplicationSettings#getDefaultMaximumUploadSize()}
is used.
- *
- *
+ *
+ *
* @return the maximum size
*/
public final Bytes getMaxSize()
@@ -599,7 +607,7 @@ public class Form<T> extends WebMarkupContainer
* max size smaller then the one specified in applications
settings because the inner form
* will return the default unless it is specifically set in the
traversal. With this method
* remaining final we can tell when the value is explicitly set
by the user.
- *
+ *
* If the value needs to be dynamic it can be set in
oncofigure() instead of overriding this
* method.
*/
@@ -625,7 +633,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Gets maximum size for each file of an upload.
- *
+ *
* @return
*/
public Bytes getFileMaxSize()
@@ -633,9 +641,19 @@ public class Form<T> extends WebMarkupContainer
return fileMaxSize;
}
+ /**
+ * Gets maximum count of files in the form
+ *
+ * @return
+ */
+ public long getFileCountMax()
+ {
+ return fileCountMax;
+ }
+
/**
* Returns the root form or this, if this is the root form.
- *
+ *
* @return root form or this form
*/
public Form<?> getRootForm()
@@ -666,7 +684,7 @@ public class Form<T> extends WebMarkupContainer
* <p>
* Returned prefix will be used for all form components. The prefix can
also be overridden on
* form component level by overriding {@link
FormComponent#getValidatorKeyPrefix()}
- *
+ *
* @return prefix prepended to validator keys
*/
public String getValidatorKeyPrefix()
@@ -676,7 +694,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Gets whether the current form has any error registered.
- *
+ *
* @return True if this form has at least one error.
*/
public final boolean hasError()
@@ -695,7 +713,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Returns whether the form is a root form, which means that there's no
other form in it's
* parent hierarchy.
- *
+ *
* @return true if form is a root form, false otherwise
*/
public boolean isRootForm()
@@ -705,7 +723,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Checks if this form has been submitted during the current request
- *
+ *
* @return true if the form has been submitted during this request,
false otherwise
*/
public final boolean isSubmitted()
@@ -715,9 +733,9 @@ public class Form<T> extends WebMarkupContainer
/**
* THIS METHOD IS NOT PART OF THE WICKET API. DO NOT ATTEMPT TO
OVERRIDE OR CALL IT.
- *
+ *
* Handles form submissions.
- *
+ *
* @see #onFormSubmitted(IFormSubmitter)
*/
@Override
@@ -731,7 +749,7 @@ public class Form<T> extends WebMarkupContainer
* {@link #getMethod()}. For example, someone can copy and paste the
action url and invoke the
* form using a {@code GET} instead of the desired {@code POST}. This
method allows the user to
* react to this situation.
- *
+ *
* @return response that can either abort or continue the processing of
the form
*/
protected MethodMismatchResponse onMethodMismatch()
@@ -741,13 +759,13 @@ public class Form<T> extends WebMarkupContainer
/**
* THIS METHOD IS NOT PART OF THE WICKET API. DO NOT ATTEMPT TO
OVERRIDE OR CALL IT.
- *
+ *
* Handles form submissions.
- *
+ *
* @param submitter
* listener that will receive form processing events, if
{@code null} the form will
* attempt to locate one
- *
+ *
* @see Form#validate()
*/
public final void onFormSubmitted(IFormSubmitter submitter)
@@ -866,7 +884,7 @@ public class Form<T> extends WebMarkupContainer
* </ul>
* </li>
* </ul>
- *
+ *
* @param submitter
* The submitting component, if any. May be null.
* @return The form that needs to be processed.
@@ -919,7 +937,7 @@ public class Form<T> extends WebMarkupContainer
* Whether this form wants to be submitted too if a nested form is
submitted. By default, this
* is false, so when a nested form is submitted, this form will
<em>not</em> be submitted. If
* this method is overridden to return true, this form <em>will</em> be
submitted.
- *
+ *
* @return Whether this form wants to be submitted too if a nested form
is submitted.
*/
// TODO wicket-7 migration guide: changed from public to protected
@@ -932,7 +950,7 @@ public class Form<T> extends WebMarkupContainer
* Whether this *nested* form wants to be submitted when parent form is
submitted. By default,
* this is true, so when a parent form is submitted, the nested form is
also submitted. If this
* method is overridden to return false, it will not be validated,
processed nor submitted.
- *
+ *
* @return {@code true} by default
*/
protected boolean wantSubmitOnParentFormSubmit()
@@ -943,15 +961,15 @@ public class Form<T> extends WebMarkupContainer
/**
* Process the form. Though you can override this method to provide
your own algorithm, it is
* not recommended to do so.
- *
+ *
* <p>
* See the class documentation for further details on the form
processing
* </p>
- *
+ *
* @param submittingComponent
* component responsible for submitting the form, or
<code>null</code> if none (eg
* the form has been submitted via the enter key or
javascript calling form.submit())
- *
+ *
* @see #delegateSubmit(IFormSubmitter) for an easy way to process
submitting component in the
* default manner
*/
@@ -1005,7 +1023,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Calls onError on this {@link Form} and any enabled and visible
nested form, if the respective
* {@link Form} actually has errors.
- *
+ *
* @param submitter
*/
protected void callOnError(IFormSubmitter submitter)
@@ -1039,20 +1057,20 @@ public class Form<T> extends WebMarkupContainer
/**
* Sets FLAG_SUBMITTED to true on this form and every enabled nested
form.
- * @param submitter
+ * @param submitter
*/
private void markFormsSubmitted(IFormSubmitter submitter)
{
setFlag(FLAG_SUBMITTED, true);
Form<?> formToProcess = findFormToProcess(submitter);
-
+
visitChildren(Form.class, new IVisitor<Component, Void>()
{
@Override
public void component(final Component component, final
IVisit<Void> visit)
{
Form<?> form = (Form<?>)component;
- if ((form.wantSubmitOnParentFormSubmit() ||
form == formToProcess)
+ if ((form.wantSubmitOnParentFormSubmit() ||
form == formToProcess)
&& form.isEnabledInHierarchy() &&
form.isVisibleInHierarchy())
{
form.setFlag(FLAG_SUBMITTED, true);
@@ -1074,7 +1092,7 @@ public class Form<T> extends WebMarkupContainer
* </p>
* There can be only one default button per form hierarchy. So if you
set default button on a
* nested form, it will actually delegate the call to root form. </b>
- *
+ *
* @param submittingComponent
* The component to set as the default submitting component,
or null when you want to
* 'unset' any previously set default component
@@ -1094,7 +1112,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Sets the maximum size for uploads. If null, the setting
* {@link
org.apache.wicket.settings.ApplicationSettings#getDefaultMaximumUploadSize()}
is used.
- *
+ *
* @param maxSize
* The maximum size
*/
@@ -1105,7 +1123,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Sets maximum size of each file in upload request.
- *
+ *
* @param fileMaxSize
*/
public void setFileMaxSize(Bytes fileMaxSize)
@@ -1113,10 +1131,20 @@ public class Form<T> extends WebMarkupContainer
this.fileMaxSize = fileMaxSize;
}
+ /**
+ * Sets maximum amount of files in upload request.
+ *
+ * @param fileCountMax
+ */
+ public void setFileCountMax(long fileCountMax)
+ {
+ this.fileCountMax = fileCountMax;
+ }
+
/**
* Set to true to use enctype='multipart/form-data', and to process
file uploads by default
* multiPart = false
- *
+ *
* @param multiPart
* whether this form should behave as a multipart form
*/
@@ -1154,7 +1182,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Convenient and typesafe way to visit all the form components on a
form.
- *
+ *
* @param <R>
* return object type
* @param visitor
@@ -1169,7 +1197,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Convenient and typesafe way to visit all the form components on a
form postorder (deepest
* first)
- *
+ *
* @param <R>
* Return object type
* @param visitor
@@ -1184,7 +1212,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Find out whether there is any registered error for a form component.
- *
+ *
* @return whether there is any registered error for a form component
*/
private boolean anyFormComponentError()
@@ -1251,7 +1279,7 @@ public class Form<T> extends WebMarkupContainer
// close div
buffer.append("</div>");
-
+
getResponse().write(buffer);
}
@@ -1277,7 +1305,7 @@ public class Form<T> extends WebMarkupContainer
* Regardless of whether a submitting component was found, the form's
onSubmit method is called
* next.
* </p>
- *
+ *
* @param submittingComponent
* the component that triggered this form processing, or
null if the processing was
* triggered by something else (like a non-Wicket submit
button or a javascript
@@ -1322,7 +1350,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Returns the id which will be used for the hidden div containing all
parameter fields.
- *
+ *
* @return the id of the hidden div
*/
private final String getHiddenFieldsId()
@@ -1337,7 +1365,7 @@ public class Form<T> extends WebMarkupContainer
* handlers may submit the form with a "get" even when the form method
is declared as "post."
* Therefore this method should not be considered a guarantee of the
HTTP method used, but a
* value for the markup only. Override if you have a requirement to
alter this behavior.
- *
+ *
* @return the submit method specified in markup.
*/
protected String getMethod()
@@ -1347,7 +1375,7 @@ public class Form<T> extends WebMarkupContainer
}
/**
- *
+ *
* @see org.apache.wicket.Component#getStatelessHint()
*/
@Override
@@ -1408,7 +1436,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Handles multi-part processing of the submitted data. <h3>
* WARNING</h3> If this method is overridden it can break {@link
FileUploadField}s on this form
- *
+ *
* @return false if form is multipart and upload failed
*/
protected boolean handleMultiPart()
@@ -1423,6 +1451,7 @@ public class Form<T> extends WebMarkupContainer
final MultipartServletWebRequest
multipartWebRequest = request.newMultipartWebRequest(
getMaxSize(), getPage().getId());
multipartWebRequest.setFileMaxSize(getFileMaxSize());
+
multipartWebRequest.setFileCountMax(getFileCountMax());
multipartWebRequest.parseFileParts();
// TODO: Can't this be detected from header?
@@ -1435,6 +1464,7 @@ public class Form<T> extends WebMarkupContainer
model.put("exception", fux);
model.put("maxSize", getMaxSize());
model.put("fileMaxSize", getFileMaxSize());
+ model.put("fileCountMax", getFileCountMax());
onFileUploadException(fux, model);
@@ -1451,7 +1481,7 @@ public class Form<T> extends WebMarkupContainer
* maxSize in the model or add you own property and use that in your
error message.
* <p>
* Don't forget to call super.onFileUploadException(e, model) at the
end of your method.
- *
+ *
* @param e
* @param model
*/
@@ -1468,6 +1498,11 @@ public class Form<T> extends WebMarkupContainer
String msg =
getString(UPLOAD_SINGLE_FILE_TOO_LARGE_RESOURCE_KEY, Model.ofMap(model));
error(msg);
}
+ else if (e instanceof FileCountLimitExceededException)
+ {
+ String msg =
getString(UPLOAD_TOO_MANY_FILES_RESOURCE_KEY, Model.ofMap(model));
+ error(msg);
+ }
else
{
String msg = getString(UPLOAD_FAILED_RESOURCE_KEY,
Model.ofMap(model));
@@ -1637,7 +1672,7 @@ public class Form<T> extends WebMarkupContainer
tag.remove("enctype");
}
}
-
+
// WICKET-6658 form is not allowed, anything else can stay as is
private void adjustNestedTagName(ComponentTag tag) {
if ("form".equalsIgnoreCase(tag.getName()))
@@ -1648,7 +1683,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Generates the action url for the form
- *
+ *
* @return action url
*/
protected CharSequence getActionUrl()
@@ -1684,7 +1719,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Append an additional hidden input tag to support anchor tags that
can submit a form.
- *
+ *
* @param markupStream
* The markup stream
* @param openTag
@@ -1717,7 +1752,7 @@ public class Form<T> extends WebMarkupContainer
getResponse().write(String.format("<div id=\"%s\"
style=\"width:0px;height:0px;position:absolute;left:-100px;top:-100px;overflow:hidden\"
class=\"%s\">", getHiddenFieldsId(), cssClass));
- AppendingStringBuffer buffer = new
AppendingStringBuffer();
+ AppendingStringBuffer buffer = new
AppendingStringBuffer();
String url = getActionUrl().toString();
int i = url.indexOf('?');
@@ -1727,7 +1762,7 @@ public class Form<T> extends WebMarkupContainer
writeParamsAsHiddenFields(params, buffer);
getResponse().write(buffer);
-
+
getResponse().write("</div>");
}
@@ -1744,7 +1779,7 @@ public class Form<T> extends WebMarkupContainer
}
/**
- *
+ *
* @param params
* @param buffer
*/
@@ -1764,7 +1799,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Take URL-encoded query string value, decode it and return
HTML-escaped version
- *
+ *
* @param s
* value to decode
* @return URL decoded and HTML escaped value
@@ -1822,10 +1857,10 @@ public class Form<T> extends WebMarkupContainer
* Update the model of all components on this form and nested forms
using the fields that were
* sent with the current request. This method only updates models when
the Form.validate() is
* called first that takes care of the conversion for the
FormComponents.
- *
+ *
* Normally this method will not be called when a validation error
occurs in one of the form
* components.
- *
+ *
* @see org.apache.wicket.markup.html.form.FormComponent#updateModel()
*/
protected final void updateFormComponentModels()
@@ -1836,7 +1871,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Update the model of all components on nested forms.
- *
+ *
* @see #updateFormComponentModels()
*/
private void updateNestedFormComponentModels()
@@ -1860,7 +1895,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Update the model of all components on this form.
- *
+ *
* @see #updateFormComponentModels()
*/
private void internalUpdateFormComponentModels()
@@ -1924,7 +1959,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Called after form components have updated their models. This is a
late-stage validation that
* allows outside frameworks to validate any beans that the form is
updating.
- *
+ *
* This validation method is not preferred because at this point any
errors will not unroll any
* changes to the model object, so the model object is in a modified
state potentially
* containing illegal values. However, with external frameworks there
may not be an alternate
@@ -1957,10 +1992,10 @@ public class Form<T> extends WebMarkupContainer
/**
* Checks if the specified form component visible and is attached to a
page
- *
+ *
* @param fc
* form component
- *
+ *
* @return true if the form component and all its parents are visible
and there component is in
* page's hierarchy
*/
@@ -1976,7 +2011,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Validates form with the given form validator
- *
+ *
* @param validator
*/
protected final void validateFormValidator(final IFormValidator
validator)
@@ -2036,7 +2071,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Validates {@link FormComponent}s as well as {@link IFormValidator}s
in nested {@link Form}s.
- *
+ *
* @see #validate()
*/
private void validateNestedForms()
@@ -2065,7 +2100,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Allows to customize input names of form components inside this form.
- *
+ *
* @return String that well be used as prefix to form component input
names
*/
protected String getInputNamePrefix()
@@ -2085,7 +2120,7 @@ public class Form<T> extends WebMarkupContainer
/**
* Utility method to assemble an id to distinct form components from
different nesting levels.
* Useful to generate input names attributes.
- *
+ *
* @param component
* @return form relative identification string
*/
@@ -2111,7 +2146,7 @@ public class Form<T> extends WebMarkupContainer
* Certain input names causes problems with JavaScript. If the
input name would cause a
* problem, we create a replacement unique name by prefixing
the name with a path that would
* otherwise never be used (blank id in path).
- *
+ *
* Input names must start with [A-Za-z] according to HTML 4.01
spec. HTML 5 allows almost
* anything.
*/
@@ -2126,9 +2161,9 @@ public class Form<T> extends WebMarkupContainer
/**
* Response when a submission method mismatch is detected
- *
+ *
* @see Form#getMethod()
- *
+ *
* @author igor
*/
public static enum MethodMismatchResponse {
diff --git
a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequest.java
b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequest.java
index 077cff441f..45fcd79523 100644
---
a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequest.java
+++
b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequest.java
@@ -31,7 +31,7 @@ import org.apache.wicket.util.lang.Bytes;
/**
* Servlet specific WebRequest subclass for multipart content uploads.
- *
+ *
* @author Matej Knopp
*/
public abstract class MultipartServletWebRequest extends ServletWebRequest
@@ -48,9 +48,15 @@ public abstract class MultipartServletWebRequest extends
ServletWebRequest
*/
private Bytes fileMaxSize;
+ /**
+ * Maximum amount of files in request.
+ * A value of -1 indicates no maximum.
+ */
+ private long fileCountMax = -1L;
+
/**
* Construct.
- *
+ *
* @param httpServletRequest
* @param filterPrefix
*/
@@ -61,7 +67,7 @@ public abstract class MultipartServletWebRequest extends
ServletWebRequest
/**
* Construct.
- *
+ *
* @param httpServletRequest
* @param filterPrefix
* @param url
@@ -131,4 +137,14 @@ public abstract class MultipartServletWebRequest extends
ServletWebRequest
{
this.fileMaxSize = fileMaxSize;
}
+
+ public long getFileCountMax()
+ {
+ return fileCountMax;
+ }
+
+ public void setFileCountMax(long fileCountMax)
+ {
+ this.fileCountMax = fileCountMax;
+ }
}
diff --git
a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
index d0d5330b70..355f8442a9 100644
---
a/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
+++
b/wicket-core/src/main/java/org/apache/wicket/protocol/http/servlet/MultipartServletWebRequestImpl.java
@@ -48,7 +48,7 @@ import org.apache.wicket.util.value.ValueMap;
/**
* Servlet specific WebRequest subclass for multipart content uploads.
- *
+ *
* @author Jonathan Locke
* @author Eelco Hillenius
* @author Cameron Braid
@@ -298,12 +298,14 @@ public class MultipartServletWebRequestImpl extends
MultipartServletWebRequest
fileUpload.setFileSizeMax(fileMaxSize.bytes());
}
+ fileUpload.setFileCountMax(getFileCountMax());
+
return fileUpload;
}
/**
* Adds a parameter to the parameters value map
- *
+ *
* @param name
* parameter name
* @param value
@@ -341,7 +343,7 @@ public class MultipartServletWebRequestImpl extends
MultipartServletWebRequest
/**
* Gets the file that was uploaded using the given field name.
- *
+ *
* @param fieldName
* the field name that was used for the upload
* @return the upload with the given field name
@@ -376,7 +378,7 @@ public class MultipartServletWebRequestImpl extends
MultipartServletWebRequest
/**
* Subclasses that want to receive upload notifications should return
true. By default it takes
* the value from {@link
org.apache.wicket.settings.ApplicationSettings#isUploadProgressUpdatesEnabled()}.
- *
+ *
* @return true if upload status update event should be invoked
*/
protected boolean wantUploadProgressUpdates()
@@ -386,7 +388,7 @@ public class MultipartServletWebRequestImpl extends
MultipartServletWebRequest
/**
* Upload start callback
- *
+ *
* @param totalBytes
*/
protected void onUploadStarted(int totalBytes)
@@ -398,7 +400,7 @@ public class MultipartServletWebRequestImpl extends
MultipartServletWebRequest
/**
* Upload status update callback
- *
+ *
* @param bytesUploaded
* @param total
*/
@@ -426,7 +428,7 @@ public class MultipartServletWebRequestImpl extends
MultipartServletWebRequest
/**
* An {@link InputStream} that updates total number of bytes read
- *
+ *
* @author Igor Vaynberg (ivaynberg)
*/
private class CountingInputStream extends InputStream
@@ -436,7 +438,7 @@ public class MultipartServletWebRequestImpl extends
MultipartServletWebRequest
/**
* Constructs a new CountingInputStream.
- *
+ *
* @param in
* InputStream to delegate to
*/
@@ -527,7 +529,7 @@ public class MultipartServletWebRequestImpl extends
MultipartServletWebRequest
/**
* Retrieves {@link UploadInfo} from session, null if not found.
- *
+ *
* @param req
* http servlet request, not null
* @param upload
@@ -542,7 +544,7 @@ public class MultipartServletWebRequestImpl extends
MultipartServletWebRequest
/**
* Sets the {@link UploadInfo} object into session.
- *
+ *
* @param req
* http servlet request, not null
* @param upload
@@ -561,7 +563,7 @@ public class MultipartServletWebRequestImpl extends
MultipartServletWebRequest
/**
* Clears the {@link UploadInfo} object from session if one exists.
- *
+ *
* @param req
* http servlet request, not null
* @param upload
diff --git
a/wicket-examples/src/main/java/org/apache/wicket/examples/upload/MultiUploadPage.java
b/wicket-examples/src/main/java/org/apache/wicket/examples/upload/MultiUploadPage.java
index 889e941179..b44ae8ef62 100644
---
a/wicket-examples/src/main/java/org/apache/wicket/examples/upload/MultiUploadPage.java
+++
b/wicket-examples/src/main/java/org/apache/wicket/examples/upload/MultiUploadPage.java
@@ -43,7 +43,7 @@ import org.apache.wicket.util.lang.Bytes;
/**
* Upload example.
- *
+ *
* @author Eelco Hillenius
*/
public class MultiUploadPage extends WicketExamplePage
@@ -55,7 +55,7 @@ public class MultiUploadPage extends WicketExamplePage
{
/**
* Construct.
- *
+ *
* @param name
* Component name
* @param files
@@ -95,7 +95,7 @@ public class MultiUploadPage extends WicketExamplePage
/**
* TODO
- *
+ *
* @return Collection
*/
public Collection<FileUpload> getUploads()
@@ -105,7 +105,7 @@ public class MultiUploadPage extends WicketExamplePage
/**
* Construct.
- *
+ *
* @param id
* Component id
*/
@@ -125,6 +125,9 @@ public class MultiUploadPage extends WicketExamplePage
// Set maximum size per file to 90K for demo purposes
setFileMaxSize(Bytes.kilobytes(90));
+
+ // Set maximum file count to 5 for demo purposes
+ setFileCountMax(5L);
}
/**
@@ -161,7 +164,7 @@ public class MultiUploadPage extends WicketExamplePage
/**
* Constructor.
- *
+ *
* @param parameters
* Page parameters
*/
@@ -196,7 +199,7 @@ public class MultiUploadPage extends WicketExamplePage
/**
* Check whether the file allready exists, and if so, try to delete it.
- *
+ *
* @param newFile
* the file to check
*/
diff --git
a/wicket-examples/src/main/java/org/apache/wicket/examples/upload/UploadPage.html
b/wicket-examples/src/main/java/org/apache/wicket/examples/upload/UploadPage.html
index 5356904adb..d5c2b76017 100644
---
a/wicket-examples/src/main/java/org/apache/wicket/examples/upload/UploadPage.html
+++
b/wicket-examples/src/main/java/org/apache/wicket/examples/upload/UploadPage.html
@@ -12,6 +12,7 @@
<p>Wicket can also handle file uploads via AJAX, please see AJAX
examples section. AJAX Functionality is not included in this example to keep
things simple.</p>
<p>The maximum file size of a single upload is: 90k!</p>
<p>The maximum size of uploading several files (third demo) is:
100k!</p>
+ <p>The maximum file count of uploading several files (third demo) is:
5</p>
<br/>
<form wicket:id="simpleUpload">
diff --git
a/wicket-examples/src/main/java/org/apache/wicket/examples/upload/UploadPage.java
b/wicket-examples/src/main/java/org/apache/wicket/examples/upload/UploadPage.java
index 8ef9177fe9..3fe09b7eef 100644
---
a/wicket-examples/src/main/java/org/apache/wicket/examples/upload/UploadPage.java
+++
b/wicket-examples/src/main/java/org/apache/wicket/examples/upload/UploadPage.java
@@ -40,7 +40,7 @@ import org.apache.wicket.util.lang.Bytes;
/**
* Upload example.
- *
+ *
* @author Eelco Hillenius
*/
@SuppressWarnings("serial")
@@ -53,7 +53,7 @@ public class UploadPage extends WicketExamplePage
{
/**
* Construct.
- *
+ *
* @param name
* Component name
* @param files
@@ -93,7 +93,7 @@ public class UploadPage extends WicketExamplePage
/**
* Construct.
- *
+ *
* @param name
* Component name
*/
@@ -112,6 +112,9 @@ public class UploadPage extends WicketExamplePage
// Set maximum size per file to 90K for demo purposes
setFileMaxSize(Bytes.kilobytes(90));
+
+ // Set maximum file count to 5 for demo purposes
+ setFileCountMax(5L);
}
@Override
@@ -149,7 +152,7 @@ public class UploadPage extends WicketExamplePage
/**
* Constructor.
- *
+ *
* @param parameters
* Page parameters
*/
@@ -195,7 +198,7 @@ public class UploadPage extends WicketExamplePage
/**
* Check whether the file allready exists, and if so, try to delete it.
- *
+ *
* @param newFile
* the file to check
*/
diff --git
a/wicket-examples/src/test/java/org/apache/wicket/examples/StartExamples.java
b/wicket-examples/src/test/java/org/apache/wicket/examples/StartExamples.java
index 18e6c26082..7e7e5dea80 100644
---
a/wicket-examples/src/test/java/org/apache/wicket/examples/StartExamples.java
+++
b/wicket-examples/src/test/java/org/apache/wicket/examples/StartExamples.java
@@ -42,7 +42,7 @@ public class StartExamples
{
/**
* Main function, starts the jetty server.
- *
+ *
* @param args
*/
public static void main(String[] args) throws Exception
diff --git
a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxFileDropBehavior.java
b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxFileDropBehavior.java
index 0501610c74..a668914a32 100644
---
a/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxFileDropBehavior.java
+++
b/wicket-extensions/src/main/java/org/apache/wicket/extensions/ajax/AjaxFileDropBehavior.java
@@ -63,6 +63,12 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
*/
private Bytes fileMaxSize;
+ /**
+ * Maximum amount of files in request.
+ * A value of -1 indicates no maximum.
+ */
+ private long fileCountMax = -1L;
+
private String parameterName = "f";
/**
@@ -97,11 +103,11 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
public CharSequence getPrecondition(Component component)
{
String css =
getComponent().getString(DRAG_OVER_CLASS_KEY);
-
+
return String.format("jQuery('#' +
attrs.c).toggleClass('%s', attrs.event.type === 'dragover'); return
(attrs.event.type === 'drop');", css);
}
});
-
+
attributes.getDynamicExtraParameters()
.add(String.format(
"return
Wicket.DataTransfer.getFilesAsParamArray(attrs.event.originalEvent, '%s');",
@@ -117,6 +123,7 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
final MultipartServletWebRequest multipartWebRequest =
request
.newMultipartWebRequest(getMaxSize(),
getComponent().getPage().getId());
multipartWebRequest.setFileMaxSize(getFileMaxSize());
+ multipartWebRequest.setFileCountMax(getFileCountMax());
multipartWebRequest.parseFileParts();
// TODO: Can't this be detected from header?
@@ -155,7 +162,7 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
/**
* Set the maximum upload size.
- *
+ *
* @param maxSize maximum size, must not be null
*/
public void setMaxSize(Bytes maxSize)
@@ -171,7 +178,7 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
/**
* Set an optional maximum size per file.
- *
+ *
* @param fileMaxSize maximum size for each uploaded file
*/
public void setFileMaxSize(Bytes fileMaxSize)
@@ -179,12 +186,32 @@ public class AjaxFileDropBehavior extends
AjaxEventBehavior
this.fileMaxSize = fileMaxSize;
}
+ /**
+ * Gets maximum count of files
+ *
+ * @return
+ */
+ public long getFileCountMax()
+ {
+ return fileCountMax;
+ }
+
+ /**
+ * Sets maximum amount of files in upload request.
+ *
+ * @param fileCountMax
+ */
+ public void setFileCountMax(long fileCountMax)
+ {
+ this.fileCountMax = fileCountMax;
+ }
+
/**
* Hook method called after a file was uploaded.
* <p>
* Note: {@link #onError(AjaxRequestTarget, FileUploadException)} is
called instead when
* uploading failed
- *
+ *
* @param target
* the current request handler
* @param files
@@ -197,7 +224,7 @@ public class AjaxFileDropBehavior extends AjaxEventBehavior
/**
* Hook method called to handle any error during uploading of the file.
* <p>
- * Default implementation re-throws the exception.
+ * Default implementation re-throws the exception.
*
* @param target
* the current request handler