You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2012/08/28 09:00:37 UTC

svn commit: r1377994 - in /sling/trunk/contrib/extensions/i18n: pom.xml src/main/java/org/apache/sling/i18n/impl/I18NFilter.java

Author: cziegeler
Date: Tue Aug 28 07:00:37 2012
New Revision: 1377994

URL: http://svn.apache.org/viewvc?rev=1377994&view=rev
Log:
SLING-2576 : I18n: Allow multiple ResourceBundleProviders, use the first one responding for a given locale

Modified:
    sling/trunk/contrib/extensions/i18n/pom.xml
    sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/impl/I18NFilter.java

Modified: sling/trunk/contrib/extensions/i18n/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/i18n/pom.xml?rev=1377994&r1=1377993&r2=1377994&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/i18n/pom.xml (original)
+++ sling/trunk/contrib/extensions/i18n/pom.xml Tue Aug 28 07:00:37 2012
@@ -70,6 +70,9 @@
                             SLING-INF/nodetypes/jcrlanguage.cnd,
                             SLING-INF/nodetypes/message.cnd
                         </Sling-Nodetypes>
+                        <Embed-Dependency>
+                            org.apache.sling.commons.osgi;inline="org/apache/sling/commons/osgi/ServiceUtil.*"
+                        </Embed-Dependency>
 
                     </instructions>
                 </configuration>
@@ -83,6 +86,12 @@
             <version>2.1.0</version>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.osgi</artifactId>
+            <version>2.1.0</version>
+            <scope>provided</scope>
+        </dependency>
 
         <dependency>
             <groupId>org.apache.sling</groupId>

Modified: sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/impl/I18NFilter.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/impl/I18NFilter.java?rev=1377994&r1=1377993&r2=1377994&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/impl/I18NFilter.java (original)
+++ sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/impl/I18NFilter.java Tue Aug 28 07:00:37 2012
@@ -23,8 +23,10 @@ import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
+import java.util.TreeMap;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
@@ -45,6 +47,7 @@ import org.apache.felix.scr.annotations.
 import org.apache.felix.scr.annotations.sling.SlingFilterScope;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
+import org.apache.sling.commons.osgi.ServiceUtil;
 import org.apache.sling.i18n.DefaultLocaleResolver;
 import org.apache.sling.i18n.LocaleResolver;
 import org.apache.sling.i18n.RequestLocaleResolver;
@@ -58,7 +61,7 @@ import org.slf4j.LoggerFactory;
  * the resource bundle for the current request.
  */
 @SlingFilter(generateComponent = false, generateService = true, order = -700, scope = SlingFilterScope.REQUEST)
-@Component(immediate = true, metatype = false)
+@Component(immediate = true, metatype = false, specVersion="1.1")
 @Properties({
     @Property(name = "pattern", value="/.*"),
     @Property(name = Constants.SERVICE_DESCRIPTION, value = "Internationalization Support Filter"),
@@ -76,8 +79,15 @@ public class I18NFilter implements Filte
     @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC)
     private RequestLocaleResolver requestLocaleResolver = DEFAULT_LOCALE_RESOLVER;
 
-    @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC)
-    private ResourceBundleProvider resourceBundleProvider;
+    @Reference(name = "resourceBundleProvider",
+               referenceInterface = ResourceBundleProvider.class,
+               cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+               policy = ReferencePolicy.DYNAMIC)
+    private final Map<Object, ResourceBundleProvider> providers = new TreeMap<Object, ResourceBundleProvider>();
+
+    private volatile ResourceBundleProvider[] sortedProviders = new ResourceBundleProvider[0];
+
+    private final ResourceBundleProvider combinedProvider = new CombinedBundleProvider();
 
     /** Count the number init() has been called. */
     private volatile int initCount;
@@ -104,13 +114,13 @@ public class I18NFilter implements Filte
             if ( !runGlobal || this.requestLocaleResolver == DEFAULT_LOCALE_RESOLVER ) {
                 // wrap with our ResourceBundle provisioning
                 request = new I18NSlingHttpServletRequest(request,
-                    resourceBundleProvider, localeResolver);
+                        combinedProvider, localeResolver);
             } else {
-                request = new BaseI18NSlingHttpServletRequest(request, resourceBundleProvider);
+                request = new BaseI18NSlingHttpServletRequest(request, combinedProvider);
             }
         } else {
             request = new I18NHttpServletRequest(request,
-                    resourceBundleProvider, requestLocaleResolver);
+                    combinedProvider, requestLocaleResolver);
         }
 
         // and forward the request
@@ -147,8 +157,60 @@ public class I18NFilter implements Filte
             this.requestLocaleResolver = DEFAULT_LOCALE_RESOLVER;
         }
     }
+
+    protected void bindResourceBundleProvider(final ResourceBundleProvider provider, final Map<String, Object> props) {
+        synchronized ( this.providers ) {
+            this.providers.put(ServiceUtil.getComparableForServiceRanking(props), provider);
+            this.sortedProviders = this.providers.values().toArray(new ResourceBundleProvider[this.providers.size()]);
+        }
+    }
+
+    protected void unbindResourceBundleProvider(final ResourceBundleProvider provider, final Map<String, Object> props) {
+        synchronized ( this.providers ) {
+            this.providers.remove(ServiceUtil.getComparableForServiceRanking(props));
+            this.sortedProviders = this.providers.values().toArray(new ResourceBundleProvider[this.providers.size()]);
+        }
+    }
+
     // ---------- internal -----------------------------------------------------
 
+    /** Provider that goes through a list of registered providers and takes the first non-null responses */
+    private class CombinedBundleProvider implements ResourceBundleProvider {
+
+        public Locale getDefaultLocale() {
+            // ask all registered providers, use the first one that returns
+            for (final ResourceBundleProvider provider : sortedProviders) {
+                final Locale locale = provider.getDefaultLocale();
+                if (locale != null) {
+                    return locale;
+                }
+            }
+            return null;
+        }
+
+        public ResourceBundle getResourceBundle(final Locale locale) {
+            // ask all registered providers, use the first one that returns
+            for (final ResourceBundleProvider provider : sortedProviders) {
+                final ResourceBundle bundle = provider.getResourceBundle(locale);
+                if (bundle != null) {
+                    return bundle;
+                }
+            }
+            return null;
+        }
+
+        public ResourceBundle getResourceBundle(final String baseName, final Locale locale) {
+            // ask all registered providers, use the first one that returns
+            for (final ResourceBundleProvider provider : sortedProviders) {
+                final ResourceBundle bundle = provider.getResourceBundle(baseName, locale);
+                if (bundle != null) {
+                    return bundle;
+                }
+            }
+            return null;
+        }
+    }
+
     // ---------- internal class -----------------------------------------------
 
     private static class I18NHttpServletRequest