KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > forms > formmodel > Upload


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.forms.formmodel;
17
18 import java.util.Locale JavaDoc;
19 import java.util.StringTokenizer JavaDoc;
20
21 import org.apache.cocoon.forms.FormsConstants;
22 import org.apache.cocoon.forms.FormContext;
23 import org.apache.cocoon.forms.event.ValueChangedEvent;
24 import org.apache.cocoon.forms.event.ValueChangedListener;
25 import org.apache.cocoon.forms.event.ValueChangedListenerEnabled;
26 import org.apache.cocoon.forms.event.WidgetEvent;
27 import org.apache.cocoon.forms.event.WidgetEventMulticaster;
28 import org.apache.cocoon.forms.util.I18nMessage;
29 import org.apache.cocoon.forms.validation.ValidationError;
30 import org.apache.cocoon.forms.validation.ValidationErrorAware;
31
32 import org.apache.cocoon.servlet.multipart.Part;
33 import org.apache.cocoon.servlet.multipart.RejectedPart;
34
35 import org.apache.cocoon.xml.AttributesImpl;
36 import org.apache.cocoon.xml.XMLUtils;
37
38 import org.apache.commons.lang.ObjectUtils;
39
40 import org.xml.sax.ContentHandler JavaDoc;
41 import org.xml.sax.SAXException JavaDoc;
42
43 /**
44  * A file-uploading Widget. This widget gives access via Cocoon Forms, to Cocoon's
45  * file upload functionality.
46  * <p>
47  * This widget accepts value-changed listeners, but the event raised does not hold
48  * the previous value, as uploads are heavyweight resources that must be released
49  * as soon as possible.
50  *
51  * @author <a HREF="mailto:uv@upaya.co.uk">Upayavira</a>
52  * @author <a HREF="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
53  * @version $Id: Upload.java 328140 2005-10-24 19:22:55Z sylvain $
54  */

55 public class Upload extends AbstractWidget
56                     implements ValidationErrorAware, ValueChangedListenerEnabled {
57
58     private static final String JavaDoc UPLOAD_EL = "upload";
59     private static final String JavaDoc VALUE_EL = "value";
60     private static final String JavaDoc VALIDATION_MSG_EL = "validation-message";
61
62     private final UploadDefinition uploadDefinition;
63     private Part part;
64     private ValidationError validationError;
65     private ValueChangedListener listener;
66
67     public Upload(UploadDefinition uploadDefinition) {
68         super(uploadDefinition);
69         this.uploadDefinition = uploadDefinition;
70         this.listener = uploadDefinition.getValueChangedListener();
71     }
72
73     public UploadDefinition getUploadDefinition() {
74         return this.uploadDefinition;
75     }
76
77     public WidgetDefinition getDefinition() {
78         return this.uploadDefinition;
79     }
80
81     public Object JavaDoc getValue() {
82         return this.isValid() ? this.part : null;
83     }
84
85     public void setValue(Object JavaDoc object) {
86         if (object == this.part) {
87             return;
88         }
89
90         if ((object == null) || (object instanceof Part)) {
91             this.part = (Part)object;
92         } else {
93             throw new RuntimeException JavaDoc("The value of an upload widget must be of type " + Part.class + ".");
94         }
95         changed();
96     }
97
98     public void readFromRequest(FormContext formContext) {
99         if (!getCombinedState().isAcceptingInputs()) {
100             return;
101         }
102
103         Object JavaDoc obj = formContext.getRequest().get(getRequestParameterName());
104
105         // If the request object is a Part, keep it
106
if (obj instanceof Part) {
107             Part requestPart = (Part)obj;
108             if (this.part != null) {
109                 // Replace the current part
110
this.part.dispose();
111             }
112
113             // Keep the request part
114
requestPart.setDisposeWithRequest(false);
115             this.part = requestPart;
116             if (validateOversize()) {
117                 // Clear any validation error
118
setValidationError(null);
119             }
120             changed();
121
122         // If it's not a part and not null, clear any existing value
123
// We also check if we're the submit widget, as a result of clicking the "..." button
124
} else if (obj != null || getForm().getSubmitWidget() == this){
125             // Clear the part, if any
126
if (this.part != null) {
127                 this.part.dispose();
128                 this.part = null;
129             }
130             setValidationError(null);
131             // Ensure we redisplay it
132
changed();
133         }
134
135         // And keep the current state if the parameter doesn't exist or is null
136
}
137     
138     private void changed() {
139         if (this.hasValueChangedListeners() || this.getForm().hasFormHandler()) {
140             this.getForm().addWidgetEvent(new ValueChangedEvent(this, null, this.part));
141         }
142         getForm().addWidgetUpdate(this);
143     }
144
145     private boolean validateMimeType() {
146         String JavaDoc mimeTypes = this.uploadDefinition.getMimeTypes();
147         if (mimeTypes != null) {
148             StringTokenizer JavaDoc tok = new StringTokenizer JavaDoc(mimeTypes, ", ");
149             String JavaDoc contentType = this.part.getMimeType();
150             while(tok.hasMoreTokens()) {
151                 if (tok.nextToken().equals(contentType)) {
152                     return true;
153                 }
154             }
155             I18nMessage message = new I18nMessage("upload.invalid-type",
156                                                   new String JavaDoc[] {contentType},
157                                                   FormsConstants.I18N_CATALOGUE);
158             setValidationError(new ValidationError(message));
159             return false;
160         }
161
162         // No mime type restriction
163
return true;
164     }
165
166     /**
167      * Check if the part is oversized, and if yes sets the validation error accordingly
168      */

169     private boolean validateOversize() {
170         if (!this.part.isRejected()) {
171             return true;
172         }
173
174         // Set a validation error indicating the sizes in kbytes (rounded)
175
RejectedPart rjp = (RejectedPart)this.part;
176         int size = (rjp.getContentLength() + 512) / 1024;
177         int maxSize = (rjp.getMaxContentLength() + 512) / 1024;
178         String JavaDoc[] i18nParams = new String JavaDoc[] { String.valueOf(size), String.valueOf(maxSize) };
179         I18nMessage i18nMessage = new I18nMessage("upload.rejected", i18nParams, FormsConstants.I18N_CATALOGUE);
180         setValidationError(new ValidationError(i18nMessage));
181         return false;
182     }
183
184     public boolean validate() {
185         if (!getCombinedState().isValidatingValues()) {
186             this.wasValid = true;
187             return true;
188         }
189
190         if (this.part == null) {
191             if (this.uploadDefinition.isRequired()) {
192                 I18nMessage i18nMessage = new I18nMessage("general.field-required", FormsConstants.I18N_CATALOGUE);
193                 setValidationError(new ValidationError(i18nMessage));
194             }
195         } else if (validateOversize() && validateMimeType()) {
196             super.validate();
197         }
198
199         this.wasValid = this.validationError == null;
200         return this.wasValid;
201     }
202
203     /**
204      * Returns the validation error, if any. There will always be a validation error in case the
205      * {@link #validate()} method returned false.
206      */

207     public ValidationError getValidationError() {
208         return this.validationError;
209     }
210
211     /**
212      * Set a validation error on this field. This allows fields to be externally marked as invalid by
213      * application logic.
214      *
215      * @param error the validation error
216      */

217     public void setValidationError(ValidationError error) {
218         if(!ObjectUtils.equals(this.validationError, error)) {
219             this.validationError = error;
220             getForm().addWidgetUpdate(this);
221         }
222     }
223
224     /**
225      * Adds a ValueChangedListener to this widget instance. Listeners defined
226      * on the widget instance will be executed in addtion to any listeners
227      * that might have been defined in the widget definition.
228      */

229     public void addValueChangedListener(ValueChangedListener listener) {
230         this.listener = WidgetEventMulticaster.add(this.listener, listener);
231     }
232
233     public void removeValueChangedListener(ValueChangedListener listener) {
234         this.listener = WidgetEventMulticaster.remove(this.listener, listener);
235     }
236     
237     public boolean hasValueChangedListeners() {
238         return this.listener != null;
239     }
240
241     public void broadcastEvent(WidgetEvent event) {
242         if (event instanceof ValueChangedEvent) {
243             if (this.listener != null) {
244                 this.listener.valueChanged((ValueChangedEvent)event);
245             }
246         } else {
247             // Other kinds of events
248
super.broadcastEvent(event);
249         }
250     }
251
252     /**
253      * @return "upload"
254      */

255     public String JavaDoc getXMLElementName() {
256         return UPLOAD_EL;
257     }
258
259     /**
260      * Adds attributes @required, @mime-types
261      */

262     public AttributesImpl getXMLElementAttributes() {
263         AttributesImpl attrs = super.getXMLElementAttributes();
264         attrs.addCDATAAttribute("id", getRequestParameterName());
265         attrs.addCDATAAttribute("required", String.valueOf(this.uploadDefinition.isRequired()));
266         if (this.uploadDefinition.getMimeTypes() != null) {
267             attrs.addCDATAAttribute("mime-types", this.uploadDefinition.getMimeTypes());
268         }
269         return attrs;
270     }
271
272     public void generateItemSaxFragment(ContentHandler JavaDoc contentHandler, Locale JavaDoc locale) throws SAXException JavaDoc {
273         if (this.part != null) {
274             String JavaDoc name = (String JavaDoc)this.part.getHeaders().get("filename");
275             contentHandler.startElement(FormsConstants.INSTANCE_NS, VALUE_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALUE_EL, XMLUtils.EMPTY_ATTRIBUTES);
276             contentHandler.characters(name.toCharArray(), 0, name.length());
277             contentHandler.endElement(FormsConstants.INSTANCE_NS, VALUE_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALUE_EL);
278         }
279
280         // validation message element: only present if the value is not valid
281
if (this.validationError != null) {
282             contentHandler.startElement(FormsConstants.INSTANCE_NS, VALIDATION_MSG_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALIDATION_MSG_EL, XMLUtils.EMPTY_ATTRIBUTES);
283             this.validationError.generateSaxFragment(contentHandler);
284             contentHandler.endElement(FormsConstants.INSTANCE_NS, VALIDATION_MSG_EL, FormsConstants.INSTANCE_PREFIX_COLON + VALIDATION_MSG_EL);
285         }
286     }
287 }
288
Popular Tags