Mercurial > projects > dwt2
comparison org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/NLS.d @ 83:0628aaa2996c
added osgi FramworkLog
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Tue, 14 Apr 2009 13:22:56 +0200 |
parents | org.eclipse.osgi/supplement/src/org/osgi/util/NLS.d@a7064d39311b |
children | 8594250b1d1c |
comparison
equal
deleted
inserted
replaced
82:b2d6122fa189 | 83:0628aaa2996c |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2005, 2008 IBM Corporation and others. | |
3 * All rights reserved. This program and the accompanying materials | |
4 * are made available under the terms of the Eclipse Public License v1.0 | |
5 * which accompanies this distribution, and is available at | |
6 * http://www.eclipse.org/legal/epl-v10.html | |
7 * | |
8 * Contributors: | |
9 * IBM - Initial API and implementation | |
10 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module org.osgi.util.NLS; | |
14 | |
15 import java.lang.all; | |
16 | |
17 // import java.io.IOException; | |
18 // import java.io.InputStream; | |
19 // import java.lang.reflect.Field; | |
20 // import java.lang.reflect.Modifier; | |
21 // import java.security.AccessController; | |
22 // import java.security.PrivilegedAction; | |
23 // import java.util.ArrayList; | |
24 // import java.util.HashMap; | |
25 // import java.util.Locale; | |
26 // import java.util.Map; | |
27 // import java.util.Properties; | |
28 // | |
29 // import org.eclipse.osgi.framework.debug.Debug; | |
30 // import org.eclipse.osgi.framework.log.FrameworkLog; | |
31 // import org.eclipse.osgi.framework.log.FrameworkLogEntry; | |
32 | |
33 /** | |
34 * Common superclass for all message bundle classes. Provides convenience | |
35 * methods for manipulating messages. | |
36 * <p> | |
37 * The <code>#bind</code> methods perform string substitution and should be considered a | |
38 * convenience and <em>not</em> a full substitute replacement for <code>MessageFormat#format</code> | |
39 * method calls. | |
40 * </p> | |
41 * <p> | |
42 * Text appearing within curly braces in the given message, will be interpreted | |
43 * as a numeric index to the corresponding substitution object in the given array. Calling | |
44 * the <code>#bind</code> methods with text that does not map to an integer will result in an | |
45 * {@link IllegalArgumentException}. | |
46 * </p> | |
47 * <p> | |
48 * Text appearing within single quotes is treated as a literal. A single quote is escaped by | |
49 * a preceeding single quote. | |
50 * </p> | |
51 * <p> | |
52 * Clients who wish to use the full substitution power of the <code>MessageFormat</code> class should | |
53 * call that class directly and not use these <code>#bind</code> methods. | |
54 * </p> | |
55 * <p> | |
56 * Clients may subclass this type. | |
57 * </p> | |
58 * | |
59 * @since 3.1 | |
60 */ | |
61 public abstract class NLS { | |
62 | |
63 // private static final Object[] EMPTY_ARGS = new Object[0]; | |
64 // private static final String EXTENSION = ".properties"; //$NON-NLS-1$ | |
65 // private static String[] nlSuffixes; | |
66 // /* | |
67 // * NOTE do not change the name of this field; it is set by the Framework using reflection | |
68 // */ | |
69 // private static FrameworkLog frameworkLog; | |
70 // | |
71 // static final int SEVERITY_ERROR = 0x04; | |
72 // static final int SEVERITY_WARNING = 0x02; | |
73 // /* | |
74 // * This object is assigned to the value of a field map to indicate | |
75 // * that a translated message has already been assigned to that field. | |
76 // */ | |
77 // static final Object ASSIGNED = new Object(); | |
78 // | |
79 // /** | |
80 // * Creates a new NLS instance. | |
81 // */ | |
82 // protected NLS() { | |
83 // super(); | |
84 // } | |
85 | |
86 /** | |
87 * Bind the given message's substitution locations with the given string value. | |
88 * | |
89 * @param message the message to be manipulated | |
90 * @param binding the object to be inserted into the message | |
91 * @return the manipulated String | |
92 * @throws IllegalArgumentException if the text appearing within curly braces in the given message does not map to an integer | |
93 */ | |
94 public static String bind(String message, Object binding) { | |
95 implMissing( __FILE__, __LINE__ ); | |
96 return null; | |
97 // return internalBind(message, null, String.valueOf(binding), null); | |
98 } | |
99 public static String bind(String message, String binding) { | |
100 implMissing( __FILE__, __LINE__ ); | |
101 return null; | |
102 // return internalBind(message, null, String.valueOf(binding), null); | |
103 } | |
104 | |
105 /** | |
106 * Bind the given message's substitution locations with the given string values. | |
107 * | |
108 * @param message the message to be manipulated | |
109 * @param binding1 An object to be inserted into the message | |
110 * @param binding2 A second object to be inserted into the message | |
111 * @return the manipulated String | |
112 * @throws IllegalArgumentException if the text appearing within curly braces in the given message does not map to an integer | |
113 */ | |
114 public static String bind(String message, Object binding1, Object binding2) { | |
115 implMissing( __FILE__, __LINE__ ); | |
116 return null; | |
117 // return internalBind(message, null, String.valueOf(binding1), String.valueOf(binding2)); | |
118 } | |
119 public static String bind(String message, String binding1, String binding2) { | |
120 implMissing( __FILE__, __LINE__ ); | |
121 return null; | |
122 // return internalBind(message, null, String.valueOf(binding1), String.valueOf(binding2)); | |
123 } | |
124 | |
125 /** | |
126 * Bind the given message's substitution locations with the given string values. | |
127 * | |
128 * @param message the message to be manipulated | |
129 * @param bindings An array of objects to be inserted into the message | |
130 * @return the manipulated String | |
131 * @throws IllegalArgumentException if the text appearing within curly braces in the given message does not map to an integer | |
132 */ | |
133 public static String bind(String message, Object[] bindings) { | |
134 implMissing( __FILE__, __LINE__ ); | |
135 return null; | |
136 // return internalBind(message, bindings, null, null); | |
137 } | |
138 public static String bind(String message, String[] bindings) { | |
139 implMissing( __FILE__, __LINE__ ); | |
140 return null; | |
141 // return internalBind(message, bindings, null, null); | |
142 } | |
143 | |
144 // /** | |
145 // * Initialize the given class with the values from the specified message bundle. | |
146 // * | |
147 // * @param bundleName fully qualified path of the class name | |
148 // * @param clazz the class where the constants will exist | |
149 // */ | |
150 // public static void initializeMessages(final String bundleName, final Class clazz) { | |
151 // if (System.getSecurityManager() is null) { | |
152 // load(bundleName, clazz); | |
153 // return; | |
154 // } | |
155 // AccessController.doPrivileged(new PrivilegedAction() { | |
156 // public Object run() { | |
157 // load(bundleName, clazz); | |
158 // return null; | |
159 // } | |
160 // }); | |
161 // } | |
162 // | |
163 // /* | |
164 // * Perform the string substitution on the given message with the specified args. | |
165 // * See the class comment for exact details. | |
166 // */ | |
167 // private static String internalBind(String message, Object[] args, String argZero, String argOne) { | |
168 // if (message is null) | |
169 // return "No message available."; //$NON-NLS-1$ | |
170 // if (args is null || args.length is 0) | |
171 // args = EMPTY_ARGS; | |
172 // | |
173 // int length = message.length(); | |
174 // //estimate correct size of string buffer to avoid growth | |
175 // int bufLen = length + (args.length * 5); | |
176 // if (argZero !is null) | |
177 // bufLen += argZero.length() - 3; | |
178 // if (argOne !is null) | |
179 // bufLen += argOne.length() - 3; | |
180 // StringBuffer buffer = new StringBuffer(bufLen < 0 ? 0 : bufLen); | |
181 // for (int i = 0; i < length; i++) { | |
182 // char c = message.charAt(i); | |
183 // switch (c) { | |
184 // case '{' : | |
185 // int index = message.indexOf('}', i); | |
186 // // if we don't have a matching closing brace then... | |
187 // if (index is -1) { | |
188 // buffer.append(c); | |
189 // break; | |
190 // } | |
191 // i++; | |
192 // if (i >= length) { | |
193 // buffer.append(c); | |
194 // break; | |
195 // } | |
196 // // look for a substitution | |
197 // int number = -1; | |
198 // try { | |
199 // number = Integer.parseInt(message.substring(i, index)); | |
200 // } catch (NumberFormatException e) { | |
201 // throw new IllegalArgumentException(); | |
202 // } | |
203 // if (number is 0 && argZero !is null) | |
204 // buffer.append(argZero); | |
205 // else if (number is 1 && argOne !is null) | |
206 // buffer.append(argOne); | |
207 // else { | |
208 // if (number >= args.length || number < 0) { | |
209 // buffer.append("<missing argument>"); //$NON-NLS-1$ | |
210 // i = index; | |
211 // break; | |
212 // } | |
213 // buffer.append(args[number]); | |
214 // } | |
215 // i = index; | |
216 // break; | |
217 // case '\'' : | |
218 // // if a single quote is the last char on the line then skip it | |
219 // int nextIndex = i + 1; | |
220 // if (nextIndex >= length) { | |
221 // buffer.append(c); | |
222 // break; | |
223 // } | |
224 // char next = message.charAt(nextIndex); | |
225 // // if the next char is another single quote then write out one | |
226 // if (next is '\'') { | |
227 // i++; | |
228 // buffer.append(c); | |
229 // break; | |
230 // } | |
231 // // otherwise we want to read until we get to the next single quote | |
232 // index = message.indexOf('\'', nextIndex); | |
233 // // if there are no more in the string, then skip it | |
234 // if (index is -1) { | |
235 // buffer.append(c); | |
236 // break; | |
237 // } | |
238 // // otherwise write out the chars inside the quotes | |
239 // buffer.append(message.substring(nextIndex, index)); | |
240 // i = index; | |
241 // break; | |
242 // default : | |
243 // buffer.append(c); | |
244 // } | |
245 // } | |
246 // return buffer.toString(); | |
247 // } | |
248 // | |
249 // /* | |
250 // * Build an array of property files to search. The returned array contains | |
251 // * the property fields in order from most specific to most generic. | |
252 // * So, in the FR_fr locale, it will return file_fr_FR.properties, then | |
253 // * file_fr.properties, and finally file.properties. | |
254 // */ | |
255 // private static String[] buildVariants(String root) { | |
256 // if (nlSuffixes is null) { | |
257 // //build list of suffixes for loading resource bundles | |
258 // String nl = Locale.getDefault().toString(); | |
259 // ArrayList result = new ArrayList(4); | |
260 // int lastSeparator; | |
261 // while (true) { | |
262 // result.add('_' + nl + EXTENSION); | |
263 // lastSeparator = nl.lastIndexOf('_'); | |
264 // if (lastSeparator is -1) | |
265 // break; | |
266 // nl = nl.substring(0, lastSeparator); | |
267 // } | |
268 // //add the empty suffix last (most general) | |
269 // result.add(EXTENSION); | |
270 // nlSuffixes = (String[]) result.toArray(new String[result.size()]); | |
271 // } | |
272 // root = root.replace('.', '/'); | |
273 // String[] variants = new String[nlSuffixes.length]; | |
274 // for (int i = 0; i < variants.length; i++) | |
275 // variants[i] = root + nlSuffixes[i]; | |
276 // return variants; | |
277 // } | |
278 // | |
279 // private static void computeMissingMessages(String bundleName, Class clazz, Map fieldMap, Field[] fieldArray, bool isAccessible) { | |
280 // // iterate over the fields in the class to make sure that there aren't any empty ones | |
281 // final int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC; | |
282 // final int MOD_MASK = MOD_EXPECTED | Modifier.FINAL; | |
283 // final int numFields = fieldArray.length; | |
284 // for (int i = 0; i < numFields; i++) { | |
285 // Field field = fieldArray[i]; | |
286 // if ((field.getModifiers() & MOD_MASK) !is MOD_EXPECTED) | |
287 // continue; | |
288 // //if the field has a a value assigned, there is nothing to do | |
289 // if (fieldMap.get(field.getName()) is ASSIGNED) | |
290 // continue; | |
291 // try { | |
292 // // Set a value for this empty field. We should never get an exception here because | |
293 // // we know we have a public static non-final field. If we do get an exception, silently | |
294 // // log it and continue. This means that the field will (most likely) be un-initialized and | |
295 // // will fail later in the code and if so then we will see both the NPE and this error. | |
296 // String value = "NLS missing message: " + field.getName() + " in: " + bundleName; //$NON-NLS-1$ //$NON-NLS-2$ | |
297 // if (Debug.DEBUG_MESSAGE_BUNDLES) | |
298 // System.out.println(value); | |
299 // log(SEVERITY_WARNING, value, null); | |
300 // if (!isAccessible) | |
301 // field.setAccessible(true); | |
302 // field.set(null, value); | |
303 // } catch (Exception e) { | |
304 // log(SEVERITY_ERROR, "Error setting the missing message value for: " + field.getName(), e); //$NON-NLS-1$ | |
305 // } | |
306 // } | |
307 // } | |
308 // | |
309 // /* | |
310 // * Load the given resource bundle using the specified class loader. | |
311 // */ | |
312 // static void load(final String bundleName, Class clazz) { | |
313 // long start = System.currentTimeMillis(); | |
314 // final Field[] fieldArray = clazz.getDeclaredFields(); | |
315 // ClassLoader loader = clazz.getClassLoader(); | |
316 // | |
317 // bool isAccessible = (clazz.getModifiers() & Modifier.PUBLIC) !is 0; | |
318 // | |
319 // //build a map of field names to Field objects | |
320 // final int len = fieldArray.length; | |
321 // Map fields = new HashMap(len * 2); | |
322 // for (int i = 0; i < len; i++) | |
323 // fields.put(fieldArray[i].getName(), fieldArray[i]); | |
324 // | |
325 // // search the variants from most specific to most general, since | |
326 // // the MessagesProperties.put method will mark assigned fields | |
327 // // to prevent them from being assigned twice | |
328 // final String[] variants = buildVariants(bundleName); | |
329 // for (int i = 0; i < variants.length; i++) { | |
330 // // loader is null if we're launched off the Java boot classpath | |
331 // final InputStream input = loader is null ? ClassLoader.getSystemResourceAsStream(variants[i]) : loader.getResourceAsStream(variants[i]); | |
332 // if (input is null) | |
333 // continue; | |
334 // try { | |
335 // final MessagesProperties properties = new MessagesProperties(fields, bundleName, isAccessible); | |
336 // properties.load(input); | |
337 // } catch (IOException e) { | |
338 // log(SEVERITY_ERROR, "Error loading " + variants[i], e); //$NON-NLS-1$ | |
339 // } finally { | |
340 // if (input !is null) | |
341 // try { | |
342 // input.close(); | |
343 // } catch (IOException e) { | |
344 // // ignore | |
345 // } | |
346 // } | |
347 // } | |
348 // computeMissingMessages(bundleName, clazz, fields, fieldArray, isAccessible); | |
349 // if (Debug.DEBUG_MESSAGE_BUNDLES) | |
350 // System.out.println("Time to load message bundle: " + bundleName + " was " + (System.currentTimeMillis() - start) + "ms."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ | |
351 // } | |
352 // | |
353 // /* | |
354 // * The method adds a log entry based on the error message and exception. | |
355 // * The output is written to the System.err. | |
356 // * | |
357 // * This method is only expected to be called if there is a problem in | |
358 // * the NLS mechanism. As a result, translation facility is not available | |
359 // * here and messages coming out of this log are generally not translated. | |
360 // * | |
361 // * @param severity - severity of the message (SEVERITY_ERROR or SEVERITY_WARNING) | |
362 // * @param message - message to log | |
363 // * @param e - exception to log | |
364 // */ | |
365 // static void log(int severity, String message, Exception e) { | |
366 // if (frameworkLog !is null) { | |
367 // frameworkLog.log(new FrameworkLogEntry("org.eclipse.osgi", severity, 1, message, 0, e, null)); //$NON-NLS-1$ | |
368 // return; | |
369 // } | |
370 // String statusMsg; | |
371 // switch (severity) { | |
372 // case SEVERITY_ERROR : | |
373 // statusMsg = "Error: "; //$NON-NLS-1$ | |
374 // break; | |
375 // case SEVERITY_WARNING : | |
376 // // intentionally fall through: | |
377 // default : | |
378 // statusMsg = "Warning: "; //$NON-NLS-1$ | |
379 // } | |
380 // if (message !is null) | |
381 // statusMsg += message; | |
382 // if (e !is null) | |
383 // statusMsg += ": " + e.getMessage(); //$NON-NLS-1$ | |
384 // System.err.println(statusMsg); | |
385 // if (e !is null) | |
386 // e.printStackTrace(); | |
387 // } | |
388 // | |
389 // /* | |
390 // * Class which sub-classes java.util.Properties and uses the #put method | |
391 // * to set field values rather than storing the values in the table. | |
392 // */ | |
393 // private static class MessagesProperties extends Properties { | |
394 // | |
395 // private static final int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC; | |
396 // private static final int MOD_MASK = MOD_EXPECTED | Modifier.FINAL; | |
397 // private static final long serialVersionUID = 1L; | |
398 // | |
399 // private final String bundleName; | |
400 // private final Map fields; | |
401 // private final bool isAccessible; | |
402 // | |
403 // public MessagesProperties(Map fieldMap, String bundleName, bool isAccessible) { | |
404 // super(); | |
405 // this.fields = fieldMap; | |
406 // this.bundleName = bundleName; | |
407 // this.isAccessible = isAccessible; | |
408 // } | |
409 // | |
410 // /* (non-Javadoc) | |
411 // * @see java.util.Hashtable#put(java.lang.Object, java.lang.Object) | |
412 // */ | |
413 // public synchronized Object put(Object key, Object value) { | |
414 // Object fieldObject = fields.put(key, ASSIGNED); | |
415 // // if already assigned, there is nothing to do | |
416 // if (fieldObject is ASSIGNED) | |
417 // return null; | |
418 // if (fieldObject is null) { | |
419 // final String msg = "NLS unused message: " + key + " in: " + bundleName;//$NON-NLS-1$ //$NON-NLS-2$ | |
420 // if (Debug.DEBUG_MESSAGE_BUNDLES) | |
421 // System.out.println(msg); | |
422 // log(SEVERITY_WARNING, msg, null); | |
423 // return null; | |
424 // } | |
425 // final Field field = (Field) fieldObject; | |
426 // //can only set value of public static non-final fields | |
427 // if ((field.getModifiers() & MOD_MASK) !is MOD_EXPECTED) | |
428 // return null; | |
429 // try { | |
430 // // Check to see if we are allowed to modify the field. If we aren't (for instance | |
431 // // if the class is not public) then change the accessible attribute of the field | |
432 // // before trying to set the value. | |
433 // if (!isAccessible) | |
434 // field.setAccessible(true); | |
435 // // Set the value into the field. We should never get an exception here because | |
436 // // we know we have a public static non-final field. If we do get an exception, silently | |
437 // // log it and continue. This means that the field will (most likely) be un-initialized and | |
438 // // will fail later in the code and if so then we will see both the NPE and this error. | |
439 // field.set(null, value); | |
440 // } catch (Exception e) { | |
441 // log(SEVERITY_ERROR, "Exception setting field value.", e); //$NON-NLS-1$ | |
442 // } | |
443 // return null; | |
444 // } | |
445 // } | |
446 } |