1 15 package org.apache.tapestry.services.impl; 16 17 import java.io.BufferedInputStream ; 18 import java.io.IOException ; 19 import java.io.InputStream ; 20 import java.net.URL ; 21 import java.util.ArrayList ; 22 import java.util.Collections ; 23 import java.util.HashMap ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 import java.util.Locale ; 27 import java.util.Map ; 28 import java.util.Properties ; 29 30 import org.apache.hivemind.ApplicationRuntimeException; 31 import org.apache.hivemind.Messages; 32 import org.apache.hivemind.Resource; 33 import org.apache.hivemind.util.Defense; 34 import org.apache.hivemind.util.LocalizedNameGenerator; 35 import org.apache.tapestry.IComponent; 36 import org.apache.tapestry.INamespace; 37 import org.apache.tapestry.event.ResetEventListener; 38 import org.apache.tapestry.services.ComponentMessagesSource; 39 import org.apache.tapestry.services.ComponentPropertySource; 40 import org.apache.tapestry.util.text.LocalizedProperties; 41 42 48 49 public class ComponentMessagesSourceImpl implements ComponentMessagesSource, ResetEventListener 50 { 51 private Properties _emptyProperties = new Properties (); 52 53 private static final String SUFFIX = ".properties"; 54 55 59 60 public static final String MESSAGES_ENCODING_PROPERTY_NAME = "org.apache.tapestry.messages-encoding"; 61 62 66 67 private Map _componentCache = new HashMap (); 68 69 private ComponentPropertySource _componentPropertySource; 70 71 75 76 protected synchronized Properties getLocalizedProperties(IComponent component) 77 { 78 Defense.notNull(component, "component"); 79 80 Resource specificationLocation = component.getSpecification().getSpecificationLocation(); 81 Locale locale = component.getPage().getLocale(); 82 83 Map propertiesMap = findPropertiesMapForResource(specificationLocation); 84 85 Properties result = (Properties ) propertiesMap.get(locale); 86 87 if (result == null) 88 { 89 90 92 result = assembleComponentProperties( 93 component, 94 specificationLocation, 95 propertiesMap, 96 locale); 97 98 propertiesMap.put(locale, result); 99 } 100 101 return result; 102 } 103 104 private Map findPropertiesMapForResource(Resource resource) 105 { 106 Map result = (Map ) _componentCache.get(resource); 107 108 if (result == null) 109 { 110 result = new HashMap (); 111 _componentCache.put(resource, result); 112 } 113 114 return result; 115 } 116 117 private Properties getNamespaceProperties(IComponent component, Locale locale) 118 { 119 INamespace namespace = component.getNamespace(); 120 121 Resource namespaceLocation = namespace.getSpecificationLocation(); 122 123 Map propertiesMap = findPropertiesMapForResource(namespaceLocation); 124 125 Properties result = (Properties ) propertiesMap.get(locale); 126 127 if (result == null) 128 { 129 result = assembleNamespaceProperties(namespace, propertiesMap, locale); 130 131 propertiesMap.put(locale, result); 132 } 133 134 return result; 135 } 136 137 private Properties assembleComponentProperties(IComponent component, 138 Resource baseResourceLocation, Map propertiesMap, Locale locale) 139 { 140 List localizations = findLocalizationsForResource(baseResourceLocation, locale); 141 142 Properties parent = getNamespaceProperties(component, locale); 143 144 Iterator i = localizations.iterator(); 145 146 while (i.hasNext()) 147 { 148 ResourceLocalization rl = (ResourceLocalization) i.next(); 149 150 Locale l = rl.getLocale(); 151 152 Properties properties = (Properties ) propertiesMap.get(l); 153 154 if (properties == null) 155 { 156 properties = readComponentProperties(component, l, rl.getResource(), parent); 157 158 propertiesMap.put(l, properties); 159 } 160 161 parent = properties; 162 } 163 164 return parent; 165 } 166 167 private Properties assembleNamespaceProperties(INamespace namespace, Map propertiesMap, 168 Locale locale) 169 { 170 List localizations = findLocalizationsForResource( 171 namespace.getSpecificationLocation(), 172 locale); 173 174 176 Properties parent = _emptyProperties; 177 178 Iterator i = localizations.iterator(); 179 180 while (i.hasNext()) 181 { 182 ResourceLocalization rl = (ResourceLocalization) i.next(); 183 184 Locale l = rl.getLocale(); 185 186 Properties properties = (Properties ) propertiesMap.get(l); 187 188 if (properties == null) 189 { 190 properties = readNamespaceProperties(namespace, l, rl.getResource(), parent); 191 192 propertiesMap.put(l, properties); 193 } 194 195 parent = properties; 196 } 197 198 return parent; 199 200 } 201 202 208 209 private List findLocalizationsForResource(Resource resource, Locale locale) 210 { 211 List result = new ArrayList (); 212 213 String baseName = extractBaseName(resource); 214 215 LocalizedNameGenerator g = new LocalizedNameGenerator(baseName, locale, SUFFIX); 216 217 while (g.more()) 218 { 219 String localizedName = g.next(); 220 Locale l = g.getCurrentLocale(); 221 Resource localizedResource = resource.getRelativeResource(localizedName); 222 223 result.add(new ResourceLocalization(l, localizedResource)); 224 } 225 226 Collections.reverse(result); 227 228 return result; 229 } 230 231 private String extractBaseName(Resource baseResourceLocation) 232 { 233 String fileName = baseResourceLocation.getName(); 234 int dotx = fileName.lastIndexOf('.'); 235 236 return fileName.substring(0, dotx); 237 } 238 239 private Properties readComponentProperties(IComponent component, Locale locale, 240 Resource propertiesResource, Properties parent) 241 { 242 String encoding = getComponentMessagesEncoding(component, locale); 243 244 return readPropertiesResource(propertiesResource.getResourceURL(), encoding, parent); 245 } 246 247 private Properties readNamespaceProperties(INamespace namespace, Locale locale, 248 Resource propertiesResource, Properties parent) 249 { 250 String encoding = getNamespaceMessagesEncoding(namespace, locale); 251 252 return readPropertiesResource(propertiesResource.getResourceURL(), encoding, parent); 253 } 254 255 private Properties readPropertiesResource(URL resourceURL, String encoding, Properties parent) 256 { 257 if (resourceURL == null) 258 return parent; 259 260 Properties result = new Properties (parent); 261 262 LocalizedProperties wrapper = new LocalizedProperties(result); 263 264 InputStream input = null; 265 266 try 267 { 268 input = new BufferedInputStream (resourceURL.openStream()); 269 270 if (encoding == null) 271 wrapper.load(input); 272 else 273 wrapper.load(input, encoding); 274 275 input.close(); 276 } 277 catch (IOException ex) 278 { 279 throw new ApplicationRuntimeException(ImplMessages.unableToLoadProperties( 280 resourceURL, 281 ex), ex); 282 } 283 finally 284 { 285 close(input); 286 } 287 288 return result; 289 } 290 291 private void close(InputStream is) 292 { 293 if (is != null) 294 try 295 { 296 is.close(); 297 } 298 catch (IOException ex) 299 { 300 } 302 } 303 304 307 308 public synchronized void resetEventDidOccur() 309 { 310 _componentCache.clear(); 311 } 312 313 public Messages getMessages(IComponent component) 314 { 315 return new ComponentMessages(component.getPage().getLocale(), 316 getLocalizedProperties(component)); 317 } 318 319 private String getComponentMessagesEncoding(IComponent component, Locale locale) 320 { 321 String encoding = _componentPropertySource.getLocalizedComponentProperty( 322 component, 323 locale, 324 MESSAGES_ENCODING_PROPERTY_NAME); 325 326 if (encoding == null) 327 encoding = _componentPropertySource.getLocalizedComponentProperty( 328 component, 329 locale, 330 TemplateSourceImpl.TEMPLATE_ENCODING_PROPERTY_NAME); 331 332 return encoding; 333 } 334 335 private String getNamespaceMessagesEncoding(INamespace namespace, Locale locale) 336 { 337 return _componentPropertySource.getLocalizedNamespaceProperty( 338 namespace, 339 locale, 340 MESSAGES_ENCODING_PROPERTY_NAME); 341 } 342 343 public void setComponentPropertySource(ComponentPropertySource componentPropertySource) 344 { 345 _componentPropertySource = componentPropertySource; 346 } 347 } | Popular Tags |