content: package org.apache.lucene.messages;
  
  /**
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (the "License"); you may not use this file except in compliance with
   * the License.  You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  import java.lang.reflect.Field;
  import java.lang.reflect.Modifier;
  import java.security.AccessController;
  import java.security.PrivilegedAction;
  import java.text.MessageFormat;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Locale;
  import java.util.Map;
  import java.util.MissingResourceException;
  import java.util.ResourceBundle;
  
  /**
   * MessageBundles classes extend this class, to implement a bundle.
   * 
   * For Native Language Support (NLS), system of software internationalization.
   * 
   * This interface is similar to the NLS class in eclipse.osgi.util.NLS class -
   * initializeMessages() method resets the values of all static strings, should
   * only be called by classes that extend from NLS (see TestMessages.java for
   * reference) - performs validation of all message in a bundle, at class load
   * time - performs per message validation at runtime - see NLSTest.java for
   * usage reference
   * 
   * MessageBundle classes may subclass this type.
   */
  public class NLS {
  
    private static Map<String, Class<? extends NLS>> bundles = 
      new HashMap<String, Class<? extends NLS>>(0);
  
    protected NLS() {
      // Do not instantiate
    }
  
    public static String getLocalizedMessage(String key) {
      return getLocalizedMessage(key, Locale.getDefault());
    }
  
    public static String getLocalizedMessage(String key, Locale locale) {
      Object message = getResourceBundleObject(key, locale);
      if (message == null) {
        return "Message with key:" + key + " and locale: " + locale
            + " not found.";
      }
      return message.toString();
    }
  
    public static String getLocalizedMessage(String key, Locale locale,
        Object... args) {
      String str = getLocalizedMessage(key, locale);
  
      if (args.length > 0) {
        str = MessageFormat.format(str, args);
      }
  
      return str;
    }
  
    public static String getLocalizedMessage(String key, Object... args) {
      return getLocalizedMessage(key, Locale.getDefault(), args);
    }
  
    /**
     * Initialize a given class with the message bundle Keys Should be called from
     * a class that extends NLS in a static block at class load time.
     * 
     * @param bundleName
     *          Property file with that contains the message bundle
     * @param clazz
     *          where constants will reside
     */
    protected static void initializeMessages(String bundleName, Class<? extends NLS> clazz) {
      try {
        load(clazz);
        if (!bundles.containsKey(bundleName))
          bundles.put(bundleName, clazz);
      } catch (Throwable e) {
        // ignore all errors and exceptions
        // because this function is supposed to be called at class load time.
      }
    }
  
    private static Object getResourceBundleObject(String messageKey, Locale locale) {
  
      // slow resource checking
      // need to loop thru all registered resource bundles
      for (Iterator<String> it = bundles.keySet().iterator(); it.hasNext();) {
        Class<? extends NLS> clazz = bundles.get(it.next());
        ResourceBundle resourceBundle = ResourceBundle.getBundle(clazz.getName(),
            locale);
        if (resourceBundle != null) {
          try {
            Object obj = resourceBundle.getObject(messageKey);
            if (obj != null)
              return obj;
          } catch (MissingResourceException e) {
            // just continue it might be on the next resource bundle
          }
        }
      }
      // if resource is not found
      return null;
    }
  
    /**
     * @param clazz
     */
    private static void load(Class<? extends NLS> clazz) {
      final Field[] fieldArray = clazz.getDeclaredFields();
  
      boolean isFieldAccessible = (clazz.getModifiers() & Modifier.PUBLIC) != 0;
  
      // build a map of field names to Field objects
      final int len = fieldArray.length;
      Map<String, Field> fields = new HashMap<String, Field>(len * 2);
      for (int i = 0; i < len; i++) {
        fields.put(fieldArray[i].getName(), fieldArray[i]);
        loadfieldValue(fieldArray[i], isFieldAccessible, clazz);
      }
    }
  
    /**
     * @param field
     * @param isFieldAccessible
     */
    private static void loadfieldValue(Field field, boolean isFieldAccessible,
        Class<? extends NLS> clazz) {
      int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC;
      int MOD_MASK = MOD_EXPECTED | Modifier.FINAL;
      if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED)
        return;
  
      // Set a value for this empty field.
      if (!isFieldAccessible)
        makeAccessible(field);
      try {
        field.set(null, field.getName());
        validateMessage(field.getName(), clazz);
      } catch (IllegalArgumentException e) {
        // should not happen
      } catch (IllegalAccessException e) {
        // should not happen
      }
    }
  
    /**
     * @param key
     *          - Message Key
     */
    private static void validateMessage(String key, Class<? extends NLS> clazz) {
      // Test if the message is present in the resource bundle
      try {
        ResourceBundle resourceBundle = ResourceBundle.getBundle(clazz.getName(),
            Locale.getDefault());
        if (resourceBundle != null) {
          Object obj = resourceBundle.getObject(key);
          if (obj == null)
            System.err.println("WARN: Message with key:" + key + " and locale: "
                + Locale.getDefault() + " not found.");
        }
      } catch (MissingResourceException e) {
        System.err.println("WARN: Message with key:" + key + " and locale: "
            + Locale.getDefault() + " not found.");
      } catch (Throwable e) {
        // ignore all other errors and exceptions
        // since this code is just a test to see if the message is present on the
        // system
      }
    }
  
    /*
     * Make a class field accessible
     */
    private static void makeAccessible(final Field field) {
      if (System.getSecurityManager() == null) {
        field.setAccessible(true);
      } else {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
          public Void run() {
            field.setAccessible(true);
            return null;
          }
        });
      }
    }
  }
  