org.eclipse.jdt.internal.compiler.util.Messages.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jdt.internal.compiler.util.Messages.java

Source

/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.util;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;

@SuppressWarnings({ "rawtypes", "unchecked" })
public final class Messages {
    private static class MessagesProperties extends Properties {

        private static final int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC;
        private static final int MOD_MASK = MOD_EXPECTED | Modifier.FINAL;
        private static final long serialVersionUID = 1L;

        private final Map fields;

        public MessagesProperties(Field[] fieldArray, String bundleName) {
            super();
            final int len = fieldArray.length;
            this.fields = new HashMap(len * 2);
            for (int i = 0; i < len; i++) {
                this.fields.put(fieldArray[i].getName(), fieldArray[i]);
            }
        }

        @Override
        public synchronized Object put(Object key, Object value) {
            try {
                Field field = (Field) this.fields.get(key);
                if (field == null) {
                    return null;
                }
                //can only set value of public static non-final fields
                if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED)
                    return null;
                // Set the value into the field. We should never get an exception here because
                // we know we have a public static non-final field. If we do get an exception, silently
                // log it and continue. This means that the field will (most likely) be un-initialized and
                // will fail later in the code and if so then we will see both the NPE and this error.
                try {
                    field.set(null, value);
                } catch (Exception e) {
                    // ignore
                }
            } catch (SecurityException e) {
                // ignore
            }
            return null;
        }
    }

    private static String[] nlSuffixes;
    private static final String EXTENSION = ".properties"; //$NON-NLS-1$

    private static final String BUNDLE_NAME = "org.eclipse.jdt.internal.compiler.messages";//$NON-NLS-1$

    private Messages() {
        // Do not instantiate
    }

    public static String compilation_unresolvedProblem;
    public static String compilation_unresolvedProblems;
    public static String compilation_request;
    public static String compilation_loadBinary;
    public static String compilation_process;
    public static String compilation_write;
    public static String compilation_done;
    public static String compilation_units;
    public static String compilation_unit;
    public static String compilation_internalError;
    public static String compilation_beginningToCompile;
    public static String compilation_processing;
    public static String output_isFile;
    public static String output_notValidAll;
    public static String output_notValid;
    public static String problem_noSourceInformation;
    public static String problem_atLine;
    public static String abort_invalidAttribute;
    public static String abort_invalidExceptionAttribute;
    public static String abort_invalidOpcode;
    public static String abort_missingCode;
    public static String abort_againstSourceModel;
    public static String abort_externaAnnotationFile;
    public static String accept_cannot;
    public static String parser_incorrectPath;
    public static String parser_moveFiles;
    public static String parser_syntaxRecovery;
    public static String parser_regularParse;
    public static String parser_missingFile;
    public static String parser_corruptedFile;
    public static String parser_endOfFile;
    public static String parser_endOfConstructor;
    public static String parser_endOfMethod;
    public static String parser_endOfInitializer;
    public static String ast_missingCode;
    public static String constant_cannotCastedInto;
    public static String constant_cannotConvertedTo;
    public static String abort_againstPreviewNotAllowed;

    static {
        initializeMessages(BUNDLE_NAME, Messages.class);
    }

    /**
     * Bind the given message's substitution locations with the given string values.
     *
     * @param message the message to be manipulated
     * @return the manipulated String
     */
    public static String bind(String message) {
        return bind(message, null);
    }

    /**
     * Bind the given message's substitution locations with the given string values.
     *
     * @param message the message to be manipulated
     * @param binding the object to be inserted into the message
     * @return the manipulated String
     */
    public static String bind(String message, Object binding) {
        return bind(message, new Object[] { binding });
    }

    /**
     * Bind the given message's substitution locations with the given string values.
     *
     * @param message the message to be manipulated
     * @param binding1 An object to be inserted into the message
     * @param binding2 A second object to be inserted into the message
     * @return the manipulated String
     */
    public static String bind(String message, Object binding1, Object binding2) {
        return bind(message, new Object[] { binding1, binding2 });
    }

    /**
     * Bind the given message's substitution locations with the given string values.
     *
     * @param message the message to be manipulated
     * @param bindings An array of objects to be inserted into the message
     * @return the manipulated String
     */
    public static String bind(String message, Object[] bindings) {
        return MessageFormat.format(message, bindings);
    }

    /*
     * Build an array of directories to search
     */
    private static String[] buildVariants(String root) {
        if (nlSuffixes == null) {
            //build list of suffixes for loading resource bundles
            String nl = Locale.getDefault().toString();
            ArrayList result = new ArrayList(4);
            int lastSeparator;
            while (true) {
                result.add('_' + nl + EXTENSION);
                lastSeparator = nl.lastIndexOf('_');
                if (lastSeparator == -1)
                    break;
                nl = nl.substring(0, lastSeparator);
            }
            //add the empty suffix last (most general)
            result.add(EXTENSION);
            nlSuffixes = (String[]) result.toArray(new String[result.size()]);
        }
        root = root.replace('.', '/');
        String[] variants = new String[nlSuffixes.length];
        for (int i = 0; i < variants.length; i++)
            variants[i] = root + nlSuffixes[i];
        return variants;
    }

    public static void initializeMessages(String bundleName, Class clazz) {
        // load the resource bundle and set the fields
        final Field[] fields = clazz.getDeclaredFields();
        load(bundleName, clazz.getClassLoader(), fields);

        // iterate over the fields in the class to make sure that there aren't any empty ones
        final int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC;
        final int MOD_MASK = MOD_EXPECTED | Modifier.FINAL;
        final int numFields = fields.length;
        for (int i = 0; i < numFields; i++) {
            Field field = fields[i];
            if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED)
                continue;
            try {
                // Set the value into the field if its empty. We should never get an exception here because
                // we know we have a public static non-final field. If we do get an exception, silently
                // log it and continue. This means that the field will (most likely) be un-initialized and
                // will fail later in the code and if so then we will see both the NPE and this error.
                if (field.get(clazz) == null) {
                    String value = "Missing message: " + field.getName() + " in: " + bundleName; //$NON-NLS-1$ //$NON-NLS-2$
                    field.set(null, value);
                }
            } catch (IllegalArgumentException | IllegalAccessException e) {
                // ignore
            }
        }
    }

    /**
     * Load the given resource bundle using the specified class loader.
     */
    public static void load(final String bundleName, final ClassLoader loader, final Field[] fields) {
        final String[] variants = buildVariants(bundleName);
        // search the dirs in reverse order so the cascading defaults is set correctly
        for (int i = variants.length; --i >= 0;) {
            InputStream input = (loader == null) ? ClassLoader.getSystemResourceAsStream(variants[i])
                    : loader.getResourceAsStream(variants[i]);
            if (input == null)
                continue;
            try {
                final MessagesProperties properties = new MessagesProperties(fields, bundleName);
                properties.load(input);
            } catch (IOException e) {
                // ignore
            } finally {
                try {
                    input.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
    }
}