FELIX-3964 Fix InventoryPrinter signature

- replace Boolean.class by Boolean.type in the signature
- Create constants
- Add unit tests

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1455065 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/inventory/src/main/java/org/apache/felix/inventory/impl/InventoryPrinterAdapter.java b/inventory/src/main/java/org/apache/felix/inventory/impl/InventoryPrinterAdapter.java
index 12f6c68..cc39692 100644
--- a/inventory/src/main/java/org/apache/felix/inventory/impl/InventoryPrinterAdapter.java
+++ b/inventory/src/main/java/org/apache/felix/inventory/impl/InventoryPrinterAdapter.java
@@ -5,9 +5,9 @@
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -32,13 +32,49 @@
 
 /**
  * Helper class for a inventory printer.
- * 
+ *
  * The adapter simplifies accessing and working with the inventory printer.
  */
 public class InventoryPrinterAdapter implements InventoryPrinterHandler, Comparable
 {
 
     /**
+     * The name of the method to look for in non-InventoryPrinter services.
+     *
+     * @see #PRINTER_SIGNATURE
+     */
+    private static final String PRINTER_METHOD = "print";
+
+    /**
+     * The signature of the {@link #PRINTER_METHOD} method to be called.
+     * This is similar to the
+     * {@link InventoryPrinter#print(PrinterMode, PrintWriter, boolean)} method
+     * where the first argument is the string value of the {@link PrinterMode}.
+     *
+     * @see InventoryPrinter#print(PrinterMode, PrintWriter, boolean)
+     */
+    private static final Class[] PRINTER_SIGNATURE = new Class[]
+        { String.class, PrintWriter.class, Boolean.TYPE };
+
+    /**
+     * The name of the method to look for in non-ZipAttachmentProvider services.
+     *
+     * @see #ATTACHMENT_SIGNATURE
+     */
+    private static final String ATTACHMENT_METHOD = "addAttachments";
+
+    /**
+     * The signature of the {@link #ATTACHMENT_METHOD} method to be called.
+     * This is similar to the
+     * {@link ZipAttachmentProvider#addAttachments(String, ZipOutputStream)}
+     * method.
+     *
+     * @see ZipAttachmentProvider#addAttachments(String, ZipOutputStream)
+     */
+    private static final Class[] ATTACHMENT_SIGNATURE = new Class[]
+        { String.class, ZipOutputStream.class };
+
+    /**
      * Formatter pattern to render the current time of inventory generation.
      */
     static final DateFormat DISPLAY_DATE_FORMAT = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG,
@@ -48,7 +84,7 @@
      * Create a new adapter if the provided service is either a printer or
      * provides
      * the print method.
-     * 
+     *
      * @return An adapter or <code>null</code> if the method is missing.
      */
     public static InventoryPrinterAdapter createAdapter(final InventoryPrinterDescription description,
@@ -60,8 +96,7 @@
         {
 
             // print(String, PrintWriter)
-            printMethod = ClassUtils.searchMethod(service.getClass(), "print", new Class[]
-                { String.class, PrintWriter.class, Boolean.class });
+            printMethod = ClassUtils.searchMethod(service.getClass(), PRINTER_METHOD, PRINTER_SIGNATURE);
             if (printMethod == null)
             {
                 return null;
@@ -72,8 +107,7 @@
         {
 
             // addAttachments()
-            attachmentMethod = ClassUtils.searchMethod(service.getClass(), "addAttachments", new Class[]
-                { String.class, ZipOutputStream.class });
+            attachmentMethod = ClassUtils.searchMethod(service.getClass(), ATTACHMENT_METHOD, ATTACHMENT_SIGNATURE);
         }
         return new InventoryPrinterAdapter(description, service, printMethod, attachmentMethod);
     }
diff --git a/inventory/src/test/java/org/apache/felix/inventory/impl/InventoryPrinterAdapterTest.java b/inventory/src/test/java/org/apache/felix/inventory/impl/InventoryPrinterAdapterTest.java
new file mode 100644
index 0000000..2639f9e
--- /dev/null
+++ b/inventory/src/test/java/org/apache/felix/inventory/impl/InventoryPrinterAdapterTest.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.inventory.impl;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarOutputStream;
+import java.util.zip.ZipOutputStream;
+
+import junit.framework.TestCase;
+
+import org.apache.felix.inventory.InventoryPrinter;
+import org.apache.felix.inventory.PrinterMode;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceReference;
+
+public class InventoryPrinterAdapterTest extends TestCase
+{
+
+    public void test_validInventoryPrinter()
+    {
+        InventoryPrinterDescription ipd = new InventoryPrinterDescription(new TestServiceReference());
+        InventoryPrinterAdapter ipa = InventoryPrinterAdapter.createAdapter(ipd, new ValidInventoryPrinter());
+        TestCase.assertNotNull(ipa);
+        StringWriter w = new StringWriter();
+        ipa.print(PrinterMode.TEXT, new PrintWriter(w), false);
+        TestCase.assertEquals(w.toString(), PrinterMode.TEXT.name());
+    }
+
+    public void test_invalidInventoryPrinter()
+    {
+        InventoryPrinterDescription ipd = new InventoryPrinterDescription(new TestServiceReference());
+        InventoryPrinterAdapter ipa = InventoryPrinterAdapter.createAdapter(ipd, new InvalidInventoryPrinter());
+        TestCase.assertNull(ipa);
+    }
+
+    public void test_validZipAttachmentProvider() throws IOException
+    {
+        InventoryPrinterDescription ipd = new InventoryPrinterDescription(new TestServiceReference());
+        InventoryPrinterAdapter ipa = InventoryPrinterAdapter.createAdapter(ipd, new ValidZipAttachmentProvider());
+        TestCase.assertNotNull(ipa);
+
+        try
+        {
+            Field f = ipa.getClass().getDeclaredField("attachmentMethod");
+            f.setAccessible(true);
+            TestCase.assertNotNull(f.get(ipa));
+        }
+        catch (Exception e)
+        {
+            TestCase.fail(e.toString());
+        }
+    }
+
+    public void test_invalidZipAttachmentProvider() throws IOException
+    {
+        InventoryPrinterDescription ipd = new InventoryPrinterDescription(new TestServiceReference());
+
+        InventoryPrinterAdapter ipa = InventoryPrinterAdapter.createAdapter(ipd,
+            new InvalidZipAttachmentProvider_wrong_signature());
+        TestCase.assertNotNull(ipa);
+
+        try
+        {
+            Field f = ipa.getClass().getDeclaredField("attachmentMethod");
+            f.setAccessible(true);
+            TestCase.assertNull(f.get(ipa));
+        }
+        catch (Exception e)
+        {
+            TestCase.fail(e.toString());
+        }
+
+        InventoryPrinterAdapter ipa2 = InventoryPrinterAdapter.createAdapter(ipd,
+            new InvalidZipAttachmentProvider_no_print_method());
+        TestCase.assertNull(ipa2);
+    }
+
+    private static class ValidInventoryPrinter
+    {
+        private void print(String mode, PrintWriter w, boolean isZip)
+        {
+            w.print(mode);
+            w.flush();
+        }
+    }
+
+    private static class InvalidInventoryPrinter
+    {
+        private void print(String mode, PrintWriter w, Boolean isZip)
+        {
+            throw new IllegalStateException("Method not expected to be called");
+        }
+    }
+
+    private static class ValidZipAttachmentProvider
+    {
+        private void print(String mode, PrintWriter w, boolean isZip)
+        {
+            w.print(mode);
+            w.flush();
+        }
+
+        private void addAttachments(String prefix, ZipOutputStream out)
+        {
+        }
+    }
+
+    private static class InvalidZipAttachmentProvider_wrong_signature
+    {
+        private void print(String mode, PrintWriter w, boolean isZip)
+        {
+            w.print(mode);
+            w.flush();
+        }
+
+        private void addAttachments(String prefix, JarOutputStream out)
+        {
+            throw new IllegalStateException("Method not expected to be called");
+        }
+    }
+
+    private static class InvalidZipAttachmentProvider_no_print_method
+    {
+        private void addAttachments(String prefix, ZipOutputStream out)
+        {
+            throw new IllegalStateException("Method not expected to be called");
+        }
+    }
+
+    private static class TestServiceReference implements ServiceReference
+    {
+
+        private Map props;
+
+        {
+            props = new HashMap();
+            props.put(InventoryPrinter.CONFIG_PRINTER_MODES, new String[]
+                { PrinterMode.TEXT.name() });
+        }
+
+        public Object getProperty(String key)
+        {
+            return this.props.get(key);
+        }
+
+        public String[] getPropertyKeys()
+        {
+            return (String[]) this.props.keySet().toArray(new String[this.props.size()]);
+        }
+
+        public Bundle getBundle()
+        {
+            return null;
+        }
+
+        public Bundle[] getUsingBundles()
+        {
+            return null;
+        }
+
+        public boolean isAssignableTo(Bundle bundle, String className)
+        {
+            return false;
+        }
+
+        public int compareTo(Object reference)
+        {
+            return 0;
+        }
+    }
+}