File Source: WeblogPageCache.java

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   *  contributor license agreements.  The ASF licenses this file to You
     4   * under the Apache License, Version 2.0 (the "License"); you may not
     5   * use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.  For additional information regarding
    15   * copyright in this work, please see the NOTICE file in the top level
    16   * directory of this distribution.
    17   */
    18  
    19  package org.apache.roller.weblogger.ui.rendering.util.cache;
    20  
    21  import java.io.UnsupportedEncodingException;
    22  import java.net.URLEncoder;
    23  import java.util.Enumeration;
    24  import java.util.HashMap;
    25  import java.util.Iterator;
    26  import java.util.Map;
    27  import java.util.Set;
    28  import java.util.TreeSet;
    29  import org.apache.commons.logging.Log;
    30  import org.apache.commons.logging.LogFactory;
    31  import org.apache.roller.weblogger.config.WebloggerConfig;
    32  import org.apache.roller.weblogger.ui.rendering.util.WeblogPageRequest;
    33  import org.apache.roller.weblogger.util.Utilities;
    34  import org.apache.roller.weblogger.util.cache.Cache;
    35  import org.apache.roller.weblogger.util.cache.CacheManager;
    36  import org.apache.roller.weblogger.util.cache.LazyExpiringCacheEntry;
    37  
    38  
    39  /**
    40   * Cache for weblog page content.
    41   */
    42  public class WeblogPageCache {
    43      
             /* 
    P/P       *  Method: org.apache.roller.weblogger.ui.rendering.util.cache.WeblogPageCache__static_init
              * 
              *  Presumptions:
              *    org.apache.commons.logging.LogFactory:getLog(...)@44 != null
              * 
              *  Postconditions:
              *    (soft) log != null
              *    singletonInstance == &new WeblogPageCache(WeblogPageCache__static_init#1)
              *    new WeblogPageCache(WeblogPageCache__static_init#1) num objects == 1
              *    init'ed(singletonInstance.cacheEnabled)
              *    init'ed(singletonInstance.contentCache)
              */
    44      private static Log log = LogFactory.getLog(WeblogPageCache.class);
    45      
    46      // a unique identifier for this cache, this is used as the prefix for
    47      // roller config properties that apply to this cache
    48      public static final String CACHE_ID = "cache.weblogpage";
    49      
    50      // keep cached content
    51      private boolean cacheEnabled = true;
    52      private Cache contentCache = null;
    53      
    54      // reference to our singleton instance
    55      private static WeblogPageCache singletonInstance = new WeblogPageCache();
    56      
    57      
             /* 
    P/P       *  Method: void org.apache.roller.weblogger.ui.rendering.util.cache.WeblogPageCache()
              * 
              *  Preconditions:
              *    log != null
              * 
              *  Presumptions:
              *    java.lang.String:length(...)@71 <= 232-2
              *    java.util.Enumeration:nextElement(...)@67 != null
              *    org.apache.roller.weblogger.config.WebloggerConfig:keys(...)@64 != null
              * 
              *  Postconditions:
              *    init'ed(this.cacheEnabled)
              *    init'ed(this.contentCache)
              * 
              *  Test Vectors:
              *    java.lang.String:startsWith(...)@70: {0}, {1}
              *    java.util.Enumeration:hasMoreElements(...)@66: {0}, {1}
              *    org.apache.roller.weblogger.config.WebloggerConfig:getBooleanProperty(...)@60: {0}, {1}
              */
    58      private WeblogPageCache() {
    59          
    60          cacheEnabled = WebloggerConfig.getBooleanProperty(CACHE_ID+".enabled");
    61          
    62          Map cacheProps = new HashMap();
    63          cacheProps.put("id", CACHE_ID);
    64          Enumeration allProps = WebloggerConfig.keys();
    65          String prop = null;
    66          while(allProps.hasMoreElements()) {
    67              prop = (String) allProps.nextElement();
    68              
    69              // we are only interested in props for this cache
    70              if(prop.startsWith(CACHE_ID+".")) {
    71                  cacheProps.put(prop.substring(CACHE_ID.length()+1), 
    72                          WebloggerConfig.getProperty(prop));
    73              }
    74          }
    75          
    76          log.info(cacheProps);
    77          
    78          if(cacheEnabled) {
    79              contentCache = CacheManager.constructCache(null, cacheProps);
    80          } else {
    81              log.warn("Caching has been DISABLED");
    82          }
    83      }
    84      
    85      
    86      public static WeblogPageCache getInstance() {
                 /* 
    P/P           *  Method: WeblogPageCache getInstance()
                  * 
                  *  Preconditions:
                  *    init'ed(singletonInstance)
                  * 
                  *  Postconditions:
                  *    return_value == singletonInstance
                  *    init'ed(return_value)
                  */
    87          return singletonInstance;
    88      }
    89      
    90      
    91      public Object get(String key, long lastModified) {
    92          
                 /* 
    P/P           *  Method: Object get(String, long)
                  * 
                  *  Preconditions:
                  *    init'ed(this.cacheEnabled)
                  *    (soft) log != null
                  *    (soft) this.contentCache != null
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    this.cacheEnabled: {1}, {0}
                  *    org.apache.roller.weblogger.util.cache.Cache:get(...)@98: Addr_Set{null}, Inverse{null}
                  *    org.apache.roller.weblogger.util.cache.LazyExpiringCacheEntry:getValue(...)@101: Addr_Set{null}, Inverse{null}
                  */
    93          if(!cacheEnabled)
    94              return null;
    95          
    96          Object entry = null;
    97          
    98          LazyExpiringCacheEntry lazyEntry =
    99                  (LazyExpiringCacheEntry) this.contentCache.get(key);
   100          if(lazyEntry != null) {
   101              entry = lazyEntry.getValue(lastModified);
   102              
   103              if(entry != null) {
   104                  log.debug("HIT "+key);
   105              } else {
   106                  log.debug("HIT-EXPIRED "+key);
   107              }
   108              
   109          } else {
   110              log.debug("MISS "+key);
   111          }
   112          
   113          return entry;
   114      }
   115      
   116      
   117      public void put(String key, Object value) {
   118          
                 /* 
    P/P           *  Method: void put(String, Object)
                  * 
                  *  Preconditions:
                  *    init'ed(this.cacheEnabled)
                  *    (soft) log != null
                  *    (soft) this.contentCache != null
                  * 
                  *  Test Vectors:
                  *    this.cacheEnabled: {1}, {0}
                  */
   119          if(!cacheEnabled)
   120              return;
   121          
   122          contentCache.put(key, new LazyExpiringCacheEntry(value));
   123          log.debug("PUT "+key);
   124      }
   125      
   126      
   127      public void remove(String key) {
   128          
                 /* 
    P/P           *  Method: void remove(String)
                  * 
                  *  Preconditions:
                  *    init'ed(this.cacheEnabled)
                  *    (soft) log != null
                  *    (soft) this.contentCache != null
                  * 
                  *  Test Vectors:
                  *    this.cacheEnabled: {1}, {0}
                  */
   129          if(!cacheEnabled)
   130              return;
   131          
   132          contentCache.remove(key);
   133          log.debug("REMOVE "+key);
   134      }
   135      
   136      
   137      public void clear() {
   138          
                 /* 
    P/P           *  Method: void clear()
                  * 
                  *  Preconditions:
                  *    init'ed(this.cacheEnabled)
                  *    (soft) log != null
                  *    (soft) this.contentCache != null
                  * 
                  *  Test Vectors:
                  *    this.cacheEnabled: {1}, {0}
                  */
   139          if(!cacheEnabled)
   140              return;
   141          
   142          contentCache.clear();
   143          log.debug("CLEAR");
   144      }
   145      
   146      
   147      /**
   148       * Generate a cache key from a parsed weblog page request.
   149       * This generates a key of the form ...
   150       *
   151       * <handle>/<ctx>[/anchor][/language][/user]
   152       *   or
   153       * <handle>/<ctx>[/weblogPage][/date][/category][/language][/user]
   154       *
   155       *
   156       * examples ...
   157       *
   158       * foo/en
   159       * foo/entry_anchor
   160       * foo/20051110/en
   161       * foo/MyCategory/en/user=myname
   162       *
   163       */
   164      public String generateKey(WeblogPageRequest pageRequest) {
   165          
                 /* 
    P/P           *  Method: String generateKey(WeblogPageRequest)
                  * 
                  *  Preconditions:
                  *    pageRequest != null
                  *    init'ed(pageRequest.locale)
                  *    init'ed(pageRequest.weblogAnchor)
                  *    init'ed(pageRequest.weblogHandle)
                  *    init'ed(pageRequest.weblogPageName)
                  *    (soft) init'ed(pageRequest.authenticUser)
                  *    (soft) init'ed(pageRequest.context)
                  *    (soft) pageRequest.customParams != null
                  *    (soft) init'ed(pageRequest.pageNum)
                  *    (soft) init'ed(pageRequest.tags)
                  *    ...
                  * 
                  *  Presumptions:
                  *    java.util.Set:size(...)@208 >= 0
                  * 
                  *  Postconditions:
                  *    init'ed(java.lang.StringBuffer:toString(...)._tainted)
                  *    return_value == &java.lang.StringBuffer:toString(...)
                  * 
                  *  Test Vectors:
                  *    pageRequest.locale: Addr_Set{null}, Inverse{null}
                  *    pageRequest.tags: Addr_Set{null}, Inverse{null}
                  *    pageRequest.weblogAnchor: Addr_Set{null}, Inverse{null}
                  *    pageRequest.weblogCategoryName: Addr_Set{null}, Inverse{null}
                  *    pageRequest.weblogDate: Addr_Set{null}, Inverse{null}
                  *    pageRequest.weblogPageName: Addr_Set{null}, Inverse{null}
                  *    java.lang.String:equals(...)@204: {0}, {1}
                  *    java.util.List:size(...)@206: {-231..0}, {1..232-1}
                  *    java.util.Map:size(...)@229: {-231..0}, {1..232-1}
                  */
   166          StringBuffer key = new StringBuffer();
   167          
   168          key.append(this.CACHE_ID).append(":");
   169          key.append(pageRequest.getWeblogHandle());
   170          
   171          if(pageRequest.getWeblogAnchor() != null) {
   172              
   173              String anchor = null;
   174              try {
   175                  // may contain spaces or other bad chars
   176                  anchor = URLEncoder.encode(pageRequest.getWeblogAnchor(), "UTF-8");
   177              } catch(UnsupportedEncodingException ex) {
   178                  // ignored
   179              }
   180              
   181              key.append("/entry/").append(anchor);
   182          } else {
   183              
   184              if(pageRequest.getWeblogPageName() != null) {
   185                  key.append("/page/").append(pageRequest.getWeblogPageName());
   186              }
   187              
   188              if(pageRequest.getWeblogDate() != null) {
   189                  key.append("/").append(pageRequest.getWeblogDate());
   190              }
   191              
   192              if(pageRequest.getWeblogCategoryName() != null) {
   193                  String cat = null;
   194                  try {
   195                      // may contain spaces or other bad chars
   196                      cat = URLEncoder.encode(pageRequest.getWeblogCategoryName(), "UTF-8");
   197                  } catch(UnsupportedEncodingException ex) {
   198                      // ignored
   199                  }
   200                  
   201                  key.append("/").append(cat);
   202              }
   203              
   204              if("tags".equals(pageRequest.getContext())) {
   205                  key.append("/tags/");
   206                  if(pageRequest.getTags() != null && pageRequest.getTags().size() > 0) {
   207                      Set ordered = new TreeSet(pageRequest.getTags());
   208                      String[] tags = (String[]) ordered.toArray(new String[ordered.size()]);
   209                      key.append(Utilities.stringArrayToString(tags,"+"));
   210                  }
   211              }
   212          }
   213          
   214          if(pageRequest.getLocale() != null) {
   215              key.append("/").append(pageRequest.getLocale());
   216          }
   217          
   218          // add page number when applicable
   219          if(pageRequest.getWeblogAnchor() == null) {
   220              key.append("/page=").append(pageRequest.getPageNum());
   221          }
   222          
   223          // add login state
   224          if(pageRequest.getAuthenticUser() != null) {
   225              key.append("/user=").append(pageRequest.getAuthenticUser());
   226          }
   227          
   228          // we allow for arbitrary query params for custom pages
   229          if(pageRequest.getWeblogPageName() != null &&
   230                  pageRequest.getCustomParams().size() > 0) {
   231              String queryString = paramsToString(pageRequest.getCustomParams());
   232              
   233              key.append("/qp=").append(queryString);
   234          }
   235          
   236          return key.toString();
   237      }
   238      
   239      
   240      private String paramsToString(Map map) {
   241          
                 /* 
    P/P           *  Method: String paramsToString(Map)
                  * 
                  *  Presumptions:
                  *    java.util.Map:keySet(...)@250 != null
                  *    value.length@253 >= 1
                  * 
                  *  Postconditions:
                  *    init'ed(return_value)
                  * 
                  *  Test Vectors:
                  *    map: Inverse{null}, Addr_Set{null}
                  *    java.util.Iterator:hasNext(...)@251: {0}, {1}
                  *    java.util.Map:get(...)@253: Addr_Set{null}, Inverse{null}
                  */
   242          if(map == null) {
   243              return null;
   244          }
   245          
   246          StringBuffer string = new StringBuffer();
   247          
   248          String key = null;
   249          String[] value = null;
   250          Iterator keys = map.keySet().iterator();
   251          while(keys.hasNext()) {
   252              key = (String) keys.next();
   253              value = (String[]) map.get(key);
   254              
   255              if(value != null) {
   256                  string.append(",").append(key).append("=").append(value[0]);
   257              }
   258          }
   259          
   260          return Utilities.toBase64(string.toString().substring(1).getBytes());
   261      }
   262      
   263  }








SofCheck Inspector Build Version : 2.18479
WeblogPageCache.java 2009-Jan-02 14:25:42
WeblogPageCache.class 2009-Sep-04 03:12:45