Move NLS class from core to OSGi packages
diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/util/NLS.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/util/NLS.java
new file mode 100644
index 0000000..ce03f5c
--- /dev/null
+++ b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/util/NLS.java
@@ -0,0 +1,119 @@
+/**********************************************************************
+ * Copyright (c) 2005 IBM Corporation and others. All rights reserved. This
+ * program and the accompanying materials are made available under the terms of
+ * the Common Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.osgi.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import org.eclipse.osgi.framework.internal.core.MessageResourceBundle;
+import org.eclipse.osgi.framework.msg.MessageFormat;
+
+
+/**
+ * Common superclass for all message bundle classes. Provides convenience
+ * methods for manipulating messages.
+ *
+ * @since 3.1
+ */
+public abstract class NLS {
+
+
+ public static boolean DEBUG_MESSAGE_BUNDLES = false;
+ /**
+ * Creates a new NLS instance.
+ */
+ protected NLS() {
+ super();
+ }
+
+ /**
+ * Bind the given message's substitution locations with the given string values.
+ *
+ * @param message the message to be manipulated
+ * @param binding the object to be inserted into the message
+ * @return the manipulated String
+ */
+ public static String bind(String message, Object binding) {
+ return bind(message, new Object[] {binding});
+ }
+
+ /**
+ * 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
+ */
+ public static String bind(String message, Object binding1, Object binding2) {
+ return bind(message, new Object[] {binding1, 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
+ */
+ public static String bind(String message, Object[] bindings) {
+ if (message == null)
+ return "No message available"; //$NON-NLS-1$
+ if (bindings == null)
+ return message;
+ return MessageFormat.format(message, bindings);
+ }
+
+ /**
+ * Initialize the given class with the values from the specified message bundle.
+ * <p>
+ * Note this is interim API and may change before the 3.1 release.
+ * </p>
+ *
+ * @param bundleName fully qualified path of the class name
+ * @param clazz the class where the constants will exist
+ */
+
+ public static void initializeMessages(String bundleName, Class clazz) {
+ long start = System.currentTimeMillis();
+ // load the resource bundle and set the fields
+ final Field[] fields = clazz.getDeclaredFields();
+ MessageResourceBundle.load(bundleName, clazz.getClassLoader(), fields);
+
+ // 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 = fields.length;
+ for (int i = 0; i < numFields; i++) {
+ Field field = fields[i];
+ if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED)
+ continue;
+ try {
+ // Set the value into the field if its empty. 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.
+ if (field.get(clazz) == null) {
+ String value = "Missing message: " + field.getName() + " in: " + bundleName; //$NON-NLS-1$ //$NON-NLS-2$
+ if (DEBUG_MESSAGE_BUNDLES)
+ System.out.println(value);
+ field.set(null, value);
+ }
+ } catch (IllegalArgumentException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ if (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$
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/MessageResourceBundle.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/MessageResourceBundle.java
new file mode 100644
index 0000000..287b5e2
--- /dev/null
+++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/MessageResourceBundle.java
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.framework.internal.core;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.*;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * Class responsible for loading message values from a property file
+ * and assigning them directly to the fields of a messages class.
+ * @since 3.1
+ */
+public class MessageResourceBundle {
+
+ /**
+ * Class which sub-classes java.util.Properties and uses the #put method
+ * to set field values rather than storing the values in the table.
+ *
+ * @since 3.1
+ */
+ 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 Map fields;
+ private final String bundleName;
+
+ public MessagesProperties(Field[] fieldArray, String bundleName) {
+ super();
+ this.bundleName = bundleName;
+ final int len = fieldArray.length;
+ fields = new HashMap(len * 2);
+ for (int i = 0; i < len; i++) {
+ fields.put(fieldArray[i].getName(), fieldArray[i]);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Hashtable#put(java.lang.Object, java.lang.Object)
+ */
+ public synchronized Object put(Object key, Object value) {
+ try {
+ Field field = (Field) fields.get(key);
+ if (field == null) {
+ if (NLS.DEBUG_MESSAGE_BUNDLES)
+ System.out.println("Unused message: " + key + " in: " + bundleName); //$NON-NLS-1$ //$NON-NLS-2$
+ return null;
+ }
+ //can only set value of public static non-final fields
+ if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED)
+ return null;
+ // 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.
+ try {
+ field.set(null, value);
+ } catch (Exception e) {
+ // TODO externalize message
+ //IStatus status = new Status(IStatus.ERROR, Platform.PI_RUNTIME, Platform.PLUGIN_ERROR, "Exception setting field value.", e);
+ //InternalPlatform.getDefault().log(status);
+ e.printStackTrace();
+ }
+ } catch (SecurityException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return null;
+ }
+ }
+
+ private static final String EXTENSION = ".properties"; //$NON-NLS-1$
+ private static String[] nlSuffixes;
+
+ /*
+ * Build an array of directories to search
+ */
+ private static String[] buildVariants(String root) {
+ if (nlSuffixes == 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 == -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;
+ }
+
+ /**
+ * Load the given resource bundle using the specified class loader.
+ */
+ public static void load(final String bundleName, final ClassLoader loader, final Field[] fields) {
+ final String[] variants = buildVariants(bundleName);
+ // search the dirs in reverse order so the cascading defaults is set correctly
+ for (int i = variants.length; --i >= 0;) {
+ final InputStream input = loader.getResourceAsStream(variants[i]);
+ if (input == null)
+ continue;
+ try {
+ final MessagesProperties properties = new MessagesProperties(fields, bundleName);
+ properties.load(input);
+ } catch (IOException e) {
+ // TODO log
+ } finally {
+ if (input != null)
+ try {
+ input.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/NLS.java b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/NLS.java
new file mode 100644
index 0000000..ce03f5c
--- /dev/null
+++ b/bundles/org.eclipse.osgi/supplement/src/org/eclipse/osgi/util/NLS.java
@@ -0,0 +1,119 @@
+/**********************************************************************
+ * Copyright (c) 2005 IBM Corporation and others. All rights reserved. This
+ * program and the accompanying materials are made available under the terms of
+ * the Common Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/cpl-v10.html
+ *
+ * Contributors:
+ * IBM - Initial API and implementation
+ **********************************************************************/
+package org.eclipse.osgi.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import org.eclipse.osgi.framework.internal.core.MessageResourceBundle;
+import org.eclipse.osgi.framework.msg.MessageFormat;
+
+
+/**
+ * Common superclass for all message bundle classes. Provides convenience
+ * methods for manipulating messages.
+ *
+ * @since 3.1
+ */
+public abstract class NLS {
+
+
+ public static boolean DEBUG_MESSAGE_BUNDLES = false;
+ /**
+ * Creates a new NLS instance.
+ */
+ protected NLS() {
+ super();
+ }
+
+ /**
+ * Bind the given message's substitution locations with the given string values.
+ *
+ * @param message the message to be manipulated
+ * @param binding the object to be inserted into the message
+ * @return the manipulated String
+ */
+ public static String bind(String message, Object binding) {
+ return bind(message, new Object[] {binding});
+ }
+
+ /**
+ * 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
+ */
+ public static String bind(String message, Object binding1, Object binding2) {
+ return bind(message, new Object[] {binding1, 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
+ */
+ public static String bind(String message, Object[] bindings) {
+ if (message == null)
+ return "No message available"; //$NON-NLS-1$
+ if (bindings == null)
+ return message;
+ return MessageFormat.format(message, bindings);
+ }
+
+ /**
+ * Initialize the given class with the values from the specified message bundle.
+ * <p>
+ * Note this is interim API and may change before the 3.1 release.
+ * </p>
+ *
+ * @param bundleName fully qualified path of the class name
+ * @param clazz the class where the constants will exist
+ */
+
+ public static void initializeMessages(String bundleName, Class clazz) {
+ long start = System.currentTimeMillis();
+ // load the resource bundle and set the fields
+ final Field[] fields = clazz.getDeclaredFields();
+ MessageResourceBundle.load(bundleName, clazz.getClassLoader(), fields);
+
+ // 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 = fields.length;
+ for (int i = 0; i < numFields; i++) {
+ Field field = fields[i];
+ if ((field.getModifiers() & MOD_MASK) != MOD_EXPECTED)
+ continue;
+ try {
+ // Set the value into the field if its empty. 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.
+ if (field.get(clazz) == null) {
+ String value = "Missing message: " + field.getName() + " in: " + bundleName; //$NON-NLS-1$ //$NON-NLS-2$
+ if (DEBUG_MESSAGE_BUNDLES)
+ System.out.println(value);
+ field.set(null, value);
+ }
+ } catch (IllegalArgumentException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ if (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$
+ }
+}
\ No newline at end of file