1 11 package org.eclipse.osgi.util; 12 13 import java.io.IOException ; 14 import java.io.InputStream ; 15 import java.lang.reflect.Field ; 16 import java.lang.reflect.Modifier ; 17 import java.security.AccessController ; 18 import java.security.PrivilegedAction ; 19 import java.util.*; 20 import org.eclipse.osgi.framework.debug.Debug; 21 import org.eclipse.osgi.framework.log.FrameworkLog; 22 import org.eclipse.osgi.framework.log.FrameworkLogEntry; 23 24 52 public abstract class NLS { 53 54 private static final Object [] EMPTY_ARGS = new Object [0]; 55 private static final String EXTENSION = ".properties"; private static String [] nlSuffixes; 57 60 private static FrameworkLog frameworkLog; 61 62 static final int SEVERITY_ERROR = 0x04; 63 static final int SEVERITY_WARNING = 0x02; 64 68 static final Object ASSIGNED = new Object (); 69 70 73 protected NLS() { 74 super(); 75 } 76 77 84 public static String bind(String message, Object binding) { 85 return internalBind(message, null, String.valueOf(binding), null); 86 } 87 88 96 public static String bind(String message, Object binding1, Object binding2) { 97 return internalBind(message, null, String.valueOf(binding1), String.valueOf(binding2)); 98 } 99 100 107 public static String bind(String message, Object [] bindings) { 108 return internalBind(message, bindings, null, null); 109 } 110 111 117 public static void initializeMessages(final String bundleName, final Class clazz) { 118 if (System.getSecurityManager() == null) { 119 load(bundleName, clazz); 120 return; 121 } 122 AccessController.doPrivileged(new PrivilegedAction () { 123 public Object run() { 124 load(bundleName, clazz); 125 return null; 126 } 127 }); 128 } 129 130 134 private static String internalBind(String message, Object [] args, String argZero, String argOne) { 135 if (message == null) 136 return "No message available."; if (args == null || args.length == 0) 138 args = EMPTY_ARGS; 139 140 int length = message.length(); 141 int bufLen = length + (args.length * 5); 143 if (argZero != null) 144 bufLen += argZero.length() - 3; 145 if (argOne != null) 146 bufLen += argOne.length() - 3; 147 StringBuffer buffer = new StringBuffer (bufLen); 148 for (int i = 0; i < length; i++) { 149 char c = message.charAt(i); 150 switch (c) { 151 case '{' : 152 int index = message.indexOf('}', i); 153 if (index == -1) { 155 buffer.append(c); 156 break; 157 } 158 i++; 159 if (i >= length) { 160 buffer.append(c); 161 break; 162 } 163 int number = -1; 165 try { 166 number = Integer.parseInt(message.substring(i, index)); 167 } catch (NumberFormatException e) { 168 throw new IllegalArgumentException (); 169 } 170 if (number == 0 && argZero != null) 171 buffer.append(argZero); 172 else if (number == 1 && argOne != null) 173 buffer.append(argOne); 174 else { 175 if (number >= args.length || number < 0) { 176 buffer.append("<missing argument>"); i = index; 178 break; 179 } 180 buffer.append(args[number]); 181 } 182 i = index; 183 break; 184 case '\'' : 185 int nextIndex = i + 1; 187 if (nextIndex >= length) { 188 buffer.append(c); 189 break; 190 } 191 char next = message.charAt(nextIndex); 192 if (next == '\'') { 194 i++; 195 buffer.append(c); 196 break; 197 } 198 index = message.indexOf('\'', nextIndex); 200 if (index == -1) { 202 buffer.append(c); 203 break; 204 } 205 buffer.append(message.substring(nextIndex, index)); 207 i = index; 208 break; 209 default : 210 buffer.append(c); 211 } 212 } 213 return buffer.toString(); 214 } 215 216 222 private static String [] buildVariants(String root) { 223 if (nlSuffixes == null) { 224 String nl = Locale.getDefault().toString(); 226 ArrayList result = new ArrayList(4); 227 int lastSeparator; 228 while (true) { 229 result.add('_' + nl + EXTENSION); 230 lastSeparator = nl.lastIndexOf('_'); 231 if (lastSeparator == -1) 232 break; 233 nl = nl.substring(0, lastSeparator); 234 } 235 result.add(EXTENSION); 237 nlSuffixes = (String []) result.toArray(new String [result.size()]); 238 } 239 root = root.replace('.', '/'); 240 String [] variants = new String [nlSuffixes.length]; 241 for (int i = 0; i < variants.length; i++) 242 variants[i] = root + nlSuffixes[i]; 243 return variants; 244 } 245 246 private static void computeMissingMessages(String bundleName, Class clazz, Map fieldMap, Field [] fieldArray, boolean isAccessible) { 247 final int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC; 249 final int MOD_MASK = MOD_EXPECTED | Modifier.FINAL; 250 final int numFields = fieldArray.length; 251 for (int i = 0; i < numFields; i++) { 252 Field field = fieldArray[i]; 253 if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED) 254 continue; 255 if (fieldMap.get(field.getName()) == ASSIGNED) 257 continue; 258 try { 259 String value = "NLS missing message: " + field.getName() + " in: " + bundleName; if (Debug.DEBUG_MESSAGE_BUNDLES) 265 System.out.println(value); 266 log(SEVERITY_WARNING, value, null); 267 if (!isAccessible) 268 field.setAccessible(true); 269 field.set(null, value); 270 } catch (Exception e) { 271 log(SEVERITY_ERROR, "Error setting the missing message value for: " + field.getName(), e); } 273 } 274 } 275 276 279 static void load(final String bundleName, Class clazz) { 280 long start = System.currentTimeMillis(); 281 final Field [] fieldArray = clazz.getDeclaredFields(); 282 ClassLoader loader = clazz.getClassLoader(); 283 284 boolean isAccessible = (clazz.getModifiers() & Modifier.PUBLIC) != 0; 285 286 final int len = fieldArray.length; 288 Map fields = new HashMap(len * 2); 289 for (int i = 0; i < len; i++) 290 fields.put(fieldArray[i].getName(), fieldArray[i]); 291 292 final String [] variants = buildVariants(bundleName); 296 for (int i = 0; i < variants.length; i++) { 297 final InputStream input = loader==null ? ClassLoader.getSystemResourceAsStream(variants[i]) : loader.getResourceAsStream(variants[i]); 299 if (input == null) 300 continue; 301 try { 302 final MessagesProperties properties = new MessagesProperties(fields, bundleName, isAccessible); 303 properties.load(input); 304 } catch (IOException e) { 305 log(SEVERITY_ERROR, "Error loading " + variants[i], e); } finally { 307 if (input != null) 308 try { 309 input.close(); 310 } catch (IOException e) { 311 } 313 } 314 } 315 computeMissingMessages(bundleName, clazz, fields, fieldArray, isAccessible); 316 if (Debug.DEBUG_MESSAGE_BUNDLES) 317 System.out.println("Time to load message bundle: " + bundleName + " was " + (System.currentTimeMillis() - start) + "ms."); } 319 320 332 static void log(int severity, String message, Exception e) { 333 if (frameworkLog != null) { 334 frameworkLog.log(new FrameworkLogEntry("org.eclipse.osgi", severity, 1, message, 0, e, null)); return; 336 } 337 String statusMsg; 338 switch (severity) { 339 case SEVERITY_ERROR : 340 statusMsg = "Error: "; break; 342 case SEVERITY_WARNING : 343 default : 345 statusMsg = "Warning: "; } 347 if (message != null) 348 statusMsg += message; 349 if (e != null) 350 statusMsg += ": " + e.getMessage(); System.err.println(statusMsg); 352 if (e != null) 353 e.printStackTrace(); 354 } 355 356 360 private static class MessagesProperties extends Properties { 361 362 private static final int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC; 363 private static final int MOD_MASK = MOD_EXPECTED | Modifier.FINAL; 364 private static final long serialVersionUID = 1L; 365 366 private final String bundleName; 367 private final Map fields; 368 private final boolean isAccessible; 369 370 public MessagesProperties(Map fieldMap, String bundleName, boolean isAccessible) { 371 super(); 372 this.fields = fieldMap; 373 this.bundleName = bundleName; 374 this.isAccessible = isAccessible; 375 } 376 377 380 public synchronized Object put(Object key, Object value) { 381 Object fieldObject = fields.put(key, ASSIGNED); 382 if (fieldObject == ASSIGNED) 384 return null; 385 if (fieldObject == null) { 386 final String msg = "NLS unused message: " + key + " in: " + bundleName; if (Debug.DEBUG_MESSAGE_BUNDLES) 388 System.out.println(msg); 389 log(SEVERITY_WARNING, msg, null); 390 return null; 391 } 392 final Field field = (Field ) fieldObject; 393 if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED) 395 return null; 396 try { 397 if (!isAccessible) 401 field.setAccessible(true); 402 field.set(null, value); 407 } catch (Exception e) { 408 log(SEVERITY_ERROR, "Exception setting field value.", e); } 410 return null; 411 } 412 } 413 } | Popular Tags |