FELIX-3963 Fix InventoryPrinter/ConfigurationPrinter reflection
- InventoryPrinter only accepted as a service implementing
the API (using ServiceFactory and dynamic import fixes
static dependency issues better)
- ConfigurationPrinter supported through reflection for
backwards compatibility (only public method in the service
object class itself)
- Removing test case checking for proper reflection support
of the InventoryPrinter (not needed any longer)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1461705 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 cc39692..dc8b501 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
@@ -39,42 +39,6 @@
{
/**
- * 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,
@@ -88,28 +52,9 @@
* @return An adapter or <code>null</code> if the method is missing.
*/
public static InventoryPrinterAdapter createAdapter(final InventoryPrinterDescription description,
- final Object service)
+ final InventoryPrinter service)
{
-
- Method printMethod = null;
- if (!(service instanceof InventoryPrinter))
- {
-
- // print(String, PrintWriter)
- printMethod = ClassUtils.searchMethod(service.getClass(), PRINTER_METHOD, PRINTER_SIGNATURE);
- if (printMethod == null)
- {
- return null;
- }
- }
- Method attachmentMethod = null;
- if (!(service instanceof ZipAttachmentProvider))
- {
-
- // addAttachments()
- attachmentMethod = ClassUtils.searchMethod(service.getClass(), ATTACHMENT_METHOD, ATTACHMENT_SIGNATURE);
- }
- return new InventoryPrinterAdapter(description, service, printMethod, attachmentMethod);
+ return new InventoryPrinterAdapter(description, service);
}
/**
@@ -125,29 +70,21 @@
};
/** The Inventory printer service. */
- private final Object printer;
+ private final InventoryPrinter printer;
/** The printer description. */
private final InventoryPrinterDescription description;
- /** The method to use if printer does not implement the service interface. */
- private final Method printMethod;
-
- private final Method attachmentMethod;
-
/** Service registration for the web console. */
private ServiceRegistration registration;
/**
* Constructor.
*/
- public InventoryPrinterAdapter(final InventoryPrinterDescription description, final Object printer,
- final Method printMethod, final Method attachmentMethod)
+ public InventoryPrinterAdapter(final InventoryPrinterDescription description, final InventoryPrinter printer)
{
this.description = description;
this.printer = printer;
- this.printMethod = printMethod;
- this.attachmentMethod = attachmentMethod;
}
public void registerConsole(final BundleContext context, final InventoryPrinterManagerImpl manager)
@@ -201,16 +138,10 @@
*/
public void addAttachments(final String namePrefix, final ZipOutputStream zos) throws IOException
{
- // check if printer implements ZipAttachmentProvider
if (printer instanceof ZipAttachmentProvider)
{
((ZipAttachmentProvider) printer).addAttachments(namePrefix, zos);
}
- else if (this.attachmentMethod != null)
- {
- ClassUtils.invoke(this.printer, this.attachmentMethod, new Object[]
- { namePrefix, zos });
- }
}
/**
@@ -236,15 +167,7 @@
{
if (this.supports(mode))
{
- if (this.printer instanceof InventoryPrinter)
- {
- ((InventoryPrinter) this.printer).print(mode, printWriter, isZip);
- }
- else
- {
- ClassUtils.invoke(this.printer, this.printMethod, new Object[]
- { mode.toString(), printWriter, Boolean.valueOf(isZip) });
- }
+ this.printer.print(mode, printWriter, isZip);
}
}
diff --git a/inventory/src/main/java/org/apache/felix/inventory/impl/InventoryPrinterManagerImpl.java b/inventory/src/main/java/org/apache/felix/inventory/impl/InventoryPrinterManagerImpl.java
index 9eee00e..9f20b36 100644
--- a/inventory/src/main/java/org/apache/felix/inventory/impl/InventoryPrinterManagerImpl.java
+++ b/inventory/src/main/java/org/apache/felix/inventory/impl/InventoryPrinterManagerImpl.java
@@ -78,9 +78,7 @@
public InventoryPrinterManagerImpl(final BundleContext btx) throws InvalidSyntaxException
{
this.bundleContext = btx;
- this.cfgPrinterTracker = new ServiceTracker(this.bundleContext, this.bundleContext.createFilter("(&("
- + InventoryPrinter.CONFIG_PRINTER_MODES + "=*)" + "(" + InventoryPrinter.CONFIG_NAME + "=*)" + "("
- + InventoryPrinter.CONFIG_TITLE + "=*))"), this);
+ this.cfgPrinterTracker = new ServiceTracker(this.bundleContext, InventoryPrinter.SERVICE, this);
this.cfgPrinterTracker.open();
final Dictionary props = new Hashtable();
@@ -126,8 +124,9 @@
final Object obj = this.bundleContext.getService(reference);
if (obj != null)
{
- this.addService(reference, obj);
+ this.addService(reference, (InventoryPrinter) obj);
}
+
return obj;
}
@@ -138,10 +137,10 @@
public void modifiedService(final ServiceReference reference, final Object service)
{
this.removeService(reference);
- this.addService(reference, service);
+ this.addService(reference, (InventoryPrinter) service);
}
- private void addService(final ServiceReference reference, final Object obj)
+ private void addService(final ServiceReference reference, final InventoryPrinter obj)
{
final InventoryPrinterDescription desc = new InventoryPrinterDescription(reference);
diff --git a/inventory/src/main/java/org/apache/felix/inventory/impl/webconsole/ConfigurationPrinterAdapter.java b/inventory/src/main/java/org/apache/felix/inventory/impl/webconsole/ConfigurationPrinterAdapter.java
index fad6d6c..35279f2 100644
--- a/inventory/src/main/java/org/apache/felix/inventory/impl/webconsole/ConfigurationPrinterAdapter.java
+++ b/inventory/src/main/java/org/apache/felix/inventory/impl/webconsole/ConfigurationPrinterAdapter.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.
@@ -18,6 +18,7 @@
import java.io.PrintWriter;
import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashSet;
@@ -25,7 +26,6 @@
import java.util.Set;
import org.apache.felix.inventory.PrinterMode;
-import org.apache.felix.inventory.impl.ClassUtils;
import org.osgi.framework.ServiceReference;
/**
@@ -86,12 +86,12 @@
{
modes = ref.getProperty(ConsoleConstants.PROPERTY_MODES);
}
- final Method titleMethod = ClassUtils.searchMethod(service.getClass(), "getTitle", null);
+ final Method titleMethod = getMethod(service.getClass(), "getTitle", null);
if (titleMethod == null)
{
return null;
}
- title = (String) ClassUtils.invoke(service, titleMethod, null);
+ title = (String) invoke(service, titleMethod, null);
}
else
{
@@ -103,7 +103,7 @@
Method printMethod = null;
// first: printConfiguration(PrintWriter, String)
- final Method method2Params = ClassUtils.searchMethod(service.getClass(), "printConfiguration", new Class[]
+ final Method method2Params = getMethod(service.getClass(), "printConfiguration", new Class[]
{ PrintWriter.class, String.class });
if (method2Params != null)
{
@@ -114,7 +114,7 @@
if (cfgPrinter == null)
{
// second: printConfiguration(PrintWriter)
- final Method method1Params = ClassUtils.searchMethod(service.getClass(), "printConfiguration", new Class[]
+ final Method method1Params = getMethod(service.getClass(), "printConfiguration", new Class[]
{ PrintWriter.class });
if (method1Params != null)
{
@@ -185,8 +185,8 @@
}
}
- return new ConfigurationPrinterAdapter(cfgPrinter, printMethod, ClassUtils.searchMethod(
- cfgPrinter.getClass(), "getAttachments", new Class[]
+ return new ConfigurationPrinterAdapter(cfgPrinter, printMethod, getMethod(cfgPrinter.getClass(),
+ "getAttachments", new Class[]
{ String.class }), title, (label instanceof String ? (String) label : null), modesArray,
!webUnescaped);
}
@@ -249,12 +249,12 @@
{
if (printMethod.getParameterTypes().length > 1)
{
- ClassUtils.invoke(this.printer, this.printMethod, new Object[]
+ invoke(this.printer, this.printMethod, new Object[]
{ pw, mode });
}
else
{
- ClassUtils.invoke(this.printer, this.printMethod, new Object[]
+ invoke(this.printer, this.printMethod, new Object[]
{ pw });
}
}
@@ -265,7 +265,7 @@
URL[] attachments = null;
if (attachmentMethod != null)
{
- attachments = (URL[]) ClassUtils.invoke(printer, attachmentMethod, new Object[]
+ attachments = (URL[]) invoke(printer, attachmentMethod, new Object[]
{ ConsoleConstants.MODE_ZIP });
}
return attachments;
@@ -278,4 +278,39 @@
{
return title + " (" + printer.getClass() + ")";
}
+
+ private static Method getMethod(final Class clazz, final String mName, final Class[] params)
+ {
+ try
+ {
+ final Method m = clazz.getDeclaredMethod(mName, params);
+ if (Modifier.isPublic(m.getModifiers()))
+ {
+ return m;
+ }
+ }
+ catch (Throwable nsme)
+ {
+ // ignore, we catch Throwable above to not only catch
+ // NoSuchMethodException
+ // but also other ones like ClassDefNotFoundError etc.
+ }
+ return null;
+ }
+
+ /**
+ * Invoke the method on the printer with the arguments.
+ */
+ private static Object invoke(final Object obj, final Method m, final Object[] args)
+ {
+ try
+ {
+ return m.invoke(obj, args);
+ }
+ catch (final Throwable e)
+ {
+ // ignore
+ }
+ return null;
+ }
}
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
deleted file mode 100644
index 2639f9e..0000000
--- a/inventory/src/test/java/org/apache/felix/inventory/impl/InventoryPrinterAdapterTest.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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;
- }
- }
-}