001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.compiler.problem;
011:
012: import java.util.Enumeration;
013: import java.util.Locale;
014: import java.util.MissingResourceException;
015: import java.util.ResourceBundle;
016:
017: import org.eclipse.jdt.core.compiler.*;
018: import org.eclipse.jdt.core.compiler.IProblem;
019: import org.eclipse.jdt.internal.compiler.IProblemFactory;
020: import org.eclipse.jdt.internal.compiler.util.HashtableOfInt;
021: import org.eclipse.jdt.internal.compiler.util.Util;
022:
023: public class DefaultProblemFactory implements IProblemFactory {
024:
025: public HashtableOfInt messageTemplates;
026: private Locale locale;
027: private static HashtableOfInt DEFAULT_LOCALE_TEMPLATES;
028: private final static char[] DOUBLE_QUOTES = "''".toCharArray(); //$NON-NLS-1$
029: private final static char[] SINGLE_QUOTE = "'".toCharArray(); //$NON-NLS-1$
030:
031: public DefaultProblemFactory() {
032: this (Locale.getDefault());
033: }
034:
035: /**
036: * @param loc the locale used to get the right message
037: */
038: public DefaultProblemFactory(Locale loc) {
039: setLocale(loc);
040: }
041:
042: /**
043: * Answer a new IProblem created according to the parameters value
044: * <ul>
045: * <li>originatingFileName the name of the file name from which the problem is originated
046: * <li>problemId the problem id
047: * <li>problemArguments the fully qualified arguments recorded inside the problem
048: * <li>messageArguments the arguments needed to set the error message (shorter names than problemArguments ones)
049: * <li>severity the severity of the problem
050: * <li>startPosition the starting position of the problem
051: * <li>endPosition the end position of the problem
052: * <li>lineNumber the line on which the problem occured
053: * </ul>
054: * @param originatingFileName char[]
055: * @param problemId int
056: * @param problemArguments String[]
057: * @param messageArguments String[]
058: * @param severity int
059: * @param startPosition int
060: * @param endPosition int
061: * @param lineNumber int
062: * @return CategorizedProblem
063: */
064: public CategorizedProblem createProblem(char[] originatingFileName,
065: int problemId, String[] problemArguments,
066: String[] messageArguments, int severity, int startPosition,
067: int endPosition, int lineNumber, int columnNumber) {
068:
069: return new DefaultProblem(originatingFileName, this
070: .getLocalizedMessage(problemId, messageArguments),
071: problemId, problemArguments, severity, startPosition,
072: endPosition, lineNumber, columnNumber);
073: }
074:
075: private final static int keyFromID(int id) {
076: return id + 1; // keys are offsetted by one in table, since it cannot handle 0 key
077: }
078:
079: /**
080: * Answer the locale used to retrieve the error messages
081: * @return java.util.Locale
082: */
083: public Locale getLocale() {
084: return this .locale;
085: }
086:
087: public void setLocale(Locale locale) {
088: if (locale == this .locale)
089: return;
090: this .locale = locale;
091: if (Locale.getDefault().equals(locale)) {
092: if (DEFAULT_LOCALE_TEMPLATES == null) {
093: DEFAULT_LOCALE_TEMPLATES = loadMessageTemplates(locale);
094: }
095: this .messageTemplates = DEFAULT_LOCALE_TEMPLATES;
096: } else {
097: this .messageTemplates = loadMessageTemplates(locale);
098: }
099: }
100:
101: public final String getLocalizedMessage(int id,
102: String[] problemArguments) {
103: String message = (String) this .messageTemplates
104: .get(keyFromID(id & IProblem.IgnoreCategoriesMask));
105: if (message == null) {
106: return "Unable to retrieve the error message for problem id: " //$NON-NLS-1$
107: + (id & IProblem.IgnoreCategoriesMask)
108: + ". Check compiler resources."; //$NON-NLS-1$
109: }
110:
111: // for compatibility with MessageFormat which eliminates double quotes in original message
112: char[] messageWithNoDoubleQuotes = CharOperation.replace(
113: message.toCharArray(), DOUBLE_QUOTES, SINGLE_QUOTE);
114:
115: if (problemArguments == null)
116: return new String(messageWithNoDoubleQuotes);
117:
118: int length = messageWithNoDoubleQuotes.length;
119: int start = 0;
120: int end = length;
121: StringBuffer output = null;
122: if ((id & IProblem.Javadoc) != 0) {
123: output = new StringBuffer(10 + length
124: + problemArguments.length * 20);
125: output.append((String) this .messageTemplates
126: .get(keyFromID(IProblem.JavadocMessagePrefix
127: & IProblem.IgnoreCategoriesMask)));
128: }
129: while (true) {
130: if ((end = CharOperation.indexOf('{',
131: messageWithNoDoubleQuotes, start)) > -1) {
132: if (output == null)
133: output = new StringBuffer(length
134: + problemArguments.length * 20);
135: output.append(messageWithNoDoubleQuotes, start, end
136: - start);
137: if ((start = CharOperation.indexOf('}',
138: messageWithNoDoubleQuotes, end + 1)) > -1) {
139: int index = -1;
140: String argId = new String(
141: messageWithNoDoubleQuotes, end + 1, start
142: - end - 1);
143: try {
144: index = Integer.parseInt(argId);
145: output.append(problemArguments[index]);
146: } catch (NumberFormatException nfe) {
147: output.append(messageWithNoDoubleQuotes,
148: end + 1, start - end);
149: } catch (ArrayIndexOutOfBoundsException e) {
150: return "Cannot bind message for problem (id: " //$NON-NLS-1$
151: + (id & IProblem.IgnoreCategoriesMask)
152: + ") \"" //$NON-NLS-1$
153: + message + "\" with arguments: {" //$NON-NLS-1$
154: + Util.toString(problemArguments) + "}"; //$NON-NLS-1$
155: }
156: start++;
157: } else {
158: output.append(messageWithNoDoubleQuotes, end,
159: length);
160: break;
161: }
162: } else {
163: if (output == null)
164: return new String(messageWithNoDoubleQuotes);
165: output.append(messageWithNoDoubleQuotes, start, length
166: - start);
167: break;
168: }
169: }
170:
171: // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=120410
172: return new String(output.toString());
173: }
174:
175: /**
176: * @param problem CategorizedProblem
177: * @return String
178: */
179: public final String localizedMessage(CategorizedProblem problem) {
180: return getLocalizedMessage(problem.getID(), problem
181: .getArguments());
182: }
183:
184: /**
185: * This method initializes the MessageTemplates class variable according
186: * to the current Locale.
187: * @param loc Locale
188: * @return HashtableOfInt
189: */
190: public static HashtableOfInt loadMessageTemplates(Locale loc) {
191: ResourceBundle bundle = null;
192: String bundleName = "org.eclipse.jdt.internal.compiler.problem.messages"; //$NON-NLS-1$
193: try {
194: bundle = ResourceBundle.getBundle(bundleName, loc);
195: } catch (MissingResourceException e) {
196: System.out
197: .println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + loc); //$NON-NLS-1$//$NON-NLS-2$
198: throw e;
199: }
200: HashtableOfInt templates = new HashtableOfInt(700);
201: Enumeration keys = bundle.getKeys();
202: while (keys.hasMoreElements()) {
203: String key = (String) keys.nextElement();
204: try {
205: int messageID = Integer.parseInt(key);
206: templates.put(keyFromID(messageID), bundle
207: .getString(key));
208: } catch (NumberFormatException e) {
209: // key ill-formed
210: } catch (MissingResourceException e) {
211: // available ID
212: }
213: }
214: return templates;
215: }
216:
217: }
|