| /* |
| * 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); |
| 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 }); |
| if (method2Params != null) |
| { |
| cfgPrinter = service; |
| printMethod = method2Params; |
| } |
| |
| if (cfgPrinter == null) |
| { |
| // second: printConfiguration(PrintWriter) |
| final Method method1Params = getMethod(service.getClass(), "printConfiguration", new Class[] |
| { PrintWriter.class }); |
| 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 }), 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) |
| { |
| 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; |
| } |
| } |