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