001    package org.apache.myfaces.tobago.validator;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one or more
005     * contributor license agreements.  See the NOTICE file distributed with
006     * this work for additional information regarding copyright ownership.
007     * The ASF licenses this file to You under the Apache License, Version 2.0
008     * (the "License"); you may not use this file except in compliance with
009     * the License.  You may obtain a copy of the License at
010     *
011     *      http://www.apache.org/licenses/LICENSE-2.0
012     *
013     * Unless required by applicable law or agreed to in writing, software
014     * distributed under the License is distributed on an "AS IS" BASIS,
015     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016     * See the License for the specific language governing permissions and
017     * limitations under the License.
018     */
019    
020    import org.apache.myfaces.tobago.component.UIFileInput;
021    import org.apache.myfaces.tobago.util.MessageFactory;
022    import org.apache.myfaces.tobago.util.ContentType;
023    import org.apache.commons.fileupload.FileItem;
024    
025    import javax.faces.validator.Validator;
026    import javax.faces.validator.ValidatorException;
027    import javax.faces.component.StateHolder;
028    import javax.faces.component.UIComponent;
029    import javax.faces.context.FacesContext;
030    import javax.faces.application.FacesMessage;
031    import java.util.Arrays;
032    
033    /**
034     * <p><strong>FileItemValidator</strong> is a {@link Validator} that checks
035     * the FileItem in the value of the associated component.
036     */
037    
038    @org.apache.myfaces.tobago.apt.annotation.Validator(id = FileItemValidator.VALIDATOR_ID)
039    public class FileItemValidator implements Validator, StateHolder {
040      public static final String VALIDATOR_ID = "org.apache.myfaces.tobago.FileItem";
041      public static final String SIZE_LIMIT_MESSAGE_ID = "org.apache.myfaces.tobago.FileItemValidator.SIZE_LIMIT";
042      public static final String CONTENT_TYPE_MESSAGE_ID = "org.apache.myfaces.tobago.FileItemValidator.CONTENT_TYPE";
043      private Integer maxSize = null;
044      private String[] contentType;
045      private boolean transientValue;
046    
047      public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
048        if (value != null && component instanceof UIFileInput) {
049          FileItem file = (FileItem) value;
050          if (maxSize != null && file.getSize() > maxSize) {
051            Object[] args = {maxSize, component.getId()};
052            FacesMessage facesMessage = MessageFactory.createFacesMessage(context,
053                SIZE_LIMIT_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, args);
054            throw new ValidatorException(facesMessage);
055          }
056          // Check only a valid file
057          if (file.getSize() > 0 && contentType != null && contentType.length > 0) {
058            boolean found = false;
059            for (String contentTypeStr : contentType) {
060              if (ContentType.valueOf(contentTypeStr).match(ContentType.valueOf(file.getContentType()))) {
061                found = true;
062                break;
063              }
064            }
065            if (!found) {
066              String message;
067              if (contentType.length == 1) {
068                message = contentType[0];
069              } else {
070                message = Arrays.toString(contentType);
071              }
072              Object[] args = {message, component.getId()};
073              FacesMessage facesMessage = MessageFactory.createFacesMessage(context,
074                  CONTENT_TYPE_MESSAGE_ID, FacesMessage.SEVERITY_ERROR, args);
075              throw new ValidatorException(facesMessage);
076            }
077          }
078        }
079      }
080    
081      public int getMaxSize() {
082        return maxSize;
083      }
084    
085      public void setMaxSize(int maxSize) {
086        if (maxSize > 0) {
087          this.maxSize = maxSize;
088        }
089      }
090    
091      public String[] getContentType() {
092        return contentType;
093      }
094    
095      public void setContentType(String[] contentType) {
096        this.contentType = contentType;
097      }
098    
099      public Object saveState(FacesContext context) {
100        Object[] values = new Object[2];
101        values[0] = maxSize;
102        values[1] = contentType;
103        return values;
104      }
105    
106      public void restoreState(FacesContext context, Object state) {
107        Object[] values = (Object[]) state;
108        maxSize = (Integer) values[0];
109        contentType = (String[]) values[1];
110      }
111    
112      public boolean isTransient() {
113        return transientValue;
114      }
115    
116      public void setTransient(boolean newTransientValue) {
117        this.transientValue = newTransientValue;
118      }
119    }