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 }