Coverage Report - org.apache.tapestry.contrib.services.impl.RoundedCornerService
 
Classes in this File Line Coverage Branch Coverage Complexity
RoundedCornerService
0%
0/97
0%
0/32
3
 
 1  
 package org.apache.tapestry.contrib.services.impl;
 2  
 
 3  
 import org.apache.commons.logging.Log;
 4  
 import org.apache.hivemind.util.Defense;
 5  
 import org.apache.tapestry.IRequestCycle;
 6  
 import org.apache.tapestry.engine.IEngineService;
 7  
 import org.apache.tapestry.engine.ILink;
 8  
 import org.apache.tapestry.error.RequestExceptionReporter;
 9  
 import org.apache.tapestry.services.LinkFactory;
 10  
 import org.apache.tapestry.services.ServiceConstants;
 11  
 import org.apache.tapestry.util.ContentType;
 12  
 import org.apache.tapestry.web.WebRequest;
 13  
 import org.apache.tapestry.web.WebResponse;
 14  
 
 15  
 import javax.imageio.ImageIO;
 16  
 import javax.servlet.http.HttpServletResponse;
 17  
 import java.awt.image.BufferedImage;
 18  
 import java.io.ByteArrayOutputStream;
 19  
 import java.io.IOException;
 20  
 import java.io.OutputStream;
 21  
 import java.util.HashMap;
 22  
 import java.util.Map;
 23  
 
 24  
 /**
 25  
  * Provides generated rounded corner images in a similar use / fashion as
 26  
  * outlined here: <a href="http://xach.livejournal.com/95656.html">google's own cornershop</a>.
 27  
  */
 28  0
 public class RoundedCornerService implements IEngineService {
 29  
 
 30  
     public static final String SERVICE_NAME = "rounded";
 31  
 
 32  
     public static final String PARM_COLOR = "c";
 33  
     public static final String PARM_BACKGROUND_COLOR = "bc";
 34  
     public static final String PARM_WIDTH = "w";
 35  
     public static final String PARM_HEIGHT = "h";
 36  
     public static final String PARM_ANGLE = "a";
 37  
 
 38  
     public static final String PARM_SHADOW_WIDTH ="sw";
 39  
     public static final String PARM_SHADOW_OPACITY ="o";
 40  
     public static final String PARM_SHADOW_SIDE = "s";
 41  
 
 42  
     public static final String PARM_WHOLE_SHADOW = "shadow";
 43  
     public static final String PARM_ARC_HEIGHT = "ah";
 44  
     public static final String PARM_ARC_WIDTH = "aw";
 45  
 
 46  
     private static final long MONTH_SECONDS = 60 * 60 * 24 * 30;
 47  
 
 48  0
     private static final long EXPIRES = System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000L;
 49  
 
 50  
     private RequestExceptionReporter _exceptionReporter;
 51  
 
 52  
     private LinkFactory _linkFactory;
 53  
 
 54  
     private WebRequest _request;
 55  
 
 56  
     private WebResponse _response;
 57  
 
 58  0
     private RoundedCornerGenerator _generator = new RoundedCornerGenerator();
 59  
 
 60  
     // holds pre-built binaries for previously generated colors
 61  0
     private Map _imageCache = new HashMap();
 62  
 
 63  
     private Log _log;
 64  
 
 65  
     /** The ImageIO format name to encode images in that don't need alpha transparency */
 66  0
     private String _nonTransparentFormatName = "gif";
 67  
 
 68  
     public void initialize()
 69  
     {
 70  0
         String[] names = ImageIO.getWriterFormatNames();
 71  
 
 72  0
         boolean supportsGif = false;
 73  
         
 74  0
         for (int i=0; i < names.length; i++)
 75  
         {
 76  0
             if (names[i].toLowerCase().equals("gif"))
 77  
             {
 78  0
                 supportsGif = true;
 79  0
                 break;
 80  
             }
 81  
         }
 82  
 
 83  0
         if (!supportsGif)
 84  
         {
 85  0
             _nonTransparentFormatName = "jpeg";
 86  
         }
 87  0
     }
 88  
 
 89  
     public ILink getLink(boolean post, Object parameter)
 90  
     {
 91  0
         Defense.notNull(parameter, "parameter");
 92  0
         Defense.isAssignable(parameter, Object[].class, "parameter");
 93  
         
 94  0
         Object[] parms = (Object[]) parameter;
 95  
         
 96  0
         Map parameters = new HashMap();
 97  0
         parameters.put(ServiceConstants.SERVICE, getName());
 98  0
         parameters.put(ServiceConstants.PARAMETER, parms);
 99  
         
 100  0
         return _linkFactory.constructLink(this, post, parameters, false);
 101  
     }
 102  
 
 103  
     public void service(IRequestCycle cycle)
 104  
             throws IOException
 105  
     {
 106  0
         if (_request.getHeader("If-Modified-Since") != null)
 107  
         {
 108  0
             _response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
 109  0
             return;
 110  
         }
 111  
 
 112  0
         String color = cycle.getParameter(PARM_COLOR);
 113  0
         String bgColor = cycle.getParameter(PARM_BACKGROUND_COLOR);
 114  0
         int width = getIntParam(cycle.getParameter(PARM_WIDTH));
 115  0
         int height = getIntParam(cycle.getParameter(PARM_HEIGHT));
 116  0
         String angle = cycle.getParameter(PARM_ANGLE);
 117  
         
 118  0
         int shadowWidth = getIntParam(cycle.getParameter(PARM_SHADOW_WIDTH));
 119  0
         float shadowOpacity = getFloatParam(cycle.getParameter(PARM_SHADOW_OPACITY));
 120  0
         String side = cycle.getParameter(PARM_SHADOW_SIDE);
 121  
 
 122  0
         boolean wholeShadow = Boolean.valueOf(cycle.getParameter(PARM_WHOLE_SHADOW)).booleanValue();
 123  0
         float arcWidth = getFloatParam(cycle.getParameter(PARM_ARC_WIDTH));
 124  0
         float arcHeight = getFloatParam(cycle.getParameter(PARM_ARC_HEIGHT));
 125  
 
 126  0
         String hashKey = color + bgColor + width + height + angle + shadowWidth + shadowOpacity + side + wholeShadow;
 127  
 
 128  0
         ByteArrayOutputStream bo = null;
 129  
         
 130  
         try {
 131  
             
 132  0
             String type = (bgColor != null) ? _nonTransparentFormatName : "png";
 133  
 
 134  0
             byte[] data = (byte[])_imageCache.get(hashKey);
 135  0
             if (data != null)
 136  
             {
 137  0
                 writeImageResponse(data, type);
 138  
                 return;
 139  
             }
 140  
 
 141  0
             BufferedImage image = null;
 142  
 
 143  0
             if (wholeShadow)
 144  
             {
 145  0
                 image = _generator.buildShadow(color, bgColor, width, height, arcWidth, arcHeight, shadowWidth, shadowOpacity);
 146  0
             } else if (side != null)
 147  
             {
 148  0
                 image = _generator.buildSideShadow(side, shadowWidth, shadowOpacity);
 149  
             } else
 150  
             {
 151  0
                 image = _generator.buildCorner(color, bgColor, width, height, angle, shadowWidth, shadowOpacity);
 152  
             }
 153  
 
 154  0
             bo = new ByteArrayOutputStream();
 155  
 
 156  0
             boolean success = ImageIO.write(image, type, bo);
 157  
 
 158  0
             data = bo.toByteArray();
 159  
 
 160  0
             if (!success || data == null || data.length < 1)
 161  
             {
 162  0
                 _log.error("Image generated had zero length byte array or failed to convert from parameters of:\n"
 163  
                            + "[color:" + color + ", bgColor:" + bgColor
 164  
                            + ", width:" + width + ", height:" + height
 165  
                            + ", angle:" + angle + ", shadowWidth:" + shadowWidth
 166  
                            + ", shadowOpacity:" + shadowOpacity + ", side:" + side
 167  
                            + ", wholeShadow: " + wholeShadow + ", arcWidth: " + arcWidth
 168  
                            + ", arcHeight:" + arcHeight + "\n image: " + image);
 169  
 
 170  0
                 _response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
 171  
                 return;
 172  
             }
 173  
 
 174  0
             _imageCache.put(hashKey, data);
 175  
 
 176  0
             writeImageResponse(data, type);
 177  
             
 178  0
         } catch (IOException eof)
 179  
         {
 180  
             // ignored / expected exceptions happen when browser prematurely abandons connections - IE does this a lot
 181  0
         } catch (Throwable ex) {
 182  
 
 183  0
             ex.printStackTrace();
 184  0
             _exceptionReporter.reportRequestException("Error creating image.", ex);
 185  
         } finally {
 186  0
             try {
 187  0
                 if (bo != null) {
 188  0
                     bo.close();
 189  
                 }
 190  0
             } catch (Throwable t) {
 191  
                 // ignore
 192  0
             }
 193  
 
 194  0
         }
 195  0
     }
 196  
 
 197  
     void writeImageResponse(byte[] data, String type)
 198  
     throws Exception
 199  
     {
 200  0
         OutputStream os = null;
 201  
 
 202  
         try {
 203  0
             _response.setDateHeader("Expires", EXPIRES);
 204  0
             _response.setHeader("Cache-Control", "public, max-age=" + (MONTH_SECONDS * 3));
 205  0
             _response.setContentLength(data.length);
 206  
 
 207  0
             os = _response.getOutputStream(new ContentType("image/" + type));
 208  
 
 209  0
             os.write(data);
 210  
 
 211  
         }  finally {
 212  0
             try {
 213  0
                 if (os != null) {
 214  0
                     os.flush();
 215  0
                     os.close();
 216  
                 }
 217  0
             } catch (Throwable t) {
 218  
                 // ignore
 219  0
             }
 220  0
         }
 221  0
     }
 222  
 
 223  
     private int getIntParam(String value)
 224  
     {
 225  0
         if (value == null)
 226  0
             return -1;
 227  
         
 228  0
         return Integer.valueOf(value).intValue();
 229  
     }
 230  
 
 231  
     private float getFloatParam(String value)
 232  
     {
 233  0
         if (value == null)
 234  0
             return -1f;
 235  
         
 236  0
         return Float.valueOf(value).floatValue();
 237  
     }
 238  
 
 239  
     public String getName()
 240  
     {
 241  0
         return SERVICE_NAME;
 242  
     }
 243  
 
 244  
     /* Injected */
 245  
     public void setExceptionReporter(RequestExceptionReporter exceptionReporter)
 246  
     {
 247  0
         _exceptionReporter = exceptionReporter;
 248  0
     }
 249  
 
 250  
     /* Injected */
 251  
     public void setLinkFactory(LinkFactory linkFactory)
 252  
     {
 253  0
         _linkFactory = linkFactory;
 254  0
     }
 255  
 
 256  
     /* Injected */
 257  
     public void setRequest(WebRequest request)
 258  
     {
 259  0
         _request = request;
 260  0
     }
 261  
 
 262  
     /* Injected */
 263  
     public void setResponse(WebResponse response)
 264  
     {
 265  0
         _response = response;
 266  0
     }
 267  
 
 268  
     public void setLog(Log log)
 269  
     {
 270  0
         _log = log;
 271  0
     }
 272  
 }