bug 366235: add tests, refactor implementation, and add usage example to interface
diff --git a/org.eclipse.gemini.mgmt.tests/src/org/eclipse/gemini/mgmt/DefaultObjectNameTranslatorTest.java b/org.eclipse.gemini.mgmt.tests/src/org/eclipse/gemini/mgmt/DefaultObjectNameTranslatorTest.java
index 2f8855d..4485ef8 100755
--- a/org.eclipse.gemini.mgmt.tests/src/org/eclipse/gemini/mgmt/DefaultObjectNameTranslatorTest.java
+++ b/org.eclipse.gemini.mgmt.tests/src/org/eclipse/gemini/mgmt/DefaultObjectNameTranslatorTest.java
@@ -14,6 +14,8 @@
 import java.util.Dictionary;
 import java.util.Hashtable;
 
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.Assert;
 import org.osgi.framework.Bundle;
@@ -21,18 +23,72 @@
 import org.easymock.EasyMock;
 
 public class DefaultObjectNameTranslatorTest {
-    
+
+    private static final ClassNotFoundException TEST_CLASS_NOT_FOUND_EXCEPTION = new ClassNotFoundException("Test");
+
+    private static final String TEST_OBJECT_NAME_TRANSLATOR_CLASS_NAME = TestObjectNameTranslator.class.getName();
+
+    private static final String UNLOADABLE_CLASS_NAME = "BAD";
+
+    private static final String UNINSTANTIABLE_OBJECT_NAME_TRANSLATOR_CLASS_NAME = UninstantiableObjectNameTranslator.class.getName();
+
+    private BundleContext mockBundleContext;
+
+    private Bundle mockBundle;
+
+    private Dictionary<String, String> headers;
+
+    @Before
+    public void setUp() throws Exception {
+        mockBundleContext = EasyMock.createMock(BundleContext.class);
+        mockBundle = EasyMock.createMock(Bundle.class);
+        headers = new Hashtable<String, String>();
+        EasyMock.expect(mockBundleContext.getBundle()).andReturn(mockBundle);
+        EasyMock.expect(mockBundle.getHeaders()).andReturn(headers);
+    }
+
+    private void replayMocks() {
+        EasyMock.replay(mockBundleContext, mockBundle);
+    }
+
+    @After
+    public void tearDown() {
+        EasyMock.verify(mockBundleContext, mockBundle);
+    }
+
     @Test
     public void testDefaultObjectNameTranslator() throws Exception {
-        BundleContext bundleContext = EasyMock.createMock(BundleContext.class);
-        Bundle bundle = EasyMock.createMock(Bundle.class);
-        EasyMock.expect(bundleContext.getBundle()).andReturn(bundle);
-        Dictionary<String, String> headers = new Hashtable<String, String>();
-        EasyMock.expect(bundle.getHeaders()).andReturn(headers);
-        EasyMock.replay(bundleContext, bundle);
-        ObjectNameTranslator defaultObjectNameTranslator = DefaultObjectNameTranslator.initialiseObjectNameTranslator(bundleContext);
+        replayMocks();
+        ObjectNameTranslator defaultObjectNameTranslator = DefaultObjectNameTranslator.initialiseObjectNameTranslator(mockBundleContext);
         Assert.assertTrue("Default ObjectNameTranslator has the wrong type", defaultObjectNameTranslator instanceof DefaultObjectNameTranslator);
-        EasyMock.verify(bundleContext, bundle);
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Test
+    public void testConfiguredObjectNameTranslator() throws Exception {
+        EasyMock.expect((Class) mockBundle.loadClass(TEST_OBJECT_NAME_TRANSLATOR_CLASS_NAME)).andReturn(TestObjectNameTranslator.class);
+        replayMocks();
+        headers.put(ObjectNameTranslator.HEADER_NAME, TEST_OBJECT_NAME_TRANSLATOR_CLASS_NAME);
+        ObjectNameTranslator testObjectNameTranslator = DefaultObjectNameTranslator.initialiseObjectNameTranslator(mockBundleContext);
+        Assert.assertTrue("Test ObjectNameTranslator has the wrong type", testObjectNameTranslator instanceof TestObjectNameTranslator);
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Test(expected = ClassNotFoundException.class)
+    public void testUnloadableObjectNameTranslator() throws Exception {
+        EasyMock.expect((Class) mockBundle.loadClass(UNLOADABLE_CLASS_NAME)).andThrow(TEST_CLASS_NOT_FOUND_EXCEPTION);
+        replayMocks();
+        headers.put(ObjectNameTranslator.HEADER_NAME, UNLOADABLE_CLASS_NAME);
+        DefaultObjectNameTranslator.initialiseObjectNameTranslator(mockBundleContext);
+    }
+
+    @SuppressWarnings("rawtypes")
+    @Test(expected = IllegalAccessException.class)
+    public void testUninstantiableObjectNameTranslator() throws Exception {
+        EasyMock.expect((Class) mockBundle.loadClass(UNINSTANTIABLE_OBJECT_NAME_TRANSLATOR_CLASS_NAME)).andReturn(UninstantiableObjectNameTranslator.class);
+        replayMocks();
+        headers.put(ObjectNameTranslator.HEADER_NAME, UNINSTANTIABLE_OBJECT_NAME_TRANSLATOR_CLASS_NAME);
+        DefaultObjectNameTranslator.initialiseObjectNameTranslator(mockBundleContext);
     }
 
 }
\ No newline at end of file
diff --git a/org.eclipse.gemini.mgmt.tests/src/org/eclipse/gemini/mgmt/TestObjectNameTranslator.java b/org.eclipse.gemini.mgmt.tests/src/org/eclipse/gemini/mgmt/TestObjectNameTranslator.java
new file mode 100755
index 0000000..0513fb9
--- /dev/null
+++ b/org.eclipse.gemini.mgmt.tests/src/org/eclipse/gemini/mgmt/TestObjectNameTranslator.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2011 VMware Inc.
+ * 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:
+ *   VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.gemini.mgmt;
+
+import javax.management.ObjectName;
+
+public class TestObjectNameTranslator implements ObjectNameTranslator {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public ObjectName translate(ObjectName objectName) {
+        return objectName;
+    }
+
+}
diff --git a/org.eclipse.gemini.mgmt.tests/src/org/eclipse/gemini/mgmt/UninstantiableObjectNameTranslator.java b/org.eclipse.gemini.mgmt.tests/src/org/eclipse/gemini/mgmt/UninstantiableObjectNameTranslator.java
new file mode 100755
index 0000000..1bff40b
--- /dev/null
+++ b/org.eclipse.gemini.mgmt.tests/src/org/eclipse/gemini/mgmt/UninstantiableObjectNameTranslator.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2011 VMware Inc.
+ * 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:
+ *   VMware Inc. - initial contribution
+ *******************************************************************************/
+
+package org.eclipse.gemini.mgmt;
+
+public class UninstantiableObjectNameTranslator {
+
+    private UninstantiableObjectNameTranslator() {
+    }
+
+}
diff --git a/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/DefaultObjectNameTranslator.java b/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/DefaultObjectNameTranslator.java
index f5aed70..2539dc9 100755
--- a/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/DefaultObjectNameTranslator.java
+++ b/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/DefaultObjectNameTranslator.java
@@ -13,6 +13,7 @@
 

 import javax.management.ObjectName;

 

+import org.osgi.framework.Bundle;

 import org.osgi.framework.BundleContext;

 

 /**

@@ -45,16 +46,14 @@
      */

     static ObjectNameTranslator initialiseObjectNameTranslator(BundleContext bundleContext) throws ClassNotFoundException, InstantiationException,

         IllegalAccessException {

-        String ontClassName = bundleContext.getBundle().getHeaders().get(ObjectNameTranslator.HEADER_NAME);

+        Bundle bundle = bundleContext.getBundle();

+        String ontClassName = bundle.getHeaders().get(ObjectNameTranslator.HEADER_NAME);

         if (ontClassName == null) {

             return new DefaultObjectNameTranslator();

         }

-        /*

-         * Attempt to load and instantiate the specified class, allowing exceptions to percolate and fail the bundle

-         * start.

-         */

+        // Attempt to load and instantiate the specified class, allowing exceptions to percolate.

         @SuppressWarnings("unchecked")

-        Class<ObjectNameTranslator> ontClass = (Class<ObjectNameTranslator>) bundleContext.getBundle().loadClass(ontClassName);

+        Class<ObjectNameTranslator> ontClass = (Class<ObjectNameTranslator>) bundle.loadClass(ontClassName);

         return ontClass.newInstance();

     }

 

diff --git a/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/ObjectNameTranslator.java b/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/ObjectNameTranslator.java
index 3603c0c..2353299 100644
--- a/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/ObjectNameTranslator.java
+++ b/org.eclipse.gemini.mgmt/src/org/eclipse/gemini/mgmt/ObjectNameTranslator.java
@@ -38,6 +38,20 @@
     /**
      * Translates the given {@link ObjectName}. The translation must be injective, which means that translations of
      * distinct object names must be distinct.
+     * <p />
+     * Example implementation:
+     * 
+     * <pre>
+     * String domain = objectName.getDomain();
+     * Hashtable&lt;String, String&gt; keyPropertyList = objectName.getKeyPropertyList();
+     * Hashtable&lt;String, String&gt; translatedKeyPropertyList = new Hashtable&lt;String, String&gt;(keyPropertyList);
+     * translatedKeyPropertyList.put(&quot;X&quot;, &quot;Y&quot;);
+     * try {
+     *     return new ObjectName(domain, translatedKeyPropertyList);
+     * } catch (MalformedObjectNameException e) {
+     *     throw new RuntimeException(&quot;Unexpected exception&quot;, e);
+     * }
+     * </pre>
      * 
      * @param objectName the {@link ObjectName} to be translated
      * @return the translated {@link ObjectName}