1 package org.apache.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.io.FileInputStream;
23 import java.io.IOException;
24 import java.util.ArrayList;
25 import java.util.Enumeration;
26 import java.util.List;
27 import java.util.Properties;
28 import java.util.StringTokenizer;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.jcs.auxiliary.AuxiliaryCache;
33 import org.apache.jcs.auxiliary.AuxiliaryCacheAttributes;
34 import org.apache.jcs.auxiliary.AuxiliaryCacheFactory;
35 import org.apache.jcs.config.OptionConverter;
36 import org.apache.jcs.config.PropertySetter;
37 import org.apache.jcs.engine.behavior.ICache;
38 import org.apache.jcs.engine.behavior.ICompositeCacheAttributes;
39 import org.apache.jcs.engine.behavior.IElementAttributes;
40
41 /***
42 * This class configures JCS based on a properties object.
43 * <p>
44 * This class is based on the log4j class org.apache.log4j.PropertyConfigurator
45 * which was made by: "Luke Blanshard" <Luke@quiq.com>"Mark DONSZELMANN"
46 * <Mark.Donszelmann@cern.ch>"Anders Kristensen" <akristensen@dynamicsoft.com>
47 *
48 */
49 public class CompositeCacheConfigurator
50 {
51 private final static Log log = LogFactory.getLog( CompositeCacheConfigurator.class );
52
53 final static String DEFAULT_REGION = "jcs.default";
54
55 final static String REGION_PREFIX = "jcs.region.";
56
57 final static String SYSTEM_REGION_PREFIX = "jcs.system.";
58
59 final static String AUXILIARY_PREFIX = "jcs.auxiliary.";
60
61 final static String ATTRIBUTE_PREFIX = ".attributes";
62
63 final static String CACHE_ATTRIBUTE_PREFIX = ".cacheattributes";
64
65 final static String ELEMENT_ATTRIBUTE_PREFIX = ".elementattributes";
66
67 private CompositeCacheManager compositeCacheManager;
68
69 /***
70 * Constructor for the CompositeCacheConfigurator object
71 *
72 * @param ccMgr
73 */
74 public CompositeCacheConfigurator( CompositeCacheManager ccMgr )
75 {
76 this.compositeCacheManager = ccMgr;
77 }
78
79 /***
80 * Configure cached for file name.
81 * <p>
82 * This is only used for testing. The manager handles the translation of a
83 * file into a properties object.
84 *
85 * @param configFileName
86 */
87 protected void doConfigure( String configFileName )
88 {
89 Properties props = new Properties();
90 try
91 {
92 FileInputStream istream = new FileInputStream( configFileName );
93 props.load( istream );
94 istream.close();
95 }
96 catch ( IOException e )
97 {
98 log.error( "Could not read configuration file, ignored: " + configFileName, e );
99 return;
100 }
101
102
103 doConfigure( props );
104 }
105
106 /***
107 * Configure cache for properties object.
108 * <p>
109 * This method proceeds in several steps:
110 * <ul>
111 * <li>Store props for use by non configured caches.
112 * <li>Set default value list
113 * <li>Set default cache attr
114 * <li>Set default element attr
115 * <li>Setup system caches to be used
116 * <li>Setup preconfigured caches
117 * </ul>
118 *
119 * @param properties
120 */
121 public void doConfigure( Properties properties )
122 {
123 long start = System.currentTimeMillis();
124
125
126 compositeCacheManager.props = properties;
127
128 setDefaultAuxValues( properties );
129
130 setDefaultCompositeCacheAttributes( properties );
131
132 setDefaultElementAttributes( properties );
133
134
135
136 parseSystemRegions( properties );
137
138
139 parseRegions( properties );
140
141 long end = System.currentTimeMillis();
142 if ( log.isInfoEnabled() )
143 {
144 log.info( "Finished configuration in " + ( end - start ) + " ms." );
145 }
146
147 }
148
149 /***
150 * Set the default aux list for new caches.
151 *
152 * @param props
153 */
154 protected void setDefaultAuxValues( Properties props )
155 {
156 String value = OptionConverter.findAndSubst( DEFAULT_REGION, props );
157 compositeCacheManager.defaultAuxValues = value;
158
159 if ( log.isInfoEnabled() )
160 {
161 log.info( "Setting default auxiliaries to " + value );
162 }
163 }
164
165 /***
166 * Set the default CompositeCacheAttributes for new caches.
167 *
168 * @param props
169 */
170 protected void setDefaultCompositeCacheAttributes( Properties props )
171 {
172 ICompositeCacheAttributes icca = parseCompositeCacheAttributes( props, "",
173 CompositeCacheConfigurator.DEFAULT_REGION );
174 compositeCacheManager.setDefaultCacheAttributes( icca );
175
176 log.info( "setting defaultCompositeCacheAttributes to " + icca );
177 }
178
179 /***
180 * Set the default ElementAttributes for new caches.
181 *
182 * @param props
183 */
184 protected void setDefaultElementAttributes( Properties props )
185 {
186 IElementAttributes iea = parseElementAttributes( props, "", CompositeCacheConfigurator.DEFAULT_REGION );
187 compositeCacheManager.setDefaultElementAttributes( iea );
188
189 log.info( "setting defaultElementAttributes to " + iea );
190 }
191
192 /***
193 * Create caches used internally. System status gives them creation
194 * priority.
195 *
196 * @param props
197 */
198 protected void parseSystemRegions( Properties props )
199 {
200 Enumeration en = props.propertyNames();
201 while ( en.hasMoreElements() )
202 {
203 String key = (String) en.nextElement();
204 if ( key.startsWith( SYSTEM_REGION_PREFIX ) && ( key.indexOf( "attributes" ) == -1 ) )
205 {
206 String regionName = key.substring( SYSTEM_REGION_PREFIX.length() );
207 String value = OptionConverter.findAndSubst( key, props );
208 ICache cache;
209 synchronized ( regionName )
210 {
211 cache = parseRegion( props, regionName, value, null, SYSTEM_REGION_PREFIX );
212 }
213 compositeCacheManager.systemCaches.put( regionName, cache );
214
215
216 compositeCacheManager.caches.put( regionName, cache );
217 }
218 }
219 }
220
221 /***
222 * Parse region elements.
223 *
224 * @param props
225 */
226 protected void parseRegions( Properties props )
227 {
228 List regionNames = new ArrayList();
229
230 Enumeration en = props.propertyNames();
231 while ( en.hasMoreElements() )
232 {
233 String key = (String) en.nextElement();
234 if ( key.startsWith( REGION_PREFIX ) && ( key.indexOf( "attributes" ) == -1 ) )
235 {
236 String regionName = key.substring( REGION_PREFIX.length() );
237
238 regionNames.add( regionName );
239
240 String value = OptionConverter.findAndSubst( key, props );
241 ICache cache;
242 synchronized ( regionName )
243 {
244 cache = parseRegion( props, regionName, value );
245 }
246 compositeCacheManager.caches.put( regionName, cache );
247 }
248 }
249
250 if ( log.isInfoEnabled() )
251 {
252 log.info( "Parsed regions " + regionNames );
253 }
254
255 }
256
257 /***
258 * Create cache region.
259 *
260 * @param props
261 * @param regName
262 * @param value
263 * @return CompositeCache
264 */
265 protected CompositeCache parseRegion( Properties props, String regName, String value )
266 {
267 return parseRegion( props, regName, value, null, REGION_PREFIX );
268 }
269
270 /***
271 * Get all the properties for a region and configure its cache.
272 * <p>
273 * This method tells the otehr parse method the name of the region prefix.
274 *
275 * @param props
276 * @param regName
277 * @param value
278 * @param cca
279 * @return CompositeCache
280 */
281 protected CompositeCache parseRegion( Properties props, String regName, String value, ICompositeCacheAttributes cca )
282 {
283 return parseRegion( props, regName, value, cca, REGION_PREFIX );
284 }
285
286 /***
287 * Get all the properties for a region and configure its cache.
288 *
289 * @param props
290 * @param regName
291 * @param value
292 * @param cca
293 * @param regionPrefix
294 * @return CompositeCache
295 */
296 protected CompositeCache parseRegion( Properties props, String regName, String value,
297 ICompositeCacheAttributes cca, String regionPrefix )
298 {
299
300
301
302 if ( cca == null )
303 {
304 cca = parseCompositeCacheAttributes( props, regName, regionPrefix );
305 }
306
307 IElementAttributes ea = parseElementAttributes( props, regName, regionPrefix );
308
309 CompositeCache cache = new CompositeCache( regName, cca, ea );
310
311
312
313 List auxList = new ArrayList();
314
315 if ( log.isDebugEnabled() )
316 {
317 log.debug( "Parsing region name '" + regName + "', value '" + value + "'" );
318 }
319
320
321 StringTokenizer st = new StringTokenizer( value, "," );
322
323
324
325
326 if ( !( value.startsWith( "," ) || value.equals( "" ) ) )
327 {
328
329 if ( !st.hasMoreTokens() )
330 {
331 return null;
332 }
333 }
334
335 AuxiliaryCache auxCache;
336 String auxName;
337 while ( st.hasMoreTokens() )
338 {
339 auxName = st.nextToken().trim();
340 if ( auxName == null || auxName.equals( "," ) )
341 {
342 continue;
343 }
344 log.debug( "Parsing auxiliary named \"" + auxName + "\"." );
345
346 auxCache = parseAuxiliary( cache, props, auxName, regName );
347
348 if ( auxCache != null )
349 {
350 auxList.add( auxCache );
351 }
352 }
353
354
355
356 cache.setAuxCaches( (AuxiliaryCache[]) auxList.toArray( new AuxiliaryCache[0] ) );
357
358
359
360 return cache;
361 }
362
363 /***
364 * Get an compositecacheattributes for the listed region.
365 *
366 * @param props
367 * @param regName
368 * @return
369 */
370 protected ICompositeCacheAttributes parseCompositeCacheAttributes( Properties props, String regName )
371 {
372 return parseCompositeCacheAttributes( props, regName, REGION_PREFIX );
373 }
374
375 /***
376 * Get the main attributes for a region.
377 *
378 * @param props
379 * @param regName
380 * @param regionPrefix
381 * @return ICompositeCacheAttributes
382 */
383 protected ICompositeCacheAttributes parseCompositeCacheAttributes( Properties props, String regName,
384 String regionPrefix )
385 {
386 ICompositeCacheAttributes ccAttr;
387
388 String attrName = regionPrefix + regName + CACHE_ATTRIBUTE_PREFIX;
389
390
391
392 ccAttr = (ICompositeCacheAttributes) OptionConverter
393 .instantiateByKey( props, attrName, org.apache.jcs.engine.behavior.ICompositeCacheAttributes.class, null );
394
395 if ( ccAttr == null )
396 {
397 if ( log.isInfoEnabled() )
398 {
399 log.info( "No special CompositeCacheAttributes class defined for key [" + attrName + "], using default class." );
400 }
401
402 ICompositeCacheAttributes ccAttr2 = compositeCacheManager.getDefaultCacheAttributes();
403 ccAttr = ccAttr2.copy();
404 }
405
406 if ( log.isDebugEnabled() )
407 {
408 log.debug( "Parsing options for '" + attrName + "'" );
409 }
410
411 PropertySetter.setProperties( ccAttr, props, attrName + "." );
412 ccAttr.setCacheName( regName );
413
414 if ( log.isDebugEnabled() )
415 {
416 log.debug( "End of parsing for \"" + attrName + "\"." );
417 }
418
419
420 ccAttr.setCacheName( regName );
421 return ccAttr;
422 }
423
424 /***
425 * Create the element attributes from the properties object for a cache
426 * region.
427 *
428 * @param props
429 * @param regName
430 * @param regionPrefix
431 * @return IElementAttributes
432 */
433 protected IElementAttributes parseElementAttributes( Properties props, String regName, String regionPrefix )
434 {
435 IElementAttributes eAttr;
436
437 String attrName = regionPrefix + regName + CompositeCacheConfigurator.ELEMENT_ATTRIBUTE_PREFIX;
438
439
440
441 eAttr = (IElementAttributes) OptionConverter
442 .instantiateByKey( props, attrName, org.apache.jcs.engine.behavior.IElementAttributes.class, null );
443 if ( eAttr == null )
444 {
445 if ( log.isInfoEnabled() )
446 {
447 log.info( "No special ElementAttribute class defined for key [" + attrName + "], using default class." );
448 }
449
450 IElementAttributes eAttr2 = compositeCacheManager.getDefaultElementAttributes();
451 eAttr = eAttr2.copy();
452 }
453
454 if ( log.isDebugEnabled() )
455 {
456 log.debug( "Parsing options for '" + attrName + "'" );
457 }
458
459 PropertySetter.setProperties( eAttr, props, attrName + "." );
460
461
462 if ( log.isDebugEnabled() )
463 {
464 log.debug( "End of parsing for \"" + attrName + "\"." );
465 }
466
467
468
469 return eAttr;
470 }
471
472 /***
473 * Get an aux cache for the listed aux for a region.
474 *
475 * @param cache
476 * the cache manager
477 * @param props
478 * the configuration propeties
479 * @param auxName
480 * the name of the auxiliary cache
481 * @param regName
482 * the name of the region.
483 * @return AuxiliaryCache
484 */
485 protected AuxiliaryCache parseAuxiliary( CompositeCache cache, Properties props, String auxName, String regName )
486 {
487 AuxiliaryCache auxCache;
488
489 if ( log.isDebugEnabled() )
490 {
491
492
493 log.debug( "parseAuxiliary, Cache = " + cache );
494 }
495
496
497 AuxiliaryCacheFactory auxFac = compositeCacheManager.registryFacGet( auxName );
498 if ( auxFac == null )
499 {
500
501 String prefix = AUXILIARY_PREFIX + auxName;
502 auxFac = (AuxiliaryCacheFactory) OptionConverter
503 .instantiateByKey( props, prefix, org.apache.jcs.auxiliary.AuxiliaryCacheFactory.class, null );
504 if ( auxFac == null )
505 {
506 log.error( "Could not instantiate auxFactory named \"" + auxName + "\"." );
507 return null;
508 }
509
510 auxFac.setName( auxName );
511
512 compositeCacheManager.registryFacPut( auxFac );
513 }
514
515
516 AuxiliaryCacheAttributes auxAttr = compositeCacheManager.registryAttrGet( auxName );
517 String attrName = AUXILIARY_PREFIX + auxName + ATTRIBUTE_PREFIX;
518 if ( auxAttr == null )
519 {
520
521 String prefix = AUXILIARY_PREFIX + auxName + ATTRIBUTE_PREFIX;
522 auxAttr = (AuxiliaryCacheAttributes) OptionConverter
523 .instantiateByKey( props, prefix, org.apache.jcs.auxiliary.AuxiliaryCacheAttributes.class, null );
524 if ( auxFac == null )
525 {
526 log.error( "Could not instantiate auxAttr named '" + attrName + "'" );
527 return null;
528 }
529 auxAttr.setName( auxName );
530 compositeCacheManager.registryAttrPut( auxAttr );
531 }
532
533 auxAttr = auxAttr.copy();
534
535 if ( log.isDebugEnabled() )
536 {
537 log.debug( "Parsing options for '" + attrName + "'" );
538 }
539
540 PropertySetter.setProperties( auxAttr, props, attrName + "." );
541 auxAttr.setCacheName( regName );
542
543 if ( log.isDebugEnabled() )
544 {
545 log.debug( "End of parsing for '" + attrName + "'" );
546 }
547
548
549 auxAttr.setCacheName( regName );
550
551
552
553
554 auxCache = auxFac.createCache( auxAttr, compositeCacheManager );
555 return auxCache;
556 }
557 }