Home » jakarta-jmeter-2.3.4_src » org.apache.jmeter.protocol.http.control » [javadoc | source]

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *   http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    *
   17    */
   18   
   19   // For unit tests @see TestCookieManager
   20   
   21   package org.apache.jmeter.protocol.http.control;
   22   
   23   import java.io.Serializable;
   24   import java.net.HttpURLConnection;
   25   import java.net.URL;
   26   import java.net.URLConnection;
   27   import java.util.HashMap;
   28   import java.util.Map;
   29   
   30   import org.apache.commons.httpclient.Header;
   31   import org.apache.commons.httpclient.HttpMethod;
   32   import org.apache.commons.httpclient.URIException;
   33   import org.apache.jmeter.config.ConfigTestElement;
   34   import org.apache.jmeter.engine.event.LoopIterationEvent;
   35   import org.apache.jmeter.protocol.http.util.HTTPConstantsInterface;
   36   import org.apache.jmeter.samplers.SampleResult;
   37   import org.apache.jmeter.testelement.TestListener;
   38   import org.apache.jmeter.testelement.property.BooleanProperty;
   39   import org.apache.jorphan.logging.LoggingManager;
   40   import org.apache.log.Logger;
   41   
   42   /**
   43    * Handles HTTP Caching
   44    */
   45   public class CacheManager extends ConfigTestElement implements TestListener, Serializable {
   46   
   47       private static final long serialVersionUID = 233L;
   48   
   49       private static final Logger log = LoggingManager.getLoggerForClass();
   50   
   51       public static final String CLEAR = "clearEachIteration"; // $NON-NLS-1$
   52   
   53       private transient ThreadLocal threadCache;
   54   
   55       public CacheManager() {
   56           setProperty(new BooleanProperty(CLEAR, false));
   57           clearCache();
   58       }
   59   
   60       /*
   61        * Holder for storing cache details.
   62        * Perhaps add original response later?
   63        */
   64       private static class CacheEntry{
   65           private final String lastModified;
   66           private final String etag;
   67           public CacheEntry(String lastModified, String etag){
   68              this.lastModified = lastModified;
   69              this.etag = etag;
   70          }
   71           public String getLastModified() {
   72               return lastModified;
   73           }
   74           public String getEtag() {
   75               return etag;
   76           }
   77           public String toString(){
   78               return lastModified+" "+etag;
   79           }
   80       }
   81   
   82       /**
   83        * Save the Last-Modified and Etag headers if the result is cacheable.
   84        *
   85        * @param conn connection
   86        * @param res result
   87        */
   88       public void saveDetails(URLConnection conn, SampleResult res){
   89           if (isCacheable(res)){
   90               String lastModified = conn.getHeaderField(HTTPConstantsInterface.LAST_MODIFIED);
   91               String etag = conn.getHeaderField(HTTPConstantsInterface.ETAG);
   92               String url = conn.getURL().toString();
   93               setCache(lastModified, etag, url);
   94           }
   95       }
   96   
   97       /**
   98        * Save the Last-Modified and Etag headers if the result is cacheable.
   99        *
  100        * @param method
  101        * @param res result
  102        */
  103       public void saveDetails(HttpMethod method, SampleResult res) throws URIException{
  104           if (isCacheable(res)){
  105               String lastModified = getHeader(method ,HTTPConstantsInterface.LAST_MODIFIED);
  106               String etag = getHeader(method ,HTTPConstantsInterface.ETAG);
  107               String url = method.getURI().toString();
  108               setCache(lastModified, etag, url);
  109           }
  110       }
  111   
  112       // helper method to save the cache entry
  113       private void setCache(String lastModified, String etag, String url) {
  114           if (log.isDebugEnabled()){
  115               log.debug("SET(both) "+url + " " + lastModified + " " + etag);
  116           }
  117           getCache().put(url, new CacheEntry(lastModified, etag));
  118       }
  119   
  120       // Helper method to deal with missing headers
  121       private String getHeader(HttpMethod method, String name){
  122           Header hdr = method.getResponseHeader(name);
  123           return hdr != null ? hdr.getValue() : null;
  124       }
  125   
  126       /*
  127        * Is the sample result OK to cache?
  128        * i.e is it in the 2xx range?
  129        */
  130       private boolean isCacheable(SampleResult res){
  131           final String responseCode = res.getResponseCode();
  132           return "200".compareTo(responseCode) <= 0  // $NON-NLS-1$
  133               && "299".compareTo(responseCode) >= 0; // $NON-NLS-1$
  134       }
  135   
  136       /**
  137        * Check the cache, and if there is a match, set the headers:<br/>
  138        * If-Modified-Since<br/>
  139        * If-None-Match<br/>
  140        * @param url URL to look up in cache
  141        * @param method where to set the headers
  142        */
  143       public void setHeaders(URL url, HttpMethod method) {
  144           CacheEntry entry = (CacheEntry) getCache().get(url.toString());
  145           if (log.isDebugEnabled()){
  146               log.debug(method.getName()+"(OAHC) "+url.toString()+" "+entry);
  147           }
  148           if (entry != null){
  149               final String lastModified = entry.getLastModified();
  150               if (lastModified != null){
  151                   method.setRequestHeader(HTTPConstantsInterface.IF_MODIFIED_SINCE, lastModified);
  152               }
  153               final String etag = entry.getEtag();
  154               if (etag != null){
  155                   method.setRequestHeader(HTTPConstantsInterface.IF_NONE_MATCH, etag);
  156               }
  157           }
  158       }
  159   
  160       /**
  161        * Check the cache, and if there is a match, set the headers:<br/>
  162        * If-Modified-Since<br/>
  163        * If-None-Match<br/>
  164        * @param url URL to look up in cache
  165        * @param conn where to set the headers
  166        */
  167       public void setHeaders(HttpURLConnection conn, URL url) {
  168           CacheEntry entry = (CacheEntry) getCache().get(url.toString());
  169           if (log.isDebugEnabled()){
  170               log.debug(conn.getRequestMethod()+"(Java) "+url.toString()+" "+entry);
  171           }
  172           if (entry != null){
  173               final String lastModified = entry.getLastModified();
  174               if (lastModified != null){
  175                   conn.addRequestProperty(HTTPConstantsInterface.IF_MODIFIED_SINCE, lastModified);
  176               }
  177               final String etag = entry.getEtag();
  178               if (etag != null){
  179                   conn.addRequestProperty(HTTPConstantsInterface.IF_NONE_MATCH, etag);
  180               }
  181           }
  182       }
  183   
  184       private Map getCache(){
  185           return (Map) threadCache.get();
  186       }
  187   
  188       public boolean getClearEachIteration() {
  189           return getPropertyAsBoolean(CLEAR);
  190       }
  191   
  192       public void setClearEachIteration(boolean clear) {
  193           setProperty(new BooleanProperty(CLEAR, clear));
  194       }
  195   
  196       public void clear(){
  197           super.clear();
  198           clearCache();
  199       }
  200   
  201       private void clearCache() {
  202           log.debug("Clear cache");
  203           threadCache = new ThreadLocal(){
  204               protected Object initialValue(){
  205                   return new HashMap();
  206               }
  207           };
  208       }
  209   
  210       public void testStarted() {
  211       }
  212   
  213       public void testEnded() {
  214       }
  215   
  216       public void testStarted(String host) {
  217       }
  218   
  219       public void testEnded(String host) {
  220       }
  221   
  222       public void testIterationStart(LoopIterationEvent event) {
  223           if (getClearEachIteration()) {
  224               clearCache();
  225           }
  226       }
  227   }

Home » jakarta-jmeter-2.3.4_src » org.apache.jmeter.protocol.http.control » [javadoc | source]