1 package org.apache.commons.jcs3.auxiliary.remote.http.server;
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.InputStream;
24 import java.io.OutputStream;
25 import java.io.Serializable;
26 import java.util.HashMap;
27 import java.util.Map;
28 import java.util.Properties;
29 import java.util.Set;
30
31 import javax.servlet.ServletConfig;
32 import javax.servlet.ServletException;
33 import javax.servlet.http.HttpServlet;
34 import javax.servlet.http.HttpServletRequest;
35 import javax.servlet.http.HttpServletResponse;
36
37 import org.apache.commons.jcs3.access.exception.CacheException;
38 import org.apache.commons.jcs3.auxiliary.AuxiliaryCacheConfigurator;
39 import org.apache.commons.jcs3.auxiliary.remote.http.behavior.IRemoteHttpCacheConstants;
40 import org.apache.commons.jcs3.auxiliary.remote.value.RemoteCacheRequest;
41 import org.apache.commons.jcs3.auxiliary.remote.value.RemoteCacheResponse;
42 import org.apache.commons.jcs3.engine.behavior.ICacheElement;
43 import org.apache.commons.jcs3.engine.behavior.ICacheServiceNonLocal;
44 import org.apache.commons.jcs3.engine.behavior.ICompositeCacheManager;
45 import org.apache.commons.jcs3.engine.control.CompositeCacheManager;
46 import org.apache.commons.jcs3.engine.logging.behavior.ICacheEventLogger;
47 import org.apache.commons.jcs3.log.Log;
48 import org.apache.commons.jcs3.log.LogManager;
49 import org.apache.commons.jcs3.utils.config.PropertySetter;
50 import org.apache.commons.jcs3.utils.serialization.StandardSerializer;
51
52
53
54
55
56 public class RemoteHttpCacheServlet
57 extends HttpServlet
58 {
59
60 private static final long serialVersionUID = 8752849397531933346L;
61
62
63 private static final Log log = LogManager.getLog( RemoteHttpCacheServlet.class );
64
65
66 private static CompositeCacheManager cacheMgr;
67
68
69 private static ICacheServiceNonLocal<Serializable, Serializable> remoteCacheService;
70
71
72 private static final StandardSerializer serializer = new StandardSerializer();
73
74
75 private int serviceCalls;
76
77
78 private static final int logInterval = 100;
79
80
81
82
83
84
85
86
87
88 @Override
89 public void init( final ServletConfig config )
90 throws ServletException
91 {
92 try
93 {
94 cacheMgr = CompositeCacheManager.getInstance();
95 }
96 catch (final CacheException e)
97 {
98 throw new ServletException(e);
99 }
100
101 remoteCacheService = createRemoteHttpCacheService( cacheMgr );
102
103 super.init( config );
104 }
105
106
107
108
109
110
111
112
113
114 @Override
115 public void service( final HttpServletRequest request, final HttpServletResponse response )
116 throws ServletException, IOException
117 {
118 incrementServiceCallCount();
119 log.debug( "Servicing a request. {0}", request );
120
121 final RemoteCacheRequest<Serializable, Serializable> remoteRequest = readRequest( request );
122 final RemoteCacheResponse<Object> cacheResponse = processRequest( remoteRequest );
123
124 writeResponse( response, cacheResponse );
125 }
126
127
128
129
130
131
132
133 protected RemoteCacheRequest<Serializable, Serializable> readRequest( final HttpServletRequest request )
134 {
135 RemoteCacheRequest<Serializable, Serializable> remoteRequest = null;
136
137 try (InputStream inputStream = request.getInputStream())
138 {
139 log.debug( "After getting input stream and before reading it" );
140 remoteRequest = readRequestFromStream( inputStream );
141 }
142 catch ( final IOException | ClassNotFoundException e )
143 {
144 log.error( "Could not get a RemoteHttpCacheRequest object from the input stream.", e );
145 }
146
147 return remoteRequest;
148 }
149
150
151
152
153
154
155
156
157
158 protected RemoteCacheRequest<Serializable, Serializable> readRequestFromStream( final InputStream inputStream )
159 throws IOException, ClassNotFoundException
160 {
161 return serializer.deSerializeFrom(inputStream, null);
162 }
163
164
165
166
167
168
169
170 protected void writeResponse( final HttpServletResponse response, final RemoteCacheResponse<Object> cacheResponse )
171 {
172 try (OutputStream outputStream = response.getOutputStream())
173 {
174 response.setContentType( "application/octet-stream" );
175 serializer.serializeTo(cacheResponse, outputStream);
176 }
177 catch ( final IOException e )
178 {
179 log.error( "Problem writing response. {0}", cacheResponse, e );
180 }
181 }
182
183
184
185
186
187
188
189 protected RemoteCacheResponse<Object> processRequest( final RemoteCacheRequest<Serializable, Serializable> request )
190 {
191 final RemoteCacheResponse<Object> response = new RemoteCacheResponse<>();
192
193 if ( request == null )
194 {
195 final String message = "The request is null. Cannot process";
196 log.warn( message );
197 response.setSuccess( false );
198 response.setErrorMessage( message );
199 }
200 else
201 {
202 try
203 {
204 switch ( request.getRequestType() )
205 {
206 case GET:
207 final ICacheElement<Serializable, Serializable> element =
208 remoteCacheService.get( request.getCacheName(), request.getKey(), request.getRequesterId() );
209 response.setPayload(element);
210 break;
211 case GET_MULTIPLE:
212 final Map<Serializable, ICacheElement<Serializable, Serializable>> elementMap =
213 remoteCacheService.getMultiple( request.getCacheName(), request.getKeySet(), request.getRequesterId() );
214 if ( elementMap != null )
215 {
216 response.setPayload(new HashMap<>(elementMap));
217 }
218 break;
219 case GET_MATCHING:
220 final Map<Serializable, ICacheElement<Serializable, Serializable>> elementMapMatching =
221 remoteCacheService.getMatching( request.getCacheName(), request.getPattern(), request.getRequesterId() );
222 if ( elementMapMatching != null )
223 {
224 response.setPayload(new HashMap<>(elementMapMatching));
225 }
226 break;
227 case REMOVE:
228 remoteCacheService.remove( request.getCacheName(), request.getKey(), request.getRequesterId() );
229 break;
230 case REMOVE_ALL:
231 remoteCacheService.removeAll( request.getCacheName(), request.getRequesterId() );
232 break;
233 case UPDATE:
234 remoteCacheService.update( request.getCacheElement(), request.getRequesterId() );
235 break;
236 case ALIVE_CHECK:
237 case DISPOSE:
238 response.setSuccess( true );
239
240 break;
241 case GET_KEYSET:
242 final Set<Serializable> keys = remoteCacheService.getKeySet( request.getCacheName() );
243 response.setPayload( keys );
244 break;
245 default:
246 final String message = "Unknown event type. Cannot process " + request;
247 log.warn( message );
248 response.setSuccess( false );
249 response.setErrorMessage( message );
250 break;
251 }
252 }
253 catch ( final IOException e )
254 {
255 final String message = "Problem processing request. " + request + " Error: " + e.getMessage();
256 log.error( message, e );
257 response.setSuccess( false );
258 response.setErrorMessage( message );
259 }
260 }
261
262 return response;
263 }
264
265
266
267
268
269
270
271 protected <K, V> RemoteHttpCacheService<K, V> createRemoteHttpCacheService( final ICompositeCacheManager cacheManager )
272 {
273 final Properties props = cacheManager.getConfigurationProperties();
274 final ICacheEventLogger cacheEventLogger = configureCacheEventLogger( props );
275 final RemoteHttpCacheServerAttributes attributes = configureRemoteHttpCacheServerAttributes( props );
276
277 final RemoteHttpCacheService<K, V> service = new RemoteHttpCacheService<>( cacheManager, attributes, cacheEventLogger );
278 log.info( "Created new RemoteHttpCacheService {0}", service );
279 return service;
280 }
281
282
283
284
285
286
287
288 protected ICacheEventLogger configureCacheEventLogger( final Properties props )
289 {
290
291 return AuxiliaryCacheConfigurator
292 .parseCacheEventLogger( props, IRemoteHttpCacheConstants.HTTP_CACHE_SERVER_PREFIX );
293 }
294
295
296
297
298
299
300
301
302
303 protected RemoteHttpCacheServerAttributes configureRemoteHttpCacheServerAttributes( final Properties prop )
304 {
305 final RemoteHttpCacheServerAttributes rcsa = new RemoteHttpCacheServerAttributes();
306
307
308 PropertySetter.setProperties( rcsa, prop,
309 IRemoteHttpCacheConstants.HTTP_CACHE_SERVER_ATTRIBUTES_PROPERTY_PREFIX + "." );
310
311 return rcsa;
312 }
313
314
315
316
317 protected void setRemoteCacheService(final ICacheServiceNonLocal<Serializable, Serializable> rcs)
318 {
319 remoteCacheService = rcs;
320 }
321
322
323
324
325 private void incrementServiceCallCount()
326 {
327
328 serviceCalls++;
329 if ( log.isInfoEnabled() && (serviceCalls % logInterval == 0) )
330 {
331 log.info( "serviceCalls = {0}", serviceCalls );
332 }
333 }
334
335
336 @Override
337 public void destroy()
338 {
339 log.info( "Servlet Destroyed, shutting down JCS." );
340
341 cacheMgr.shutDown();
342 }
343
344
345
346
347
348
349 @Override
350 public String getServletInfo()
351 {
352 return "RemoteHttpCacheServlet";
353 }
354 }