1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.tomcat.util.http; 19 20 import java.util.Enumeration; 21 import java.util.Hashtable; 22 import java.util.Locale; 23 import java.util.StringTokenizer; 24 import java.util.Vector; 25 26 /** 27 * Util to process the "Accept-Language" header. Used by facade to implement 28 * getLocale() and by StaticInterceptor. 29 * 30 * Not optimized - it's very slow. 31 * 32 * @author James Duncan Davidson [duncan@eng.sun.com] 33 * @author James Todd [gonzo@eng.sun.com] 34 * @author Jason Hunter [jch@eng.sun.com] 35 * @author Harish Prabandham 36 * @author costin@eng.sun.com 37 */ 38 public class AcceptLanguage { 39 40 public static Locale getLocale(String acceptLanguage) { 41 if( acceptLanguage == null ) return Locale.getDefault(); 42 43 Hashtable<String,Vector<String>> languages = 44 new Hashtable<String,Vector<String>>(); 45 Vector<Double> quality = new Vector<Double>(); 46 processAcceptLanguage(acceptLanguage, languages, quality); 47 48 if (languages.size() == 0) return Locale.getDefault(); 49 50 Vector<Locale> l = new Vector<Locale>(); 51 extractLocales( languages,quality, l); 52 53 return (Locale)l.elementAt(0); 54 } 55 56 public static Enumeration getLocales(String acceptLanguage) { 57 // Short circuit with an empty enumeration if null header 58 if (acceptLanguage == null) { 59 Vector<Locale> v = new Vector<Locale>(); 60 v.addElement(Locale.getDefault()); 61 return v.elements(); 62 } 63 64 Hashtable<String,Vector<String>> languages = 65 new Hashtable<String,Vector<String>>(); 66 Vector<Double> quality=new Vector<Double>(); 67 processAcceptLanguage(acceptLanguage, languages , quality); 68 69 if (languages.size() == 0) { 70 Vector<Locale> v = new Vector<Locale>(); 71 v.addElement(Locale.getDefault()); 72 return v.elements(); 73 } 74 Vector<Locale> l = new Vector<Locale>(); 75 extractLocales( languages, quality , l); 76 return l.elements(); 77 } 78 79 private static void processAcceptLanguage( String acceptLanguage, 80 Hashtable<String,Vector<String>> languages, Vector<Double> q) 81 { 82 StringTokenizer languageTokenizer = 83 new StringTokenizer(acceptLanguage, ","); 84 85 while (languageTokenizer.hasMoreTokens()) { 86 String language = languageTokenizer.nextToken().trim(); 87 int qValueIndex = language.indexOf(';'); 88 int qIndex = language.indexOf('q'); 89 int equalIndex = language.indexOf('='); 90 Double qValue = new Double(1); 91 92 if (qValueIndex > -1 && 93 qValueIndex < qIndex && 94 qIndex < equalIndex) { 95 String qValueStr = language.substring(qValueIndex + 1); 96 language = language.substring(0, qValueIndex); 97 qValueStr = qValueStr.trim().toLowerCase(); 98 qValueIndex = qValueStr.indexOf('='); 99 qValue = new Double(0); 100 if (qValueStr.startsWith("q") && 101 qValueIndex > -1) { 102 qValueStr = qValueStr.substring(qValueIndex + 1); 103 try { 104 qValue = new Double(qValueStr.trim()); 105 } catch (NumberFormatException nfe) { 106 } 107 } 108 } 109 110 // XXX 111 // may need to handle "*" at some point in time 112 113 if (! language.equals("*")) { 114 String key = qValue.toString(); 115 Vector<String> v; 116 if (languages.containsKey(key)) { 117 v = languages.get(key) ; 118 } else { 119 v= new Vector<String>(); 120 q.addElement(qValue); 121 } 122 v.addElement(language); 123 languages.put(key, v); 124 } 125 } 126 } 127 128 private static void extractLocales(Hashtable languages, Vector q, 129 Vector<Locale> l) 130 { 131 // XXX We will need to order by q value Vector in the Future ? 132 Enumeration e = q.elements(); 133 while (e.hasMoreElements()) { 134 Vector v = 135 (Vector)languages.get(((Double)e.nextElement()).toString()); 136 Enumeration le = v.elements(); 137 while (le.hasMoreElements()) { 138 String language = (String)le.nextElement(); 139 String country = ""; 140 int countryIndex = language.indexOf("-"); 141 if (countryIndex > -1) { 142 country = language.substring(countryIndex + 1).trim(); 143 language = language.substring(0, countryIndex).trim(); 144 } 145 l.addElement(new Locale(language, country)); 146 } 147 } 148 } 149 150 151 }