Coverage Report - org.apache.tapestry.contrib.services.impl.RoundedCornerService
 
Classes in this File Line Coverage Branch Coverage Complexity
RoundedCornerService
0% 
0% 
2.636
 
 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  
     public ILink getLink(boolean post, Object parameter)
 66  
     {
 67  0
         Defense.notNull(parameter, "parameter");
 68  0
         Defense.isAssignable(parameter, Object[].class, "parameter");
 69  
         
 70  0
         Object[] parms = (Object[]) parameter;
 71  
         
 72  0
         Map parameters = new HashMap();
 73  0
         parameters.put(ServiceConstants.SERVICE, getName());
 74  0
         parameters.put(ServiceConstants.PARAMETER, parms);
 75  
         
 76  0
         return _linkFactory.constructLink(this, post, parameters, false);
 77  
     }
 78  
 
 79  
     public void service(IRequestCycle cycle)
 80  
             throws IOException
 81  
     {
 82  0
         if (_request.getHeader("If-Modified-Since") != null)
 83  
         {
 84  0
             _response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
 85  0
             return;
 86  
         }
 87  
 
 88  0
         String color = cycle.getParameter(PARM_COLOR);
 89  0
         String bgColor = cycle.getParameter(PARM_BACKGROUND_COLOR);
 90  0
         int width = getIntParam(cycle.getParameter(PARM_WIDTH));
 91  0
         int height = getIntParam(cycle.getParameter(PARM_HEIGHT));
 92  0
         String angle = cycle.getParameter(PARM_ANGLE);
 93  
         
 94  0
         int shadowWidth = getIntParam(cycle.getParameter(PARM_SHADOW_WIDTH));
 95  0
         float shadowOpacity = getFloatParam(cycle.getParameter(PARM_SHADOW_OPACITY));
 96  0
         String side = cycle.getParameter(PARM_SHADOW_SIDE);
 97  
 
 98  0
         boolean wholeShadow = Boolean.valueOf(cycle.getParameter(PARM_WHOLE_SHADOW)).booleanValue();
 99  0
         float arcWidth = getFloatParam(cycle.getParameter(PARM_ARC_WIDTH));
 100  0
         float arcHeight = getFloatParam(cycle.getParameter(PARM_ARC_HEIGHT));
 101  
 
 102  0
         String hashKey = color + bgColor + width + height + angle + shadowWidth + shadowOpacity + side + wholeShadow;
 103  
 
 104  0
         ByteArrayOutputStream bo = null;
 105  
         
 106  
         try {
 107  
             
 108  0
             String type = (bgColor != null) ? "gif" : "png";
 109  
 
 110  0
             byte[] data = (byte[])_imageCache.get(hashKey);
 111  0
             if (data != null)
 112  
             {
 113  0
                 writeImageResponse(data, type);
 114  
                 return;
 115  
             }
 116  
 
 117  0
             BufferedImage image = null;
 118  
 
 119  0
             if (wholeShadow)
 120  
             {
 121  0
                 image = _generator.buildShadow(color, bgColor, width, height, arcWidth, arcHeight, shadowWidth, shadowOpacity);
 122  0
             } else if (side != null)
 123  
             {
 124  0
                 image = _generator.buildSideShadow(side, shadowWidth, shadowOpacity);
 125  
             } else
 126  
             {
 127  0
                 image = _generator.buildCorner(color, bgColor, width, height, angle, shadowWidth, shadowOpacity);
 128  
             }
 129  
 
 130  0
             bo = new ByteArrayOutputStream();
 131  
 
 132  0
             ImageIO.write(image, type, bo);
 133  
 
 134  0
             data = bo.toByteArray();
 135  
 
 136  0
             if (data == null || data.length < 1)
 137  
             {
 138  0
                 _log.error("Image generated had zero length byte array from parameters of:\n"
 139  
                            + "[color:" + color + ", bgColor:" + bgColor
 140  
                            + ", width:" + width + ", height:" + height
 141  
                            + ", angle:" + angle + ", shadowWidth:" + shadowWidth
 142  
                            + ", shadowOpacity:" + shadowOpacity + ", side:" + side
 143  
                            + ", wholeShadow: " + wholeShadow + ", arcWidth: " + arcWidth
 144  
                            + ", arcHeight:" + arcHeight + "\n image: " + image);
 145  
 
 146  0
                 _response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
 147  
                 return;
 148  
             }
 149  
 
 150  0
             _imageCache.put(hashKey, data);
 151  
 
 152  0
             writeImageResponse(data, type);
 153  
             
 154  0
         } catch (IOException eof)
 155  
         {
 156  
             // ignored / expected exceptions happen when browser prematurely abandons connections - IE does this a lot
 157  0
         } catch (Throwable ex) {
 158  
 
 159  0
             ex.printStackTrace();
 160  0
             _exceptionReporter.reportRequestException("Error creating image.", ex);
 161  
         } finally {
 162  0
             try {
 163  0
                 if (bo != null) {
 164  0
                     bo.close();
 165  
                 }
 166  0
             } catch (Throwable t) {
 167  
                 // ignore
 168  0
             }
 169  
 
 170  0
         }
 171  0
     }
 172  
 
 173  
     void writeImageResponse(byte[] data, String type)
 174  
     throws Exception
 175  
     {
 176  0
         OutputStream os = null;
 177  
 
 178  
         try {
 179  0
             _response.setDateHeader("Expires", EXPIRES);
 180  0
             _response.setHeader("Cache-Control", "public, max-age=" + (MONTH_SECONDS * 3));
 181  0
             _response.setContentLength(data.length);
 182  
 
 183  0
             os = _response.getOutputStream(new ContentType("image/" + type));
 184  
 
 185  0
             os.write(data);
 186  
 
 187  
         }  finally {
 188  0
             try {
 189  0
                 if (os != null) {
 190  0
                     os.flush();
 191  0
                     os.close();
 192  
                 }
 193  0
             } catch (Throwable t) {
 194  
                 // ignore
 195  0
             }
 196  0
         }
 197  0
     }
 198  
 
 199  
     private int getIntParam(String value)
 200  
     {
 201  0
         if (value == null)
 202  0
             return -1;
 203  
         
 204  0
         return Integer.valueOf(value).intValue();
 205  
     }
 206  
 
 207  
     private float getFloatParam(String value)
 208  
     {
 209  0
         if (value == null)
 210  0
             return -1f;
 211  
         
 212  0
         return Float.valueOf(value).floatValue();
 213  
     }
 214  
 
 215  
     public String getName()
 216  
     {
 217  0
         return SERVICE_NAME;
 218  
     }
 219  
 
 220  
     /* Injected */
 221  
     public void setExceptionReporter(RequestExceptionReporter exceptionReporter)
 222  
     {
 223  0
         _exceptionReporter = exceptionReporter;
 224  0
     }
 225  
 
 226  
     /* Injected */
 227  
     public void setLinkFactory(LinkFactory linkFactory)
 228  
     {
 229  0
         _linkFactory = linkFactory;
 230  0
     }
 231  
 
 232  
     /* Injected */
 233  
     public void setRequest(WebRequest request)
 234  
     {
 235  0
         _request = request;
 236  0
     }
 237  
 
 238  
     /* Injected */
 239  
     public void setResponse(WebResponse response)
 240  
     {
 241  0
         _response = response;
 242  0
     }
 243  
 
 244  
     public void setLog(Log log)
 245  
     {
 246  0
         _log = log;
 247  0
     }
 248  
 }