You are viewing a plain text version of this content. The canonical link for it is here.
Posted to adffaces-commits@incubator.apache.org by aw...@apache.org on 2006/10/19 21:05:27 UTC

svn commit: r465884 - in /incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource: TrTranslationsResourceLoader.java TranslationsResourceLoader.java

Author: awiner
Date: Thu Oct 19 14:05:26 2006
New Revision: 465884

URL: http://svn.apache.org/viewvc?view=rev&rev=465884
Log:
Rewrite translations resource loader to be much more performant, properly support non-ASCII characters, more generic, comply with coding standards, easily subclassed, etc.

Added:
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TranslationsResourceLoader.java
Modified:
    incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TrTranslationsResourceLoader.java

Modified: incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TrTranslationsResourceLoader.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TrTranslationsResourceLoader.java?view=diff&rev=465884&r1=465883&r2=465884
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TrTranslationsResourceLoader.java (original)
+++ incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TrTranslationsResourceLoader.java Thu Oct 19 14:05:26 2006
@@ -15,17 +15,11 @@
 */
 package org.apache.myfaces.trinidadinternal.resource;
 
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.URL;
+import javax.faces.context.FacesContext;
 
-import org.apache.myfaces.trinidad.resource.StringContentResourceLoader;
-import org.apache.myfaces.trinidad.util.ClassLoaderUtils;
+import org.apache.myfaces.trinidad.skin.Skin;
 
-import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.XhtmlUtils;
-
-public class TrTranslationsResourceLoader extends StringContentResourceLoader
+public class TrTranslationsResourceLoader extends TranslationsResourceLoader
 {
   /**
    * Constructs a dynamic resouce loader for this path which serves up translations
@@ -35,116 +29,37 @@
   public TrTranslationsResourceLoader(String path)
   {
     super(path);
-    setMap("TrMessageFactory._TRANSLATIONS");
-    setBundle("org.apache.myfaces.trinidad.resource.MessageBundle");
   }
-  
-  protected void setMap(String mapName)
+
+
+  @Override
+  protected int getDefaultSize()
   {
-    this.mapName = mapName;
+    // We're coming in at about 13K for Japanese, which is probably
+    // about as big as this will get
+    return 20000;
   }
   
-  protected void setBundle(String bundleName)
+  protected String getJSVarName()
   {
-    this.bundleName = bundleName;
+    return "TrMessageFactory._TRANSLATIONS";
   }
-  
-  @Override
-  protected String getString(String path) throws IOException
+
+  protected String getBundleName()
   {
-    // its always better to initialize the StringBuffer with size instead of leaving it unset
-    StringBuffer bundleMap = new StringBuffer(50000);
-    String content   = "";
-    
-    String locale = CoreRenderKitResourceLoader.getLocale();
-    
-    bundleMap.append(mapName)
-             .append(" = ")
-             .append("\n{\n");
-    
-    content += _processBundle(bundleName, locale);
-    
-    //Remove the last 2 characters( ie, newLine & ',')
-    bundleMap.append(content.substring(0, content.length()-2))
-             .append("\n};");
-    
-    return bundleMap.toString();
+    return "org.apache.myfaces.trinidad.resource.MessageBundle";
   }
-  
+
   @Override
-  protected String getContentType(String path)
+  protected String getLocaleString(FacesContext context)
   {
-    return _CONTENT_TYPE;
+    return CoreRenderKitResourceLoader.getLocale();
   }
-  
+
+  // These translations do not go through the skin
   @Override
-  protected URL findResource(
-    String path) throws IOException
+  protected Skin getSkin(FacesContext context)
   {
-    return getURL(path);
-  }
-  
-  protected String _processBundle(
-    String  bundleName,
-    String  localeName
-    ) throws IOException
-  {
-    StringBuffer transMap = new StringBuffer(50000);
-    Object obj = invokeGetContents(bundleName, localeName);
-    
-    if( obj != null)
-    {
-      Object entry[] = (Object [])obj;
-      
-      for(int i=0; i< entry.length; i++)
-      {
-        transMap.append("'" + ((Object [])entry[i])[0] + "'")
-                .append(":")
-                .append("'" + XhtmlUtils.escapeJS(((Object [])entry[i])[1].toString(), true) + "',")
-                .append("\n");
-      }
-    }
-    
-    return transMap.toString();
+    return null;
   }
-  
-  protected Object invokeGetContents(
-    String  bundleName,
-    String  localeName
-    ) throws IOException
-  {
-    String className  = bundleName + "_" + localeName; 
-    Object obj = null;
-    
-    try
-    {
-      Class<?> clazz;
-      try
-      {
-        clazz = ClassLoaderUtils.loadClass(className);
-      }
-      catch (ClassNotFoundException e)    
-      { 
-        // If there is no bundle specific to locale, use Default locale
-        clazz = ClassLoaderUtils.loadClass(bundleName);    
-      }
-      
-      //Invoke getContents() method which gives us the Translations
-      Method x = clazz.getMethod("getContents", (Class[]) null);  
-      obj = x.invoke(clazz.newInstance(), (Object[]) null);
-    
-    } catch (NoSuchMethodException e)     { ;
-    } catch (InvocationTargetException e) { ;
-    } catch (IllegalAccessException e)    { ;
-    } catch (InstantiationException e)    { ;
-    } catch (ClassNotFoundException e)    { ;
-    }
-    
-    return obj;  
-  }
-  
-  protected String mapName;
-  protected String bundleName;
-  
-  private static final String _CONTENT_TYPE = "text/javascript";
 }

Added: incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TranslationsResourceLoader.java
URL: http://svn.apache.org/viewvc/incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TranslationsResourceLoader.java?view=auto&rev=465884
==============================================================================
--- incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TranslationsResourceLoader.java (added)
+++ incubator/adffaces/trunk/trinidad/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/resource/TranslationsResourceLoader.java Thu Oct 19 14:05:26 2006
@@ -0,0 +1,222 @@
+/*
+* Copyright 2006 The Apache Software Foundation.
+*
+* Licensed 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.myfaces.trinidadinternal.resource;
+
+import java.io.IOException;
+
+import java.net.URL;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import javax.faces.context.FacesContext;
+
+import org.apache.myfaces.trinidad.context.LocaleContext;
+import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidad.resource.StringContentResourceLoader;
+import org.apache.myfaces.trinidad.skin.Skin;
+import org.apache.myfaces.trinidad.skin.SkinFactory;
+
+import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.XhtmlUtils;
+import org.apache.myfaces.trinidadinternal.share.nls.LocaleContextImpl;
+import org.apache.myfaces.trinidadinternal.util.nls.LocaleUtils;
+
+abstract public class TranslationsResourceLoader
+                           extends StringContentResourceLoader
+{
+  /**
+   * Constructs a dynamic resouce loader for this path which serves up
+   * translations.
+   * 
+   * @param path the path of this dynamic resource loader
+   */
+  public TranslationsResourceLoader(String path)
+  {
+    super(path);
+  }
+
+  abstract protected String getJSVarName();
+
+  abstract protected String getBundleName();
+
+  /**
+   * Override to increase the default size of the buffer.
+   */
+  protected int getDefaultSize()
+  {
+    return 10000;
+  }
+
+  protected String getLocaleString(FacesContext context)
+  {
+    Object localeObj = context.getExternalContext().getRequestParameterMap().
+      get("loc");
+    return (localeObj == null || "".equals(localeObj))
+      ? null : localeObj.toString();
+  }
+
+  @Override
+  protected String getContentType(String path)
+  {
+    return _CONTENT_TYPE;
+  }
+  
+  @Override
+  protected URL findResource(
+    String path) throws IOException
+  {
+    return getURL(path);
+  }
+
+  @Override
+  protected String getString(String path) throws IOException
+  {
+    FacesContext context = FacesContext.getCurrentInstance();
+    String localeStr = getLocaleString(context);
+
+    Locale locale = LocaleUtils.getLocaleForIANAString(localeStr);
+    if (locale == null)
+      locale = Locale.getDefault();
+
+    ResourceBundle bundle;
+    try
+    {
+      bundle = _getResourceBundle(locale);
+    }
+    catch (MissingResourceException mre)
+    {
+      _LOG.severe("Could not find bundle " + getBundleName(), mre);
+      return "/* COULD NOT FIND BUNDLE " + getBundleName() + " */";
+    }
+
+    // FIXME: would be much better to directly stream the contents
+    // rather than using StringContentResourceLoader
+    StringBuilder builder = new StringBuilder(getDefaultSize());
+
+    builder.append(getJSVarName())
+      .append("=")
+      .append("{\n");
+
+    _processBundle(context, builder, bundle, locale);
+    
+    builder.append("\n}");
+
+    return builder.toString();
+  }
+  
+  private ResourceBundle _getResourceBundle(Locale locale)
+    throws MissingResourceException
+  {
+    ClassLoader loader = Thread.currentThread().getContextClassLoader();
+    return ResourceBundle.getBundle(getBundleName(),
+                                    locale,
+                                    loader);
+  }
+
+  protected Skin getSkin(FacesContext context)
+  {
+    Skin skin = null;
+    SkinFactory skinFactory = SkinFactory.getFactory();
+    Object skinIdObj = context.getExternalContext().getRequestParameterMap().
+      get("skinId");
+    if (skinIdObj != null)
+      skin = skinFactory.getSkin(context, skinIdObj.toString());
+
+    return skin;
+  }
+
+  private void _processBundle(
+    FacesContext   context,
+    StringBuilder  builder,
+    ResourceBundle bundle,
+    Locale         locale)
+  {
+    Skin             skin = getSkin(context);
+    LocaleContext    lc = new LocaleContextImpl(locale);
+
+    // We get the keys from the bundle, but try to get the values from
+    // the skin if possible
+    Enumeration<String> keys = bundle.getKeys();
+    boolean writtenOne = false;
+    while (keys.hasMoreElements())
+    {
+      if (writtenOne)
+        builder.append(",\n");
+      else
+        writtenOne = true;
+
+      String key = keys.nextElement();
+      String value;
+      // If we can get it from the skin, that's better, but if not,
+      // go to the bundle
+      if (skin == null)
+        value = bundle.getString(key);
+      else
+        value = skin.getTranslatedString(lc, key);
+      
+      builder.append("'");
+      builder.append(key);
+      builder.append("':'");
+      _appendUnicodeString(builder, value);
+      builder.append("'");
+    }
+  }
+
+  private void _appendUnicodeString(
+    StringBuilder builder,
+    String        value)
+  {
+    if (value == null)
+      return;
+
+    int length = value.length();
+    for (int i = 0; i < length; i++)
+    {
+      char c = value.charAt(i);
+      if ((c >= 0x20) && (c < 0x80))
+      {
+        if (c == '\'')
+          builder.append("\\'");
+        else if (c == '\\')
+          builder.append("\\\\");
+        else
+          builder.append(c);
+      }
+      else
+      {
+        // Unicode escape any non-ascii characters
+        builder.append("\\u");
+        String hex = Integer.toHexString(c);
+        int hexLen = hex.length();
+        // Javascript is lame, and requires padding Unicode escapes
+        // to four-digits
+        if (hexLen == 1)
+          builder.append("000");
+        else if (hexLen == 2)
+          builder.append("00");
+        else if (hexLen == 3)
+          builder.append("0");
+        builder.append(hex);
+      }
+    }
+  }
+
+  private static final String _CONTENT_TYPE = "text/javascript";
+  private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(
+                                       TranslationsResourceLoader.class);
+}