This project has retired. For details please refer to its
Attic page.
CachingLocaleUrlDefinitionDAO xref
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.tiles.definition.dao;
23
24 import java.net.MalformedURLException;
25 import java.net.URL;
26 import java.util.HashMap;
27 import java.util.LinkedHashMap;
28 import java.util.Locale;
29 import java.util.Map;
30
31 import org.apache.tiles.Definition;
32 import org.apache.tiles.definition.DefinitionsFactoryException;
33 import org.apache.tiles.definition.NoSuchDefinitionException;
34 import org.apache.tiles.definition.Refreshable;
35 import org.apache.tiles.definition.pattern.BasicPatternDefinitionResolver;
36 import org.apache.tiles.definition.pattern.PatternDefinitionResolver;
37 import org.apache.tiles.definition.pattern.PatternDefinitionResolverAware;
38 import org.apache.tiles.definition.pattern.wildcard.WildcardDefinitionPatternMatcherFactory;
39 import org.apache.tiles.util.LocaleUtil;
40
41 /***
42 * <p>
43 * A definitions DAO (loading URLs and using Locale as a customization key) that
44 * caches definitions that have been loaded in a raw way (i.e. with inheritance
45 * that is not resolved).
46 * </p>
47 * <p>
48 * It can check if the URLs change, but by default this feature is turned off.
49 * </p>
50 *
51 * @version $Rev: 823662 $ $Date: 2009-10-09 20:48:03 +0200 (ven, 09 ott 2009) $
52 * @since 2.1.0
53 */
54 public class CachingLocaleUrlDefinitionDAO extends BaseLocaleUrlDefinitionDAO
55 implements Refreshable, PatternDefinitionResolverAware<Locale> {
56
57 /***
58 * Initialization parameter to set whether we want to refresh URLs when they
59 * change.
60 *
61 * @since 2.1.0
62 */
63 public static final String CHECK_REFRESH_INIT_PARAMETER =
64 "org.apache.tiles.definition.dao.LocaleUrlDefinitionDAO.CHECK_REFRESH";
65
66 /***
67 * The locale-specific set of definitions objects.
68 *
69 * @since 2.1.0
70 */
71 protected Map<Locale, Map<String, Definition>> locale2definitionMap;
72
73 /***
74 * Flag that, when <code>true</code>, enables automatic checking of URLs
75 * changing.
76 *
77 * @since 2.1.0
78 */
79 protected boolean checkRefresh = false;
80
81 /***
82 * Resolves definitions using patterns.
83 *
84 * @since 2.2.0
85 */
86 protected PatternDefinitionResolver<Locale> definitionResolver;
87
88 /***
89 * Constructor.
90 *
91 * @since 2.1.0
92 */
93 public CachingLocaleUrlDefinitionDAO() {
94 locale2definitionMap = new HashMap<Locale, Map<String, Definition>>();
95 }
96
97 /*** {@inheritDoc} */
98 @Override
99 public void init(Map<String, String> params) {
100 super.init(params);
101
102 String param = params.get(CHECK_REFRESH_INIT_PARAMETER);
103 checkRefresh = "true".equals(param);
104 WildcardDefinitionPatternMatcherFactory definitionPatternMatcherFactory =
105 new WildcardDefinitionPatternMatcherFactory();
106 definitionResolver = new BasicPatternDefinitionResolver<Locale>(
107 definitionPatternMatcherFactory,
108 definitionPatternMatcherFactory);
109 }
110
111 /*** {@inheritDoc} */
112 public void setPatternDefinitionResolver(
113 PatternDefinitionResolver<Locale> definitionResolver) {
114 this.definitionResolver = definitionResolver;
115 }
116
117 /*** {@inheritDoc} */
118 public Definition getDefinition(String name, Locale customizationKey) {
119 Definition retValue = null;
120 if (customizationKey == null) {
121 customizationKey = LocaleUtil.NULL_LOCALE;
122 }
123 Map<String, Definition> definitions = getDefinitions(customizationKey);
124 if (definitions != null) {
125 retValue = definitions.get(name);
126
127 if (retValue == null) {
128 retValue = getDefinitionFromResolver(name, customizationKey);
129
130 if (retValue != null) {
131 try {
132 synchronized (definitions) {
133 definitions.put(name, retValue);
134 }
135 } catch (NoSuchDefinitionException ex) {
136 throw new IllegalStateException(
137 "Unable to resolve wildcard mapping", ex);
138 }
139 }
140 }
141 }
142
143 return retValue;
144 }
145
146 /*** {@inheritDoc} */
147 public Map<String, Definition> getDefinitions(Locale customizationKey) {
148 if (customizationKey == null) {
149 customizationKey = LocaleUtil.NULL_LOCALE;
150 }
151 Map<String, Definition> retValue = locale2definitionMap
152 .get(customizationKey);
153 if (retValue == null || (checkRefresh && refreshRequired())) {
154 retValue = checkAndloadDefinitions(customizationKey);
155 }
156 return retValue;
157 }
158
159 /*** {@inheritDoc} */
160 public synchronized void refresh() {
161 if (refreshRequired()) {
162 locale2definitionMap.clear();
163 }
164 }
165
166 /***
167 * Sets the flag to check URL refresh. If not called, the default is
168 * <code>false</code>.
169 *
170 * @param checkRefresh When <code>true</code>, enables automatic checking
171 * of URLs changing.
172 * @since 2.1.0
173 */
174 public void setCheckRefresh(boolean checkRefresh) {
175 this.checkRefresh = checkRefresh;
176 }
177
178 /***
179 * Returns a definition from the definition resolver.
180 *
181 * @param name The name of the definition.
182 * @param customizationKey The customization key to use.
183 * @return The resolved definition.
184 */
185 protected Definition getDefinitionFromResolver(String name,
186 Locale customizationKey) {
187 return definitionResolver.resolveDefinition(name,
188 customizationKey);
189 }
190
191 /***
192 * Checks if URLs have changed. If yes, it clears the cache. Then continues
193 * loading definitions.
194 *
195 * @param customizationKey The locale to use when loading URLs.
196 * @return The loaded definitions.
197 * @since 2.1.0
198 */
199 protected synchronized Map<String, Definition> checkAndloadDefinitions(
200 Locale customizationKey) {
201 if (checkRefresh && refreshRequired()) {
202 locale2definitionMap.clear();
203 }
204 loadDefinitions(customizationKey);
205 return locale2definitionMap.get(customizationKey);
206 }
207
208 /***
209 * Tries to load definitions if necessary.
210 *
211 * @param customizationKey The locale to use when loading URLs.
212 * @return The loaded definitions.
213 * @since 2.1.0
214 */
215 protected Map<String, Definition> loadDefinitions(Locale customizationKey) {
216 Map<String, Definition> localeDefsMap = locale2definitionMap
217 .get(customizationKey);
218 if (localeDefsMap != null) {
219 return localeDefsMap;
220 }
221
222 return loadDefinitionsFromURLs(customizationKey);
223 }
224
225 /***
226 * Loads definitions from the URLs.
227 *
228 * @param customizationKey The locale to use when loading URLs.
229 * @return The loaded definitions.
230 * @since 2.1.0
231 */
232 protected Map<String, Definition> loadDefinitionsFromURLs(Locale customizationKey) {
233 Map<String, Definition> localeDefsMap;
234
235 String postfix = LocaleUtil.calculatePostfix(customizationKey);
236 Locale parentLocale = LocaleUtil.getParentLocale(customizationKey);
237 localeDefsMap = new LinkedHashMap<String, Definition>();
238 if (parentLocale != null) {
239 Map<String, Definition> parentDefs = loadParentDefinitions(parentLocale);
240 if (parentDefs != null) {
241 localeDefsMap.putAll(parentDefs);
242 }
243 }
244
245 for (URL url : sourceURLs) {
246 String path = url.toExternalForm();
247
248 String newPath = LocaleUtil.concatPostfix(path, postfix);
249 try {
250 URL newUrl = new URL(newPath);
251 Map<String, Definition> defsMap = loadDefinitionsFromURL(newUrl);
252 if (defsMap != null) {
253 localeDefsMap.putAll(defsMap);
254 }
255 } catch (MalformedURLException e) {
256 throw new DefinitionsFactoryException("Error parsing URL "
257 + newPath, e);
258 }
259 }
260 Map<String, Definition> defsMap = definitionResolver
261 .storeDefinitionPatterns(copyDefinitionMap(localeDefsMap),
262 customizationKey);
263 locale2definitionMap.put(customizationKey, defsMap);
264 return localeDefsMap;
265 }
266
267 /***
268 * Loads the raw definitions from the URLs associated with a locale.
269 *
270 * @param customizationKey The locale to use when loading URLs.
271 * @return The loaded definitions.
272 * @since 2.1.3
273 * @deprecated Use {@link #loadDefinitionsFromURLs(Locale)}.
274 */
275 protected Map<String, Definition> loadRawDefinitionsFromURLs(
276 Locale customizationKey) {
277 return loadDefinitionsFromURLs(customizationKey);
278 }
279
280 /***
281 * Loads parent definitions, i.e. definitions mapped to a parent locale.
282 *
283 * @param parentLocale The locale to use when loading URLs.
284 * @return The loaded parent definitions.
285 * @since 2.1.0
286 */
287 protected Map<String, Definition> loadParentDefinitions(Locale parentLocale) {
288 return loadDefinitions(parentLocale);
289 }
290
291 /***
292 * Operations to be done after definitions are loaded.
293 *
294 * @param localeDefsMap The loaded definitions.
295 * @param customizationKey The locale to use when loading URLs.
296 * @since 2.1.0
297 * @deprecated Never used.
298 */
299 protected void postDefinitionLoadOperations(
300 Map<String, Definition> localeDefsMap, Locale customizationKey) {
301
302 definitionResolver.storeDefinitionPatterns(localeDefsMap, customizationKey);
303 }
304
305 /***
306 * Copies the definition map to be passed to a higher level of customization
307 * key.
308 *
309 * @param localeDefsMap The map of definition to be copied.
310 * @return The copy of the definition map. This particular implementation
311 * return the <code>localeDefsMap</code> itself.
312 * @since 2.1.4
313 */
314 protected Map<String, Definition> copyDefinitionMap(
315 Map<String, Definition> localeDefsMap) {
316 return localeDefsMap;
317 }
318 }