1 package org.apache.commons.jcs.engine.control;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.Properties;
25 import java.util.StringTokenizer;
26
27 import org.apache.commons.jcs.auxiliary.AuxiliaryCache;
28 import org.apache.commons.jcs.auxiliary.AuxiliaryCacheAttributes;
29 import org.apache.commons.jcs.auxiliary.AuxiliaryCacheConfigurator;
30 import org.apache.commons.jcs.auxiliary.AuxiliaryCacheFactory;
31 import org.apache.commons.jcs.engine.behavior.ICache;
32 import org.apache.commons.jcs.engine.behavior.ICompositeCacheAttributes;
33 import org.apache.commons.jcs.engine.behavior.IElementAttributes;
34 import org.apache.commons.jcs.engine.behavior.IElementSerializer;
35 import org.apache.commons.jcs.engine.behavior.IRequireScheduler;
36 import org.apache.commons.jcs.engine.logging.behavior.ICacheEventLogger;
37 import org.apache.commons.jcs.engine.match.KeyMatcherPatternImpl;
38 import org.apache.commons.jcs.engine.match.behavior.IKeyMatcher;
39 import org.apache.commons.jcs.utils.config.OptionConverter;
40 import org.apache.commons.jcs.utils.config.PropertySetter;
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43
44
45
46
47
48
49
50
51 public class CompositeCacheConfigurator
52 {
53
54 private static final Log log = LogFactory.getLog( CompositeCacheConfigurator.class );
55
56
57 protected static final String SYSTEM_PROPERTY_KEY_PREFIX = "jcs";
58
59
60 protected static final String REGION_PREFIX = "jcs.region.";
61
62
63 protected static final String SYSTEM_REGION_PREFIX = "jcs.system.";
64
65
66 protected static final String AUXILIARY_PREFIX = "jcs.auxiliary.";
67
68
69 protected static final String ATTRIBUTE_PREFIX = ".attributes";
70
71
72 protected static final String CACHE_ATTRIBUTE_PREFIX = ".cacheattributes";
73
74
75 protected static final String ELEMENT_ATTRIBUTE_PREFIX = ".elementattributes";
76
77
78
79
80
81
82 public static final String KEY_MATCHER_PREFIX = ".keymatcher";
83
84
85
86
87 public CompositeCacheConfigurator()
88 {
89
90 }
91
92
93
94
95
96
97
98 protected void parseSystemRegions( Properties props, CompositeCacheManager ccm )
99 {
100 for (String key : props.stringPropertyNames() )
101 {
102 if ( key.startsWith( SYSTEM_REGION_PREFIX ) && key.indexOf( "attributes" ) == -1 )
103 {
104 String regionName = key.substring( SYSTEM_REGION_PREFIX.length() );
105 String auxiliaries = OptionConverter.findAndSubst( key, props );
106 ICache<?, ?> cache;
107 synchronized ( regionName )
108 {
109 cache = parseRegion( props, ccm, regionName, auxiliaries, null, SYSTEM_REGION_PREFIX );
110 }
111 ccm.addCache( regionName, cache );
112 }
113 }
114 }
115
116
117
118
119
120
121
122 protected void parseRegions( Properties props, CompositeCacheManager ccm )
123 {
124 List<String> regionNames = new ArrayList<String>();
125
126 for (String key : props.stringPropertyNames() )
127 {
128 if ( key.startsWith( REGION_PREFIX ) && key.indexOf( "attributes" ) == -1 )
129 {
130 String regionName = key.substring( REGION_PREFIX.length() );
131 regionNames.add( regionName );
132 String auxiliaries = OptionConverter.findAndSubst( key, props );
133 ICache<?, ?> cache;
134 synchronized ( regionName )
135 {
136 cache = parseRegion( props, ccm, regionName, auxiliaries );
137 }
138 ccm.addCache( regionName, cache );
139 }
140 }
141
142 if ( log.isInfoEnabled() )
143 {
144 log.info( "Parsed regions " + regionNames );
145 }
146 }
147
148
149
150
151
152
153
154
155
156
157
158 protected <K, V> CompositeCache<K, V> parseRegion(
159 Properties props, CompositeCacheManager ccm, String regName, String auxiliaries )
160 {
161 return parseRegion( props, ccm, regName, auxiliaries, null, REGION_PREFIX );
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 protected <K, V> CompositeCache<K, V> parseRegion(
178 Properties props, CompositeCacheManager ccm, String regName, String auxiliaries,
179 ICompositeCacheAttributes cca )
180 {
181 return parseRegion( props, ccm, regName, auxiliaries, cca, REGION_PREFIX );
182 }
183
184
185
186
187
188
189
190
191
192
193
194
195
196 protected <K, V> CompositeCache<K, V> parseRegion(
197 Properties props, CompositeCacheManager ccm, String regName, String auxiliaries,
198 ICompositeCacheAttributes cca, String regionPrefix )
199 {
200
201
202 IElementAttributes ea = parseElementAttributes( props, regName,
203 ccm.getDefaultElementAttributes(), regionPrefix );
204
205 ICompositeCacheAttributes instantiationCca = cca == null
206 ? parseCompositeCacheAttributes(props, regName, ccm.getDefaultCacheAttributes(), regionPrefix)
207 : cca;
208 CompositeCache<K, V> cache = newCache(instantiationCca, ea);
209
210
211 cache.setCompositeCacheManager(ccm);
212
213
214 cache.setScheduledExecutorService(ccm.getScheduledExecutorService());
215
216
217 cache.setElementEventQueue(ccm.getElementEventQueue());
218
219 if (cache.getMemoryCache() instanceof IRequireScheduler)
220 {
221 ((IRequireScheduler)cache.getMemoryCache()).setScheduledExecutorService(
222 ccm.getScheduledExecutorService());
223 }
224
225 if (auxiliaries != null)
226 {
227
228 List<AuxiliaryCache<K, V>> auxList = new ArrayList<AuxiliaryCache<K, V>>();
229
230 if ( log.isDebugEnabled() )
231 {
232 log.debug( "Parsing region name '" + regName + "', value '" + auxiliaries + "'" );
233 }
234
235
236 StringTokenizer st = new StringTokenizer( auxiliaries, "," );
237
238
239
240
241 if ( !( auxiliaries.startsWith( "," ) || auxiliaries.equals( "" ) ) )
242 {
243
244 if ( !st.hasMoreTokens() )
245 {
246 return null;
247 }
248 }
249
250 AuxiliaryCache<K, V> auxCache;
251 String auxName;
252 while ( st.hasMoreTokens() )
253 {
254 auxName = st.nextToken().trim();
255 if ( auxName == null || auxName.equals( "," ) )
256 {
257 continue;
258 }
259 log.debug( "Parsing auxiliary named \"" + auxName + "\"." );
260
261 auxCache = parseAuxiliary( props, ccm, auxName, regName );
262
263 if ( auxCache != null )
264 {
265 if (auxCache instanceof IRequireScheduler)
266 {
267 ((IRequireScheduler) auxCache).setScheduledExecutorService(
268 ccm.getScheduledExecutorService());
269 }
270
271 auxList.add( auxCache );
272 }
273 }
274
275
276 @SuppressWarnings("unchecked")
277 AuxiliaryCache<K, V>[] auxArray = auxList.toArray( new AuxiliaryCache[0] );
278 cache.setAuxCaches( auxArray );
279 }
280
281
282 return cache;
283 }
284
285 protected <K, V> CompositeCache<K, V> newCache(
286 ICompositeCacheAttributes cca, IElementAttributes ea)
287 {
288 return new CompositeCache<K, V>( cca, ea );
289 }
290
291
292
293
294
295
296
297
298
299
300 protected ICompositeCacheAttributes parseCompositeCacheAttributes( Properties props,
301 String regName, ICompositeCacheAttributes defaultCCAttr )
302 {
303 return parseCompositeCacheAttributes( props, regName, defaultCCAttr, REGION_PREFIX );
304 }
305
306
307
308
309
310
311
312
313
314
315
316 protected ICompositeCacheAttributes parseCompositeCacheAttributes( Properties props,
317 String regName, ICompositeCacheAttributes defaultCCAttr, String regionPrefix )
318 {
319 ICompositeCacheAttributes ccAttr;
320
321 String attrName = regionPrefix + regName + CACHE_ATTRIBUTE_PREFIX;
322
323
324
325 ccAttr = OptionConverter.instantiateByKey( props, attrName, null );
326
327 if ( ccAttr == null )
328 {
329 if ( log.isInfoEnabled() )
330 {
331 log.info( "No special CompositeCacheAttributes class defined for key [" + attrName
332 + "], using default class." );
333 }
334
335 ccAttr = defaultCCAttr;
336 }
337
338 if ( log.isDebugEnabled() )
339 {
340 log.debug( "Parsing options for '" + attrName + "'" );
341 }
342
343 PropertySetter.setProperties( ccAttr, props, attrName + "." );
344 ccAttr.setCacheName( regName );
345
346 if ( log.isDebugEnabled() )
347 {
348 log.debug( "End of parsing for \"" + attrName + "\"." );
349 }
350
351
352 ccAttr.setCacheName( regName );
353 return ccAttr;
354 }
355
356
357
358
359
360
361
362
363
364
365
366 protected IElementAttributes parseElementAttributes( Properties props, String regName,
367 IElementAttributes defaultEAttr, String regionPrefix )
368 {
369 IElementAttributes eAttr;
370
371 String attrName = regionPrefix + regName + CompositeCacheConfigurator.ELEMENT_ATTRIBUTE_PREFIX;
372
373
374
375 eAttr = OptionConverter.instantiateByKey( props, attrName, null );
376 if ( eAttr == null )
377 {
378 if ( log.isInfoEnabled() )
379 {
380 log.info( "No special ElementAttribute class defined for key [" + attrName + "], using default class." );
381 }
382
383 eAttr = defaultEAttr;
384 }
385
386 if ( log.isDebugEnabled() )
387 {
388 log.debug( "Parsing options for '" + attrName + "'" );
389 }
390
391 PropertySetter.setProperties( eAttr, props, attrName + "." );
392
393
394 if ( log.isDebugEnabled() )
395 {
396 log.debug( "End of parsing for \"" + attrName + "\"." );
397 }
398
399
400
401 return eAttr;
402 }
403
404
405
406
407
408
409
410
411
412
413 protected <K, V> AuxiliaryCache<K, V> parseAuxiliary( Properties props, CompositeCacheManager ccm,
414 String auxName, String regName )
415 {
416 if ( log.isDebugEnabled() )
417 {
418 log.debug( "parseAuxiliary " + auxName );
419 }
420
421
422 @SuppressWarnings("unchecked")
423 AuxiliaryCache<K, V> auxCache = (AuxiliaryCache<K, V>) ccm.getAuxiliaryCache(auxName, regName);
424
425 if (auxCache == null)
426 {
427
428 AuxiliaryCacheFactory auxFac = ccm.registryFacGet( auxName );
429 if ( auxFac == null )
430 {
431
432 String prefix = AUXILIARY_PREFIX + auxName;
433 auxFac = OptionConverter.instantiateByKey( props, prefix, null );
434 if ( auxFac == null )
435 {
436 log.error( "Could not instantiate auxFactory named \"" + auxName + "\"." );
437 return null;
438 }
439
440 auxFac.setName( auxName );
441
442 if ( auxFac instanceof IRequireScheduler)
443 {
444 ((IRequireScheduler)auxFac).setScheduledExecutorService(ccm.getScheduledExecutorService());
445 }
446
447 auxFac.initialize();
448 ccm.registryFacPut( auxFac );
449 }
450
451
452 AuxiliaryCacheAttributes auxAttr = ccm.registryAttrGet( auxName );
453 String attrName = AUXILIARY_PREFIX + auxName + ATTRIBUTE_PREFIX;
454 if ( auxAttr == null )
455 {
456
457 String prefix = AUXILIARY_PREFIX + auxName + ATTRIBUTE_PREFIX;
458 auxAttr = OptionConverter.instantiateByKey( props, prefix, null );
459 if ( auxAttr == null )
460 {
461 log.error( "Could not instantiate auxAttr named '" + attrName + "'" );
462 return null;
463 }
464 auxAttr.setName( auxName );
465 ccm.registryAttrPut( auxAttr );
466 }
467
468 auxAttr = auxAttr.clone();
469
470 if ( log.isDebugEnabled() )
471 {
472 log.debug( "Parsing options for '" + attrName + "'" );
473 }
474
475 PropertySetter.setProperties( auxAttr, props, attrName + "." );
476 auxAttr.setCacheName( regName );
477
478 if ( log.isDebugEnabled() )
479 {
480 log.debug( "End of parsing for '" + attrName + "'" );
481 }
482
483
484 auxAttr.setCacheName( regName );
485
486 String auxPrefix = AUXILIARY_PREFIX + auxName;
487
488
489 ICacheEventLogger cacheEventLogger =
490 AuxiliaryCacheConfigurator.parseCacheEventLogger( props, auxPrefix );
491
492
493 IElementSerializer elementSerializer =
494 AuxiliaryCacheConfigurator.parseElementSerializer( props, auxPrefix );
495
496
497
498
499
500
501
502
503
504 try
505 {
506 auxCache = auxFac.createCache( auxAttr, ccm, cacheEventLogger, elementSerializer );
507 }
508 catch (Exception e)
509 {
510 log.error( "Could not instantiate auxiliary cache named \"" + regName + "\"." );
511 return null;
512 }
513
514 ccm.addAuxiliaryCache(auxName, regName, auxCache);
515 }
516
517 return auxCache;
518 }
519
520
521
522
523
524
525 protected static void overrideWithSystemProperties( Properties props )
526 {
527
528 Properties sysProps = System.getProperties();
529 for (String key : sysProps.stringPropertyNames())
530 {
531 if ( key.startsWith( SYSTEM_PROPERTY_KEY_PREFIX ) )
532 {
533 if ( log.isInfoEnabled() )
534 {
535 log.info( "Using system property [[" + key + "] [" + sysProps.getProperty( key ) + "]]" );
536 }
537 props.setProperty( key, sysProps.getProperty( key ) );
538 }
539 }
540 }
541
542
543
544
545
546
547
548
549 protected <K> IKeyMatcher<K> parseKeyMatcher( Properties props, String auxPrefix )
550 {
551
552
553 String keyMatcherClassName = auxPrefix + KEY_MATCHER_PREFIX;
554 IKeyMatcher<K> keyMatcher = OptionConverter.instantiateByKey( props, keyMatcherClassName, null );
555 if ( keyMatcher != null )
556 {
557 String attributePrefix = auxPrefix + KEY_MATCHER_PREFIX + ATTRIBUTE_PREFIX;
558 PropertySetter.setProperties( keyMatcher, props, attributePrefix + "." );
559 if ( log.isInfoEnabled() )
560 {
561 log.info( "Using custom key matcher [" + keyMatcher + "] for auxiliary [" + auxPrefix
562 + "]" );
563 }
564 }
565 else
566 {
567
568 keyMatcher = new KeyMatcherPatternImpl<K>();
569 if ( log.isInfoEnabled() )
570 {
571 log.info( "Using standard key matcher [" + keyMatcher + "] for auxiliary [" + auxPrefix + "]" );
572 }
573 }
574 return keyMatcher;
575 }
576 }