/******************************************************************************* * Copyright (c) 2000, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.compiler.problem; import java.util.Enumeration; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.internal.compiler.IProblemFactory; import org.eclipse.jdt.internal.compiler.util.HashtableOfInt; import org.eclipse.jdt.internal.compiler.util.Util; public class DefaultProblemFactory implements IProblemFactory { public HashtableOfInt messageTemplates; private Locale locale; private static HashtableOfInt DEFAULT_LOCALE_TEMPLATES; private final static char[] DOUBLE_QUOTES= "''".toCharArray(); //$NON-NLS-1$ private final static char[] SINGLE_QUOTE= "'".toCharArray(); //$NON-NLS-1$ private final static char[] FIRST_ARGUMENT= "{0}".toCharArray(); //$NON-NLS-1$ public DefaultProblemFactory() { this(Locale.getDefault()); } /** * @param loc the locale used to get the right message */ public DefaultProblemFactory(Locale loc) { setLocale(loc); } /** * Answer a new IProblem created according to the parameters value * <ul> * <li>originatingFileName the name of the file name from which the problem is originated * <li>problemId the problem id * <li>problemArguments the fully qualified arguments recorded inside the problem * <li>messageArguments the arguments needed to set the error message (shorter names than * problemArguments ones) * <li>severity the severity of the problem * <li>startPosition the starting position of the problem * <li>endPosition the end position of the problem * <li>lineNumber the line on which the problem occured * </ul> * * @param originatingFileName char[] * @param problemId int * @param problemArguments String[] * @param messageArguments String[] * @param severity int * @param startPosition int * @param endPosition int * @param lineNumber int * @return CategorizedProblem */ public CategorizedProblem createProblem( char[] originatingFileName, int problemId, String[] problemArguments, String[] messageArguments, int severity, int startPosition, int endPosition, int lineNumber, int columnNumber) { return new DefaultProblem( originatingFileName, this.getLocalizedMessage(problemId, messageArguments), problemId, problemArguments, severity, startPosition, endPosition, lineNumber, columnNumber); } public CategorizedProblem createProblem( char[] originatingFileName, int problemId, String[] problemArguments, int elaborationId, String[] messageArguments, int severity, int startPosition, int endPosition, int lineNumber, int columnNumber) { return new DefaultProblem( originatingFileName, this.getLocalizedMessage(problemId, elaborationId, messageArguments), problemId, problemArguments, severity, startPosition, endPosition, lineNumber, columnNumber); } private final static int keyFromID(int id) { return id + 1; // keys are offsetted by one in table, since it cannot handle 0 key } /** * Answer the locale used to retrieve the error messages * * @return java.util.Locale */ public Locale getLocale() { return this.locale; } public void setLocale(Locale locale) { if (locale == this.locale) return; this.locale= locale; if (Locale.getDefault().equals(locale)) { if (DEFAULT_LOCALE_TEMPLATES == null) { DEFAULT_LOCALE_TEMPLATES= loadMessageTemplates(locale); } this.messageTemplates= DEFAULT_LOCALE_TEMPLATES; } else { this.messageTemplates= loadMessageTemplates(locale); } } public final String getLocalizedMessage(int id, String[] problemArguments) { return getLocalizedMessage(id, 0, problemArguments); } public final String getLocalizedMessage(int id, int elaborationId, String[] problemArguments) { String rawMessage= (String)this.messageTemplates.get(keyFromID(id & IProblem.IgnoreCategoriesMask)); if (rawMessage == null) { return "Unable to retrieve the error message for problem id: " //$NON-NLS-1$ + (id & IProblem.IgnoreCategoriesMask) + ". Check compiler resources."; //$NON-NLS-1$ } char[] message= rawMessage.toCharArray(); if (elaborationId != 0) { String elaboration= (String)this.messageTemplates.get(keyFromID(elaborationId)); if (elaboration == null) { return "Unable to retrieve the error message elaboration for elaboration id: " //$NON-NLS-1$ + elaborationId + ". Check compiler resources."; //$NON-NLS-1$ } message= CharOperation.replace(message, FIRST_ARGUMENT, elaboration.toCharArray()); } // for compatibility with MessageFormat which eliminates double quotes in original message message= CharOperation.replace(message, DOUBLE_QUOTES, SINGLE_QUOTE); if (problemArguments == null) { return new String(message); } int length= message.length; int start= 0; int end= length; StringBuffer output= null; if ((id & IProblem.Javadoc) != 0) { output= new StringBuffer(10 + length + problemArguments.length * 20); output.append((String)this.messageTemplates.get(keyFromID(IProblem.JavadocMessagePrefix & IProblem.IgnoreCategoriesMask))); } while (true) { if ((end= CharOperation.indexOf('{', message, start)) > -1) { if (output == null) output= new StringBuffer(length + problemArguments.length * 20); output.append(message, start, end - start); if ((start= CharOperation.indexOf('}', message, end + 1)) > -1) { try { output.append(problemArguments[CharOperation.parseInt(message, end + 1, start - end - 1)]); } catch (NumberFormatException nfe) { output.append(message, end + 1, start - end); } catch (ArrayIndexOutOfBoundsException e) { return "Cannot bind message for problem (id: " //$NON-NLS-1$ + (id & IProblem.IgnoreCategoriesMask) + ") \"" //$NON-NLS-1$ + new String(message) + "\" with arguments: {" //$NON-NLS-1$ + Util.toString(problemArguments) + "}"; //$NON-NLS-1$ } start++; } else { output.append(message, end, length); break; } } else { if (output == null) { return new String(message); } output.append(message, start, length - start); break; } } // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=120410 return new String(output.toString()); } /** * @param problem CategorizedProblem * @return String */ public final String localizedMessage(CategorizedProblem problem) { return getLocalizedMessage(problem.getID(), problem.getArguments()); } /** * This method initializes the MessageTemplates class variable according to the current Locale. * * @param loc Locale * @return HashtableOfInt */ public static HashtableOfInt loadMessageTemplates(Locale loc) { ResourceBundle bundle= null; String bundleName= "org.eclipse.jdt.internal.compiler.problem.messages"; //$NON-NLS-1$ try { bundle= ResourceBundle.getBundle(bundleName, loc); } catch (MissingResourceException e) { System.out.println("Missing resource : " + bundleName.replace('.', '/') + ".properties for locale " + loc); //$NON-NLS-1$//$NON-NLS-2$ throw e; } HashtableOfInt templates= new HashtableOfInt(700); Enumeration keys= bundle.getKeys(); while (keys.hasMoreElements()) { String key= (String)keys.nextElement(); try { int messageID= Integer.parseInt(key); templates.put(keyFromID(messageID), bundle.getString(key)); } catch (NumberFormatException e) { // key ill-formed } catch (MissingResourceException e) { // available ID } } return templates; } }