Clover coverage report - Code Coverage for tapestry release 4.0-alpha-3
Coverage timestamp: Mon May 16 2005 09:05:49 EDT
file stats: LOC: 128   Methods: 5
NCLOC: 79   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
ResourceDigestSourceImpl.java 100% 93.1% 100% 95%
coverage coverage
 1   
 // Copyright 2005 The Apache Software Foundation
 2   
 //
 3   
 // Licensed under the Apache License, Version 2.0 (the "License");
 4   
 // you may not use this file except in compliance with the License.
 5   
 // You may obtain a copy of the License at
 6   
 //
 7   
 //     http://www.apache.org/licenses/LICENSE-2.0
 8   
 //
 9   
 // Unless required by applicable law or agreed to in writing, software
 10   
 // distributed under the License is distributed on an "AS IS" BASIS,
 11   
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12   
 // See the License for the specific language governing permissions and
 13   
 // limitations under the License.
 14   
 
 15   
 package org.apache.tapestry.asset;
 16   
 
 17   
 import java.io.BufferedInputStream;
 18   
 import java.io.IOException;
 19   
 import java.io.InputStream;
 20   
 import java.net.URL;
 21   
 import java.security.MessageDigest;
 22   
 import java.util.HashMap;
 23   
 import java.util.Map;
 24   
 
 25   
 import org.apache.commons.codec.binary.Hex;
 26   
 import org.apache.hivemind.ApplicationRuntimeException;
 27   
 import org.apache.hivemind.ClassResolver;
 28   
 import org.apache.hivemind.util.IOUtils;
 29   
 import org.apache.tapestry.event.ResetEventListener;
 30   
 
 31   
 /**
 32   
  * Implementation of {@link org.apache.tapestry.asset.ResourceDigestSource} that calculates an
 33   
  * DIGEST checksum digest and converts it to a string of hex digits.
 34   
  * 
 35   
  * @author Howard M. Lewis Ship
 36   
  * @since 4.0
 37   
  */
 38   
 public class ResourceDigestSourceImpl implements ResourceDigestSource, ResetEventListener
 39   
 {
 40   
     private ClassResolver _classResolver;
 41   
 
 42   
     private static final int BUFFER_SIZE = 5000;
 43   
 
 44   
     /**
 45   
      * Map keyed on resource path of DIGEST checksum (as a string).
 46   
      */
 47   
 
 48   
     private final Map _cache = new HashMap();
 49   
 
 50  64
     public synchronized String getDigestForResource(String resourcePath)
 51   
     {
 52  64
         String result = (String) _cache.get(resourcePath);
 53   
 
 54  64
         if (result == null)
 55   
         {
 56  37
             result = computeMD5(resourcePath);
 57  36
             _cache.put(resourcePath, result);
 58   
         }
 59   
 
 60  63
         return result;
 61   
     }
 62   
 
 63  1
     public synchronized void resetEventDidOccur()
 64   
     {
 65  1
         _cache.clear();
 66   
     }
 67   
 
 68  37
     private String computeMD5(String resourcePath)
 69   
     {
 70  37
         URL url = _classResolver.getResource(resourcePath);
 71   
 
 72  37
         if (url == null)
 73  1
             throw new ApplicationRuntimeException(AssetMessages.noSuchResource(resourcePath));
 74   
 
 75  36
         InputStream stream = null;
 76   
 
 77  36
         try
 78   
         {
 79  36
             MessageDigest digest = MessageDigest.getInstance("MD5");
 80   
 
 81  36
             stream = new BufferedInputStream(url.openStream());
 82   
 
 83  36
             digestStream(digest, stream);
 84   
 
 85  36
             stream.close();
 86  36
             stream = null;
 87   
 
 88  36
             byte[] bytes = digest.digest();
 89  36
             char[] encoded = Hex.encodeHex(bytes);
 90   
 
 91  36
             return new String(encoded);
 92   
         }
 93   
         catch (IOException ex)
 94   
         {
 95  0
             throw new ApplicationRuntimeException(AssetMessages.unableToReadResource(
 96   
                     resourcePath,
 97   
                     ex));
 98   
         }
 99   
         catch (Exception ex)
 100   
         {
 101  0
             throw new ApplicationRuntimeException(ex);
 102   
         }
 103   
         finally
 104   
         {
 105  36
             IOUtils.close(stream);
 106   
         }
 107   
     }
 108   
 
 109  36
     private void digestStream(MessageDigest digest, InputStream stream) throws IOException
 110   
     {
 111  36
         byte[] buffer = new byte[BUFFER_SIZE];
 112   
 
 113  36
         while (true)
 114   
         {
 115  84
             int length = stream.read(buffer);
 116   
 
 117  84
             if (length < 0)
 118  36
                 return;
 119   
 
 120  48
             digest.update(buffer, 0, length);
 121   
         }
 122   
     }
 123   
 
 124  30
     public void setClassResolver(ClassResolver classResolver)
 125   
     {
 126  30
         _classResolver = classResolver;
 127   
     }
 128   
 }