/******************************************************************************* * Copyright (c) 2007, 2009 SpringSource, a divison of VMware, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * SpringSource, a divison of VMware, Inc. - initial API and implementation *******************************************************************************/ package org.eclipse.virgo.ide.management.remote; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Arrays; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import org.eclipse.osgi.framework.console.CommandProvider; import org.eclipse.osgi.framework.internal.core.Util; import org.eclipse.osgi.service.resolver.BundleDescription; import org.eclipse.osgi.service.resolver.ExportPackageDescription; import org.eclipse.osgi.service.resolver.PlatformAdmin; import org.eclipse.virgo.ide.management.remote.ServiceReference.Type; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; import org.osgi.framework.ServiceReference; import org.osgi.service.packageadmin.PackageAdmin; import org.osgi.util.tracker.ServiceTracker; import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedResource; import org.springframework.osgi.util.OsgiServiceReferenceUtils; /** * @author Christian Dupuis */ @ManagedResource(objectName = "com.springsource.server:type=BundleAdmin", description = "SpringSource Tool Suite Connector Bean") public class StandardBundleAdmin implements BundleAdmin { private final PlatformAdmin platformAdmin; @SuppressWarnings("unused") private final PackageAdmin packageAdmin; private final BundleContext bundleContext; private ServiceTracker consoleProviderTracker; public StandardBundleAdmin(PlatformAdmin platformAdmin, PackageAdmin packageAdmin, BundleContext bundleContext) { this.platformAdmin = platformAdmin; this.packageAdmin = packageAdmin; this.bundleContext = bundleContext; this.consoleProviderTracker = new ServiceTracker(bundleContext, CommandProvider.class.getName(), null); this.consoleProviderTracker.open(); } @ManagedOperation(description = "Stop the given bundle") public void stop(long bundleId) { execute("stop " + bundleId); } @ManagedOperation(description = "Start the given bundle") public void start(long bundleId) { execute("start " + bundleId); } @ManagedOperation(description = "Refresh the given bundle") public void refresh(long bundleId) { execute("refresh " + bundleId); } @ManagedOperation(description = "Refresh the given bundle") public void update(long bundleId) { execute("update " + bundleId); } @ManagedOperation(description = "Executes the given command") public String execute(String cmdLine) { StringWriter writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); try { ServerCommandInterpreter interpreter = new ServerCommandInterpreter( cmdLine, getServices(), printWriter); interpreter.execute(interpreter.nextArgument()); try { writer.close(); printWriter.close(); } catch (IOException e) { } return writer.toString(); } finally { try { writer.close(); printWriter.close(); } catch (IOException e) { } } } @ManagedOperation(description = "Returns the current OSGi Bundles") public Map<Long, Bundle> retrieveBundles() { Map<Long, Bundle> bundles = new HashMap<Long, Bundle>(); for (org.osgi.framework.Bundle b : bundleContext.getBundles()) { Object version = b.getHeaders().get("Bundle-Version"); Bundle bundle = new Bundle(Long.toString(b.getBundleId()), b .getSymbolicName(), (version != null ? version.toString() : "0"), getState(b), b.getLocation()); Dictionary<?, ?> headers = b.getHeaders(); Enumeration<?> keys = headers.keys(); while (keys.hasMoreElements()) { Object key = keys.nextElement(); Object value = headers.get(key); bundle.addHeader(key.toString(), value.toString()); } BundleDescription bundleDescription = platformAdmin.getState(false) .getBundle(b.getBundleId()); ExportPackageDescription[] exportedPackages = bundleDescription .getExportPackages(); if (exportedPackages != null) { for (ExportPackageDescription exportedPackage : exportedPackages) { PackageExport packageExport = new PackageExport( exportedPackage.getName(), (exportedPackage .getVersion() != null ? exportedPackage .getVersion().toString() : "0")); bundle.addPackageExport(packageExport); } } ExportPackageDescription[] visiblePackages = platformAdmin .getStateHelper().getVisiblePackages(bundleDescription); if (visiblePackages != null) { for (ExportPackageDescription visiblePackage : visiblePackages) { PackageImport packageImport = new PackageImport( visiblePackage.getName(), (visiblePackage .getVersion() != null ? visiblePackage .getVersion().toString() : "0"), Long .toString(visiblePackage.getSupplier() .getBundleId())); bundle.addPackageImport(packageImport); } } if (b.getRegisteredServices() != null) { for (ServiceReference ref : b.getRegisteredServices()) { org.eclipse.virgo.ide.management.remote.ServiceReference reference = new org.eclipse.virgo.ide.management.remote.ServiceReference( Type.REGISTERED, ref.getBundle().getBundleId(), OsgiServiceReferenceUtils .getServiceObjectClasses(ref)); Map<?, ?> props = OsgiServiceReferenceUtils .getServicePropertiesAsMap(ref); for (Object key : props.keySet()) { String value = props.get(key).toString(); if (props.get(key).getClass().isArray()) { value = Arrays.deepToString((Object[]) props .get(key)); } reference.addProperty(key.toString(), value); } if (ref.getUsingBundles() != null) { for (org.osgi.framework.Bundle usingBundle : ref .getUsingBundles()) { reference.addUsingBundle(usingBundle.getBundleId()); } } bundle.addRegisteredService(reference); } } if (b.getServicesInUse() != null) { for (ServiceReference ref : b.getServicesInUse()) { org.eclipse.virgo.ide.management.remote.ServiceReference reference = new org.eclipse.virgo.ide.management.remote.ServiceReference( Type.IN_USE, ref.getBundle().getBundleId(), OsgiServiceReferenceUtils .getServiceObjectClasses(ref)); Map<?, ?> props = OsgiServiceReferenceUtils .getServicePropertiesAsMap(ref); for (Object key : props.keySet()) { String value = props.get(key).toString(); if (props.get(key).getClass().isArray()) { value = Arrays.deepToString((Object[]) props .get(key)); } reference.addProperty(key.toString(), value); } if (ref.getUsingBundles() != null) { for (org.osgi.framework.Bundle usingBundle : ref .getUsingBundles()) { reference.addUsingBundle(usingBundle.getBundleId()); } } bundle.addUsingService(reference); } } bundles.put(Long.valueOf(bundle.getId()), bundle); } return bundles; } private Object[] getServices() { ServiceReference[] serviceRefs = consoleProviderTracker .getServiceReferences(); if (serviceRefs == null) return new Object[0]; Util.dsort(serviceRefs, 0, serviceRefs.length); Object[] serviceObjects = new Object[serviceRefs.length]; for (int i = 0; i < serviceRefs.length; i++) { serviceObjects[i] = bundleContext.getService(serviceRefs[i]); } return serviceObjects; } private String getState(org.osgi.framework.Bundle b) { switch (b.getState()) { case org.osgi.framework.Bundle.ACTIVE: return "ACTIVE"; case org.osgi.framework.Bundle.INSTALLED: return "INSTALLED"; case org.osgi.framework.Bundle.RESOLVED: return "RESOLVED"; case org.osgi.framework.Bundle.STARTING: return "STARTING"; case org.osgi.framework.Bundle.STOPPING: return ""; case org.osgi.framework.Bundle.UNINSTALLED: return "UNINSTALLED"; default: return "UNKNOWN"; } } }