/* * 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.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.net.URL; import java.util.ArrayList; import java.util.Dictionary; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.ResourceBundle; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import org.apache.felix.inventory.InventoryPrinter; import org.apache.felix.inventory.Format; import org.apache.felix.inventory.ZipAttachmentProvider; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import org.osgi.util.tracker.ServiceTracker; import org.osgi.util.tracker.ServiceTrackerCustomizer; /** * The web console adapter registers web console status printers * as inventory printers. */ public class WebConsoleAdapter implements ServiceTrackerCustomizer { private final BundleContext bundleContext; private final ServiceTracker cfgPrinterTracker; private final Map registrations = new HashMap(); private final ResourceBundleManager rbManager; public WebConsoleAdapter(final BundleContext btx) throws InvalidSyntaxException { this.bundleContext = btx; this.rbManager = new ResourceBundleManager(btx); this.cfgPrinterTracker = new ServiceTracker(this.bundleContext, this.bundleContext.createFilter("(|(" + Constants.OBJECTCLASS + "=" + ConsoleConstants.INTERFACE_CONFIGURATION_PRINTER + ")" + "(&(" + ConsoleConstants.PLUGIN_LABEL + "=*)(&(" + ConsoleConstants.PLUGIN_TITLE + "=*)(" + ConsoleConstants.CONFIG_PRINTER_MODES + "=*))))"), this); this.cfgPrinterTracker.open(); } /** * Dispose this service */ public void dispose() { this.cfgPrinterTracker.close(); final List regs = new ArrayList(); synchronized (this.registrations) { regs.addAll(this.registrations.values()); this.registrations.clear(); } final Iterator i = regs.iterator(); while (i.hasNext()) { final ServiceRegistration reg = (ServiceRegistration) i.next(); reg.unregister(); } this.rbManager.dispose(); } private void add(final ServiceReference reference, final Object service) { final ConfigurationPrinterAdapter cpa = ConfigurationPrinterAdapter.createAdapter(service, reference); if (cpa != null && cpa.title != null) { if (cpa.title.startsWith("%")) { String title = cpa.title.substring(1); final ResourceBundle rb = this.rbManager.getResourceBundle(reference.getBundle()); if (rb != null) { try { title = rb.getString(title); } catch (Exception e) { // ClassCastException, MissingResourceException // ignore } } cpa.title = title; } if (cpa.label == null) { cpa.label = cpa.title; } final Dictionary props = new Hashtable(); props.put(InventoryPrinter.NAME, cpa.label); props.put(InventoryPrinter.TITLE, cpa.title); props.put(InventoryPrinter.FORMAT, cpa.getPrinterModes()); final ServiceRegistration reg = this.bundleContext.registerService(InventoryPrinter.class.getName(), new WebConsolePrinter(cpa), props); synchronized (this.registrations) { this.registrations.put(reference, reg); } } } private final void remove(final ServiceReference reference) { final ServiceRegistration reg; synchronized (this.registrations) { reg = (ServiceRegistration) this.registrations.remove(reference); } if (reg != null) { reg.unregister(); } } /** * @see org.osgi.util.tracker.ServiceTrackerCustomizer#addingService(org.osgi.framework.ServiceReference) */ public Object addingService(final ServiceReference reference) { final Object service = this.bundleContext.getService(reference); if (service != null) { this.add(reference, service); } return service; } /** * @see org.osgi.util.tracker.ServiceTrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, * java.lang.Object) */ public void modifiedService(final ServiceReference reference, final Object service) { this.remove(reference); this.add(reference, service); } /** * @see org.osgi.util.tracker.ServiceTrackerCustomizer#removedService(org.osgi.framework.ServiceReference, * java.lang.Object) */ public void removedService(final ServiceReference reference, final Object service) { this.remove(reference); this.bundleContext.ungetService(reference); } private static class WebConsolePrinter implements InventoryPrinter, ZipAttachmentProvider { final ConfigurationPrinterAdapter cpa; public WebConsolePrinter(final ConfigurationPrinterAdapter cpa) { this.cpa = cpa; } /** * @see org.apache.felix.inventory.InventoryPrinter#print(org.apache.felix.inventory.Format, * java.io.PrintWriter) */ public void print(final PrintWriter printWriter, final Format format, final boolean isZip) { final String m; if (!isZip && format == Format.HTML) { m = ConsoleConstants.MODE_WEB; } else if (!isZip && format == Format.TEXT) { m = ConsoleConstants.MODE_TXT; } else if (isZip && (format == Format.TEXT || format == Format.HTML)) { m = ConsoleConstants.MODE_ZIP; } else { m = null; } if (m != null) { cpa.printConfiguration(printWriter, m); } } /** * @see org.apache.felix.inventory.ZipAttachmentProvider#addAttachments(java.util.zip.ZipOutputStream, * java.lang.String) */ public void addAttachments(final ZipOutputStream zos, final String namePrefix) throws IOException { final URL[] attachments = cpa.getAttachments(); if (attachments != null) { for (int i = 0; i < attachments.length; i++) { final URL current = attachments[i]; final String path = current.getPath(); final String name; if (path == null || path.length() == 0) { // sanity code, we should have a path, but if not let's // just create some random name name = "file" + Double.doubleToLongBits(Math.random()); } else { final int pos = path.lastIndexOf('/'); name = (pos == -1 ? path : path.substring(pos + 1)); } final ZipEntry entry = new ZipEntry(namePrefix + name); zos.putNextEntry(entry); final InputStream is = current.openStream(); try { byte[] buffer = new byte[4096]; int n = 0; while (-1 != (n = is.read(buffer))) { zos.write(buffer, 0, n); } } finally { if (is != null) { try { is.close(); } catch (final IOException ignore) { } } } zos.closeEntry(); } } } } }