content: 
  package org.opencms.jsp;
  
  import org.opencms.file.CmsObject;
  import org.opencms.flex.CmsFlexController;
  import org.opencms.jsp.util.CmsJspImageBean;
  import org.opencms.loader.CmsImageScaler;
  import org.opencms.main.CmsException;
  import org.opencms.main.CmsLog;
  import org.opencms.staticexport.CmsLinkManager;
  
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.List;
  
  import javax.servlet.ServletRequest;
  import javax.servlet.jsp.JspException;
  
  import org.apache.commons.lang3.StringUtils;
  import org.apache.commons.logging.Log;
  
  /**
   * This tag allows using the OpenCms native image scaling mechanism within JSP.<p>
   *
   * <em>No output is generated by this tag!</em>
   * Instead the tag generates a {@link org.opencms.jsp.util.CmsJspImageBean}.
   * This can be used to further process the selected image
   * with the provided image scaling parameters.<p>
   *
   * The following image formats are supported: BMP, GIF, JPEG, PNG, PNM, TIFF.<p>
   *
   * <em>
   * Note: Picture scaling is by default only enabled for target size with width and height
   * &lt;=1500. The size can be changed in the image scaler configuration in the file
   * <code>opencms-vfs.xml</code> in the body of the tag <code>&lt;loader&gt;</code>. Also other
   * options for the image scaler are set there.
   * </em>
   * <p>
   * This tag is an alternative to the OpenCms standard tag cms:img, providing additional flexibility.
   * This way you can use scaled images for:
   * <ul>
   *   <li>The standard HTML &lt;img&gt;-Tag.</li>
   *   <li>
   *     The HTML 5 &lt;picture&gt;-Tag with multiple sources (hi-DPI variants for retina displays)
   *     for responsive design.
   *   </li>
   *   <li>Further processing a scaled image anyway you want on your JSP.</li>
   * </ul>
   * </em>
   *
   * <p>
   * Example for a simple JSP that uses this tag to obtain information about an image:
   * <code>
   * &lt;%@ taglib prefix=&quot;c&quot; uri=&quot;http://java.sun.com/jsp/jstl/core&quot; %&gt;<br>
   * &lt;%@ taglib prefix=&quot;cms&quot; uri=&quot;http://www.opencms.org/taglib/cms&quot;%&gt;<br>
   *<br>
   * &lt;cms:scaleImage var=&quot;imgBean&quot; src=&quot;/.galleries/samples/09.jpg?__scale=h:385,w:961,cx:42,cy:32,ch:385,cw:961&quot; /&gt;<br>
   * srcUrl: &lt;c:out value=&quot;${imgBean.srcUrl}&quot; /&gt;&lt;br&gt;<br>
   * vfsUri: &lt;c:out value=&quot;${imgBean.vfsUri}&quot; /&gt;&lt;br&gt;<br>
   * scalerParams: &lt;c:out value=&quot;${imgBean.scaler.requestParam}&quot; /&gt;&lt;br&gt;<br>
   * Width: &lt;c:out value=&quot;${imgBean.width}&quot; /&gt;&lt;br&gt;<br>
   * Height: &lt;c:out value=&quot;${imgBean.height}&quot; /&gt;&lt;br&gt;<br>
   * scaledWidth: &lt;c:out value=&quot;${imgBean.scaler.width}&quot; /&gt;&lt;br&gt;<br>
   * scaledHeight: &lt;c:out value=&quot;${imgBean.scaler.height}&quot; /&gt;&lt;br&gt;<br>
   * isScaled: &lt;c:out value=&quot;${imgBean.scaled}&quot; /&gt;&lt;br&gt;<br>
   * </code>
   */
  public class CmsJspTagScaleImage extends CmsJspImageScalerTagSupport {
  
      /** The log object for this class. */
      private static final Log LOG = CmsLog.getLog(CmsJspTagScaleImage.class);
  
      /** Serial version UID required for safe serialization. */
      private static final long serialVersionUID = -6639978110802734737L;
  
      /** List of hi-DPI variant sizes to produce, e.g. 1.3x, 1.5x, 2x, 3x */
      private List<String> m_hiDpiVariantList;
  
      /** Name of the request attribute used to store the created image bean. */
      private String m_var;
  
      /**
       * Creates a new image scaling tag instance.<p>
       */
      public CmsJspTagScaleImage() {
          super();
      }
  
      /**
       * Internal action method to create the scaled image bean.<p>
       *
       * @param cms the cms context
       * @param imageUri the image URI
       * @param targetScaler the target image scaler
       * @param hiDpiVariantList  optional list of hi-DPI variant sizes to produce, e.g. 1.3x, 1.5x, 2x, 3x
       *
       * @return the created ScaledImageBean bean
       *
       * @throws CmsException in case something goes wrong
       */
      public static CmsJspImageBean imageTagAction(
          CmsObject cms,
          String imageUri,
          CmsImageScaler targetScaler,
          List<String> hiDpiVariantList)
      throws CmsException {
  
          CmsJspImageBean image = new CmsJspImageBean(cms, imageUri, targetScaler);
  
          // now handle (preset) hi-DPI variants
          if ((hiDpiVariantList != null) && (hiDpiVariantList.size() > 0)) {
              for (String hiDpiVariant : hiDpiVariantList) {
  
                  CmsJspImageBean hiDpiVersion = image.createHiDpiVariation(hiDpiVariant);
  
                  if (hiDpiVersion != null) {
                      image.addHiDpiImage(hiDpiVariant, hiDpiVersion);
                  }
              }
          }
          return image;
      }
  
      /**
       * Does some cleanup before returning EVAL_PAGE
       *
       * @see javax.servlet.jsp.tagext.Tag#doEndTag()
       */
      @SuppressWarnings("unused")
      @Override
      public int doEndTag() throws JspException {
  
          release();
          return EVAL_PAGE;
      }
  
      /**
       * Handles the Start tag, checks some parameters, uses the CmsImageScaler to create a scaled
       * version of the image (and hi-DPI variants if necessary), stores all information in a
       * image bean and stores it as a request attribute (the name for this attribute is given
       * with the tag attribute "var").
       *
       * @return EVAL_BODY_INCLUDE or SKIP_BODY in case of an unexpected Exception (please consult
       * the OpenCms log file if that happens)
       */
      @Override
      public int doStartTag() {
  
          ServletRequest req = pageContext.getRequest();
  
          // this will always be true if the page is called through OpenCms
          if (CmsFlexController.isCmsRequest(req)) {
  
              try {
                  CmsJspImageBean scaledImage = null;
                  try {
                      CmsFlexController controller = CmsFlexController.getController(req);
                      CmsObject cms = controller.getCmsObject();
                      String src = CmsLinkManager.getAbsoluteUri(m_src, controller.getCurrentRequest().getElementUri());
                      scaledImage = imageTagAction(cms, src, m_scaler, m_hiDpiVariantList);
                  } catch (CmsException e) {
                      // any issue accessing the VFS - just return SKIP_BODY
                      // otherwise template layout will get mixed up with nasty exception messages
                      if (LOG.isWarnEnabled()) {
                          LOG.warn(Messages.get().getBundle().key(Messages.ERR_IMAGE_TAG_VFS_ACCESS_1, m_src), e);
                      }
                  }
                  pageContext.getRequest().setAttribute(m_var, scaledImage);
              } catch (Exception ex) {
                  if (LOG.isErrorEnabled()) {
                      LOG.error(Messages.get().getBundle().key(Messages.ERR_PROCESS_TAG_1, "scaleImage"), ex);
                  }
                  return SKIP_BODY;
              }
          }
          return EVAL_BODY_INCLUDE;
      }
  
      /**
       * Does some cleanup before the tag is released to the tag pool
       *
       * @see javax.servlet.jsp.tagext.Tag#release()
       */
      @Override
      public void release() {
  
          m_hiDpiVariantList = null;
          m_var = null;
          super.release();
      }
  
      /**
       * Sets the String containing a comma separated list of hi-DPI variants to produce line "1.3x,1.5x,2x,3x".<p>
       *
       * Currently in most cases "2x" should suffice to generate an additiona image for retina screens.
       *
       * Please note that since 11.0 the variants are created by lazy initialization, so there is usually no
       * need to use this.<p>
       *
       * @param value comma separated list of hi-DPI variants to produce, e.g. "1.3x,1.5x,2x,3x"
       */
      public void setHiDpiVariants(String value) {
  
          m_hiDpiVariantList = new ArrayList<>(4);
          String[] multipliers = StringUtils.split(value, ',');
          Collections.addAll(m_hiDpiVariantList, multipliers);
      }
  
      /**
       * Sets the name of the variable used for storing the resulting bean.
       *
       * @param value name of the resulting CmsJspScaledImage bean
       */
      public void setVar(String value) {
  
          m_var = value;
      }
  }
  