diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/NLS.d	Tue Apr 14 13:22:56 2009 +0200
@@ -0,0 +1,446 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM - Initial API and implementation
+ * Port to the D programming language:
+ *     Frank Benoit <benoit@tionex.de>
+ *******************************************************************************/
+module org.osgi.util.NLS;
+
+import java.lang.all;
+
+// import java.io.IOException;
+// import java.io.InputStream;
+// import java.lang.reflect.Field;
+// import java.lang.reflect.Modifier;
+// import java.security.AccessController;
+// import java.security.PrivilegedAction;
+// import java.util.ArrayList;
+// import java.util.HashMap;
+// import java.util.Locale;
+// import java.util.Map;
+// import java.util.Properties;
+//
+// import org.eclipse.osgi.framework.debug.Debug;
+// import org.eclipse.osgi.framework.log.FrameworkLog;
+// import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+
+/**
+ * Common superclass for all message bundle classes.  Provides convenience
+ * methods for manipulating messages.
+ * <p>
+ * The <code>#bind</code> methods perform string substitution and should be considered a
+ * convenience and <em>not</em> a full substitute replacement for <code>MessageFormat#format</code>
+ * method calls.
+ * </p>
+ * <p>
+ * Text appearing within curly braces in the given message, will be interpreted
+ * as a numeric index to the corresponding substitution object in the given array. Calling
+ * the <code>#bind</code> methods with text that does not map to an integer will result in an
+ * {@link IllegalArgumentException}.
+ * </p>
+ * <p>
+ * Text appearing within single quotes is treated as a literal. A single quote is escaped by
+ * a preceeding single quote.
+ * </p>
+ * <p>
+ * Clients who wish to use the full substitution power of the <code>MessageFormat</code> class should
+ * call that class directly and not use these <code>#bind</code> methods.
+ * </p>
+ * <p>
+ * Clients may subclass this type.
+ * </p>
+ *
+ * @since 3.1
+ */
+public abstract class NLS {
+
+//     private static final Object[] EMPTY_ARGS = new Object[0];
+//     private static final String EXTENSION = ".properties"; //$NON-NLS-1$
+//     private static String[] nlSuffixes;
+//     /*
+//      * NOTE do not change the name of this field; it is set by the Framework using reflection
+//      */
+//     private static FrameworkLog frameworkLog;
+//
+//     static final int SEVERITY_ERROR = 0x04;
+//     static final int SEVERITY_WARNING = 0x02;
+//     /*
+//      * This object is assigned to the value of a field map to indicate
+//      * that a translated message has already been assigned to that field.
+//      */
+//     static final Object ASSIGNED = new Object();
+//
+//     /**
+//      * Creates a new NLS instance.
+//      */
+//     protected NLS() {
+//         super();
+//     }
+
+    /**
+     * Bind the given message's substitution locations with the given string value.
+     *
+     * @param message the message to be manipulated
+     * @param binding the object to be inserted into the message
+     * @return the manipulated String
+     * @throws IllegalArgumentException if the text appearing within curly braces in the given message does not map to an integer
+     */
+    public static String bind(String message, Object binding) {
+        implMissing( __FILE__, __LINE__ );
+        return null;
+//         return internalBind(message, null, String.valueOf(binding), null);
+    }
+    public static String bind(String message, String binding) {
+        implMissing( __FILE__, __LINE__ );
+        return null;
+//         return internalBind(message, null, String.valueOf(binding), null);
+    }
+
+    /**
+     * Bind the given message's substitution locations with the given string values.
+     *
+     * @param message the message to be manipulated
+     * @param binding1 An object to be inserted into the message
+     * @param binding2 A second object to be inserted into the message
+     * @return the manipulated String
+     * @throws IllegalArgumentException if the text appearing within curly braces in the given message does not map to an integer
+     */
+    public static String bind(String message, Object binding1, Object binding2) {
+        implMissing( __FILE__, __LINE__ );
+        return null;
+//         return internalBind(message, null, String.valueOf(binding1), String.valueOf(binding2));
+    }
+    public static String bind(String message, String binding1, String binding2) {
+        implMissing( __FILE__, __LINE__ );
+        return null;
+//         return internalBind(message, null, String.valueOf(binding1), String.valueOf(binding2));
+    }
+
+    /**
+     * Bind the given message's substitution locations with the given string values.
+     *
+     * @param message the message to be manipulated
+     * @param bindings An array of objects to be inserted into the message
+     * @return the manipulated String
+     * @throws IllegalArgumentException if the text appearing within curly braces in the given message does not map to an integer
+     */
+    public static String bind(String message, Object[] bindings) {
+        implMissing( __FILE__, __LINE__ );
+        return null;
+//         return internalBind(message, bindings, null, null);
+    }
+    public static String bind(String message, String[] bindings) {
+        implMissing( __FILE__, __LINE__ );
+        return null;
+//         return internalBind(message, bindings, null, null);
+    }
+
+//     /**
+//      * Initialize the given class with the values from the specified message bundle.
+//      *
+//      * @param bundleName fully qualified path of the class name
+//      * @param clazz the class where the constants will exist
+//      */
+//     public static void initializeMessages(final String bundleName, final Class clazz) {
+//         if (System.getSecurityManager() is null) {
+//             load(bundleName, clazz);
+//             return;
+//         }
+//         AccessController.doPrivileged(new PrivilegedAction() {
+//             public Object run() {
+//                 load(bundleName, clazz);
+//                 return null;
+//             }
+//         });
+//     }
+//
+//     /*
+//      * Perform the string substitution on the given message with the specified args.
+//      * See the class comment for exact details.
+//      */
+//     private static String internalBind(String message, Object[] args, String argZero, String argOne) {
+//         if (message is null)
+//             return "No message available."; //$NON-NLS-1$
+//         if (args is null || args.length is 0)
+//             args = EMPTY_ARGS;
+//
+//         int length = message.length();
+//         //estimate correct size of string buffer to avoid growth
+//         int bufLen = length + (args.length * 5);
+//         if (argZero !is null)
+//             bufLen += argZero.length() - 3;
+//         if (argOne !is null)
+//             bufLen += argOne.length() - 3;
+//         StringBuffer buffer = new StringBuffer(bufLen < 0 ? 0 : bufLen);
+//         for (int i = 0; i < length; i++) {
+//             char c = message.charAt(i);
+//             switch (c) {
+//                 case '{' :
+//                     int index = message.indexOf('}', i);
+//                     // if we don't have a matching closing brace then...
+//                     if (index is -1) {
+//                         buffer.append(c);
+//                         break;
+//                     }
+//                     i++;
+//                     if (i >= length) {
+//                         buffer.append(c);
+//                         break;
+//                     }
+//                     // look for a substitution
+//                     int number = -1;
+//                     try {
+//                         number = Integer.parseInt(message.substring(i, index));
+//                     } catch (NumberFormatException e) {
+//                         throw new IllegalArgumentException();
+//                     }
+//                     if (number is 0 && argZero !is null)
+//                         buffer.append(argZero);
+//                     else if (number is 1 && argOne !is null)
+//                         buffer.append(argOne);
+//                     else {
+//                         if (number >= args.length || number < 0) {
+//                             buffer.append("<missing argument>"); //$NON-NLS-1$
+//                             i = index;
+//                             break;
+//                         }
+//                         buffer.append(args[number]);
+//                     }
+//                     i = index;
+//                     break;
+//                 case '\'' :
+//                     // if a single quote is the last char on the line then skip it
+//                     int nextIndex = i + 1;
+//                     if (nextIndex >= length) {
+//                         buffer.append(c);
+//                         break;
+//                     }
+//                     char next = message.charAt(nextIndex);
+//                     // if the next char is another single quote then write out one
+//                     if (next is '\'') {
+//                         i++;
+//                         buffer.append(c);
+//                         break;
+//                     }
+//                     // otherwise we want to read until we get to the next single quote
+//                     index = message.indexOf('\'', nextIndex);
+//                     // if there are no more in the string, then skip it
+//                     if (index is -1) {
+//                         buffer.append(c);
+//                         break;
+//                     }
+//                     // otherwise write out the chars inside the quotes
+//                     buffer.append(message.substring(nextIndex, index));
+//                     i = index;
+//                     break;
+//                 default :
+//                     buffer.append(c);
+//             }
+//         }
+//         return buffer.toString();
+//     }
+//
+//     /*
+//      * Build an array of property files to search.  The returned array contains
+//      * the property fields in order from most specific to most generic.
+//      * So, in the FR_fr locale, it will return file_fr_FR.properties, then
+//      * file_fr.properties, and finally file.properties.
+//      */
+//     private static String[] buildVariants(String root) {
+//         if (nlSuffixes is null) {
+//             //build list of suffixes for loading resource bundles
+//             String nl = Locale.getDefault().toString();
+//             ArrayList result = new ArrayList(4);
+//             int lastSeparator;
+//             while (true) {
+//                 result.add('_' + nl + EXTENSION);
+//                 lastSeparator = nl.lastIndexOf('_');
+//                 if (lastSeparator is -1)
+//                     break;
+//                 nl = nl.substring(0, lastSeparator);
+//             }
+//             //add the empty suffix last (most general)
+//             result.add(EXTENSION);
+//             nlSuffixes = (String[]) result.toArray(new String[result.size()]);
+//         }
+//         root = root.replace('.', '/');
+//         String[] variants = new String[nlSuffixes.length];
+//         for (int i = 0; i < variants.length; i++)
+//             variants[i] = root + nlSuffixes[i];
+//         return variants;
+//     }
+//
+//     private static void computeMissingMessages(String bundleName, Class clazz, Map fieldMap, Field[] fieldArray, bool isAccessible) {
+//         // iterate over the fields in the class to make sure that there aren't any empty ones
+//         final int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC;
+//         final int MOD_MASK = MOD_EXPECTED | Modifier.FINAL;
+//         final int numFields = fieldArray.length;
+//         for (int i = 0; i < numFields; i++) {
+//             Field field = fieldArray[i];
+//             if ((field.getModifiers() & MOD_MASK) !is MOD_EXPECTED)
+//                 continue;
+//             //if the field has a a value assigned, there is nothing to do
+//             if (fieldMap.get(field.getName()) is ASSIGNED)
+//                 continue;
+//             try {
+//                 // Set a value for this empty field. We should never get an exception here because
+//                 // we know we have a public static non-final field. If we do get an exception, silently
+//                 // log it and continue. This means that the field will (most likely) be un-initialized and
+//                 // will fail later in the code and if so then we will see both the NPE and this error.
+//                 String value = "NLS missing message: " + field.getName() + " in: " + bundleName; //$NON-NLS-1$ //$NON-NLS-2$
+//                 if (Debug.DEBUG_MESSAGE_BUNDLES)
+//                     System.out.println(value);
+//                 log(SEVERITY_WARNING, value, null);
+//                 if (!isAccessible)
+//                     field.setAccessible(true);
+//                 field.set(null, value);
+//             } catch (Exception e) {
+//                 log(SEVERITY_ERROR, "Error setting the missing message value for: " + field.getName(), e); //$NON-NLS-1$
+//             }
+//         }
+//     }
+//
+//     /*
+//      * Load the given resource bundle using the specified class loader.
+//      */
+//     static void load(final String bundleName, Class clazz) {
+//         long start = System.currentTimeMillis();
+//         final Field[] fieldArray = clazz.getDeclaredFields();
+//         ClassLoader loader = clazz.getClassLoader();
+//
+//         bool isAccessible = (clazz.getModifiers() & Modifier.PUBLIC) !is 0;
+//
+//         //build a map of field names to Field objects
+//         final int len = fieldArray.length;
+//         Map fields = new HashMap(len * 2);
+//         for (int i = 0; i < len; i++)
+//             fields.put(fieldArray[i].getName(), fieldArray[i]);
+//
+//         // search the variants from most specific to most general, since
+//         // the MessagesProperties.put method will mark assigned fields
+//         // to prevent them from being assigned twice
+//         final String[] variants = buildVariants(bundleName);
+//         for (int i = 0; i < variants.length; i++) {
+//             // loader is null if we're launched off the Java boot classpath
+//             final InputStream input = loader is null ? ClassLoader.getSystemResourceAsStream(variants[i]) : loader.getResourceAsStream(variants[i]);
+//             if (input is null)
+//                 continue;
+//             try {
+//                 final MessagesProperties properties = new MessagesProperties(fields, bundleName, isAccessible);
+//                 properties.load(input);
+//             } catch (IOException e) {
+//                 log(SEVERITY_ERROR, "Error loading " + variants[i], e); //$NON-NLS-1$
+//             } finally {
+//                 if (input !is null)
+//                     try {
+//                         input.close();
+//                     } catch (IOException e) {
+//                         // ignore
+//                     }
+//             }
+//         }
+//         computeMissingMessages(bundleName, clazz, fields, fieldArray, isAccessible);
+//         if (Debug.DEBUG_MESSAGE_BUNDLES)
+//             System.out.println("Time to load message bundle: " + bundleName + " was " + (System.currentTimeMillis() - start) + "ms."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+//     }
+//
+//     /*
+//      * The method adds a log entry based on the error message and exception.
+//      * The output is written to the System.err.
+//      *
+//      * This method is only expected to be called if there is a problem in
+//      * the NLS mechanism. As a result, translation facility is not available
+//      * here and messages coming out of this log are generally not translated.
+//      *
+//      * @param severity - severity of the message (SEVERITY_ERROR or SEVERITY_WARNING)
+//      * @param message - message to log
+//      * @param e - exception to log
+//      */
+//     static void log(int severity, String message, Exception e) {
+//         if (frameworkLog !is null) {
+//             frameworkLog.log(new FrameworkLogEntry("org.eclipse.osgi", severity, 1, message, 0, e, null)); //$NON-NLS-1$
+//             return;
+//         }
+//         String statusMsg;
+//         switch (severity) {
+//             case SEVERITY_ERROR :
+//                 statusMsg = "Error: "; //$NON-NLS-1$
+//                 break;
+//             case SEVERITY_WARNING :
+//                 // intentionally fall through:
+//             default :
+//                 statusMsg = "Warning: "; //$NON-NLS-1$
+//         }
+//         if (message !is null)
+//             statusMsg += message;
+//         if (e !is null)
+//             statusMsg += ": " + e.getMessage(); //$NON-NLS-1$
+//         System.err.println(statusMsg);
+//         if (e !is null)
+//             e.printStackTrace();
+//     }
+//
+//     /*
+//      * Class which sub-classes java.util.Properties and uses the #put method
+//      * to set field values rather than storing the values in the table.
+//      */
+//     private static class MessagesProperties extends Properties {
+//
+//         private static final int MOD_EXPECTED = Modifier.PUBLIC | Modifier.STATIC;
+//         private static final int MOD_MASK = MOD_EXPECTED | Modifier.FINAL;
+//         private static final long serialVersionUID = 1L;
+//
+//         private final String bundleName;
+//         private final Map fields;
+//         private final bool isAccessible;
+//
+//         public MessagesProperties(Map fieldMap, String bundleName, bool isAccessible) {
+//             super();
+//             this.fields = fieldMap;
+//             this.bundleName = bundleName;
+//             this.isAccessible = isAccessible;
+//         }
+//
+//         /* (non-Javadoc)
+//          * @see java.util.Hashtable#put(java.lang.Object, java.lang.Object)
+//          */
+//         public synchronized Object put(Object key, Object value) {
+//             Object fieldObject = fields.put(key, ASSIGNED);
+//             // if already assigned, there is nothing to do
+//             if (fieldObject is ASSIGNED)
+//                 return null;
+//             if (fieldObject is null) {
+//                 final String msg = "NLS unused message: " + key + " in: " + bundleName;//$NON-NLS-1$ //$NON-NLS-2$
+//                 if (Debug.DEBUG_MESSAGE_BUNDLES)
+//                     System.out.println(msg);
+//                 log(SEVERITY_WARNING, msg, null);
+//                 return null;
+//             }
+//             final Field field = (Field) fieldObject;
+//             //can only set value of public static non-final fields
+//             if ((field.getModifiers() & MOD_MASK) !is MOD_EXPECTED)
+//                 return null;
+//             try {
+//                 // Check to see if we are allowed to modify the field. If we aren't (for instance
+//                 // if the class is not public) then change the accessible attribute of the field
+//                 // before trying to set the value.
+//                 if (!isAccessible)
+//                     field.setAccessible(true);
+//                 // Set the value into the field. We should never get an exception here because
+//                 // we know we have a public static non-final field. If we do get an exception, silently
+//                 // log it and continue. This means that the field will (most likely) be un-initialized and
+//                 // will fail later in the code and if so then we will see both the NPE and this error.
+//                 field.set(null, value);
+//             } catch (Exception e) {
+//                 log(SEVERITY_ERROR, "Exception setting field value.", e); //$NON-NLS-1$
+//             }
+//             return null;
+//         }
+//     }
+}