KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > sape > carbon > core > config > cache > SynchronizedConfigurationCache


1 /*
2  * The contents of this file are subject to the Sapient Public License
3  * Version 1.0 (the "License"); you may not use this file except in compliance
4  * with the License. You may obtain a copy of the License at
5  * http://carbon.sf.net/License.html.
6  *
7  * Software distributed under the License is distributed on an "AS IS" basis,
8  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
9  * the specific language governing rights and limitations under the License.
10  *
11  * The Original Code is The Carbon Component Framework.
12  *
13  * The Initial Developer of the Original Code is Sapient Corporation
14  *
15  * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
16  */

17
18 package org.sape.carbon.core.config.cache;
19
20 import java.util.Collections JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Map JavaDoc;
23
24 import org.sape.carbon.core.config.Configuration;
25 import org.sape.carbon.core.config.ConfigurationNotFoundException;
26 import org.sape.carbon.core.config.ConfigurationService;
27 import org.sape.carbon.core.config.format.ConfigurationFormatException;
28 import org.sape.carbon.core.config.node.ConfigurationDocument;
29 import org.sape.carbon.core.config.node.Node;
30 import org.sape.carbon.core.config.node.NodeIOException;
31 import org.sape.carbon.core.config.node.NodeNotFoundException;
32 import org.sape.carbon.core.config.node.event.NodeEventListener;
33 import org.sape.carbon.core.exception.ExceptionUtility;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37
38
39 /**
40  * <p>
41  * This implementation uses a synchronized hash map to store all configurations.
42  * This is a bottleneck and may be a point of contention when many threads
43  * required configurations simultaniously.
44  * </p>
45  * <p>
46  * Configuration objects are cached lazily, i.e. they are cached after they
47  * are requested the first time. Once a configuration object is cached, the
48  * cache will listen for Node events on the configuration. If a node event
49  * occurs, the entire cache is cleared. This is done to prevent inconsistencies
50  * between this cache and caches internal to the configuration objects
51  * themselves in the case of nested configurations.
52  * </p>
53  *
54  * Copyright 2002 Sapient
55  * @since carbon 1.1
56  * @author Douglas Voet, Oct 24, 2002
57  * @version $Revision: 1.11 $($Author: dvoet $ / $Date: 2003/05/05 21:21:16 $)
58  */

59 public class SynchronizedConfigurationCache
60     implements ConfigurationCache, NodeEventListener {
61
62     /** Provides a handle to Apache-commons logger */
63     private Log log = LogFactory.getLog(this.getClass());
64
65     /** Holds a synchronized cache of value. */
66     private Map JavaDoc cache = Collections.synchronizedMap(new HashMap JavaDoc());
67
68     /** Holds the config service being cached. */
69     private ConfigurationService configService;
70
71     /**
72      * Constructs a new SynchronizedConfigurationCache.
73      *
74      * @param configService the service to cache
75      */

76     public SynchronizedConfigurationCache(ConfigurationService configService) {
77         this.configService = configService;
78     }
79
80     /**
81      * Gets back a configuration with the given name. This will
82      * either return the configuration from the cache or load it
83      * if needed.
84      *
85      * @param name the name of the configuration to load
86      * @return configuration at the given name
87      * @throws ConfigurationNotFoundException indicates there is
88      * no configuration at the given name
89      */

90     public Configuration getConfiguration(String JavaDoc name) {
91         Configuration config = (Configuration) this.cache.get(name);
92         if (config == null) {
93             config = loadConfiguration(name);
94         }
95         return config;
96     }
97
98     /**
99      * Updates the configuration cache with the new instance of the node.
100      *
101      * @param changedNode the node that has been changed
102      */

103     public void nodeChanged(Node changedNode) {
104         try {
105             this.cache.clear();
106             this.cache.put(
107                 changedNode.getAbsoluteName(),
108                 ((ConfigurationDocument) changedNode).readConfiguration());
109
110         } catch (NodeIOException nioe) {
111             if (log.isWarnEnabled()) {
112                 log.warn("Could not read new configuration: "
113                     + ExceptionUtility.printStackTracesToString(nioe));
114             }
115         } catch (ConfigurationFormatException cfe) {
116             if (log.isWarnEnabled()) {
117                 log.warn("Could not read new configuration: "
118                     + ExceptionUtility.printStackTracesToString(cfe));
119             }
120         }
121     }
122
123     /**
124      * Removes the node from the cache.
125      *
126      * @param removedNodeName name of the node to remove
127      */

128     public void nodeRemoved(String JavaDoc removedNodeName) {
129         this.cache.clear();
130     }
131
132     /**
133      * Synchronized method to load configurations. Ensures that any
134      * configuration is loaded only once.
135      *
136      * @param name name of the requested configuration
137      * @return Configuration at the given name
138      * @throws ConfigurationNotFoundException indicates there is
139      * no configuration at the given name
140      */

141     private synchronized Configuration loadConfiguration(String JavaDoc name) {
142         // this is a legal double check because this.cache is synchronized,
143
// at no point is unsynchronized data accessed
144
// this double check exists to ensure that any configuration is only
145
// loaded into the cache once
146
Configuration config = (Configuration) this.cache.get(name);
147         if (config == null) {
148             try {
149                 config = this.configService.fetchWritableConfiguration(name);
150                 this.cache.put(name, config);
151
152                 if (log.isTraceEnabled()) {
153                     log.trace("Marking configuration ["
154                         + name
155                         + "] as read only");
156                 }
157                 config.setConfigurationReadOnly();
158                 this.configService.addNodeListener(name, this);
159             } catch (NodeNotFoundException nnfe) {
160                 // Catch checked configuration exception and rethrow as runtime
161
throw new ConfigurationNotFoundException(
162                     this.getClass(),
163                     "The configuration [" + name
164                         + "] was not found", nnfe);
165             }
166         }
167         return config;
168     }
169
170 }
171
Popular Tags