1 16 package org.apache.cocoon.i18n; 17 18 import org.apache.avalon.framework.activity.Disposable; 19 import org.apache.avalon.framework.component.ComponentException; 20 import org.apache.avalon.framework.configuration.Configurable; 21 import org.apache.avalon.framework.configuration.Configuration; 22 import org.apache.avalon.framework.configuration.ConfigurationException; 23 import org.apache.avalon.framework.logger.AbstractLogEnabled; 24 import org.apache.avalon.framework.logger.LogEnabled; 25 import org.apache.avalon.framework.service.ServiceException; 26 import org.apache.avalon.framework.service.ServiceManager; 27 import org.apache.avalon.framework.service.Serviceable; 28 import org.apache.avalon.framework.thread.ThreadSafe; 29 import org.apache.excalibur.source.Source; 30 import org.apache.excalibur.source.SourceResolver; 31 import org.apache.excalibur.store.Store; 32 33 import org.apache.cocoon.util.NetUtils; 34 35 import java.io.IOException ; 36 import java.util.Collections ; 37 import java.util.HashMap ; 38 import java.util.Locale ; 39 import java.util.Map ; 40 41 52 public class XMLResourceBundleFactory extends AbstractLogEnabled 53 implements BundleFactory, Serviceable, Configurable, 54 Disposable, ThreadSafe, LogEnabled { 55 56 59 private String directory; 60 61 67 private long interval; 68 69 72 protected ServiceManager manager; 73 74 77 protected SourceResolver resolver; 78 79 82 protected Store cache; 83 84 85 89 public void service(ServiceManager manager) throws ServiceException { 90 this.manager = manager; 91 this.resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE); 92 } 93 94 99 public void configure(Configuration configuration) throws ConfigurationException { 100 this.directory = configuration.getChild(ConfigurationKeys.ROOT_DIRECTORY).getValue(""); 101 102 String cacheRole = configuration.getChild(ConfigurationKeys.STORE_ROLE).getValue(Store.TRANSIENT_STORE); 103 try { 104 this.cache = (Store) this.manager.lookup(cacheRole); 105 } catch (ServiceException e) { 106 throw new ConfigurationException("Unable to lookup store '" + cacheRole + "'"); 107 } 108 109 this.interval = configuration.getChild(ConfigurationKeys.RELOAD_INTERVAL).getValueAsLong(60000L); 110 111 if (getLogger().isDebugEnabled()) { 112 getLogger().debug("Bundle directory '" + this.directory + "'"); 113 getLogger().debug("Store role '" + cacheRole + "'"); 114 } 115 } 116 117 120 public void dispose() { 121 this.manager.release(this.resolver); 122 this.manager.release(this.cache); 123 this.resolver = null; 124 this.cache = null; 125 this.manager = null; 126 } 127 128 132 137 protected String getDirectory() { 138 return this.directory; 139 } 140 141 149 public Bundle select(String name, String locale) throws ComponentException { 150 return select(getDirectory(), name, locale); 151 } 152 153 161 public Bundle select(String name, Locale locale) throws ComponentException { 162 return select(getDirectory(), name, locale); 163 } 164 165 175 public Bundle select(String directory, String name, String localeName) 176 throws ComponentException { 177 return select(directory, name, new Locale (localeName, localeName)); 178 } 179 180 190 public Bundle select(String directory, String name, Locale locale) 191 throws ComponentException { 192 return select(new String [] { directory }, name, locale); 193 } 194 195 205 public Bundle select(String [] directories, String name, Locale locale) 206 throws ComponentException { 207 Bundle bundle = _select(directories, 0, name, locale); 208 if (bundle == null) { 209 throw new ComponentException(name, "Unable to locate resource: " + name); 210 } 211 return bundle; 212 } 213 214 public void release(Bundle bundle) { 215 } 217 218 222 230 private XMLResourceBundle _select(String [] directories, int index, String name, 231 Locale locale) 232 throws ComponentException { 233 if (getLogger().isDebugEnabled()) { 234 getLogger().debug("Selecting from: " + name + ", locale: " + locale + 235 ", directory: " + directories[index]); 236 } 237 238 final String cacheKey = getCacheKey(directories, index, name, locale); 239 240 XMLResourceBundle bundle = selectCached(cacheKey); 241 if (bundle == null) { 242 synchronized (this) { 243 bundle = selectCached(cacheKey); 244 if (bundle == null) { 245 boolean localeAvailable = (locale != null && !locale.getLanguage().equals("")); 246 index++; 247 248 XMLResourceBundle parent = null; 250 if (localeAvailable && index == directories.length) { 251 parent = _select(directories, 0, name, getParentLocale(locale)); 254 } else if (index < directories.length) { 255 parent = _select(directories, index, name, locale); 257 } 258 259 final String sourceURI = getSourceURI(directories[index - 1], name, locale); 261 bundle = _create(sourceURI, locale, parent); 262 updateCache(cacheKey, bundle); 263 } 264 } 265 } 266 return bundle; 267 } 268 269 280 private XMLResourceBundle _create(String sourceURI, 281 Locale locale, 282 XMLResourceBundle parent) { 283 if (getLogger().isDebugEnabled()) { 284 getLogger().debug("Creating bundle <" + sourceURI + ">"); 285 } 286 287 XMLResourceBundle bundle = new XMLResourceBundle(sourceURI, locale, parent); 288 bundle.enableLogging(getLogger()); 289 bundle.reload(this.resolver, this.interval); 290 return bundle; 291 } 292 293 301 protected Locale getParentLocale(Locale locale) { 302 Locale newloc; 303 if (locale.getVariant().equals("")) { 304 if (locale.getCountry().equals("")) { 305 newloc = new Locale ("", "", ""); 306 } else { 307 newloc = new Locale (locale.getLanguage(), "", ""); 308 } 309 } else { 310 newloc = new Locale (locale.getLanguage(), locale.getCountry(), ""); 311 } 312 return newloc; 313 } 314 315 319 protected String getCacheKey(String [] directories, int index, String name, Locale locale) 320 throws ComponentException { 321 StringBuffer cacheKey = new StringBuffer ("XRB"); 322 for (; index < directories.length; index++) { 323 cacheKey.append(":"); 324 cacheKey.append(getSourceURI(directories[index], name, locale)); 325 } 326 return cacheKey.toString(); 327 } 328 329 338 protected String getSourceURI(String base, String name, Locale locale) 339 throws ComponentException { 340 if (base == null) { 342 base = ""; 343 } 344 345 Source src = null; 347 Map parameters = Collections.EMPTY_MAP; 348 StringBuffer sb = new StringBuffer (); 349 try { 350 src = this.resolver.resolveURI(base); 351 352 String uri = NetUtils.deparameterize(src.getURI(), 354 parameters = new HashMap (7)); 355 356 sb.append(uri); 358 if (!uri.endsWith("/")) { 359 sb.append('/'); 360 } 361 362 } catch (IOException e) { 363 throw new ComponentException("Cannot resolve catalogue base URI <" + base + ">", name, e); 364 } finally { 365 this.resolver.release(src); 366 } 367 368 sb.append(name); 370 371 if (locale != null) { 373 if (!locale.getLanguage().equals("")) { 374 sb.append("_"); 375 sb.append(locale.getLanguage()); 376 } 377 if (!locale.getCountry().equals("")) { 378 sb.append("_"); 379 sb.append(locale.getCountry()); 380 } 381 if (!locale.getVariant().equals("")) { 382 sb.append("_"); 383 sb.append(locale.getVariant()); 384 } 385 } 386 sb.append(".xml"); 387 388 String uri = NetUtils.parameterize(sb.toString(), parameters); 390 391 if (getLogger().isDebugEnabled()) { 392 getLogger().debug("Resolved name: " + name + 393 ", locale: " + locale + " --> " + uri); 394 } 395 return uri; 396 } 397 398 404 protected XMLResourceBundle selectCached(String cacheKey) { 405 XMLResourceBundle bundle = (XMLResourceBundle) this.cache.get(cacheKey); 406 407 if (bundle != null && this.interval != -1) { 408 for (XMLResourceBundle b = bundle; b != null; b = (XMLResourceBundle) b.parent) { 410 b.reload(this.resolver, this.interval); 411 } 412 } 413 414 return bundle; 415 } 416 417 423 protected void updateCache(String cacheKey, XMLResourceBundle bundle) { 424 try { 425 this.cache.store(cacheKey, bundle); 426 } catch (IOException e) { 427 getLogger().error("Bundle <" + bundle.getSourceURI() + ">: unable to store.", e); 428 } 429 } 430 } 431 | Popular Tags |