You are viewing a plain text version of this content. The canonical link for it is here.
Posted to taglibs-dev@jakarta.apache.org by ba...@apache.org on 2009/04/28 07:42:50 UTC

svn commit: r769250 - in /jakarta/taglibs/proper/standard/trunk/spec: pom.xml src/main/java/javax/servlet/jsp/jstl/fmt/JakartaInline.java src/main/java/javax/servlet/jsp/jstl/fmt/LocaleSupport.java

Author: bayard
Date: Tue Apr 28 05:42:50 2009
New Revision: 769250

URL: http://svn.apache.org/viewvc?rev=769250&view=rev
Log:
Code needed to be copied over from the Standard jar due to an ugly cyclic dependency

Added:
    jakarta/taglibs/proper/standard/trunk/spec/pom.xml   (with props)
    jakarta/taglibs/proper/standard/trunk/spec/src/main/java/javax/servlet/jsp/jstl/fmt/JakartaInline.java   (with props)
Modified:
    jakarta/taglibs/proper/standard/trunk/spec/src/main/java/javax/servlet/jsp/jstl/fmt/LocaleSupport.java

Added: jakarta/taglibs/proper/standard/trunk/spec/pom.xml
URL: http://svn.apache.org/viewvc/jakarta/taglibs/proper/standard/trunk/spec/pom.xml?rev=769250&view=auto
==============================================================================
--- jakarta/taglibs/proper/standard/trunk/spec/pom.xml (added)
+++ jakarta/taglibs/proper/standard/trunk/spec/pom.xml Tue Apr 28 05:42:50 2009
@@ -0,0 +1,100 @@
+<?xml version="1.0"?>
+<!--
+   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.
+-->
+<project
+    xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.taglibs</groupId>
+    <artifactId>taglibs-parent</artifactId>
+    <version>1-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>taglibs-standard-spec</artifactId>
+  <version>1.2-SNAPSHOT</version>
+  <name>Jakarta Standard Taglib - JSTL Specification API</name>
+
+  <inceptionYear>2001</inceptionYear>
+  <description>
+    An implementation of the JSP Standard Tag Library (JSTL) Specification API.
+  </description>
+
+  <url>http://jakarta.apache.org/taglibs/standard/</url>
+
+  <scm>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/jakarta/taglibs/proper/standard/trunk/spec</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/jakarta/taglibs/proper/standard/trunk/spec</developerConnection>
+    <url>http://svn.apache.org/viewvc/jakarta/taglibs/proper/standard/trunk/spec</url>
+  </scm>
+
+  <developers>
+    <developer><name>Pierre Delisle</name></developer>
+    <developer><name>Shawn Bayern</name></developer>
+    <developer><name>Nathan Abramson</name></developer>
+    <developer><name>Hans Bergsten</name></developer>
+    <developer><name>Scott Hasse</name></developer>
+    <developer><name>Justyna Horwat</name></developer>
+    <developer><name>Mark Kolb</name></developer>
+    <developer><name>Jan Luehe</name></developer>
+    <developer><name>Glenn Nielsen</name></developer>
+    <developer><name>Dmitri Plotnikov</name></developer>
+    <developer><name>Felipe Leme</name></developer>
+    <developer><name>Henri Yandell</name></developer>
+    <developer><name>Bjorn Townsend</name></developer>
+  </developers>
+
+  <contributors>
+    <contributor><name>Robert Goff</name></contributor>
+  </contributors>
+
+  <dependencies>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <version>2.5</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet.jsp</groupId>
+      <artifactId>jsp-api</artifactId>
+      <version>2.1</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>javax.el</groupId>
+      <artifactId>el-api</artifactId>
+      <version>1.0</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies> 
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.5</source>
+          <target>1.5</target>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>

Propchange: jakarta/taglibs/proper/standard/trunk/spec/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jakarta/taglibs/proper/standard/trunk/spec/src/main/java/javax/servlet/jsp/jstl/fmt/JakartaInline.java
URL: http://svn.apache.org/viewvc/jakarta/taglibs/proper/standard/trunk/spec/src/main/java/javax/servlet/jsp/jstl/fmt/JakartaInline.java?rev=769250&view=auto
==============================================================================
--- jakarta/taglibs/proper/standard/trunk/spec/src/main/java/javax/servlet/jsp/jstl/fmt/JakartaInline.java (added)
+++ jakarta/taglibs/proper/standard/trunk/spec/src/main/java/javax/servlet/jsp/jstl/fmt/JakartaInline.java Tue Apr 28 05:42:50 2009
@@ -0,0 +1,436 @@
+/*
+ * 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 javax.servlet.jsp.jstl.fmt;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.text.MessageFormat;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+import java.util.Vector;
+
+import javax.servlet.ServletResponse;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.jstl.core.Config;
+import javax.servlet.jsp.jstl.fmt.LocalizationContext;
+
+class JakartaInline {
+
+    // The jstl.jar and standard.jar had a cyclic dependency in this class. 
+    // It depended on MessageSupport and BundleSupport in the standard.jar.
+    // Inlining code from standard.jar as private code here - note exists 
+    // in the originals to keep in sync. Ick.
+
+
+    // Copied over from the implementation's MessageSupport class
+    // while making the jars non-cyclic
+    // impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/MessageSupport.java
+    static final String UNDEFINED_KEY = "???";
+
+
+    // All of the rest is copied from 
+    // impl/src/main/java/org/apache/taglibs/standard/tag/common/fmt/BundleSupport.java
+    // === START OF COPY FROM BundleSupport ===
+    //*********************************************************************
+    // Private constants
+    private static final Locale EMPTY_LOCALE = new Locale("", "");
+
+    /**
+     * Gets the default I18N localization context.
+     *
+     * @param pc Page in which to look up the default I18N localization context
+     */    
+    static LocalizationContext getLocalizationContext(PageContext pc) {
+	LocalizationContext locCtxt = null;
+
+	Object obj = Config.find(pc, Config.FMT_LOCALIZATION_CONTEXT);
+	if (obj == null) {
+	    return null;
+	}
+
+	if (obj instanceof LocalizationContext) {
+	    locCtxt = (LocalizationContext) obj;
+	} else {
+	    // localization context is a bundle basename
+	    locCtxt = getLocalizationContext(pc, (String) obj);
+	}
+
+	return locCtxt;
+    }
+
+    /**
+     * Gets the resource bundle with the given base name, whose locale is
+     * determined as follows:
+     *
+     * Check if a match exists between the ordered set of preferred
+     * locales and the available locales, for the given base name.
+     * The set of preferred locales consists of a single locale
+     * (if the <tt>javax.servlet.jsp.jstl.fmt.locale</tt> configuration
+     * setting is present) or is equal to the client's preferred locales
+     * determined from the client's browser settings.
+     *
+     * <p> If no match was found in the previous step, check if a match
+     * exists between the fallback locale (given by the
+     * <tt>javax.servlet.jsp.jstl.fmt.fallbackLocale</tt> configuration
+     * setting) and the available locales, for the given base name.
+     *
+     * @param pageContext Page in which the resource bundle with the
+     * given base name is requested
+     * @param basename Resource bundle base name
+     *
+     * @return Localization context containing the resource bundle with the
+     * given base name and the locale that led to the resource bundle match,
+     * or the empty localization context if no resource bundle match was found
+     */
+    static LocalizationContext getLocalizationContext(PageContext pc,
+							     String basename) {
+	LocalizationContext locCtxt = null;
+	ResourceBundle bundle = null;
+
+	if ((basename == null) || basename.equals("")) {
+	    return new LocalizationContext();
+	}
+
+	// Try preferred locales
+	Locale pref = getLocale(pc, Config.FMT_LOCALE);
+	if (pref != null) {
+	    // Preferred locale is application-based
+	    bundle = findMatch(basename, pref);
+	    if (bundle != null) {
+		locCtxt = new LocalizationContext(bundle, pref);
+	    }
+	} else {
+	    // Preferred locales are browser-based
+	    locCtxt = findMatch(pc, basename);
+	}
+	
+	if (locCtxt == null) {
+	    // No match found with preferred locales, try using fallback locale
+	    pref = getLocale(pc, Config.FMT_FALLBACK_LOCALE);
+	    if (pref != null) {
+		bundle = findMatch(basename, pref);
+		if (bundle != null) {
+		    locCtxt = new LocalizationContext(bundle, pref);
+		}
+	    }
+	}
+
+	if (locCtxt == null) {
+	    // try using the root resource bundle with the given basename
+	    try {
+	        ClassLoader cl = getClassLoaderCheckingPrivilege();
+            bundle = ResourceBundle.getBundle(basename, EMPTY_LOCALE, cl);
+		if (bundle != null) {
+		    locCtxt = new LocalizationContext(bundle, null);
+		}
+	    } catch (MissingResourceException mre) {
+		// do nothing
+	    }
+	}
+		 
+	if (locCtxt != null) {
+	    // set response locale
+	    if (locCtxt.getLocale() != null) {
+		setResponseLocale(pc, locCtxt.getLocale());
+	    }
+	} else {
+	    // create empty localization context
+	    locCtxt = new LocalizationContext();
+	}
+
+	return locCtxt;
+    }
+
+
+    //*********************************************************************
+    // Private utility methods
+    
+    /*
+     * Determines the client's preferred locales from the request, and compares
+     * each of the locales (in order of preference) against the available
+     * locales in order to determine the best matching locale.
+     *
+     * @param pageContext the page in which the resource bundle with the
+     * given base name is requested
+     * @param basename the resource bundle's base name
+     *
+     * @return the localization context containing the resource bundle with
+     * the given base name and best matching locale, or <tt>null</tt> if no
+     * resource bundle match was found
+     */
+    private static LocalizationContext findMatch(PageContext pageContext,
+						 String basename) {
+	LocalizationContext locCtxt = null;
+	
+	// Determine locale from client's browser settings.
+        
+	for (Enumeration enum_ = getRequestLocales((HttpServletRequest)pageContext.getRequest());
+	     enum_.hasMoreElements(); ) {
+	    Locale pref = (Locale) enum_.nextElement();
+	    ResourceBundle match = findMatch(basename, pref);
+	    if (match != null) {
+		locCtxt = new LocalizationContext(match, pref);
+		break;
+	    }
+	}
+        	
+	return locCtxt;
+    }
+
+    /*
+     * Gets the resource bundle with the given base name and preferred locale.
+     * 
+     * This method calls java.util.ResourceBundle.getBundle(), but ignores
+     * its return value unless its locale represents an exact or language match
+     * with the given preferred locale.
+     *
+     * @param basename the resource bundle base name
+     * @param pref the preferred locale
+     *
+     * @return the requested resource bundle, or <tt>null</tt> if no resource
+     * bundle with the given base name exists or if there is no exact- or
+     * language-match between the preferred locale and the locale of
+     * the bundle returned by java.util.ResourceBundle.getBundle().
+     */
+    private static ResourceBundle findMatch(String basename, Locale pref) {
+	ResourceBundle match = null;
+
+	try {
+	    ClassLoader cl = getClassLoaderCheckingPrivilege();
+        ResourceBundle bundle = ResourceBundle.getBundle(basename, pref, cl);
+	    Locale avail = bundle.getLocale();
+	    if (pref.equals(avail)) {
+		// Exact match
+		match = bundle;
+	    } else {
+                /*
+                 * We have to make sure that the match we got is for
+                 * the specified locale. The way ResourceBundle.getBundle()
+                 * works, if a match is not found with (1) the specified locale,
+                 * it tries to match with (2) the current default locale as 
+                 * returned by Locale.getDefault() or (3) the root resource 
+                 * bundle (basename).
+                 * We must ignore any match that could have worked with (2) or (3).
+                 * So if an exact match is not found, we make the following extra
+                 * tests:
+                 *     - avail locale must be equal to preferred locale
+                 *     - avail country must be empty or equal to preferred country
+                 *       (the equality match might have failed on the variant)
+		 */
+                if (pref.getLanguage().equals(avail.getLanguage())
+		    && ("".equals(avail.getCountry()) || pref.getCountry().equals(avail.getCountry()))) {
+		    /*
+		     * Language match.
+		     * By making sure the available locale does not have a 
+		     * country and matches the preferred locale's language, we
+		     * rule out "matches" based on the container's default
+		     * locale. For example, if the preferred locale is 
+		     * "en-US", the container's default locale is "en-UK", and
+		     * there is a resource bundle (with the requested base
+		     * name) available for "en-UK", ResourceBundle.getBundle()
+		     * will return it, but even though its language matches
+		     * that of the preferred locale, we must ignore it,
+		     * because matches based on the container's default locale
+		     * are not portable across different containers with
+		     * different default locales.
+		     */
+		    match = bundle;
+		}
+	    }
+	} catch (MissingResourceException mre) {
+	}
+
+	return match;
+    }
+    
+    private static ClassLoader getClassLoaderCheckingPrivilege() {
+        ClassLoader cl;
+        SecurityManager sm = System.getSecurityManager();
+        if (sm == null) {
+            cl = Thread.currentThread().getContextClassLoader();
+        } else {
+            cl = java.security.AccessController.doPrivileged(
+                new java.security.PrivilegedAction<ClassLoader>() 
+                {public ClassLoader run() {return Thread.currentThread().getContextClassLoader();}});
+        }
+        return cl;
+    }
+    // === END OF COPY FROM BundleSupport ===
+
+    // impl/src/main/java/org/apache/taglibs/standard/tag/common/core/Util.java
+    // === START OF COPY FROM Util TO SUPPORT BundleSupport ===
+    /**
+     * HttpServletRequest.getLocales() returns the server's default locale 
+     * if the request did not specify a preferred language.
+     * We do not want this behavior, because it prevents us from using
+     * the fallback locale. 
+     * We therefore need to return an empty Enumeration if no preferred 
+     * locale has been specified. This way, the logic for the fallback 
+     * locale will be able to kick in.
+     */
+    public static Enumeration getRequestLocales(HttpServletRequest request) {        
+        Enumeration values = request.getHeaders("accept-language");
+        if (values == null) {
+            // No header for "accept-language". Simply return
+            // a new empty enumeration.
+            // System.out.println("Null accept-language");
+            return new Vector().elements();
+        } else
+        if (values.hasMoreElements()) {
+            // At least one "accept-language". Simply return
+            // the enumeration returned by request.getLocales().
+            // System.out.println("At least one accept-language");
+            return request.getLocales();
+        } else {
+            // No header for "accept-language". Simply return
+            // the empty enumeration.
+            // System.out.println("No accept-language");
+            return values;
+        }
+    }
+    // === END OF COPY FROM Util TO SUPPORT BundleSupport ===
+
+    // === START OF COPY FROM SetLocaleSupport TO SUPPORT BundleSupport ===
+
+    //*********************************************************************
+    // Private constants
+
+    private static final char HYPHEN = '-';
+    private static final char UNDERSCORE = '_';
+
+    /*
+     * Stores the given locale in the response object of the given page
+     * context, and stores the locale's associated charset in the
+     * javax.servlet.jsp.jstl.fmt.request.charset session attribute, which
+     * may be used by the <requestEncoding> action in a page invoked by a
+     * form included in the response to set the request charset to the same as
+     * the response charset (this makes it possible for the container to
+     * decode the form parameter values properly, since browsers typically
+     * encode form field values using the response's charset).
+     *
+     * @param pageContext the page context whose response object is assigned
+     * the given locale
+     * @param locale the response locale
+     */
+    static void setResponseLocale(PageContext pc, Locale locale) {
+	// set response locale
+	ServletResponse response = pc.getResponse();
+	response.setLocale(locale);
+	
+	// get response character encoding and store it in session attribute
+	if (pc.getSession() != null) {
+            try {
+	        pc.setAttribute(REQUEST_CHAR_SET, response.getCharacterEncoding(),
+			    PageContext.SESSION_SCOPE);
+            } catch (IllegalStateException ex) {} // invalidated session ignored
+	}
+    }
+
+    /*
+     * Returns the locale specified by the named scoped attribute or context
+     * configuration parameter.
+     *
+     * <p> The named scoped attribute is searched in the page, request,
+     * session (if valid), and application scope(s) (in this order). If no such
+     * attribute exists in any of the scopes, the locale is taken from the
+     * named context configuration parameter.
+     *
+     * @param pageContext the page in which to search for the named scoped
+     * attribute or context configuration parameter
+     * @param name the name of the scoped attribute or context configuration
+     * parameter
+     *
+     * @return the locale specified by the named scoped attribute or context
+     * configuration parameter, or <tt>null</tt> if no scoped attribute or
+     * configuration parameter with the given name exists
+     */
+    static Locale getLocale(PageContext pageContext, String name) {
+	Locale loc = null;
+
+	Object obj = Config.find(pageContext, name);
+	if (obj != null) {
+	    if (obj instanceof Locale) {
+		loc = (Locale) obj;
+	    } else {
+		loc = parseLocale((String) obj, null);
+	    }
+	}
+
+	return loc;
+    }
+
+    /**
+     * Parses the given locale string into its language and (optionally)
+     * country components, and returns the corresponding
+     * <tt>java.util.Locale</tt> object.
+     *
+     * If the given locale string is null or empty, the runtime's default
+     * locale is returned.
+     *
+     * @param locale the locale string to parse
+     * @param variant the variant
+     *
+     * @return <tt>java.util.Locale</tt> object corresponding to the given
+     * locale string, or the runtime's default locale if the locale string is
+     * null or empty
+     *
+     * @throws IllegalArgumentException if the given locale does not have a
+     * language component or has an empty country component
+     */
+    private static Locale parseLocale(String locale, String variant) {
+
+	Locale ret = null;
+	String language = locale;
+	String country = null;
+	int index = -1;
+
+	if (((index = locale.indexOf(HYPHEN)) > -1)
+	        || ((index = locale.indexOf(UNDERSCORE)) > -1)) {
+	    language = locale.substring(0, index);
+	    country = locale.substring(index+1);
+	}
+
+	if ((language == null) || (language.length() == 0)) {
+        // LOCALE_NO_LANGUAGE
+	    throw new IllegalArgumentException("Missing language component in 'value' attribute in &lt;setLocale&gt;");
+	}
+
+	if (country == null) {
+	    if (variant != null)
+		ret = new Locale(language, "", variant);
+	    else
+		ret = new Locale(language, "");
+	} else if (country.length() > 0) {
+	    if (variant != null)
+		ret = new Locale(language, country, variant);
+	    else
+		ret = new Locale(language, country);
+	} else {
+        // LOCALE_EMPTY_COUNTRY
+	    throw new IllegalArgumentException("Empty country component in 'value' attribute in &lt;setLocale&gt;");
+	}
+
+	return ret;
+    }
+    // === END OF COPY FROM SetLocaleSupport TO SUPPORT BundleSupport ===
+
+    static final String REQUEST_CHAR_SET =
+	"javax.servlet.jsp.jstl.fmt.request.charset";
+}

Propchange: jakarta/taglibs/proper/standard/trunk/spec/src/main/java/javax/servlet/jsp/jstl/fmt/JakartaInline.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jakarta/taglibs/proper/standard/trunk/spec/src/main/java/javax/servlet/jsp/jstl/fmt/LocaleSupport.java
URL: http://svn.apache.org/viewvc/jakarta/taglibs/proper/standard/trunk/spec/src/main/java/javax/servlet/jsp/jstl/fmt/LocaleSupport.java?rev=769250&r1=769249&r2=769250&view=diff
==============================================================================
--- jakarta/taglibs/proper/standard/trunk/spec/src/main/java/javax/servlet/jsp/jstl/fmt/LocaleSupport.java (original)
+++ jakarta/taglibs/proper/standard/trunk/spec/src/main/java/javax/servlet/jsp/jstl/fmt/LocaleSupport.java Tue Apr 28 05:42:50 2009
@@ -17,14 +17,19 @@
 
 package javax.servlet.jsp.jstl.fmt;
 
+import java.util.Enumeration;
+import java.util.Locale;
 import java.text.MessageFormat;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
+import java.util.Vector;
 
-import javax.servlet.jsp.PageContext;
+import javax.servlet.ServletResponse;
 
-import org.apache.taglibs.standard.tag.common.fmt.BundleSupport;
-import org.apache.taglibs.standard.tag.common.fmt.MessageSupport;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.jsp.PageContext;
+import javax.servlet.jsp.jstl.core.Config;
+import javax.servlet.jsp.jstl.fmt.LocalizationContext;
 
 /**
  * Class which exposes the locale-determination logic for resource bundles
@@ -135,13 +140,12 @@
                                              Object[] args, 
                                              String basename) {
 	LocalizationContext locCtxt = null;
-	String message = MessageSupport.UNDEFINED_KEY + key
-	    + MessageSupport.UNDEFINED_KEY;
+	String message = JakartaInline.UNDEFINED_KEY + key + JakartaInline.UNDEFINED_KEY;
 
 	if (basename != null) {
-	    locCtxt = BundleSupport.getLocalizationContext(pageContext, basename);
+	    locCtxt = JakartaInline.getLocalizationContext(pageContext, basename);
 	} else {
-	    locCtxt = BundleSupport.getLocalizationContext(pageContext);
+	    locCtxt = JakartaInline.getLocalizationContext(pageContext);
 	}
 
 	if (locCtxt != null) {
@@ -165,4 +169,3 @@
 	return message;
     }
 }
-



---------------------------------------------------------------------
To unsubscribe, e-mail: taglibs-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: taglibs-dev-help@jakarta.apache.org