1 package org.apache.jcs.admin;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.io.ObjectOutputStream;
24 import java.io.Serializable;
25 import java.text.DateFormat;
26 import java.util.Arrays;
27 import java.util.Date;
28 import java.util.Iterator;
29 import java.util.LinkedList;
30 import java.util.Map;
31
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.apache.jcs.engine.behavior.ICacheElement;
35 import org.apache.jcs.engine.behavior.IElementAttributes;
36 import org.apache.jcs.engine.control.CompositeCache;
37 import org.apache.jcs.engine.control.CompositeCacheManager;
38 import org.apache.jcs.engine.memory.behavior.IMemoryCache;
39
40 /***
41 * A servlet which provides HTTP access to JCS. Allows a summary of regions to be viewed, and
42 * removeAll to be run on individual regions or all regions. Also provides the ability to remove
43 * items (any number of key arguments can be provided with action 'remove'). Should be initialized
44 * with a properties file that provides at least a classpath resource loader.
45 */
46 public class JCSAdminBean
47 {
48 /*** The logger. */
49 private static final Log log = LogFactory.getLog( JCSAdminBean.class );
50
51 /*** The cache maanger. */
52 private CompositeCacheManager cacheHub = CompositeCacheManager.getInstance();
53
54 /***
55 * Builds up info about each element in a region.
56 * <p>
57 * @param cacheName
58 * @return List of CacheElementInfo objects
59 * @throws Exception
60 */
61 public LinkedList buildElementInfo( String cacheName )
62 throws Exception
63 {
64 CompositeCache cache = cacheHub.getCache( cacheName );
65
66 Object[] keys = cache.getMemoryCache().getKeyArray();
67
68
69
70
71 try
72 {
73 Arrays.sort( keys );
74 }
75 catch ( Exception e )
76 {
77 keys = cache.getMemoryCache().getKeyArray();
78 }
79
80 LinkedList records = new LinkedList();
81
82 ICacheElement element;
83 IElementAttributes attributes;
84 CacheElementInfo elementInfo;
85
86 DateFormat format = DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.SHORT );
87
88 long now = System.currentTimeMillis();
89
90 for ( int i = 0; i < keys.length; i++ )
91 {
92 element = cache.getMemoryCache().getQuiet( (Serializable) keys[i] );
93
94 attributes = element.getElementAttributes();
95
96 elementInfo = new CacheElementInfo();
97
98 elementInfo.key = String.valueOf( keys[i] );
99 elementInfo.eternal = attributes.getIsEternal();
100 elementInfo.maxLifeSeconds = attributes.getMaxLifeSeconds();
101
102 elementInfo.createTime = format.format( new Date( attributes.getCreateTime() ) );
103
104 elementInfo.expiresInSeconds = ( now - attributes.getCreateTime() - ( attributes.getMaxLifeSeconds() * 1000 ) )
105 / -1000;
106
107 records.add( elementInfo );
108 }
109
110 return records;
111 }
112
113 /***
114 * Builds up data on every region.
115 * <p>
116 * @TODO we need a most light weight method that does not count bytes. The byte counting can
117 * really swamp a server.
118 * @return list of CacheRegionInfo objects
119 * @throws Exception
120 */
121 public LinkedList buildCacheInfo()
122 throws Exception
123 {
124 String[] cacheNames = cacheHub.getCacheNames();
125
126 Arrays.sort( cacheNames );
127
128 LinkedList cacheInfo = new LinkedList();
129
130 CacheRegionInfo regionInfo;
131 CompositeCache cache;
132
133 for ( int i = 0; i < cacheNames.length; i++ )
134 {
135 cache = cacheHub.getCache( cacheNames[i] );
136
137 regionInfo = new CacheRegionInfo();
138
139 regionInfo.cache = cache;
140 regionInfo.byteCount = getByteCount( cache );
141
142 cacheInfo.add( regionInfo );
143 }
144
145 return cacheInfo;
146 }
147
148 /***
149 * Tries to estimate how much data is in a region. This is expensive. If there are any non
150 * serializable objects in the region, the count will stop when it encouters the first one.
151 * <p>
152 * @param cache
153 * @return int
154 * @throws Exception
155 */
156 public int getByteCount( CompositeCache cache )
157 throws Exception
158 {
159 IMemoryCache memCache = cache.getMemoryCache();
160
161 Iterator iter = memCache.getIterator();
162
163 CountingOnlyOutputStream counter = new CountingOnlyOutputStream();
164 ObjectOutputStream out = new ObjectOutputStream( counter );
165
166
167
168 try
169 {
170 while ( iter.hasNext() )
171 {
172 ICacheElement ce = (ICacheElement) ( (Map.Entry) iter.next() ).getValue();
173
174 out.writeObject( ce.getVal() );
175 }
176 }
177 catch ( Exception e )
178 {
179 log.info( "Problem getting byte count. Likley cause is a non serilizable object." + e.getMessage() );
180 }
181
182
183
184 return counter.getCount() - 4;
185 }
186
187 /***
188 * Clears all regions in the cache.
189 * <p>
190 * @throws IOException
191 */
192 public void clearAllRegions()
193 throws IOException
194 {
195 String[] names = cacheHub.getCacheNames();
196
197 for ( int i = 0; i < names.length; i++ )
198 {
199 cacheHub.getCache( names[i] ).removeAll();
200 }
201 }
202
203 /***
204 * Clears a particular cache region.
205 * <p>
206 * @param cacheName
207 * @throws IOException
208 */
209 public void clearRegion( String cacheName )
210 throws IOException
211 {
212 cacheHub.getCache( cacheName ).removeAll();
213 }
214
215 /***
216 * Removes a particular item from a particular region.
217 * <p>
218 * @param cacheName
219 * @param key
220 * @throws IOException
221 */
222 public void removeItem( String cacheName, String key )
223 throws IOException
224 {
225 cacheHub.getCache( cacheName ).remove( key );
226 }
227 }