• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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