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

[email protected]
Newsgroups gmane.comp.jakarta.taglibs.devel
Message-ID <[email protected]>
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;
     }
 }
-
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.