Coverage Report - org.apache.tapestry.asset.ResourceDigestSourceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
ResourceDigestSourceImpl
0%
0/45
0%
0/10
3
 
 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.Iterator;
 24  
 import java.util.Map;
 25  
 
 26  
 import org.apache.commons.codec.binary.Hex;
 27  
 import org.apache.hivemind.ApplicationRuntimeException;
 28  
 import org.apache.hivemind.ClassResolver;
 29  
 import org.apache.hivemind.util.IOUtils;
 30  
 import org.apache.tapestry.event.ReportStatusEvent;
 31  
 import org.apache.tapestry.event.ReportStatusListener;
 32  
 import org.apache.tapestry.event.ResetEventListener;
 33  
 
 34  
 /**
 35  
  * Implementation of {@link org.apache.tapestry.asset.ResourceDigestSource} that calculates an
 36  
  * DIGEST checksum digest and converts it to a string of hex digits.
 37  
  * 
 38  
  * @author Howard M. Lewis Ship
 39  
  * @since 4.0
 40  
  */
 41  0
 public class ResourceDigestSourceImpl implements ResourceDigestSource, ResetEventListener,
 42  
         ReportStatusListener
 43  
 {
 44  
     private static final int BUFFER_SIZE = 5000;
 45  
 
 46  
     private String _serviceId;
 47  
 
 48  
     private ClassResolver _classResolver;
 49  
 
 50  
     /**
 51  
      * Map keyed on resource path of DIGEST checksum (as a string).
 52  
      */
 53  
 
 54  0
     private final Map _cache = new HashMap();
 55  
 
 56  
     public synchronized String getDigestForResource(String resourcePath)
 57  
     {
 58  0
         if (resourcePath == null) return null;
 59  
         
 60  0
         String result = (String) _cache.get(resourcePath);
 61  
 
 62  0
         if (result == null)
 63  
         {
 64  0
             result = computeMD5(resourcePath);
 65  0
             _cache.put(resourcePath, result);
 66  
         }
 67  
 
 68  0
         return result;
 69  
     }
 70  
 
 71  
     public synchronized void resetEventDidOccur()
 72  
     {
 73  0
         _cache.clear();
 74  0
     }
 75  
 
 76  
     public synchronized void reportStatus(ReportStatusEvent event)
 77  
     {
 78  0
         event.title(_serviceId);
 79  0
         event.property("resource count", _cache.size());
 80  
 
 81  0
         Iterator i = _cache.entrySet().iterator();
 82  
 
 83  0
         while (i.hasNext())
 84  
         {
 85  0
             Map.Entry entry = (Map.Entry) i.next();
 86  
 
 87  0
             event.property(entry.getKey().toString(), entry.getValue());
 88  0
         }
 89  0
     }
 90  
 
 91  
     private String computeMD5(String resourcePath)
 92  
     {
 93  0
         URL url = _classResolver.getResource(resourcePath);
 94  
 
 95  0
         if (url == null)
 96  0
             throw new ApplicationRuntimeException(AssetMessages.noSuchResource(resourcePath));
 97  
 
 98  0
         InputStream stream = null;
 99  
 
 100  
         try
 101  
         {
 102  0
             MessageDigest digest = MessageDigest.getInstance("MD5");
 103  
 
 104  0
             stream = new BufferedInputStream(url.openStream());
 105  
 
 106  0
             digestStream(digest, stream);
 107  
 
 108  0
             stream.close();
 109  0
             stream = null;
 110  
 
 111  0
             byte[] bytes = digest.digest();
 112  0
             char[] encoded = Hex.encodeHex(bytes);
 113  
 
 114  0
             return new String(encoded);
 115  
         }
 116  0
         catch (IOException ex)
 117  
         {
 118  0
             throw new ApplicationRuntimeException(AssetMessages.unableToReadResource(
 119  
                     resourcePath,
 120  
                     ex));
 121  
         }
 122  0
         catch (Exception ex)
 123  
         {
 124  0
             throw new ApplicationRuntimeException(ex);
 125  
         }
 126  
         finally
 127  
         {
 128  0
             IOUtils.close(stream);
 129  
         }
 130  
     }
 131  
 
 132  
     private void digestStream(MessageDigest digest, InputStream stream) throws IOException
 133  
     {
 134  0
         byte[] buffer = new byte[BUFFER_SIZE];
 135  
 
 136  
         while (true)
 137  
         {
 138  0
             int length = stream.read(buffer);
 139  
 
 140  0
             if (length < 0)
 141  0
                 return;
 142  
 
 143  0
             digest.update(buffer, 0, length);
 144  0
         }
 145  
     }
 146  
 
 147  
     public void setClassResolver(ClassResolver classResolver)
 148  
     {
 149  0
         _classResolver = classResolver;
 150  0
     }
 151  
 
 152  
     public void setServiceId(String serviceId)
 153  
     {
 154  0
         _serviceId = serviceId;
 155  0
     }
 156  
 }