1 package org.apache.velocity.runtime.resource; 2 3 /* 4 * Licensed to the Apache Software Foundation (ASF) under one 5 * or more contributor license agreements. See the NOTICE file 6 * distributed with this work for additional information 7 * regarding copyright ownership. The ASF licenses this file 8 * to you under the Apache License, Version 2.0 (the 9 * "License"); you may not use this file except in compliance 10 * with the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, 15 * software distributed under the License is distributed on an 16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 17 * KIND, either express or implied. See the License for the 18 * specific language governing permissions and limitations 19 * under the License. 20 */ 21 22 import org.apache.velocity.runtime.RuntimeConstants; 23 import org.apache.velocity.runtime.RuntimeServices; 24 import org.slf4j.Logger; 25 26 import java.util.Collections; 27 import java.util.Iterator; 28 import java.util.LinkedHashMap; 29 import java.util.LinkedHashSet; 30 import java.util.Map; 31 import java.util.Map.Entry; 32 import java.util.concurrent.ConcurrentHashMap; 33 34 /** 35 * Default implementation of the resource cache for the default 36 * ResourceManager. The cache uses a <i>least recently used</i> (LRU) 37 * algorithm, with a maximum size specified via the 38 * <code>resource.manager.cache.size</code> property (identified by the 39 * {@link 40 * org.apache.velocity.runtime.RuntimeConstants#RESOURCE_MANAGER_DEFAULTCACHE_SIZE} 41 * constant). This property get be set to <code>0</code> or less for 42 * a greedy, unbounded cache (the behavior from pre-v1.5). 43 * 44 * @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a> 45 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> 46 * @version $Id$ 47 */ 48 public class ResourceCacheImpl implements ResourceCache 49 { 50 51 /** 52 * A simple LRU Map based on {@link LinkedHashSet}. 53 * 54 * @param <K> The key type of the map. 55 * @param <V> The value type of the map. 56 */ 57 private static class LRUMap<K, V> extends LinkedHashMap<K, V>{ 58 59 /** 60 * The serial version uid; 61 */ 62 private static final long serialVersionUID = 5889225121697975043L; 63 64 /** 65 * The size of the cache. 66 */ 67 private int cacheSize; 68 69 /** 70 * Constructor. 71 * 72 * @param cacheSize The size of the cache. After reaching this size, the 73 * eldest-accessed element will be erased. 74 */ LRUMap(int cacheSize)75 public LRUMap(int cacheSize) 76 { 77 this.cacheSize = cacheSize; 78 } 79 80 /** {@inheritDoc} */ 81 @Override removeEldestEntry(Entry<K, V> eldest)82 protected boolean removeEldestEntry(Entry<K, V> eldest) 83 { 84 return size() > cacheSize; 85 } 86 } 87 88 /** 89 * Cache storage, assumed to be thread-safe. 90 */ 91 protected Map<Object, Resource> cache = new ConcurrentHashMap<>(512, 0.5f, 30); 92 93 /** 94 * Runtime services, generally initialized by the 95 * <code>initialize()</code> method. 96 */ 97 protected RuntimeServices rsvc = null; 98 99 protected Logger log; 100 101 /** 102 * @see org.apache.velocity.runtime.resource.ResourceCache#initialize(org.apache.velocity.runtime.RuntimeServices) 103 */ 104 @Override initialize(RuntimeServices rs )105 public void initialize(RuntimeServices rs ) 106 { 107 rsvc = rs; 108 109 int maxSize = 110 rsvc.getInt(RuntimeConstants.RESOURCE_MANAGER_DEFAULTCACHE_SIZE, 89); 111 if (maxSize > 0) 112 { 113 // Create a whole new Map here to avoid hanging on to a 114 // handle to the unsynch'd LRUMap for our lifetime. 115 Map<Object, Resource> lruCache = Collections.synchronizedMap(new LRUMap<>(maxSize)); 116 lruCache.putAll(cache); 117 cache = lruCache; 118 } 119 rsvc.getLog().debug("initialized ({}) with {} cache map.", this.getClass(), cache.getClass()); 120 } 121 122 /** 123 * @see org.apache.velocity.runtime.resource.ResourceCache#get(java.lang.Object) 124 */ 125 @Override get(Object key )126 public Resource get(Object key ) 127 { 128 return cache.get( key ); 129 } 130 131 /** 132 * @see org.apache.velocity.runtime.resource.ResourceCache#put(java.lang.Object, org.apache.velocity.runtime.resource.Resource) 133 */ 134 @Override put(Object key, Resource value )135 public Resource put(Object key, Resource value ) 136 { 137 return cache.put( key, value ); 138 } 139 140 /** 141 * @see org.apache.velocity.runtime.resource.ResourceCache#remove(java.lang.Object) 142 */ 143 @Override remove(Object key )144 public Resource remove(Object key ) 145 { 146 return cache.remove( key ); 147 } 148 149 /** 150 * @see org.apache.velocity.runtime.resource.ResourceCache#clear() 151 * @since 2.0 152 */ 153 @Override clear()154 public void clear() 155 { 156 cache.clear(); 157 } 158 159 /** 160 * @see org.apache.velocity.runtime.resource.ResourceCache#enumerateKeys() 161 */ 162 @Override enumerateKeys()163 public Iterator<Object> enumerateKeys() 164 { 165 return cache.keySet().iterator(); 166 } 167 } 168 169