1 16 package org.apache.cocoon.forms.formmodel; 17 18 import java.util.Locale ; 19 import java.util.StringTokenizer ; 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 ; 41 import org.xml.sax.SAXException ; 42 43 55 public class Upload extends AbstractWidget 56 implements ValidationErrorAware, ValueChangedListenerEnabled { 57 58 private static final String UPLOAD_EL = "upload"; 59 private static final String VALUE_EL = "value"; 60 private static final String 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 getValue() { 82 return this.isValid() ? this.part : null; 83 } 84 85 public void setValue(Object 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 ("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 obj = formContext.getRequest().get(getRequestParameterName()); 104 105 if (obj instanceof Part) { 107 Part requestPart = (Part)obj; 108 if (this.part != null) { 109 this.part.dispose(); 111 } 112 113 requestPart.setDisposeWithRequest(false); 115 this.part = requestPart; 116 if (validateOversize()) { 117 setValidationError(null); 119 } 120 changed(); 121 122 } else if (obj != null || getForm().getSubmitWidget() == this){ 125 if (this.part != null) { 127 this.part.dispose(); 128 this.part = null; 129 } 130 setValidationError(null); 131 changed(); 133 } 134 135 } 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 mimeTypes = this.uploadDefinition.getMimeTypes(); 147 if (mimeTypes != null) { 148 StringTokenizer tok = new StringTokenizer (mimeTypes, ", "); 149 String 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 [] {contentType}, 157 FormsConstants.I18N_CATALOGUE); 158 setValidationError(new ValidationError(message)); 159 return false; 160 } 161 162 return true; 164 } 165 166 169 private boolean validateOversize() { 170 if (!this.part.isRejected()) { 171 return true; 172 } 173 174 RejectedPart rjp = (RejectedPart)this.part; 176 int size = (rjp.getContentLength() + 512) / 1024; 177 int maxSize = (rjp.getMaxContentLength() + 512) / 1024; 178 String [] i18nParams = new String [] { 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 207 public ValidationError getValidationError() { 208 return this.validationError; 209 } 210 211 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 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 super.broadcastEvent(event); 249 } 250 } 251 252 255 public String getXMLElementName() { 256 return UPLOAD_EL; 257 } 258 259 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 contentHandler, Locale locale) throws SAXException { 273 if (this.part != null) { 274 String name = (String )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 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 |