Package com.aurifa.struts2.plugin.image.validator

Source Code of com.aurifa.struts2.plugin.image.validator.CombinedImageValidator

/**
*
*/
package com.aurifa.struts2.plugin.image.validator;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.opensymphony.xwork2.validator.ValidationException;
import com.opensymphony.xwork2.validator.validators.FieldValidatorSupport;

/**
* <p>
* <!-- START SNIPPET: javadoc --> This is an image validator. You can use this
* to validate images by passing urls or uploaded files. For now, you can
* specify:
* <ul>
* <li>min/max dimensions</li>
* <li>the mimetype (JPEG, GIF, BMP, PCX, PNG, IFF, RAS, PBM, PGM, PPM and PSD
* formats are supported)</li>
* <li>max filesize in bytes</li>
* <li>if uploads and/or remote images (specified by url) are allowed</li>
* </ul>
* This class uses the excellent ImageInfo (written by Marco Schmidt), which
* allows us to validate the image without fully loading it (when using urls).
* <!-- END SNIPPET: javadoc -->
* </p>
* <p>
* Possible parameters for this validator:
*
* <!-- START SNIPPET: parameters -->
* <ul>
* <li>maxWidth - in pixels</li>
* <li>minWidth - in pixels</li>
* <li>maxHeight - in pixels</li>
* <li>minHeight - in pixels</li>
* <li>maxSize - in bytes</li>
* <li>remote - boolean (default false)</li>
* <li>upload - boolean (default false)</li>
* <li>allowedMimeTypes - comma seperated list of allowed mime types</li>
* </ul>
* <!-- END SNIPPET: parameters -->
* </p>
* <p>
* <!-- START SNIPPET: example --> Here's an example to validate an avatar for a
* standard webbased forum:
*
* <pre>
*       &lt;field name=&quot;avatar&quot;&gt; 
*            &lt;field-validator type=&quot;image&quot;&gt;
*                &lt;param name=&quot;maxWidth&quot;&gt;80&lt;/param&gt;
*                   &lt;param name=&quot;maxHeight&quot;&gt;80&lt;/param&gt;
*                   &lt;param name=&quot;minWidth&quot;&gt;40&lt;/param&gt;
*                   &lt;param name=&quot;minHeight&quot;&gt;40&lt;/param&gt;
*                   &lt;param name=&quot;maxSize&quot;&gt;40000&lt;/param&gt;
*                   &lt;param name=&quot;remote&quot;&gt;false&lt;/param&gt; &lt;!--only uploads allowed !--&gt;
*                   &lt;param name=&quot;allowedMimeTypes&quot;&gt;image/gif,image/jpg,image/png&lt;/param&gt;
*                   &lt;message key=&quot;uploaded.avatar&quot; /&gt;
*              &lt;/field-validator&gt;
*       &lt;/field&gt;
* </pre>
*
* </p>
* <!-- END SNIPPET: example --> <!-- START SNIPPET: error -->
* <p>
* The keys you should be using for your localised error reporting are always
* made of the original key you provided in the validator + the possible error.
* So, if you have a key named 'uploaded.avatar' (=key_name), and the image
* would be too wide, you would get a message key back named
* 'uploaded.avatar.invalid.width.max'
*
* The other keys:
* <ul>
* <li>key_name + 'invalid': the provided image was not valid</li>
* <li>key_name + 'invalid.location': the remote image location should start with http://</li>
* <li>key_name + 'invalid.notallowed': the requested action (remote or fileupload) is not allowed</li>
* <li>key_name + 'invalid.notfound': the image could not be located</li>
* <li>key_name + 'invalid.mime': the mimetype of the image was not listed in
* the allowedMimeTypes parameter</li>
* <li>key_name + 'invalid.width.min': the image's width didn't meet the
* required minimal width in pixels</li>
* <li>key_name + 'invalid.width.max': the image's width didn't meet the
* required maximal width in pixels</li>
* <li>key_name + 'invalid.height.min': the image's height didn't meet the
* required minimal height in pixels</li>
* <li>key_name + 'invalid.height.max': the image's height didn't meet the
* required maximal height in pixels</li>
* <li>key_name + 'invalid.size': the image file size was too big</li>
*
* </ul>
* <!-- END SNIPPET: error -->
* </p>
*
* @author <a href="mailto:philip.luppens@gmail.com">Philip Luppens</a>
* @version 1.0
*/
public class CombinedImageValidator extends FieldValidatorSupport {

  private final static Log logger = LogFactory
      .getLog(CombinedImageValidator.class);

  private Integer maxWidth, maxHeight;

  private Integer minWidth, minHeight;

  private Long maxSize;

  private int imageWidth, imageHeight, imageSize;

  private String imageMimeType;
 
  private boolean remote, upload = false;

  private List allowed;

  private ImageInfo ii;

  // tokens of mimetypes, seperated by commas
  private String allowedMimeTypes;

  /*
   * (non-Javadoc)
   *
   * @see com.opensymphony.xwork.validator.Validator#validate(java.lang.Object)
   */
  public void validate(Object object) throws ValidationException {
    allowed = tokenizeMimeTypes();
    String fieldName = getFieldName();
   
    Object fieldValue = getFieldValue(fieldName, object);
   
    if (fieldValue != null) {

      Object[] images;
      if (fieldValue.getClass().isArray()) {
        images = (Object[]) fieldValue;
      } else {
        images = new Object[] { fieldValue };
      }
      for (int i = 0; i < images.length; i++) {
        if (logger.isDebugEnabled()) {
          logger.debug("Image: " + images[i]);
        }
      }
      for (int i = 0; i < images.length; i++) {
        ii = new ImageInfo();
        if (logger.isDebugEnabled()) {
          logger.debug("Validating Image: " + images[i]);
        }
        if (!isValid(images[i])) {
          addFieldError(fieldName, object);
          return;
        }
      }

    } else {
      logger.warn("Field value not found");
      addFieldError(fieldName, object);
      return;
    }
  }

  /*
   * Simply tokenize the allowedMimeTypes String from our validator
   * parameters.
   *
   */
  private final List tokenizeMimeTypes() {
    // make sure we don't get a npe
    if (allowedMimeTypes == null) {
      return new ArrayList();
    }
    StringTokenizer st = new StringTokenizer(allowedMimeTypes, ",");
    List<String> types = new ArrayList<String>();
    while (st.hasMoreTokens()) {
      types.add((st.nextToken()).trim());
    }
    return types;
  }

  /**
   * This method will try to validate an image Object. Be aware that this
   * could mean it is a String with the location or an uploaded File.
   *
   * @param image
   * @return
   * @throws ValidationException
   */
  public boolean isValid(Object image) throws ValidationException {

    if (image instanceof String) {
      if (!remote){
        //we're not allowed to pass remote images
        setMessageKey(getMessageKey() + ".invalid.notallowed");
        // no need to continue
        return false;
      }
      // ah, this is a remote file location
      if (((String) image).toLowerCase().startsWith("http://")) {

        URL url = null;
        try {
          url = new URL((String) image);
          // set up our image info stream
          ii.setInput(url.openStream());
        } catch (Exception e) {
          logger.error(e);
          setMessageKey(getMessageKey() + ".invalid.notfound");
          // no need to continue
          return false;
        }
        // image's filesize is checked by requesting the content
        // length header
        try {
          imageSize = url.openConnection().getContentLength();
        } catch (Exception e) {
          logger.error(e);
          // could not check the content length ?
          setMessageKey(getMessageKey() + ".invalid.size");
          // no need to continue
          return false;
        }
      } else {
        //non-remote urls are not accepted
        setMessageKey(getMessageKey() + ".invalid.location");
        return false;
      }

    } else if (image instanceof File) {
      if (!upload){
        //we're not allowed to upload images
        setMessageKey(getMessageKey() + ".invalid.notallowed");
        // no need to continue
        return false;
      }
     
      // file upload
      File i = (File) image;
      try {
        ii.setInput(new FileInputStream(i));
      } catch (FileNotFoundException e) {
        // could not find the file ? Highly unlikely, but it *could*
        // happen
        // This is a critical exception, so we better throw a
        // ValidationException
        // no need to continue
        logger.error(e);
        throw new ValidationException("Could not open inputstream for "
            + i);
      }
      imageSize = (int) i.length();
    } else {
      // it's .. uhm, something else. A football ? A hot blonde's address
      // ? Fourty Two ? We'll never know ..
      throw new ValidationException(
          "Invalid object. Expect either a String or File object. Object is "
              + image.getClass().getName());
    }
    if (!ii.check()) {
      setMessageKey(getMessageKey() + ".invalid");
      return false;
    }
    // check if the mimetype is allowed
    imageMimeType = ii.getMimeType();
    if (!allowed.contains(imageMimeType)) {
      if (logger.isDebugEnabled()) {
        logger.debug("Invalid mimetype: " + ii.getMimeType());
      }
      setMessageKey(getMessageKey() + ".invalid.mime");
      return false;
    }
    imageWidth = ii.getWidth();
    imageHeight = ii.getHeight();

    // not entirely sure about the best error reporting way ..

    if (maxWidth != null && ii.getWidth() > maxWidth.intValue()) {
      if (logger.isDebugEnabled()) {
        logger.debug("Invalid width: " + ii.getWidth());
      }
      setMessageKey(getMessageKey() + ".invalid.width.max");
      return false;
    }
    if (minWidth != null && ii.getWidth() < minWidth.intValue()) {
      if (logger.isDebugEnabled()) {
        logger.debug("Invalid width: " + ii.getWidth());
      }
      setMessageKey(getMessageKey() + ".invalid.width.min");
      return false;
    }
    if (maxHeight != null && ii.getHeight() > maxHeight.intValue()) {
      if (logger.isDebugEnabled()) {
        logger.debug("Invalid height: " + ii.getHeight());
      }
      setMessageKey(getMessageKey() + ".invalid.height.max");
      return false;
    }
    if (minHeight != null && ii.getHeight() < minHeight.intValue()) {
      if (logger.isDebugEnabled()) {
        logger.debug("Invalid height: " + ii.getHeight());
      }
      setMessageKey(getMessageKey() + ".invalid.height.min");
      return false;
    }
    if (maxSize != null && imageSize > maxSize.longValue()) {
      if (logger.isDebugEnabled()) {
        logger.debug("Invalid size: " + imageSize);
      }
      setMessageKey(getMessageKey() + ".invalid.size");
      return false;
    }
    return true;
  }

  public Integer getMaxHeight() {
    return maxHeight;
  }

  public void setMaxHeight(Integer maxHeight) {
    this.maxHeight = maxHeight;
  }

  public Long getMaxSize() {
    return maxSize;
  }

  public void setMaxSize(Long maxSize) {
    this.maxSize = maxSize;
  }

  public Integer getMaxWidth() {
    return maxWidth;
  }

  public void setMaxWidth(Integer maxWidth) {
    this.maxWidth = maxWidth;
  }

  public String getAllowedMimeTypes() {
    return allowedMimeTypes;
  }

  public void setAllowedMimeTypes(String allowedMimeTypes) {
    this.allowedMimeTypes = allowedMimeTypes;
  }

  // image properties after processing
  public int getImageHeight() {
    return imageHeight;
  }

  public String getImageMimeType() {
    return imageMimeType;
  }

  public int getImageSize() {
    return imageSize;
  }

  public int getImageWidth() {
    return imageWidth;
  }

  public Integer getMinHeight() {
    return minHeight;
  }

  public void setMinHeight(Integer minHeight) {
    this.minHeight = minHeight;
  }

  public Integer getMinWidth() {
    return minWidth;
  }

  public void setMinWidth(Integer minWidth) {
    this.minWidth = minWidth;
  }

  /**
   * @return Returns the remote.
   */
  public boolean isRemote() {
    return remote;
  }

  /**
   * @param remote The remote to set.
   */
  public void setRemote(boolean remote) {
    this.remote = remote;
  }

  /**
   * @return Returns the upload.
   */
  public boolean isUpload() {
    return upload;
  }

  /**
   * @param upload The upload to set.
   */
  public void setUpload(boolean upload) {
    this.upload = upload;
  }

}
TOP

Related Classes of com.aurifa.struts2.plugin.image.validator.CombinedImageValidator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.