CompositeResourceBundle.java
001 /*
002  * Copyright 2010-2013 the original author or authors.
003  *
004  * Licensed under the Apache License, Version 2.0 (the "License");
005  * you may not use this file except in compliance with the License.
006  * You may obtain a copy of the License at
007  *
008  *      http://www.apache.org/licenses/LICENSE-2.0
009  *
010  * Unless required by applicable law or agreed to in writing, software
011  * distributed under the License is distributed on an "AS IS" BASIS,
012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013  * See the License for the specific language governing permissions and
014  * limitations under the License.
015  */
016 
017 package org.codehaus.griffon.runtime.util;
018 
019 import griffon.util.ApplicationHolder;
020 import org.slf4j.Logger;
021 import org.slf4j.LoggerFactory;
022 
023 import java.io.IOException;
024 import java.net.URL;
025 import java.util.*;
026 
027 import static griffon.util.GriffonNameUtils.isBlank;
028 
029 /**
030  @author Andres Almiray
031  @since 1.1.0
032  */
033 public class CompositeResourceBundle extends ResourceBundle {
034     private static final Logger LOG = LoggerFactory.getLogger(CompositeResourceBundle.class);
035     private final ResourceBundle[] bundles;
036     private final List<String> keys = new ArrayList<String>();
037 
038     public static ResourceBundle create(String basename) {
039         return create(basename, Locale.getDefault());
040     }
041 
042     public static ResourceBundle create(String basename, Locale locale) {
043         if (isBlank(basename)) {
044             throw new IllegalArgumentException("Cannot create CompositeResourceBundle with basename = '" + basename + "'");
045         }
046 
047         String[] combinations = {
048                 locale.getLanguage() "_" + locale.getCountry() "_" + locale.getVariant(),
049                 locale.getLanguage() "_" + locale.getCountry(),
050                 locale.getLanguage()
051         };
052 
053         List<ResourceBundle> bundles = new ArrayList<ResourceBundle>();
054         for (String suffix : combinations) {
055             if (suffix.endsWith("_")) continue;
056             bundles.addAll(loadBundleFromProperties(basename + "_" + suffix));
057             bundles.addAll(loadBundleFromScript(basename + "_" + suffix));
058         }
059         bundles.addAll(loadBundleFromProperties(basename));
060         bundles.addAll(loadBundleFromScript(basename));
061 
062         return new CompositeResourceBundle(bundles);
063     }
064 
065     private static Collection<ResourceBundle> loadBundleFromProperties(String fileName) {
066         List<ResourceBundle> bundles = new ArrayList<ResourceBundle>();
067         for (URL resource : ApplicationHolder.getApplication().getResources(fileName + ".properties")) {
068             if (null == resourcecontinue;
069             try {
070                 bundles.add(new PropertyResourceBundle(resource.openStream()));
071             catch (IOException e) {
072                 // ignore
073             }
074         }
075         return bundles;
076     }
077 
078     private static Collection<ResourceBundle> loadBundleFromScript(String fileName) {
079         List<ResourceBundle> bundles = new ArrayList<ResourceBundle>();
080         for (URL resource : ApplicationHolder.getApplication().getResources(fileName + ".groovy")) {
081             if (null == resourcecontinue;
082             bundles.add(new GroovyScriptResourceBundle(resource));
083         }
084         return bundles;
085     }
086 
087     public CompositeResourceBundle(List<ResourceBundle> bundles) {
088         this(toResourceBundleArray(bundles));
089     }
090 
091     public CompositeResourceBundle(ResourceBundle[] bundles) {
092         this.bundles = bundles;
093         for (ResourceBundle bundle : bundles) {
094             Enumeration<String> ks = bundle.getKeys();
095             while (ks.hasMoreElements()) {
096                 String key = ks.nextElement();
097                 if (!keys.contains(key)) {
098                     keys.add(key);
099                 }
100             }
101         }
102     }
103 
104     protected Object handleGetObject(String key) {
105         if(LOG.isTraceEnabled()){
106             LOG.trace("Searching key=" + key);
107         }
108         for (ResourceBundle bundle : bundles) {
109             try {
110                 Object value = bundle.getObject(key);
111                 if(LOG.isTraceEnabled()) {
112                     LOG.trace("Bundle " + bundle + "; key=" + key + "; value='" + value + "'");
113                 }
114                 if (value != null) {
115                     return value;
116                 }
117             catch (Exception e) {
118                 // ignore
119             }
120         }
121         return null;
122     }
123 
124     @Override
125     public Enumeration<String> getKeys() {
126         return new IteratorAsEnumeration<String>(keys.iterator());
127     }
128 
129     private static class IteratorAsEnumeration<E> implements Enumeration<E> {
130         private final Iterator<E> iterator;
131 
132         public IteratorAsEnumeration(Iterator<E> iterator) {
133             this.iterator = iterator;
134         }
135 
136         public boolean hasMoreElements() {
137             return iterator.hasNext();
138         }
139 
140         public E nextElement() {
141             return iterator.next();
142         }
143     }
144 
145     private static ResourceBundle[] toResourceBundleArray(List<ResourceBundle> bundles) {
146         if (null == bundles || bundles.isEmpty()) {
147             return new ResourceBundle[0];
148         }
149         return bundles.toArray(new ResourceBundle[bundles.size()]);
150     }
151 }