1 package org.codehaus.plexus.i18n;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import org.codehaus.plexus.logging.AbstractLogEnabled;
20 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
21 import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
22 import org.codehaus.plexus.util.StringUtils;
23
24 import java.text.MessageFormat;
25 import java.util.HashMap;
26 import java.util.Locale;
27 import java.util.Map;
28 import java.util.MissingResourceException;
29 import java.util.ResourceBundle;
30 import java.lang.reflect.Field;
31
32
33
34
35
36 public class DefaultI18N
37 extends AbstractLogEnabled
38 implements I18N, Initializable
39 {
40 private static final Object[] NO_ARGS = new Object[0];
41
42 private HashMap bundles;
43
44 private String[] bundleNames;
45
46 private String defaultBundleName;
47
48 private Locale defaultLocale = Locale.getDefault();
49
50 private String defaultLanguage = Locale.getDefault().getLanguage();
51
52 private String defaultCountry = Locale.getDefault().getCountry();
53
54 private boolean devMode;
55
56
57
58
59
60 public String getDefaultLanguage()
61 {
62 return defaultLanguage;
63 }
64
65 public String getDefaultCountry()
66 {
67 return defaultCountry;
68 }
69
70 public String getDefaultBundleName()
71 {
72 return defaultBundleName;
73 }
74
75 public String[] getBundleNames()
76 {
77 return (String[]) bundleNames.clone();
78 }
79
80 public ResourceBundle getBundle()
81 {
82 return getBundle( getDefaultBundleName(), (Locale) null );
83 }
84
85 public ResourceBundle getBundle( String bundleName )
86 {
87 return getBundle( bundleName, (Locale) null );
88 }
89
90
91
92
93
94
95
96
97
98
99 public ResourceBundle getBundle( String bundleName, String languageHeader )
100 {
101 return getBundle( bundleName, getLocale( languageHeader ) );
102 }
103
104
105
106
107
108
109
110
111
112
113
114 public ResourceBundle getBundle( String bundleName, Locale locale )
115 {
116
117 bundleName = ( bundleName == null ? getDefaultBundleName() : bundleName.trim() );
118
119
120
121
122
123 if ( devMode )
124 {
125 try
126 {
127 Class klass = ResourceBundle.getBundle( bundleName ).getClass().getSuperclass();
128
129 Field field = klass.getDeclaredField( "cacheList" );
130
131 field.setAccessible( true );
132
133
134
135
136
137 Object cache = field.get( null );
138
139 cache.getClass().getDeclaredMethod( "clear", null ).invoke( cache, null );
140
141 field.setAccessible( false );
142 }
143 catch ( Exception e )
144 {
145
146 }
147 }
148
149 if ( locale == null )
150 {
151 locale = getLocale( null );
152 }
153
154
155 ResourceBundle rb;
156
157 HashMap bundlesByLocale = (HashMap) bundles.get( bundleName );
158
159 if ( bundlesByLocale != null )
160 {
161
162
163 rb = (ResourceBundle) bundlesByLocale.get( locale );
164
165 if ( rb == null )
166 {
167
168 rb = cacheBundle( bundleName, locale );
169 }
170 }
171 else
172 {
173 rb = cacheBundle( bundleName, locale );
174 }
175
176 return rb;
177 }
178
179
180
181
182 public Locale getLocale( String header )
183 {
184 if ( !StringUtils.isEmpty( header ) )
185 {
186 I18NTokenizer tok = new I18NTokenizer( header );
187
188 if ( tok.hasNext() )
189 {
190 return (Locale) tok.next();
191 }
192 }
193
194
195 return defaultLocale;
196 }
197
198 public String getString( String key )
199 {
200 return getString( key, null );
201 }
202
203 public String getString( String key, Locale locale )
204 {
205 return getString( getDefaultBundleName(), locale, key );
206 }
207
208
209
210
211
212 public String getString( String bundleName, Locale locale, String key )
213 {
214 String value;
215
216 if ( locale == null )
217 {
218 locale = getLocale( null );
219 }
220
221
222 ResourceBundle rb = getBundle( bundleName, locale );
223
224 value = getStringOrNull( rb, key );
225
226
227 if ( value == null && bundleNames.length > 0 )
228 {
229 String name;
230 for ( int i = 0; i < bundleNames.length; i++ )
231 {
232 name = bundleNames[i];
233
234 if ( !name.equals( bundleName ) )
235 {
236 rb = getBundle( name, locale );
237
238 value = getStringOrNull( rb, key );
239
240 if ( value != null )
241 {
242 locale = rb.getLocale();
243
244 break;
245 }
246 }
247 }
248 }
249
250 if ( value == null )
251 {
252 String loc = locale.toString();
253
254 String mesg = "Noticed missing resource: " + "bundleName=" + bundleName + ", locale=" + loc + ", key=" + key;
255
256 getLogger().debug( mesg );
257
258
259
260 value = key;
261 }
262
263 return value;
264 }
265
266 public String format( String key, Object arg1 )
267 {
268 return format( defaultBundleName, defaultLocale, key, new Object[]{arg1} );
269 }
270
271 public String format( String key, Object arg1, Object arg2 )
272 {
273 return format( defaultBundleName, defaultLocale, key, new Object[]{arg1, arg2} );
274 }
275
276
277
278
279 public String format( String bundleName,
280 Locale locale,
281 String key,
282 Object arg1 )
283 {
284 return format( bundleName, locale, key, new Object[]{arg1} );
285 }
286
287
288
289
290 public String format( String bundleName,
291 Locale locale,
292 String key,
293 Object arg1,
294 Object arg2 )
295 {
296 return format( bundleName, locale, key, new Object[]{arg1, arg2} );
297 }
298
299
300
301
302
303
304
305
306
307
308 public String format( String bundleName, Locale locale, String key, Object[] args )
309 {
310 if ( locale == null )
311 {
312
313
314 locale = getLocale( null );
315 }
316
317 String value = getString( bundleName, locale, key );
318 if ( args == null )
319 {
320 args = NO_ARGS;
321 }
322
323
324
325
326
327 MessageFormat messageFormat = new MessageFormat( "" );
328 messageFormat.setLocale( locale );
329 messageFormat.applyPattern( value );
330
331 return messageFormat.format( args );
332 }
333
334
335
336
337
338 public void initialize()
339 throws InitializationException
340 {
341 bundles = new HashMap();
342
343 defaultLocale = new Locale( defaultLanguage, defaultCountry );
344
345 initializeBundleNames();
346
347 if ( "true".equals( System.getProperty( "PLEXUS_DEV_MODE" ) ) )
348 {
349 devMode = true;
350 }
351 }
352
353
354
355
356
357 protected void initializeBundleNames()
358 {
359
360 if ( defaultBundleName != null && defaultBundleName.length() > 0 )
361 {
362
363 if ( bundleNames == null || bundleNames.length <= 0 )
364 {
365 bundleNames = new String[]{defaultBundleName};
366 }
367 else
368 {
369
370 String[] array = new String[bundleNames.length + 1];
371 array[0] = defaultBundleName;
372 System.arraycopy( bundleNames, 0, array, 1, bundleNames.length );
373 bundleNames = array;
374 }
375 }
376 if ( bundleNames == null )
377 {
378 bundleNames = new String[0];
379 }
380 }
381
382
383
384
385
386
387
388
389 private synchronized ResourceBundle cacheBundle( String bundleName, Locale locale )
390 throws MissingResourceException
391 {
392 HashMap bundlesByLocale = (HashMap) bundles.get( bundleName );
393
394 ResourceBundle rb = ( bundlesByLocale == null ? null : (ResourceBundle) bundlesByLocale.get( locale ) );
395
396 if ( rb == null )
397 {
398 bundlesByLocale = ( bundlesByLocale == null ? new HashMap( 3 ) : new HashMap( bundlesByLocale ) );
399
400 try
401 {
402 rb = ResourceBundle.getBundle( bundleName, locale );
403 }
404 catch ( MissingResourceException e )
405 {
406 rb = findBundleByLocale( bundleName, locale, bundlesByLocale );
407
408 if ( rb == null )
409 {
410 throw (MissingResourceException) e.fillInStackTrace();
411 }
412 }
413
414 if ( rb != null )
415 {
416
417 bundlesByLocale.put( rb.getLocale(), rb );
418
419 HashMap bundlesByName = new HashMap( bundles );
420
421 bundlesByName.put( bundleName, bundlesByLocale );
422
423 this.bundles = bundlesByName;
424 }
425 }
426
427 return rb;
428 }
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445 private ResourceBundle findBundleByLocale( String bundleName,
446 Locale locale,
447 Map bundlesByLocale )
448 {
449 ResourceBundle rb = null;
450
451 if ( !StringUtils.isNotEmpty( locale.getCountry() ) &&
452 defaultLanguage.equals( locale.getLanguage() ) )
453 {
454
455
456
457
458
459 Locale withDefaultCountry = new Locale( locale.getLanguage(),
460 defaultCountry );
461 rb = (ResourceBundle) bundlesByLocale.get( withDefaultCountry );
462 if ( rb == null )
463 {
464 rb = getBundleIgnoreException( bundleName, withDefaultCountry );
465 }
466 }
467 else if ( !StringUtils.isNotEmpty( locale.getLanguage() ) &&
468 defaultCountry.equals( locale.getCountry() ) )
469 {
470 Locale withDefaultLanguage = new Locale( defaultLanguage,
471 locale.getCountry() );
472 rb = (ResourceBundle) bundlesByLocale.get( withDefaultLanguage );
473 if ( rb == null )
474 {
475 rb = getBundleIgnoreException( bundleName, withDefaultLanguage );
476 }
477 }
478
479 if ( rb == null && !defaultLocale.equals( locale ) )
480 {
481 rb = getBundleIgnoreException( bundleName, defaultLocale );
482 }
483
484 return rb;
485 }
486
487
488
489
490
491
492
493 private ResourceBundle getBundleIgnoreException( String bundleName, Locale locale )
494 {
495 try
496 {
497 return ResourceBundle.getBundle( bundleName, locale );
498 }
499 catch ( MissingResourceException ignored )
500 {
501 return null;
502 }
503 }
504
505
506
507
508
509
510
511 protected final String getStringOrNull( ResourceBundle rb, String key )
512 {
513 if ( rb != null )
514 {
515 try
516 {
517 return rb.getString( key );
518 }
519 catch ( MissingResourceException ignored )
520 {
521
522 }
523 }
524 return null;
525 }
526
527 }