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 2011/08/16 12:47:36 UTC

svn commit: r1158191 - in /sling/trunk/contrib/extensions/i18n: ./ src/main/java/org/apache/sling/i18n/ src/main/java/org/apache/sling/i18n/impl/

Author: cziegeler
Date: Tue Aug 16 10:47:36 2011
New Revision: 1158191

URL: http://svn.apache.org/viewvc?rev=1158191&view=rev
Log:
SLING-2180 : Provide a resource bundle for all requests

Added:
    sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/RequestLocaleResolver.java   (with props)
Modified:
    sling/trunk/contrib/extensions/i18n/pom.xml
    sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/DefaultLocaleResolver.java
    sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/LocaleResolver.java
    sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/ResourceBundleProvider.java
    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=1158191&r1=1158190&r2=1158191&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/i18n/pom.xml (original)
+++ sling/trunk/contrib/extensions/i18n/pom.xml Tue Aug 16 10:47:36 2011
@@ -60,7 +60,7 @@
                             javax.jcr.*;version=1.0,*
                         </Import-Package>
                         <Export-Package>
-                            org.apache.sling.i18n;version=2.0.4
+                            org.apache.sling.i18n;version=2.2.0
                         </Export-Package>
                         <Private-Package>
                             org.apache.sling.i18n.impl.*

Modified: sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/DefaultLocaleResolver.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/DefaultLocaleResolver.java?rev=1158191&r1=1158190&r2=1158191&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/DefaultLocaleResolver.java (original)
+++ sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/DefaultLocaleResolver.java Tue Aug 16 10:47:36 2011
@@ -23,6 +23,8 @@ import java.util.Enumeration;
 import java.util.List;
 import java.util.Locale;
 
+import javax.servlet.http.HttpServletRequest;
+
 import org.apache.sling.api.SlingHttpServletRequest;
 
 /**
@@ -31,14 +33,21 @@ import org.apache.sling.api.SlingHttpSer
  * will be the Servlet Container's implementation of this method and thus be
  * based on the client's <code>Accept-Language</code> header.
  */
-public class DefaultLocaleResolver implements LocaleResolver {
+public class DefaultLocaleResolver implements LocaleResolver, RequestLocaleResolver {
 
     /**
      * Return the Locales provided by the
      * <code>ServletRequest.getLocales()</code> method collected in a
      * <code>List</code>.
      */
-    public List<Locale> resolveLocale(SlingHttpServletRequest request) {
+    public List<Locale> resolveLocale(final SlingHttpServletRequest request) {
+        return this.resolveLocale((HttpServletRequest)request);
+    }
+
+    /**
+     * @see org.apache.sling.i18n.RequestLocaleResolver#resolveLocale(javax.servlet.http.HttpServletRequest)
+     */
+    public List<Locale> resolveLocale(final HttpServletRequest request) {
         Enumeration<?> locales = request.getLocales();
         ArrayList<Locale> localeList = new ArrayList<Locale>();
         while (locales.hasMoreElements()) {
@@ -46,5 +55,4 @@ public class DefaultLocaleResolver imple
         }
         return localeList;
     }
-
 }

Modified: sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/LocaleResolver.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/LocaleResolver.java?rev=1158191&r1=1158190&r2=1158191&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/LocaleResolver.java (original)
+++ sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/LocaleResolver.java Tue Aug 16 10:47:36 2011
@@ -32,7 +32,9 @@ import org.apache.sling.api.SlingHttpSer
  * resolve one or more <code>Locale</code>s applicable to handle the request.
  * <p>
  * Only a single <code>LocaleResolver</code> service is currently used.
+ * @deprecated The {@link RequestLocaleResolver} should be used instead.
  */
+@Deprecated
 public interface LocaleResolver {
 
     /**

Added: sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/RequestLocaleResolver.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/RequestLocaleResolver.java?rev=1158191&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/RequestLocaleResolver.java (added)
+++ sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/RequestLocaleResolver.java Tue Aug 16 10:47:36 2011
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.i18n;
+
+import java.util.List;
+import java.util.Locale;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * The <code>GlobalLocaleResolver</code> service interface may be implemented by a
+ * service registered under this name to allow the resolution of the request
+ * <code>Locale</code> to apply.
+ * <p>
+ * This interface is intended to be implemented by providers knowing how to
+ * resolve one or more <code>Locale</code>s applicable to handle the request.
+ * <p>
+ * Only a single <code>GlobalLocaleResolver</code> service is currently used.
+ * @since 2.2
+ */
+public interface RequestLocaleResolver {
+
+    /**
+     * Return a non-<code>null</code> but possiby empty list of
+     * <code>Locale</code> instances to consider for localization of the current
+     * request. The list returned is assumed to be ordered by preference where
+     * the first entry is the prefered <code>Locale</code> and the last entry is
+     * the least prefered <code>Locale</code>.
+     * <p>
+     * Returning an empty list is equivalent to returning a singleton list whose
+     * single entry is the {@link ResourceBundleProvider#getDefaultLocale()}.
+     *
+     * @param request The <code>SlingHttpServletRequest</code> providing hints
+     *            and information for the <code>Locale</code> resolution.
+     * @return The list of <code>Locale</code>s to use for internationalization
+     *         of request processing
+     */
+    List<Locale> resolveLocale(HttpServletRequest request);
+
+}

Propchange: sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/RequestLocaleResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/RequestLocaleResolver.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/RequestLocaleResolver.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/ResourceBundleProvider.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/ResourceBundleProvider.java?rev=1158191&r1=1158190&r2=1158191&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/ResourceBundleProvider.java (original)
+++ sling/trunk/contrib/extensions/i18n/src/main/java/org/apache/sling/i18n/ResourceBundleProvider.java Tue Aug 16 10:47:36 2011
@@ -34,6 +34,12 @@ import java.util.ResourceBundle;
 public interface ResourceBundleProvider {
 
     /**
+     * Request attribute to get the resource bundle.
+     * @since 2.2
+     */
+    String BUNDLE_REQ_ATTR = "org.apache.sling.i18n.resourcebundle";
+
+    /**
      * Returns the default <code>Locale</code> assumed by this instance.
      */
     Locale getDefaultLocale();

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=1158191&r1=1158190&r2=1158191&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 16 10:47:36 2011
@@ -32,6 +32,9 @@ import javax.servlet.FilterConfig;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Properties;
 import org.apache.felix.scr.annotations.Property;
@@ -44,6 +47,7 @@ import org.apache.sling.api.SlingHttpSer
 import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
 import org.apache.sling.i18n.DefaultLocaleResolver;
 import org.apache.sling.i18n.LocaleResolver;
+import org.apache.sling.i18n.RequestLocaleResolver;
 import org.apache.sling.i18n.ResourceBundleProvider;
 import org.osgi.framework.Constants;
 import org.slf4j.Logger;
@@ -56,58 +60,156 @@ import org.slf4j.LoggerFactory;
 @SlingFilter(generateComponent = false, generateService = true, order = -700, scope = SlingFilterScope.REQUEST)
 @Component(immediate = true, metatype = false)
 @Properties({
+    @Property(name = "pattern", value="/.*"),
     @Property(name = Constants.SERVICE_DESCRIPTION, value = "Internationalization Support Filter"),
     @Property(name = Constants.SERVICE_VENDOR, value = "The Apache Software Foundation") })
 public class I18NFilter implements Filter {
 
-    /** default log */
-    private static final Logger log = LoggerFactory.getLogger(I18NFilter.class.getName());
+    /** Logger */
+    private final static Logger LOG = LoggerFactory.getLogger(I18NFilter.class.getName());
 
-    private static LocaleResolver DEFAULT_LOCALE_RESOLVER = new DefaultLocaleResolver();
+    private final DefaultLocaleResolver DEFAULT_LOCALE_RESOLVER = new DefaultLocaleResolver();
 
     @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC)
     private LocaleResolver localeResolver = DEFAULT_LOCALE_RESOLVER;
 
     @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;
 
+    /** Count the number init() has been called. */
+    private volatile int initCount;
+
+    /**
+     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
+     */
     public void init(FilterConfig filterConfig) {
-        // nothing to do
+        synchronized(this) {
+            initCount++;
+        }
     }
 
-    public void doFilter(ServletRequest request, ServletResponse response,
-            FilterChain chain) throws IOException, ServletException {
-
-        // wrap with our ResourceBundle provisioning
-        request = new I18NSlingHttpServletRequest(request,
-            resourceBundleProvider, localeResolver);
+    /**
+     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
+     */
+    public void doFilter(ServletRequest request,
+                         final ServletResponse response,
+                         final FilterChain chain)
+    throws IOException, ServletException {
+        final boolean runGlobal = this.initCount == 2;
+        if ( request instanceof SlingHttpServletRequest ) {
+            // check if we have to wrap
+            if ( !runGlobal || this.requestLocaleResolver == DEFAULT_LOCALE_RESOLVER ) {
+                // wrap with our ResourceBundle provisioning
+                request = new I18NSlingHttpServletRequest(request,
+                    resourceBundleProvider, localeResolver);
+            }
+        } else {
+            request = new I18NHttpServletRequest(request,
+                    resourceBundleProvider, requestLocaleResolver);
+        }
 
         // and forward the request
         chain.doFilter(request, response);
     }
 
+    /**
+     * @see javax.servlet.Filter#destroy()
+     */
     public void destroy() {
-        // nothing to do
+        synchronized(this) {
+            initCount--;
+        }
     }
 
     // ---------- SCR Integration ----------------------------------------------
 
-    protected void bindLocaleResolver(LocaleResolver localeResolver) {
-        this.localeResolver = localeResolver;
+    protected void bindLocaleResolver(final LocaleResolver resolver) {
+        this.localeResolver = resolver;
     }
 
-    protected void unbindLocaleResolver(LocaleResolver localeResolver) {
-        if (this.localeResolver == localeResolver) {
+    protected void unbindLocaleResolver(final LocaleResolver resolver) {
+        if (this.localeResolver == resolver) {
             this.localeResolver = DEFAULT_LOCALE_RESOLVER;
         }
     }
 
+    protected void bindRequestLocaleResolver(final RequestLocaleResolver resolver) {
+        this.requestLocaleResolver = resolver;
+    }
+
+    protected void unbindRequestLocaleResolver(final RequestLocaleResolver resolver) {
+        if (this.requestLocaleResolver == resolver) {
+            this.requestLocaleResolver = DEFAULT_LOCALE_RESOLVER;
+        }
+    }
     // ---------- internal -----------------------------------------------------
 
     // ---------- internal class -----------------------------------------------
 
-    private static class I18NSlingHttpServletRequest extends
-            SlingHttpServletRequestWrapper {
+    private static class I18NHttpServletRequest
+        extends HttpServletRequestWrapper {
+
+        private final ResourceBundleProvider bundleProvider;
+
+        private final RequestLocaleResolver localeResolver;
+
+        private Locale locale;
+
+        private List<Locale> localeList;
+
+        private ResourceBundle resourceBundle;
+
+        I18NHttpServletRequest(final ServletRequest delegatee,
+                final ResourceBundleProvider bundleProvider,
+                final RequestLocaleResolver localeResolver) {
+            super((HttpServletRequest)delegatee);
+            this.bundleProvider = bundleProvider;
+            this.localeResolver = localeResolver;
+        }
+
+        @Override
+        public Locale getLocale() {
+            if (locale == null) {
+                locale = this.getLocaleList().get(0);
+            }
+
+            return locale;
+        }
+
+        @Override
+        public Enumeration<?> getLocales() {
+            return Collections.enumeration(getLocaleList());
+        }
+
+        @Override
+        public Object getAttribute(final String name) {
+            if ( ResourceBundleProvider.BUNDLE_REQ_ATTR.equals(name) ) {
+                if ( this.resourceBundle == null && this.bundleProvider != null) {
+                    this.resourceBundle = this.bundleProvider.getResourceBundle(this.getLocale());
+                }
+                return this.resourceBundle;
+            }
+            return super.getAttribute(name);
+        }
+
+        private List<Locale> getLocaleList() {
+            if (localeList == null) {
+                List<Locale> resolved = localeResolver.resolveLocale((HttpServletRequest)this.getRequest());
+                this.localeList = (resolved != null && !resolved.isEmpty())
+                        ? resolved
+                        : Collections.singletonList(this.bundleProvider.getDefaultLocale());
+            }
+
+            return localeList;
+        }
+
+    }
+
+    private static class I18NSlingHttpServletRequest
+        extends SlingHttpServletRequestWrapper {
 
         private final ResourceBundleProvider bundleProvider;
 
@@ -117,9 +219,9 @@ public class I18NFilter implements Filte
 
         private List<Locale> localeList;
 
-        I18NSlingHttpServletRequest(ServletRequest delegatee,
-                ResourceBundleProvider bundleProvider,
-                LocaleResolver localeResolver) {
+        I18NSlingHttpServletRequest(final ServletRequest delegatee,
+                final ResourceBundleProvider bundleProvider,
+                final LocaleResolver localeResolver) {
             super((SlingHttpServletRequest) delegatee);
             this.bundleProvider = bundleProvider;
             this.localeResolver = localeResolver;
@@ -131,6 +233,15 @@ public class I18NFilter implements Filte
         }
 
         @Override
+        public Object getAttribute(final String name) {
+            if ( ResourceBundleProvider.BUNDLE_REQ_ATTR.equals(name) ) {
+                final Object superValue = super.getAttribute(name);
+                return (superValue != null ? superValue : this.getResourceBundle(null));
+            }
+            return super.getAttribute(name);
+        }
+
+        @Override
         public ResourceBundle getResourceBundle(String baseName, Locale locale) {
             if (bundleProvider != null) {
                 if (locale == null) {
@@ -140,12 +251,12 @@ public class I18NFilter implements Filte
                 try {
                     return bundleProvider.getResourceBundle(baseName, locale);
                 } catch (MissingResourceException mre) {
-                    log.warn(
+                    LOG.warn(
                         "getResourceBundle: Cannot get ResourceBundle from provider",
                         mre);
                 }
             } else {
-                log.info("getResourceBundle: ResourceBundleProvider not available, calling default implementation");
+                LOG.info("getResourceBundle: ResourceBundleProvider not available, calling default implementation");
             }
 
             return super.getResourceBundle(baseName, locale);