Thu, 12 Jan 2012 15:28:34 +0000
7123100: javac fails with java.lang.StackOverflowError
Summary: Inference of under-constrained type-variables creates erroneous recursive wildcard types
Reviewed-by: jjg
1 /*
2 * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.tools.javadoc;
28 import java.util.Locale;
29 import java.util.HashSet;
30 import java.text.Collator;
31 import java.text.BreakIterator;
33 /**
34 * This class holds the information about locales.
35 *
36 * @since 1.4
37 * @author Robert Field
38 */
39 class DocLocale {
41 /**
42 * The locale name will be set by Main, if option is provided on the
43 * command line.
44 */
45 final String localeName;
47 /**
48 * The locale to be used. If user doesen't provide this,
49 * then set it to default locale value.
50 */
51 final Locale locale;
53 /**
54 * The collator for this application. This is to take care of Locale
55 * Specific or Natural Language Text sorting.
56 */
57 final Collator collator;
59 /**
60 * Enclosing DocEnv
61 */
62 private final DocEnv docenv;
64 /**
65 * Sentence instance from the BreakIterator.
66 */
67 private final BreakIterator sentenceBreaker;
69 /**
70 * True is we should use <code>BreakIterator</code>
71 * to compute first sentence.
72 */
73 private boolean useBreakIterator = false;
75 /**
76 * The HTML sentence terminators.
77 */
78 static final String[] sentenceTerminators =
79 {
80 "<p>", "</p>", "<h1>", "<h2>",
81 "<h3>", "<h4>", "<h5>", "<h6>",
82 "</h1>", "</h2>", "</h3>", "</h4>", "</h5>",
83 "</h6>", "<hr>", "<pre>", "</pre>"
84 };
86 /**
87 * Constructor
88 */
89 DocLocale(DocEnv docenv, String localeName, boolean useBreakIterator) {
90 this.docenv = docenv;
91 this.localeName = localeName;
92 this.useBreakIterator = useBreakIterator;
93 locale = getLocale();
94 if (locale == null) {
95 docenv.exit();
96 } else {
97 Locale.setDefault(locale);
98 }
99 collator = Collator.getInstance(locale);
100 sentenceBreaker = BreakIterator.getSentenceInstance(locale);
101 }
103 /**
104 * Get the locale if specified on the command line
105 * else return null and if locale option is not used
106 * then return default locale.
107 */
108 private Locale getLocale() {
109 Locale userlocale = null;
110 if (localeName.length() > 0) {
111 int firstuscore = localeName.indexOf('_');
112 int seconduscore = -1;
113 String language = null;
114 String country = null;
115 String variant = null;
116 if (firstuscore == 2) {
117 language = localeName.substring(0, firstuscore);
118 seconduscore = localeName.indexOf('_', firstuscore + 1);
119 if (seconduscore > 0) {
120 if (seconduscore != firstuscore + 3 ||
121 localeName.length() <= seconduscore + 1) {
122 docenv.error(null, "main.malformed_locale_name", localeName);
123 return null;
124 }
125 country = localeName.substring(firstuscore + 1,
126 seconduscore);
127 variant = localeName.substring(seconduscore + 1);
128 } else if (localeName.length() == firstuscore + 3) {
129 country = localeName.substring(firstuscore + 1);
130 } else {
131 docenv.error(null, "main.malformed_locale_name", localeName);
132 return null;
133 }
134 } else if (firstuscore == -1 && localeName.length() == 2) {
135 language = localeName;
136 } else {
137 docenv.error(null, "main.malformed_locale_name", localeName);
138 return null;
139 }
140 userlocale = searchLocale(language, country, variant);
141 if (userlocale == null) {
142 docenv.error(null, "main.illegal_locale_name", localeName);
143 return null;
144 } else {
145 return userlocale;
146 }
147 } else {
148 return Locale.getDefault();
149 }
150 }
152 /**
153 * Search the locale for specified language, specified country and
154 * specified variant.
155 */
156 private Locale searchLocale(String language, String country,
157 String variant) {
158 Locale[] locales = Locale.getAvailableLocales();
159 for (int i = 0; i < locales.length; i++) {
160 if (locales[i].getLanguage().equals(language) &&
161 (country == null || locales[i].getCountry().equals(country)) &&
162 (variant == null || locales[i].getVariant().equals(variant))) {
163 return locales[i];
164 }
165 }
166 return null;
167 }
169 String localeSpecificFirstSentence(DocImpl doc, String s) {
170 if (s == null || s.length() == 0) {
171 return "";
172 }
173 int index = s.indexOf("-->");
174 if(s.trim().startsWith("<!--") && index != -1) {
175 return localeSpecificFirstSentence(doc, s.substring(index + 3, s.length()));
176 }
177 if (useBreakIterator || !locale.getLanguage().equals("en")) {
178 sentenceBreaker.setText(s.replace('\n', ' '));
179 int start = sentenceBreaker.first();
180 int end = sentenceBreaker.next();
181 return s.substring(start, end).trim();
182 } else {
183 return englishLanguageFirstSentence(s).trim();
184 }
185 }
187 /**
188 * Return the first sentence of a string, where a sentence ends
189 * with a period followed be white space.
190 */
191 private String englishLanguageFirstSentence(String s) {
192 if (s == null) {
193 return null;
194 }
195 int len = s.length();
196 boolean period = false;
197 for (int i = 0 ; i < len ; i++) {
198 switch (s.charAt(i)) {
199 case '.':
200 period = true;
201 break;
202 case ' ':
203 case '\t':
204 case '\n':
205 case '\r':
206 case '\f':
207 if (period) {
208 return s.substring(0, i);
209 }
210 break;
211 case '<':
212 if (i > 0) {
213 if (htmlSentenceTerminatorFound(s, i)) {
214 return s.substring(0, i);
215 }
216 }
217 break;
218 default:
219 period = false;
220 }
221 }
222 return s;
223 }
225 /**
226 * Find out if there is any HTML tag in the given string. If found
227 * return true else return false.
228 */
229 private boolean htmlSentenceTerminatorFound(String str, int index) {
230 for (int i = 0; i < sentenceTerminators.length; i++) {
231 String terminator = sentenceTerminators[i];
232 if (str.regionMatches(true, index, terminator,
233 0, terminator.length())) {
234 return true;
235 }
236 }
237 return false;
238 }
239 }