add --shared
[pylucene.git] / lucene-java-3.4.0 / lucene / src / java / org / apache / lucene / messages / NLS.java
1 package org.apache.lucene.messages;
2
3 /**
4  * Licensed to the Apache Software Foundation (ASF) under one or more
5  * contributor license agreements.  See the NOTICE file distributed with
6  * this work for additional information regarding copyright ownership.
7  * The ASF licenses this file to You under the Apache License, Version 2.0
8  * (the "License"); you may not use this file except in compliance with
9  * the License.  You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 import java.lang.reflect.Field;
21 import java.lang.reflect.Modifier;
22 import java.security.AccessController;
23 import java.security.PrivilegedAction;
24 import java.text.MessageFormat;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.Locale;
28 import java.util.Map;
29 import java.util.MissingResourceException;
30 import java.util.ResourceBundle;
31
32 /**
33  * MessageBundles classes extend this class, to implement a bundle.
34  * 
35  * For Native Language Support (NLS), system of software internationalization.
36  * 
37  * This interface is similar to the NLS class in eclipse.osgi.util.NLS class -
38  * initializeMessages() method resets the values of all static strings, should
39  * only be called by classes that extend from NLS (see TestMessages.java for
40  * reference) - performs validation of all message in a bundle, at class load
41  * time - performs per message validation at runtime - see NLSTest.java for
42  * usage reference
43  * 
44  * MessageBundle classes may subclass this type.
45  */
46 public class NLS {
47
48   private static Map<String, Class<? extends NLS>> bundles = 
49     new HashMap<String, Class<? extends NLS>>(0);
50
51   protected NLS() {
52     // Do not instantiate
53   }
54
55   public static String getLocalizedMessage(String key) {
56     return getLocalizedMessage(key, Locale.getDefault());
57   }
58
59   public static String getLocalizedMessage(String key, Locale locale) {
60     Object message = getResourceBundleObject(key, locale);
61     if (message == null) {
62       return "Message with key:" + key + " and locale: " + locale
63           + " not found.";
64     }
65     return message.toString();
66   }
67
68   public static String getLocalizedMessage(String key, Locale locale,
69       Object... args) {
70     String str = getLocalizedMessage(key, locale);
71
72     if (args.length > 0) {
73       str = MessageFormat.format(str, args);
74     }
75
76     return str;
77   }
78
79   public static String getLocalizedMessage(String key, Object... args) {
80     return getLocalizedMessage(key, Locale.getDefault(), args);
81   }
82
83   /**
84    * Initialize a given class with the message bundle Keys Should be called from
85    * a class that extends NLS in a static block at class load time.
86    * 
87    * @param bundleName
88    *          Property file with that contains the message bundle
89    * @param clazz
90    *          where constants will reside
91    */
92   protected static void initializeMessages(String bundleName, Class<? extends NLS> clazz) {
93     try {
94       load(clazz);
95       if (!bundles.containsKey(bundleName))
96         bundles.put(bundleName, clazz);
97     } catch (Throwable e) {
98       // ignore all errors and exceptions
99       // because this function is supposed to be called at class load time.
100     }
101   }
102
103   private static Object getResourceBundleObject(String messageKey, Locale locale) {
104
105     // slow resource checking
106     // need to loop thru all registered resource bundles
107     for (Iterator<String> it = bundles.keySet().iterator(); it.hasNext();) {
108       Class<? extends NLS> clazz = bundles.get(it.next());
109       ResourceBundle resourceBundle = ResourceBundle.getBundle(clazz.getName(),
110           locale);
111       if (resourceBundle != null) {
112         try {
113           Object obj = resourceBundle.getObject(messageKey);
114           if (obj != null)
115             return obj;
116         } catch (MissingResourceException e) {
117           // just continue it might be on the next resource bundle
118         }
119       }
120     }
121     // if resource is not found
122     return null;
123   }
124
125   /**
126    * @param clazz
127    */
128   private static void load(Class<? extends NLS> clazz) {
129     final Field[] fieldArray = clazz.getDeclaredFields();
130
131     boolean isFieldAccessible = (clazz.getModifiers() & Modifier.PUBLIC) != 0;
132
133     // build a map of field names to Field objects
134     final int len = fieldArray.length;
135     Map<String, Field> fields = new HashMap<String, Field>(len * 2);
136     for (int i = 0; i < len; i++) {
137       fields.put(fieldArray[i].getName(), fieldArray[i]);
138       loadfieldValue(fieldArray[i], isFieldAccessible, clazz);
139     }
140   }
141
142   /**
143    * @param field
144    * @param isFieldAccessible
145    */
146   private static void loadfieldValue(Field field, boolean isFieldAccessible,
147       Class<? extends NLS> clazz) {
148     int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC;
149     int MOD_MASK = MOD_EXPECTED | Modifier.FINAL;
150     if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED)
151       return;
152
153     // Set a value for this empty field.
154     if (!isFieldAccessible)
155       makeAccessible(field);
156     try {
157       field.set(null, field.getName());
158       validateMessage(field.getName(), clazz);
159     } catch (IllegalArgumentException e) {
160       // should not happen
161     } catch (IllegalAccessException e) {
162       // should not happen
163     }
164   }
165
166   /**
167    * @param key
168    *          - Message Key
169    */
170   private static void validateMessage(String key, Class<? extends NLS> clazz) {
171     // Test if the message is present in the resource bundle
172     try {
173       ResourceBundle resourceBundle = ResourceBundle.getBundle(clazz.getName(),
174           Locale.getDefault());
175       if (resourceBundle != null) {
176         Object obj = resourceBundle.getObject(key);
177         if (obj == null)
178           System.err.println("WARN: Message with key:" + key + " and locale: "
179               + Locale.getDefault() + " not found.");
180       }
181     } catch (MissingResourceException e) {
182       System.err.println("WARN: Message with key:" + key + " and locale: "
183           + Locale.getDefault() + " not found.");
184     } catch (Throwable e) {
185       // ignore all other errors and exceptions
186       // since this code is just a test to see if the message is present on the
187       // system
188     }
189   }
190
191   /*
192    * Make a class field accessible
193    */
194   private static void makeAccessible(final Field field) {
195     if (System.getSecurityManager() == null) {
196       field.setAccessible(true);
197     } else {
198       AccessController.doPrivileged(new PrivilegedAction<Void>() {
199         public Void run() {
200           field.setAccessible(true);
201           return null;
202         }
203       });
204     }
205   }
206 }