001 002package org.opencms.jsp; 003 004import org.opencms.file.CmsObject; 005import org.opencms.flex.CmsFlexController; 006import org.opencms.jsp.util.CmsJspImageBean; 007import org.opencms.loader.CmsImageScaler; 008import org.opencms.main.CmsException; 009import org.opencms.main.CmsLog; 010import org.opencms.staticexport.CmsLinkManager; 011 012import java.util.ArrayList; 013import java.util.Collections; 014import java.util.List; 015 016import javax.servlet.ServletRequest; 017import javax.servlet.jsp.JspException; 018 019import org.apache.commons.lang3.StringUtils; 020import org.apache.commons.logging.Log; 021 022/** 023 * This tag allows using the OpenCms native image scaling mechanism within JSP.<p> 024 * 025 * <em>No output is generated by this tag!</em> 026 * Instead the tag generates a {@link org.opencms.jsp.util.CmsJspImageBean}. 027 * This can be used to further process the selected image 028 * with the provided image scaling parameters.<p> 029 * 030 * The following image formats are supported: BMP, GIF, JPEG, PNG, PNM, TIFF.<p> 031 * 032 * <em> 033 * Note: Picture scaling is by default only enabled for target size with width and height 034 * <=1500. The size can be changed in the image scaler configuration in the file 035 * <code>opencms-vfs.xml</code> in the body of the tag <code><loader></code>. Also other 036 * options for the image scaler are set there. 037 * </em> 038 * <p> 039 * This tag is an alternative to the OpenCms standard tag cms:img, providing additional flexibility. 040 * This way you can use scaled images for: 041 * <ul> 042 * <li>The standard HTML <img>-Tag.</li> 043 * <li> 044 * The HTML 5 <picture>-Tag with multiple sources (hi-DPI variants for retina displays) 045 * for responsive design. 046 * </li> 047 * <li>Further processing a scaled image anyway you want on your JSP.</li> 048 * </ul> 049 * </em> 050 * 051 * <p> 052 * Example for a simple JSP that uses this tag to obtain information about an image: 053 * <code> 054 * <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><br> 055 * <%@ taglib prefix="cms" uri="http://www.opencms.org/taglib/cms"%><br> 056 *<br> 057 * <cms:scaleImage var="imgBean" src="/.galleries/samples/09.jpg?__scale=h:385,w:961,cx:42,cy:32,ch:385,cw:961" /><br> 058 * srcUrl: <c:out value="${imgBean.srcUrl}" /><br><br> 059 * vfsUri: <c:out value="${imgBean.vfsUri}" /><br><br> 060 * scalerParams: <c:out value="${imgBean.scaler.requestParam}" /><br><br> 061 * Width: <c:out value="${imgBean.width}" /><br><br> 062 * Height: <c:out value="${imgBean.height}" /><br><br> 063 * scaledWidth: <c:out value="${imgBean.scaler.width}" /><br><br> 064 * scaledHeight: <c:out value="${imgBean.scaler.height}" /><br><br> 065 * isScaled: <c:out value="${imgBean.scaled}" /><br><br> 066 * </code> 067 */ 068public class CmsJspTagScaleImage extends CmsJspImageScalerTagSupport { 069 070 /** The log object for this class. */ 071 private static final Log LOG = CmsLog.getLog(CmsJspTagScaleImage.class); 072 073 /** Serial version UID required for safe serialization. */ 074 private static final long serialVersionUID = -6639978110802734737L; 075 076 /** List of hi-DPI variant sizes to produce, e.g. 1.3x, 1.5x, 2x, 3x */ 077 private List<String> m_hiDpiVariantList; 078 079 /** Name of the request attribute used to store the created image bean. */ 080 private String m_var; 081 082 /** 083 * Creates a new image scaling tag instance.<p> 084 */ 085 public CmsJspTagScaleImage() { 086 super(); 087 } 088 089 /** 090 * Internal action method to create the scaled image bean.<p> 091 * 092 * @param cms the cms context 093 * @param imageUri the image URI 094 * @param targetScaler the target image scaler 095 * @param hiDpiVariantList optional list of hi-DPI variant sizes to produce, e.g. 1.3x, 1.5x, 2x, 3x 096 * 097 * @return the created ScaledImageBean bean 098 * 099 * @throws CmsException in case something goes wrong 100 */ 101 public static CmsJspImageBean imageTagAction( 102 CmsObject cms, 103 String imageUri, 104 CmsImageScaler targetScaler, 105 List<String> hiDpiVariantList) 106 throws CmsException { 107 108 CmsJspImageBean image = new CmsJspImageBean(cms, imageUri, targetScaler); 109 110 // now handle (preset) hi-DPI variants 111 if ((hiDpiVariantList != null) && (hiDpiVariantList.size() > 0)) { 112 for (String hiDpiVariant : hiDpiVariantList) { 113 114 CmsJspImageBean hiDpiVersion = image.createHiDpiVariation(hiDpiVariant); 115 116 if (hiDpiVersion != null) { 117 image.addHiDpiImage(hiDpiVariant, hiDpiVersion); 118 } 119 } 120 } 121 return image; 122 } 123 124 /** 125 * Does some cleanup before returning EVAL_PAGE 126 * 127 * @see javax.servlet.jsp.tagext.Tag#doEndTag() 128 */ 129 @SuppressWarnings("unused") 130 @Override 131 public int doEndTag() throws JspException { 132 133 release(); 134 return EVAL_PAGE; 135 } 136 137 /** 138 * Handles the Start tag, checks some parameters, uses the CmsImageScaler to create a scaled 139 * version of the image (and hi-DPI variants if necessary), stores all information in a 140 * image bean and stores it as a request attribute (the name for this attribute is given 141 * with the tag attribute "var"). 142 * 143 * @return EVAL_BODY_INCLUDE or SKIP_BODY in case of an unexpected Exception (please consult 144 * the OpenCms log file if that happens) 145 */ 146 @Override 147 public int doStartTag() { 148 149 ServletRequest req = pageContext.getRequest(); 150 151 // this will always be true if the page is called through OpenCms 152 if (CmsFlexController.isCmsRequest(req)) { 153 154 try { 155 CmsJspImageBean scaledImage = null; 156 try { 157 CmsFlexController controller = CmsFlexController.getController(req); 158 CmsObject cms = controller.getCmsObject(); 159 String src = CmsLinkManager.getAbsoluteUri(m_src, controller.getCurrentRequest().getElementUri()); 160 scaledImage = imageTagAction(cms, src, m_scaler, m_hiDpiVariantList); 161 } catch (CmsException e) { 162 // any issue accessing the VFS - just return SKIP_BODY 163 // otherwise template layout will get mixed up with nasty exception messages 164 if (LOG.isWarnEnabled()) { 165 LOG.warn(Messages.get().getBundle().key(Messages.ERR_IMAGE_TAG_VFS_ACCESS_1, m_src), e); 166 } 167 } 168 pageContext.getRequest().setAttribute(m_var, scaledImage); 169 } catch (Exception ex) { 170 if (LOG.isErrorEnabled()) { 171 LOG.error(Messages.get().getBundle().key(Messages.ERR_PROCESS_TAG_1, "scaleImage"), ex); 172 } 173 return SKIP_BODY; 174 } 175 } 176 return EVAL_BODY_INCLUDE; 177 } 178 179 /** 180 * Does some cleanup before the tag is released to the tag pool 181 * 182 * @see javax.servlet.jsp.tagext.Tag#release() 183 */ 184 @Override 185 public void release() { 186 187 m_hiDpiVariantList = null; 188 m_var = null; 189 super.release(); 190 } 191 192 /** 193 * Sets the String containing a comma separated list of hi-DPI variants to produce line "1.3x,1.5x,2x,3x".<p> 194 * 195 * Currently in most cases "2x" should suffice to generate an additiona image for retina screens. 196 * 197 * Please note that since 11.0 the variants are created by lazy initialization, so there is usually no 198 * need to use this.<p> 199 * 200 * @param value comma separated list of hi-DPI variants to produce, e.g. "1.3x,1.5x,2x,3x" 201 */ 202 public void setHiDpiVariants(String value) { 203 204 m_hiDpiVariantList = new ArrayList<>(4); 205 String[] multipliers = StringUtils.split(value, ','); 206 Collections.addAll(m_hiDpiVariantList, multipliers); 207 } 208 209 /** 210 * Sets the name of the variable used for storing the resulting bean. 211 * 212 * @param value name of the resulting CmsJspScaledImage bean 213 */ 214 public void setVar(String value) { 215 216 m_var = value; 217 } 218}