Lucene.Net  3.0.3
Lucene.Net is a port of the Lucene search engine library, written in C# and targeted at .NET runtime users.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Pages
NLS.cs
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 using System;
19 using System.Collections.Generic;
20 using Lucene.Net.Support;
21 
22 namespace Lucene.Net.Messages
23 {
24 
25  /// <summary> MessageBundles classes extend this class, to implement a bundle.
26  ///
27  /// For Native Language Support (NLS), system of software internationalization.
28  ///
29  /// This interface is similar to the NLS class in eclipse.osgi.util.NLS class -
30  /// initializeMessages() method resets the values of all static strings, should
31  /// only be called by classes that extend from NLS (see TestMessages.java for
32  /// reference) - performs validation of all message in a bundle, at class load
33  /// time - performs per message validation at runtime - see NLSTest.java for
34  /// usage reference
35  ///
36  /// MessageBundle classes may subclass this type.
37  /// </summary>
38  public class NLS
39  {
40  public interface IPriviligedAction
41  {
42  /// <summary>
43  /// Performs the priviliged action.
44  /// </summary>
45  /// <returns>A value that may represent the result of the action.</returns>
46  System.Object Run();
47  }
48 
49  private class AnonymousClassPrivilegedAction : IPriviligedAction
50  {
51  public AnonymousClassPrivilegedAction(System.Reflection.FieldInfo field)
52  {
53  InitBlock(field);
54  }
55  private void InitBlock(System.Reflection.FieldInfo field)
56  {
57  this.field = field;
58  }
59  private System.Reflection.FieldInfo field;
60  public virtual System.Object Run()
61  {
62  // field.setAccessible(true); // {{Aroush-2.9}} java.lang.reflect.AccessibleObject.setAccessible
63  return null;
64  }
65  }
66 
67  private static IDictionary<string, Type> bundles = new HashMap<string, Type>(0);
68 
69  protected internal NLS()
70  {
71  // Do not instantiate
72  }
73 
74  public static System.String GetLocalizedMessage(System.String key)
75  {
76  return GetLocalizedMessage(key, System.Threading.Thread.CurrentThread.CurrentCulture);
77  }
78 
79  public static System.String GetLocalizedMessage(System.String key, System.Globalization.CultureInfo locale)
80  {
81  System.Object message = GetResourceBundleObject(key, locale);
82  if (message == null)
83  {
84  return "Message with key:" + key + " and locale: " + locale + " not found.";
85  }
86  return message.ToString();
87  }
88 
89  public static System.String GetLocalizedMessage(System.String key, System.Globalization.CultureInfo locale, params System.Object[] args)
90  {
91  System.String str = GetLocalizedMessage(key, locale);
92 
93  if (args.Length > 0)
94  {
95  str = System.String.Format(str, args);
96  }
97 
98  return str;
99  }
100 
101  public static System.String GetLocalizedMessage(System.String key, params System.Object[] args)
102  {
103  return GetLocalizedMessage(key, System.Threading.Thread.CurrentThread.CurrentCulture, args);
104  }
105 
106  /// <summary> Initialize a given class with the message bundle Keys Should be called from
107  /// a class that extends NLS in a static block at class load time.
108  ///
109  /// </summary>
110  /// <param name="bundleName">Property file with that contains the message bundle
111  /// </param>
112  /// <param name="clazz">where constants will reside
113  /// </param>
114  //@SuppressWarnings("unchecked")
115  protected internal static void InitializeMessages<T>(System.String bundleName)
116  {
117  try
118  {
119  Load<T>();
120  if (!bundles.ContainsKey(bundleName))
121  bundles[bundleName] = typeof(T);
122  }
123  catch (System.Exception)
124  {
125  // ignore all errors and exceptions
126  // because this function is supposed to be called at class load time.
127  }
128  }
129 
130  private static System.Object GetResourceBundleObject(System.String messageKey, System.Globalization.CultureInfo locale)
131  {
132 
133  // slow resource checking
134  // need to loop thru all registered resource bundles
135  for (var it = bundles.Keys.GetEnumerator(); it.MoveNext(); )
136  {
137  System.Type clazz = bundles[it.Current];
138  System.Threading.Thread.CurrentThread.CurrentUICulture = locale;
139  System.Resources.ResourceManager resourceBundle = System.Resources.ResourceManager.CreateFileBasedResourceManager(clazz.Name, "Messages", null); //{{Lucene.Net-2.9.1}} Can we make resourceDir "Messages" more general?
140  if (resourceBundle != null)
141  {
142  try
143  {
144  System.Object obj = resourceBundle.GetObject(messageKey);
145  if (obj != null)
146  return obj;
147  }
148  catch (System.Resources.MissingManifestResourceException)
149  {
150  // just continue it might be on the next resource bundle
151  }
152  }
153  }
154  // if resource is not found
155  return null;
156  }
157 
158  private static void Load<T>()
159  {
160  var clazz = typeof (T);
161  System.Reflection.FieldInfo[] fieldArray = clazz.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.Static);
162 
163  bool isFieldAccessible = clazz.IsPublic;
164 
165  // build a map of field names to Field objects
166  int len = fieldArray.Length;
167  var fields = new HashMap<string, System.Reflection.FieldInfo>(len * 2);
168  for (int i = 0; i < len; i++)
169  {
170  fields[fieldArray[i].Name] = fieldArray[i];
171  LoadfieldValue<T>(fieldArray[i], isFieldAccessible);
172  }
173  }
174 
175  /// <param name="field"></param>
176  /// <param name="isFieldAccessible"></param>
177  private static void LoadfieldValue<T>(System.Reflection.FieldInfo field, bool isFieldAccessible)
178  {
179  var clazz = typeof (T);
180  /*
181  int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC;
182  int MOD_MASK = MOD_EXPECTED | Modifier.FINAL;
183  if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED)
184  return ;
185  */
186  if (!(field.IsPublic || field.IsStatic))
187  return ;
188 
189  // Set a value for this empty field.
190  if (!isFieldAccessible)
191  MakeAccessible(field);
192  try
193  {
194  field.SetValue(null, field.Name);
195  ValidateMessage<T>(field.Name);
196  }
197  catch (System.ArgumentException)
198  {
199  // should not happen
200  }
201  catch (System.UnauthorizedAccessException)
202  {
203  // should not happen
204  }
205  }
206 
207  /// <param name="key">- Message Key
208  /// </param>
209  private static void ValidateMessage<T>(System.String key)
210  {
211  // Test if the message is present in the resource bundle
212  var clazz = typeof (T);
213  try
214  {
215  System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture;
216  System.Resources.ResourceManager resourceBundle = System.Resources.ResourceManager.CreateFileBasedResourceManager(clazz.FullName, "", null);
217  if (resourceBundle != null)
218  {
219  System.Object obj = resourceBundle.GetObject(key);
220  if (obj == null)
221  {
222  System.Console.Error.WriteLine("WARN: Message with key:" + key + " and locale: " + System.Threading.Thread.CurrentThread.CurrentCulture + " not found.");
223  }
224  }
225  }
226  catch (System.Resources.MissingManifestResourceException)
227  {
228  System.Console.Error.WriteLine("WARN: Message with key:" + key + " and locale: " + System.Threading.Thread.CurrentThread.CurrentCulture + " not found.");
229  }
230  catch (System.Exception)
231  {
232  // ignore all other errors and exceptions
233  // since this code is just a test to see if the message is present on the
234  // system
235  }
236  }
237 
238  /*
239  * Make a class field accessible
240  */
241  //@SuppressWarnings("unchecked")
242  private static void MakeAccessible(System.Reflection.FieldInfo field)
243  {
244  if (System.Security.SecurityManager.SecurityEnabled)
245  {
246  //field.setAccessible(true); // {{Aroush-2.9}} java.lang.reflect.AccessibleObject.setAccessible
247  }
248  else
249  {
250  //AccessController.doPrivileged(new AnonymousClassPrivilegedAction(field)); // {{Aroush-2.9}} java.security.AccessController.doPrivileged
251  }
252  }
253  }
254 }