blob: 1ada58e3d6982cb518a0f0cd1811e2de00386507 [file] [log] [blame]
/*
* 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.webconsole;
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;
import java.util.List;
import java.util.Set;
import org.apache.felix.inventory.Format;
import org.osgi.framework.ServiceReference;
/**
* Helper class for a configuration printer.
*/
public class ConfigurationPrinterAdapter
{
private final Object printer;
public String title;
public String label;
private final String[] modes;
private final boolean escapeHtml;
private final Method printMethod;
private final Method attachmentMethod;
private static final List CUSTOM_MODES = new ArrayList();
static
{
CUSTOM_MODES.add(ConsoleConstants.MODE_TXT);
CUSTOM_MODES.add(ConsoleConstants.MODE_WEB);
CUSTOM_MODES.add(ConsoleConstants.MODE_ZIP);
}
/**
* Check whether the class implements the configuration printer.
* This is done manually to avoid having the configuration printer class
* available.
*/
private static boolean isConfigurationPrinter(final Class clazz)
{
final Class[] interf = clazz.getInterfaces();
for (int i = 0; i < interf.length; i++)
{
if (interf[i].getName().equals(ConsoleConstants.INTERFACE_CONFIGURATION_PRINTER))
{
return true;
}
}
if (clazz.getSuperclass() != null)
{
return isConfigurationPrinter(clazz.getSuperclass());
}
return false;
}
/**
* Try to create a new configuration printer adapter.
*/
public static ConfigurationPrinterAdapter createAdapter(final Object service, final ServiceReference ref)
{
String title;
Object modes = null;
if (isConfigurationPrinter(service.getClass()))
{
modes = ref.getProperty(ConsoleConstants.CONFIG_PRINTER_MODES);
if (modes == null)
{
modes = ref.getProperty(ConsoleConstants.PROPERTY_MODES);
}
final Method titleMethod = getMethod(service.getClass(), "getTitle", null, false);
if (titleMethod == null)
{
return null;
}
title = (String) invoke(service, titleMethod, null);
}
else
{
modes = ref.getProperty(ConsoleConstants.CONFIG_PRINTER_MODES);
title = (String) ref.getProperty(ConsoleConstants.PLUGIN_TITLE);
}
Object cfgPrinter = null;
Method printMethod = null;
// first: printConfiguration(PrintWriter, String)
final Method method2Params = getMethod(service.getClass(), "printConfiguration", new Class[]
{ PrintWriter.class, String.class }, true);
if (method2Params != null)
{
cfgPrinter = service;
printMethod = method2Params;
}
if (cfgPrinter == null)
{
// second: printConfiguration(PrintWriter)
final Method method1Params = getMethod(service.getClass(), "printConfiguration", new Class[]
{ PrintWriter.class }, true);
if (method1Params != null)
{
cfgPrinter = service;
printMethod = method1Params;
}
}
if (cfgPrinter != null)
{
final Object label = ref.getProperty(ConsoleConstants.PLUGIN_LABEL);
// check escaping
boolean webUnescaped;
Object ehObj = ref.getProperty(ConsoleConstants.CONFIG_PRINTER_WEB_UNESCAPED);
if (ehObj instanceof Boolean)
{
webUnescaped = ((Boolean) ehObj).booleanValue();
}
else if (ehObj instanceof String)
{
webUnescaped = Boolean.valueOf((String) ehObj).booleanValue();
}
else
{
webUnescaped = false;
}
final String[] modesArray;
// check modes
if (modes == null || !(modes instanceof String || modes instanceof String[]))
{
modesArray = null;
}
else
{
if (modes instanceof String)
{
if (CUSTOM_MODES.contains(modes))
{
modesArray = new String[]
{ modes.toString() };
}
else
{
modesArray = null;
}
}
else
{
final String[] values = (String[]) modes;
boolean valid = values.length > 0;
for (int i = 0; i < values.length; i++)
{
if (!CUSTOM_MODES.contains(values[i]))
{
valid = false;
break;
}
}
if (valid)
{
modesArray = values;
}
else
{
modesArray = null;
}
}
}
return new ConfigurationPrinterAdapter(cfgPrinter, printMethod, getMethod(cfgPrinter.getClass(),
"getAttachments", new Class[]
{ String.class }, true), title, (label instanceof String ? (String) label : null), modesArray,
!webUnescaped);
}
return null;
}
private ConfigurationPrinterAdapter(final Object printer, final Method printMethod, final Method attachmentMethod,
final String title, final String label, final String[] modesArray, final boolean escapeHtml)
{
this.printer = printer;
this.title = title;
this.label = label;
this.escapeHtml = escapeHtml;
this.printMethod = printMethod;
this.attachmentMethod = attachmentMethod;
this.modes = modesArray;
}
/**
* Map the modes to inventory printer modes
*/
public String[] getPrinterModes()
{
final Set list = new HashSet();
if (this.match(ConsoleConstants.MODE_TXT) || this.match(ConsoleConstants.MODE_ZIP))
{
list.add(Format.TEXT.toString());
}
if (this.match(ConsoleConstants.MODE_WEB))
{
if (!escapeHtml)
{
list.add(Format.HTML.toString());
}
else
{
list.add(Format.TEXT.toString());
}
}
return (String[]) list.toArray(new String[list.size()]);
}
private boolean match(final String mode)
{
if (this.modes == null)
{
return true;
}
for (int i = 0; i < this.modes.length; i++)
{
if (this.modes[i].equals(mode))
{
return true;
}
}
return false;
}
public final void printConfiguration(final PrintWriter pw, final String mode)
{
if (printMethod.getParameterTypes().length > 1)
{
invoke(this.printer, this.printMethod, new Object[]
{ pw, mode });
}
else
{
invoke(this.printer, this.printMethod, new Object[]
{ pw });
}
}
public URL[] getAttachments()
{
// check if printer implements binary configuration printer
URL[] attachments = null;
if (attachmentMethod != null)
{
attachments = (URL[]) invoke(printer, attachmentMethod, new Object[]
{ ConsoleConstants.MODE_ZIP });
}
return attachments;
}
/**
* @see java.lang.Object#toString()
*/
public String toString()
{
return title + " (" + printer.getClass() + ")";
}
private static Method getMethod(final Class clazz, final String mName, final Class[] params, final boolean declaredByClass)
{
try
{
if (declaredByClass)
{
final Method m = clazz.getDeclaredMethod(mName, params);
if (Modifier.isPublic(m.getModifiers()))
{
return m;
}
}
return clazz.getMethod(mName, params);
}
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;
}
}