001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.tomcat.util.http;
019:
020: import java.util.Enumeration;
021: import java.util.Hashtable;
022: import java.util.Locale;
023: import java.util.StringTokenizer;
024: import java.util.Vector;
025:
026: /**
027: * Util to process the "Accept-Language" header. Used by facade to implement
028: * getLocale() and by StaticInterceptor.
029: *
030: * Not optimized - it's very slow.
031: *
032: * @author James Duncan Davidson [duncan@eng.sun.com]
033: * @author James Todd [gonzo@eng.sun.com]
034: * @author Jason Hunter [jch@eng.sun.com]
035: * @author Harish Prabandham
036: * @author costin@eng.sun.com
037: */
038: public class AcceptLanguage {
039:
040: public static Locale getLocale(String acceptLanguage) {
041: if (acceptLanguage == null)
042: return Locale.getDefault();
043:
044: Hashtable<String, Vector<String>> languages = new Hashtable<String, Vector<String>>();
045: Vector<Double> quality = new Vector<Double>();
046: processAcceptLanguage(acceptLanguage, languages, quality);
047:
048: if (languages.size() == 0)
049: return Locale.getDefault();
050:
051: Vector<Locale> l = new Vector<Locale>();
052: extractLocales(languages, quality, l);
053:
054: return (Locale) l.elementAt(0);
055: }
056:
057: public static Enumeration getLocales(String acceptLanguage) {
058: // Short circuit with an empty enumeration if null header
059: if (acceptLanguage == null) {
060: Vector<Locale> v = new Vector<Locale>();
061: v.addElement(Locale.getDefault());
062: return v.elements();
063: }
064:
065: Hashtable<String, Vector<String>> languages = new Hashtable<String, Vector<String>>();
066: Vector<Double> quality = new Vector<Double>();
067: processAcceptLanguage(acceptLanguage, languages, quality);
068:
069: if (languages.size() == 0) {
070: Vector<Locale> v = new Vector<Locale>();
071: v.addElement(Locale.getDefault());
072: return v.elements();
073: }
074: Vector<Locale> l = new Vector<Locale>();
075: extractLocales(languages, quality, l);
076: return l.elements();
077: }
078:
079: private static void processAcceptLanguage(String acceptLanguage,
080: Hashtable<String, Vector<String>> languages,
081: Vector<Double> q) {
082: StringTokenizer languageTokenizer = new StringTokenizer(
083: acceptLanguage, ",");
084:
085: while (languageTokenizer.hasMoreTokens()) {
086: String language = languageTokenizer.nextToken().trim();
087: int qValueIndex = language.indexOf(';');
088: int qIndex = language.indexOf('q');
089: int equalIndex = language.indexOf('=');
090: Double qValue = new Double(1);
091:
092: if (qValueIndex > -1 && qValueIndex < qIndex
093: && qIndex < equalIndex) {
094: String qValueStr = language.substring(qValueIndex + 1);
095: language = language.substring(0, qValueIndex);
096: qValueStr = qValueStr.trim().toLowerCase();
097: qValueIndex = qValueStr.indexOf('=');
098: qValue = new Double(0);
099: if (qValueStr.startsWith("q") && qValueIndex > -1) {
100: qValueStr = qValueStr.substring(qValueIndex + 1);
101: try {
102: qValue = new Double(qValueStr.trim());
103: } catch (NumberFormatException nfe) {
104: }
105: }
106: }
107:
108: // XXX
109: // may need to handle "*" at some point in time
110:
111: if (!language.equals("*")) {
112: String key = qValue.toString();
113: Vector<String> v;
114: if (languages.containsKey(key)) {
115: v = languages.get(key);
116: } else {
117: v = new Vector<String>();
118: q.addElement(qValue);
119: }
120: v.addElement(language);
121: languages.put(key, v);
122: }
123: }
124: }
125:
126: private static void extractLocales(Hashtable languages, Vector q,
127: Vector<Locale> l) {
128: // XXX We will need to order by q value Vector in the Future ?
129: Enumeration e = q.elements();
130: while (e.hasMoreElements()) {
131: Vector v = (Vector) languages
132: .get(((Double) e.nextElement()).toString());
133: Enumeration le = v.elements();
134: while (le.hasMoreElements()) {
135: String language = (String) le.nextElement();
136: String country = "";
137: int countryIndex = language.indexOf("-");
138: if (countryIndex > -1) {
139: country = language.substring(countryIndex + 1)
140: .trim();
141: language = language.substring(0, countryIndex)
142: .trim();
143: }
144: l.addElement(new Locale(language, country));
145: }
146: }
147: }
148:
149: }
|