001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.woody.formmodel;
018:
019: import java.util.Locale;
020: import java.util.StringTokenizer;
021:
022: import org.apache.cocoon.servlet.multipart.Part;
023: import org.apache.cocoon.woody.Constants;
024: import org.apache.cocoon.woody.FormContext;
025: import org.apache.cocoon.woody.validation.ValidationError;
026: import org.apache.cocoon.woody.util.I18nMessage;
027: import org.apache.cocoon.woody.validation.ValidationErrorAware;
028: import org.apache.cocoon.xml.AttributesImpl;
029: import org.xml.sax.ContentHandler;
030: import org.xml.sax.SAXException;
031:
032: /**
033: * A file-uploading Widget. This widget gives access via Woody, to Cocoon's
034: * file upload functionality.
035: *
036: * @author <a href="mailto:uv@upaya.co.uk">Upayavira</a>
037: * @author <a href="http://www.apache.org/~sylvain/">Sylvain Wallez</a>
038: * @version CVS $Id: Upload.java 433543 2006-08-22 06:22:54Z crossley $
039: */
040: public class Upload extends AbstractWidget implements
041: ValidationErrorAware {
042: private UploadDefinition uploadDefinition;
043: private Part part;
044: private ValidationError validationError;
045:
046: public Upload(UploadDefinition uploadDefinition) {
047: this .uploadDefinition = uploadDefinition;
048: this .setDefinition(uploadDefinition);
049: setLocation(uploadDefinition.getLocation());
050: }
051:
052: public UploadDefinition getUploadDefinition() {
053: return this .uploadDefinition;
054: }
055:
056: public String getId() {
057: return definition.getId();
058: }
059:
060: public Object getValue() {
061: return this .part;
062: }
063:
064: public void setValue(Object object) {
065: throw new RuntimeException(
066: "Cannot manually set the value of an upload widget for field \""
067: + getFullyQualifiedId() + "\"");
068: }
069:
070: public void readFromRequest(FormContext formContext) {
071: Object obj = formContext.getRequest()
072: .get(getFullyQualifiedId());
073:
074: // If the request object is a Part, keep it
075: if (obj instanceof Part) {
076: Part requestPart = (Part) obj;
077: if (this .part != null) {
078: // Replace the current part
079: this .part.dispose();
080: }
081:
082: // Keep the request part
083: requestPart.setDisposeWithRequest(false);
084: this .part = requestPart;
085: this .validationError = null;
086:
087: // If it's not a part and not null, clear any existing value
088: // We also check if we're the submit widget, as a result of clicking the "..." button
089: } else if (obj != null || getForm().getSubmitWidget() == this ) {
090: // Clear the part, if any
091: if (this .part != null) {
092: this .part.dispose();
093: this .part = null;
094: }
095: this .validationError = null;
096: }
097:
098: // And keep the current state if the parameter doesn't exist or is null
099: }
100:
101: public boolean validate(FormContext formContext) {
102: if (this .part == null) {
103: if (this .uploadDefinition.isRequired()) {
104: this .validationError = new ValidationError(
105: new I18nMessage("general.field-required",
106: Constants.I18N_CATALOGUE));
107: }
108: } else {
109: String mimeTypes = this .uploadDefinition.getMimeTypes();
110: if (mimeTypes != null) {
111: StringTokenizer tok = new StringTokenizer(
112: this .uploadDefinition.getMimeTypes(), ", ");
113: this .validationError = new ValidationError(
114: new I18nMessage("upload.invalid-type",
115: Constants.I18N_CATALOGUE));
116: String contentType = this .part.getMimeType();
117: while (tok.hasMoreTokens()) {
118: if (tok.nextToken().equals(contentType)) {
119: this .validationError = null;
120: }
121: }
122: } else {
123: this .validationError = null;
124: }
125: }
126:
127: return validationError == null ? super .validate(formContext)
128: : false;
129: }
130:
131: /**
132: * Returns the validation error, if any. There will always be a validation error in case the
133: * {@link #validate(FormContext)} method returned false.
134: */
135: public ValidationError getValidationError() {
136: return validationError;
137: }
138:
139: /**
140: * Set a validation error on this field. This allows fields to be externally marked as invalid by
141: * application logic.
142: *
143: * @param error the validation error
144: */
145: public void setValidationError(ValidationError error) {
146: this .validationError = error;
147: }
148:
149: private static final String FIELD_EL = "upload";
150: private static final String VALUE_EL = "value";
151: private static final String VALIDATION_MSG_EL = "validation-message";
152:
153: public void generateSaxFragment(ContentHandler contentHandler,
154: Locale locale) throws SAXException {
155: AttributesImpl fieldAttrs = new AttributesImpl();
156: fieldAttrs.addCDATAAttribute("id", getFullyQualifiedId());
157: fieldAttrs.addCDATAAttribute("required", String
158: .valueOf(uploadDefinition.isRequired()));
159: if (uploadDefinition.getMimeTypes() != null) {
160: fieldAttrs.addCDATAAttribute("mime-types", uploadDefinition
161: .getMimeTypes());
162: }
163: contentHandler.startElement(Constants.WI_NS, FIELD_EL,
164: Constants.WI_PREFIX_COLON + FIELD_EL, fieldAttrs);
165:
166: if (this .part != null) {
167: String name = (String) this .part.getHeaders().get(
168: "filename");
169: contentHandler.startElement(Constants.WI_NS, VALUE_EL,
170: Constants.WI_PREFIX_COLON + VALUE_EL,
171: Constants.EMPTY_ATTRS);
172: contentHandler.characters(name.toCharArray(), 0, name
173: .length());
174: contentHandler.endElement(Constants.WI_NS, VALUE_EL,
175: Constants.WI_PREFIX_COLON + VALUE_EL);
176: }
177:
178: // validation message element: only present if the value is not valid
179: if (validationError != null) {
180: contentHandler.startElement(Constants.WI_NS,
181: VALIDATION_MSG_EL, Constants.WI_PREFIX_COLON
182: + VALIDATION_MSG_EL, Constants.EMPTY_ATTRS);
183: validationError.generateSaxFragment(contentHandler);
184: contentHandler.endElement(Constants.WI_NS,
185: VALIDATION_MSG_EL, Constants.WI_PREFIX_COLON
186: + VALIDATION_MSG_EL);
187: }
188:
189: // the display data
190: this .definition.generateDisplayData(contentHandler);
191:
192: contentHandler.endElement(Constants.WI_NS, FIELD_EL,
193: Constants.WI_PREFIX_COLON + FIELD_EL);
194: }
195:
196: public void generateLabel(ContentHandler contentHandler)
197: throws SAXException {
198: definition.generateLabel(contentHandler);
199: }
200: }
|