You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2012/01/04 14:22:42 UTC
svn commit: r1227144 [11/18] - in /karaf/eik/trunk: ./ features/
features/info.evanchik.eclipse.karaf.feature/
features/info.evanchik.eclipse.karaf.jmx.feature/
features/info.evanchik.eclipse.karaf.update/
features/info.evanchik.eclipse.karaf.update/fe...
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/KarafMBeanProvider.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/KarafMBeanProvider.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/KarafMBeanProvider.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/KarafMBeanProvider.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,165 @@
+/**
+ * Copyright (c) 2009 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.internal;
+
+import info.evanchik.eclipse.karaf.workbench.KarafWorkbenchActivator;
+import info.evanchik.eclipse.karaf.workbench.MBeanProvider;
+import info.evanchik.eclipse.karaf.workbench.jmx.JMXServiceDescriptor;
+
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import javax.management.ListenerNotFoundException;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+
+import org.eclipse.core.runtime.PlatformObject;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class KarafMBeanProvider extends PlatformObject implements MBeanProvider, NotificationListener {
+
+ private final JMXConnector connector;
+
+ private final ExecutorService connectionHandler;
+
+ private final JMXServiceDescriptor jmxServiceDescriptor;
+
+ private final MBeanServerConnection mbeanServer;
+
+ private Object memento;
+
+ private ServiceRegistration mbeanProviderService;
+
+ /**
+ * Constructs an {@link MBeanProvider} that opens a connection to a
+ * {@link MBeanServerConnection}
+ *
+ * @param jmxServiceDescriptor
+ * the {@link JMXServiceDescriptor} which was used to make the
+ * connection to the JMX end point
+ * @param connector
+ * the {@link JMXConnector} that represents the JMX connection
+ * @throws IOException
+ * if the connection to the MBean Server cannot be made
+ */
+ public KarafMBeanProvider(final JMXServiceDescriptor jmxServiceDescriptor, final JMXConnector connector) throws IOException {
+ this.connector = connector;
+ this.jmxServiceDescriptor = jmxServiceDescriptor;
+ this.mbeanServer = connector.getMBeanServerConnection();
+
+ this.connectionHandler = Executors.newSingleThreadExecutor();
+
+ this.connector.addConnectionNotificationListener(this, null, null);
+ }
+
+ @Override
+ public void close() {
+
+ // JMXConnector.close() is a potentially long running operation.
+ final Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ connector.removeConnectionNotificationListener(KarafMBeanProvider.this);
+ connector.close();
+ } catch (final IOException e) {
+ // Do nothing
+ // KarafWorkbenchActivator.getLogger().info("Unable to close connection to JMX MBeanServer", e);
+ } catch (final ListenerNotFoundException e) {
+ // Nothing to do since this is impossible
+ }
+ }
+ };
+
+ connectionHandler.submit(r);
+
+ if (isOpen()) {
+ unregisterServices();
+ }
+ }
+
+ @Override
+ public JMXServiceDescriptor getJMXServiceDescriptor() {
+ return jmxServiceDescriptor;
+ }
+
+ @Override
+ public <T> T getMBean(final ObjectName objectName, final Class<T> interfaceClass) {
+ return MBeanServerInvocationHandler.newProxyInstance(
+ mbeanServer,
+ objectName,
+ interfaceClass,
+ false);
+ }
+
+ @Override
+ public MBeanServerConnection getMBeanServerConnection() {
+ return mbeanServer;
+ }
+
+ @Override
+ public void handleNotification(final Notification notification, final Object handback) {
+ }
+
+ /**
+ * Determines if this provider is open by examining if a memento has been
+ * set.
+ *
+ * @return true if the memento has been set, false otherwise
+ */
+ @Override
+ public boolean isOpen() {
+ return memento != null;
+ }
+
+ @Override
+ public void open(final Object memento) {
+ if (memento == null) {
+ throw new NullPointerException("Cannot specify a null memento");
+ }
+
+ if (isOpen()) {
+ // Log something at Trace level?
+ return;
+ }
+
+ this.memento = memento;
+
+ registerServices();
+ }
+
+ private void registerServices() {
+ final BundleContext bundleContext =
+ KarafWorkbenchActivator.getDefault().getBundle().getBundleContext();
+
+ final Dictionary<String, Object> dictionary = new Hashtable<String, Object>();
+ dictionary.put(MBeanProvider.KARAF_WORKBENCH_SERVICES_ID, memento);
+
+ mbeanProviderService = bundleContext.registerService(MBeanProvider.class.getName(), this, dictionary);
+ }
+
+ private void unregisterServices() {
+ mbeanProviderService.unregister();
+ mbeanProviderService = null;
+ }
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/KarafMBeanProviderWorkbenchService.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/KarafMBeanProviderWorkbenchService.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/KarafMBeanProviderWorkbenchService.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/KarafMBeanProviderWorkbenchService.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,361 @@
+/**
+ * Copyright (c) 2010 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.internal;
+
+import info.evanchik.eclipse.karaf.core.KarafCorePluginUtils;
+import info.evanchik.eclipse.karaf.core.KarafWorkingPlatformModel;
+import info.evanchik.eclipse.karaf.core.equinox.BundleEntry;
+import info.evanchik.eclipse.karaf.ui.workbench.KarafWorkbenchService;
+import info.evanchik.eclipse.karaf.workbench.KarafWorkbenchActivator;
+import info.evanchik.eclipse.karaf.workbench.MBeanProvider;
+import info.evanchik.eclipse.karaf.workbench.WorkbenchServiceManager;
+import info.evanchik.eclipse.karaf.workbench.jmx.JMXServiceDescriptor;
+import info.evanchik.eclipse.karaf.workbench.jmx.LocalJMXServiceDescriptor;
+import info.evanchik.eclipse.karaf.workbench.provider.RuntimeDataProvider;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.remote.JMXServiceURL;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.IJobChangeEvent;
+import org.eclipse.core.runtime.jobs.IJobChangeListener;
+import org.eclipse.core.runtime.jobs.JobChangeAdapter;
+import org.eclipse.debug.core.DebugEvent;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IDebugEventSetListener;
+import org.eclipse.debug.core.ILaunch;
+import org.eclipse.debug.core.ILaunchConfiguration;
+import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
+import org.eclipse.debug.core.ILaunchListener;
+import org.eclipse.debug.core.model.IProcess;
+import org.eclipse.jdt.launching.SocketUtil;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class KarafMBeanProviderWorkbenchService implements KarafWorkbenchService {
+
+ /**
+ *
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+ private final class JMXServiceCleanupLaunchListener implements ILaunchListener {
+
+ @Override
+ public void launchAdded(final ILaunch launch) {
+ }
+
+ @Override
+ public void launchChanged(final ILaunch launch) {
+ }
+
+ @Override
+ public void launchRemoved(final ILaunch launch) {
+ try {
+ final String memento = launch.getLaunchConfiguration().getMemento();
+
+ final JMXServiceDescriptor jmxServiceDescriptor = mbeanProviderDataMap.get(memento).getJmxServiceDescriptor();
+
+ if (jmxServiceDescriptor == null) {
+ return;
+ }
+
+ jmxServiceManager.remove(jmxServiceDescriptor);
+
+ mbeanProviderDataMap.remove(memento);
+ } catch (final CoreException e) {
+ // Log something
+ }
+ }
+ };
+
+ private static final class KarafMBeanProviderEntry {
+
+ private JMXServiceDescriptor jmxServiceDescriptor;
+
+ private MBeanProvider mbeanProvider;
+
+ private MBeanServerConnectionJob mbeanServerConnectionJob;
+
+ private RuntimeDataProvider runtimeDataProvider;
+
+ public JMXServiceDescriptor getJmxServiceDescriptor() {
+ return jmxServiceDescriptor;
+ }
+
+ public MBeanProvider getMbeanProvider() {
+ return mbeanProvider;
+ }
+
+ public MBeanServerConnectionJob getMBeanServerConnectionJob() {
+ return mbeanServerConnectionJob;
+ }
+
+ public RuntimeDataProvider getRuntimeDataProvider() {
+ return runtimeDataProvider;
+ }
+
+ public void setJmxServiceDescriptor(
+ final JMXServiceDescriptor jmxServiceDescriptor) {
+ this.jmxServiceDescriptor = jmxServiceDescriptor;
+ }
+
+ public void setMbeanConnectionJob(final MBeanServerConnectionJob mbeanServerConnectionJob) {
+ this.mbeanServerConnectionJob = mbeanServerConnectionJob;
+ }
+
+ public void setMbeanProvider(final MBeanProvider mbeanProvider) {
+ this.mbeanProvider = mbeanProvider;
+ }
+
+ public void setRuntimeDataProvider(final RuntimeDataProvider runtimeDataProvider) {
+ this.runtimeDataProvider = runtimeDataProvider;
+ }
+ };
+
+ public static final String JMX_JMXRMI_DOMAIN = "jmxrmi"; //$NON-NLS-1$
+
+ private WorkbenchServiceManager<JMXServiceDescriptor> jmxServiceManager;
+
+ private final Map<String, KarafMBeanProviderEntry> mbeanProviderDataMap =
+ Collections.synchronizedMap(new HashMap<String, KarafMBeanProviderEntry>());
+
+ private WorkbenchServiceManager<MBeanProvider> mbeanProviderManager;
+
+ private WorkbenchServiceManager<RuntimeDataProvider> runtimeDataProviderManager;
+
+ public KarafMBeanProviderWorkbenchService() {
+ DebugPlugin.getDefault().getLaunchManager().addLaunchListener(new JMXServiceCleanupLaunchListener());
+
+ jmxServiceManager = KarafWorkbenchActivator.getDefault().getJMXServiceManager();
+ mbeanProviderManager = KarafWorkbenchActivator.getDefault().getMBeanProviderManager();
+ runtimeDataProviderManager = KarafWorkbenchActivator.getDefault().getRuntimeDataProviderManager();
+ }
+
+ @Override
+ public List<BundleEntry> getAdditionalBundles(
+ final KarafWorkingPlatformModel platformModel,
+ final ILaunchConfiguration configuration)
+ {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Map<String, String> getAdditionalEquinoxConfiguration(
+ final KarafWorkingPlatformModel platformModel,
+ final ILaunchConfiguration configuration)
+ {
+ return Collections.emptyMap();
+ }
+
+ /**
+ * Starts a background system job that will connect to the Karaf MBeanServer
+ *
+ * 1. Register a remote JMX port to bind the JMX server to
+ * 2. Establish an MBeanServerConnectionJob to connect to that port
+ * 3. When connected: Register OSGi C&C MBeanProvider in the service registry
+ * 4. When connected: Register the RuntimeDataProvider in the service registry
+ */
+ @Override
+ public List<String> getVMArguments(
+ final KarafWorkingPlatformModel platformModel,
+ final ILaunchConfiguration configuration) throws CoreException
+ {
+ final String memento = configuration.getMemento();
+ mbeanProviderDataMap.put(memento, new KarafMBeanProviderEntry());
+
+ final List<String> arguments = new ArrayList<String>();
+
+ /*
+ * Ensure the Remote JMX connector port is unique
+ */
+ final int jmxPort = SocketUtil.findFreePort();
+
+ if (jmxPort == -1) {
+ throw new CoreException(new Status(IStatus.ERROR, KarafWorkbenchActivator.PLUGIN_ID,
+ "Could not find suitable TCP/IP port for JMX connection"));
+ }
+
+ arguments.add(
+ KarafCorePluginUtils.constructSystemProperty(
+ "com.sun.management.jmxremote.authenticate", //$NON-NLS-1$
+ "false")); //$NON-NLS-1$
+ arguments.add(
+ KarafCorePluginUtils.constructSystemProperty(
+ "com.sun.management.jmxremote.ssl", //$NON-NLS-1$
+ "false")); //$NON-NLS-1$
+ arguments.add(
+ KarafCorePluginUtils.constructSystemProperty(
+ "com.sun.management.jmxremote.port", //$NON-NLS-1$
+ new Integer(jmxPort).toString()));
+
+ final MBeanServerConnectionJob mbeanConnectionJob;
+ try {
+ final JMXServiceURL standardJmxConnection = new JMXServiceURL(
+ "service:jmx:rmi:///jndi/rmi://localhost:" + jmxPort + "/jmxrmi"); //$NON-NLS-1$ $NON-NLS-2$
+
+ final JMXServiceDescriptor descriptor = new LocalJMXServiceDescriptor(
+ configuration.getName(),
+ platformModel,
+ standardJmxConnection,
+ null,
+ null,
+ JMX_JMXRMI_DOMAIN);
+
+ mbeanConnectionJob = new MBeanServerConnectionJob(configuration.getName(), descriptor);
+
+ mbeanProviderDataMap.get(memento).setMbeanConnectionJob(mbeanConnectionJob);
+ mbeanProviderDataMap.get(memento).setJmxServiceDescriptor(descriptor);
+
+ jmxServiceManager.add(descriptor);
+ } catch(final MalformedURLException e) {
+ KarafWorkbenchActivator.getLogger().error("Unable to connect to JMX endpoint on Karaf instance", e);
+
+ throw new CoreException(new Status(IStatus.ERROR, "", "")); //$NON-NLS-1$ $NON-NLS-2$
+ }
+
+ final IJobChangeListener listener = new JobChangeAdapter() {
+ @Override
+ public void done(final IJobChangeEvent event) {
+ final IStatus result = event.getResult();
+ if (result == null || !result.isOK()) {
+ // TODO: Log something
+ return;
+ }
+
+ if (!mbeanConnectionJob.isConnected()) {
+ // TODO: Log something
+ return;
+ }
+
+ final KarafMBeanProvider mbeanProvider;
+ try {
+ final JMXServiceDescriptor jmxServiceDescriptor = mbeanProviderDataMap.get(memento).getJmxServiceDescriptor();
+ mbeanProvider = new LocalKarafMBeanProvider(jmxServiceDescriptor, mbeanConnectionJob.getJmxClient(), platformModel);
+ mbeanProvider.open(memento);
+
+ mbeanProviderDataMap.get(memento).setMbeanProvider(mbeanProvider);
+ mbeanProviderManager.add(mbeanProvider);
+ } catch (final IOException e) {
+ KarafWorkbenchActivator.getLogger().error("Unable to create MBeanProvider from JMXConnector", e);
+
+ return;
+ }
+
+ final KarafRuntimeDataProvider runtimeDataProvider = new KarafRuntimeDataProvider(configuration.getName(), mbeanProvider);
+ runtimeDataProvider.start();
+
+ mbeanProviderDataMap.get(memento).setRuntimeDataProvider(runtimeDataProvider);
+ runtimeDataProviderManager.add(runtimeDataProvider);
+ }
+ };
+
+ mbeanConnectionJob.addJobChangeListener(listener);
+ mbeanConnectionJob.schedule(MBeanServerConnectionJob.DEFAULT_INITIAL_SCHEDULE_DELAY);
+
+ return arguments;
+ }
+
+ @Override
+ public void initialize(final KarafWorkingPlatformModel platformModel,
+ final ILaunchConfigurationWorkingCopy configuration) {
+ }
+
+ @Override
+ public void launch(
+ final KarafWorkingPlatformModel platformModel,
+ final ILaunchConfiguration configuration,
+ final String mode,
+ final ILaunch launch,
+ final IProgressMonitor monitor) throws CoreException
+ {
+ final IDebugEventSetListener debugListener = getDebugEventListener(launch);
+ DebugPlugin.getDefault().addDebugEventListener(debugListener);
+ }
+
+ public void setJmxServiceManager(final WorkbenchServiceManager<JMXServiceDescriptor> jmxServiceManager) {
+ this.jmxServiceManager = jmxServiceManager;
+ }
+
+ public void setMbeanProviderManager(final WorkbenchServiceManager<MBeanProvider> mbeanProviderManager) {
+ this.mbeanProviderManager = mbeanProviderManager;
+ }
+
+ public void setRuntimeDataProviderManager(final WorkbenchServiceManager<RuntimeDataProvider> runtimeDataProviderManager) {
+ this.runtimeDataProviderManager = runtimeDataProviderManager;
+ }
+
+ /**
+ * Registers an event listener on the debug session that responds to
+ * {@link DebugEvent.TERMINATE} events. This will stop the MBBean connection
+ * job, the {@link RuntimeDataProvider} and the {@link MBeanProvider}<br>
+ * <br>
+ * This will also cleanup the services registered during this debug session.
+ *
+ * @param launch
+ * the launch process
+ */
+ private IDebugEventSetListener getDebugEventListener(final ILaunch launch) throws CoreException {
+ final IProcess process = launch.getProcesses()[0];
+
+ final String memento =
+ launch.getLaunchConfiguration().getMemento();
+
+ return new IDebugEventSetListener() {
+ @Override
+ public void handleDebugEvents(final DebugEvent[] events) {
+ if (events == null) {
+ return;
+ }
+
+ for (final DebugEvent event : events) {
+ if ( process != null
+ && process.equals(event.getSource())
+ && event.getKind() == DebugEvent.TERMINATE)
+ {
+ final JMXServiceDescriptor descriptor = mbeanProviderDataMap.get(memento).getJmxServiceDescriptor();
+ jmxServiceManager.remove(descriptor);
+
+ final MBeanServerConnectionJob job = mbeanProviderDataMap.get(memento).getMBeanServerConnectionJob();
+ if (job != null) {
+ job.cancel();
+ }
+
+ final RuntimeDataProvider runtimeDataProvider = mbeanProviderDataMap.get(memento).getRuntimeDataProvider();
+ runtimeDataProviderManager.remove(runtimeDataProvider);
+ if (runtimeDataProvider != null) {
+ runtimeDataProvider.stop();
+ }
+
+ final MBeanProvider mbeanProvider = mbeanProviderDataMap.get(memento).getMbeanProvider();
+ mbeanProviderManager.remove(mbeanProvider);
+
+ if (mbeanProvider != null) {
+ mbeanProvider.close();
+ }
+ }
+ }
+ }
+ };
+ }
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/KarafRuntimeDataProvider.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/KarafRuntimeDataProvider.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/KarafRuntimeDataProvider.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/KarafRuntimeDataProvider.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,304 @@
+/**
+ * Copyright (c) 2009 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.internal;
+
+import info.evanchik.eclipse.karaf.workbench.KarafWorkbenchActivator;
+import info.evanchik.eclipse.karaf.workbench.MBeanProvider;
+import info.evanchik.eclipse.karaf.workbench.provider.AbstractRuntimeDataProvider;
+import info.evanchik.eclipse.karaf.workbench.provider.BundleItem;
+import info.evanchik.eclipse.karaf.workbench.provider.RuntimeDataProvider;
+import info.evanchik.eclipse.karaf.workbench.provider.RuntimeDataProviderListener;
+import info.evanchik.eclipse.karaf.workbench.provider.ServiceItem;
+
+import java.io.IOException;
+import java.util.EnumSet;
+
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+
+import org.apache.aries.jmx.codec.ServiceData;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.swt.graphics.Image;
+import org.osgi.jmx.framework.BundleStateMBean;
+import org.osgi.jmx.framework.ServiceStateMBean;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class KarafRuntimeDataProvider extends AbstractRuntimeDataProvider {
+
+ private static final ObjectName BUNDLE_STATE;
+
+ @SuppressWarnings("unused")
+ private static final ObjectName CM_SERVICE;
+
+ @SuppressWarnings("unused")
+ private static final ObjectName PACKAGE_STATE;
+
+ private static final ObjectName SERVICE_STATE;
+
+ /*
+ * If this throws an exception we're in trouble because it means that the
+ * constants are invalid
+ */
+ static {
+ try {
+ BUNDLE_STATE = new ObjectName("osgi.core:type=bundleState,version=1.5");
+ CM_SERVICE = new ObjectName("osgi.core:type=cm,version=1.3");
+ PACKAGE_STATE = new ObjectName("osgi.core:type=packageState,version=1.5");
+ SERVICE_STATE = new ObjectName("osgi.core:type=serviceState,version=1.5");
+ } catch (final Exception e) {
+ throw new IllegalStateException("The OSGi JMX implementation references an invalid ObjectName", e);
+ }
+ }
+
+ private final String name;
+
+ private final MBeanProvider mbeanProvider;
+
+ /**
+ * Updates the runtime data referenced by the {@link BundleStateMBean} and
+ * {@link ServiceStateMBean}
+ */
+ private final Job updateDataJob;
+
+ /**
+ * A {@link RuntimeDataProvider} implementation specific to Karaf instances
+ * being run/debugged in Eclipse.
+ *
+ * @param name
+ * the human readable name of this provider
+ * @param provider
+ * the {@link MBeanProvider} for the running Karaf instance
+ */
+ public KarafRuntimeDataProvider(final String name, final MBeanProvider provider) {
+ super();
+
+ this.name = name;
+ this.mbeanProvider = provider;
+
+ this.updateDataJob = new Job("Populating OSGi Runtime view data for: " + name) {
+
+ private volatile boolean cancel = false;
+
+ @Override
+ public IStatus run(IProgressMonitor monitor) {
+ if (monitor == null) {
+ monitor = new NullProgressMonitor();
+ }
+
+ if ( !KarafRuntimeDataProvider.this.mbeanProvider.isOpen()
+ && !cancel)
+ {
+ this.schedule(25000);
+ }
+
+ monitor.beginTask("Populating view data set", IProgressMonitor.UNKNOWN);
+
+ IStatus status = loadBundleData(monitor);
+ if (!status.isOK()) {
+ // Do something?
+ }
+
+ if (monitor.isCanceled()) {
+ return Status.OK_STATUS;
+ }
+
+ status = loadServiceData(monitor);
+ if (!status.isOK()) {
+ // Do something?
+ }
+
+ monitor.done();
+
+ if (monitor.isCanceled()) {
+ return Status.OK_STATUS;
+ }
+
+ if (!cancel) {
+ /*
+ * Poll every 25 seconds because the MBeans are not notification
+ * enabled
+ */
+ this.schedule(25000);
+ }
+
+ fireProviderChangeEvent(EnumSet.of(RuntimeDataProviderListener.EventType.CHANGE));
+
+ return Status.OK_STATUS;
+ }
+
+ @Override
+ protected void canceling() {
+ cancel = true;
+ }
+ };
+
+ this.updateDataJob.setSystem(true);
+ this.updateDataJob.setPriority(Job.LONG);
+ }
+
+ @Override
+ public Object getAdapter(@SuppressWarnings("rawtypes") final Class adapter) {
+ if (MBeanProvider.class.equals(adapter)) {
+ return mbeanProvider;
+ } else {
+ return super.getAdapter(adapter);
+ }
+ }
+
+ @Override
+ public Image getIcon() {
+ return KarafWorkbenchActivator.getDefault().getImageRegistry().get(KarafWorkbenchActivator.LOGO_16X16_IMG);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Starts the {@link RuntimeDataProvider} which will collect the OSGi
+ * runtime information from the running Karaf instance.
+ */
+ @Override
+ public void start() {
+ fireStartEvent();
+
+ updateDataJob.schedule();
+ }
+
+ @Override
+ public void stop() {
+ updateDataJob.cancel();
+
+ synchronized (bundleSet) {
+ bundleSet.clear();
+ idToBundleMap.clear();
+ }
+
+ synchronized (serviceSet) {
+ serviceSet.clear();
+ idToServiceMap.clear();
+ }
+
+ fireStopEvent();
+ }
+
+ private IStatus loadBundleData(final IProgressMonitor monitor) {
+ monitor.subTask("OSGi Bundles");
+
+ if (monitor.isCanceled()) {
+ return Status.OK_STATUS;
+ }
+
+ if (!mbeanProvider.isOpen()) {
+ return new Status(IStatus.WARNING, KarafWorkbenchActivator.PLUGIN_ID, "Connection to MBean server has been closed");
+ }
+
+ try {
+ final TabularData rawBundleData = mbeanProvider.getMBean(BUNDLE_STATE, BundleStateMBean.class).listBundles();
+
+ synchronized (bundleSet) {
+ bundleSet.clear();
+ idToBundleMap.clear();
+ }
+
+ for (final Object o : rawBundleData.values()) {
+ final CompositeData composite = (CompositeData) o;
+ final BundleItem bundle = new BundleItem(composite);
+
+ synchronized (bundleSet) {
+ bundleSet.add(bundle);
+ idToBundleMap.put(bundle.getIdentifier(), bundle);
+ }
+
+ monitor.worked(1);
+
+ if (monitor.isCanceled()) {
+ break;
+ }
+
+ }
+
+ } catch (final IOException e) {
+ return new Status(IStatus.ERROR, KarafWorkbenchActivator.PLUGIN_ID, "Unable to connect to MBeanServer", e);
+ } catch (final Exception e) {
+ KarafWorkbenchActivator.getLogger().warn("Unable to update OSGi Bundles", e);
+ }
+
+ return Status.OK_STATUS;
+ }
+
+ private IStatus loadServiceData(final IProgressMonitor monitor) {
+ monitor.subTask("OSGi Services");
+
+ if (monitor.isCanceled()) {
+ return Status.OK_STATUS;
+ }
+
+ if (!mbeanProvider.isOpen()) {
+ return new Status(IStatus.WARNING, KarafWorkbenchActivator.PLUGIN_ID, "Connection to MBean server has been closed");
+ }
+
+ try {
+ final TabularData rawServiceData = mbeanProvider.getMBean(SERVICE_STATE, ServiceStateMBean.class).listServices();
+
+ synchronized (serviceSet) {
+ serviceSet.clear();
+ idToServiceMap.clear();
+ }
+
+ for (final Object o : rawServiceData.values()) {
+ final CompositeData composite = (CompositeData) o;
+ final ServiceData service = ServiceData.from(composite);
+
+ /*
+ * Get the service's properties from the JMX enabled runtime
+ */
+ if (!mbeanProvider.isOpen()) {
+ return new Status(IStatus.WARNING, KarafWorkbenchActivator.PLUGIN_ID, "Connection to MBean server has been closed");
+ }
+
+ final ServiceItem serviceWrapper = new MBeanServiceItem(composite, mbeanProvider, idToBundleMap);
+
+ synchronized (serviceSet) {
+ serviceSet.add(serviceWrapper);
+ idToServiceMap.put(service.getServiceId(), serviceWrapper);
+ }
+
+ monitor.worked(1);
+
+ if (monitor.isCanceled()) {
+ break;
+ }
+
+ }
+ } catch (final IOException e) {
+ if (monitor.isCanceled()) {
+ return new Status(IStatus.CANCEL, KarafWorkbenchActivator.PLUGIN_ID, "Unable to connect to MBeanServer", e);
+ } else {
+ return new Status(IStatus.ERROR, KarafWorkbenchActivator.PLUGIN_ID, "Unable to connect to MBeanServer", e);
+ }
+ } catch (final Exception e) {
+ KarafWorkbenchActivator.getLogger().warn("Unable to update OSGi Services", e);
+ }
+
+ return Status.OK_STATUS;
+ }
+
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/LocalKarafMBeanProvider.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/LocalKarafMBeanProvider.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/LocalKarafMBeanProvider.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/LocalKarafMBeanProvider.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2011 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.internal;
+
+import info.evanchik.eclipse.karaf.core.KarafPlatformModel;
+import info.evanchik.eclipse.karaf.workbench.jmx.JMXServiceDescriptor;
+
+import java.io.IOException;
+
+import javax.management.remote.JMXConnector;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class LocalKarafMBeanProvider extends KarafMBeanProvider {
+
+ private final KarafPlatformModel platformModel;
+
+ /**
+ * @param jmxServiceDescriptor
+ * @param connector
+ * @param platformModel
+ * @throws IOException
+ */
+ public LocalKarafMBeanProvider(final JMXServiceDescriptor jmxServiceDescriptor, final JMXConnector connector, final KarafPlatformModel platforModel) throws IOException {
+ super(jmxServiceDescriptor, connector);
+
+ this.platformModel = platforModel;
+ }
+
+ @Override
+ public Object getAdapter(final @SuppressWarnings("rawtypes") Class adapter) {
+ if (KarafPlatformModel.class.equals(adapter)) {
+ return platformModel;
+ } else {
+ return super.getAdapter(adapter);
+ }
+ }
+
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/MBeanProviderManager.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/MBeanProviderManager.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/MBeanProviderManager.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/MBeanProviderManager.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2011 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.internal;
+
+import info.evanchik.eclipse.karaf.workbench.MBeanProvider;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class MBeanProviderManager extends AbstractWorkbenchServiceManager<MBeanProvider> {
+
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/MBeanServerConnectionJob.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/MBeanServerConnectionJob.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/MBeanServerConnectionJob.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/MBeanServerConnectionJob.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,172 @@
+/**
+ * Copyright (c) 2009 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.internal;
+
+import info.evanchik.eclipse.karaf.workbench.KarafWorkbenchActivator;
+import info.evanchik.eclipse.karaf.workbench.jmx.JMXServiceDescriptor;
+
+import java.io.IOException;
+import java.util.Hashtable;
+
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class MBeanServerConnectionJob extends Job {
+
+ /**
+ * Default maximum number of connection attempts
+ */
+ public static final int DEFAULT_MAX_RETRIES = 5;
+
+ /**
+ * Default number of milliseconds between rescheduling
+ */
+ public static final long DEFAULT_RESCHEDULE_DELAY = 5 * 1000;
+
+ /**
+ * Default number of milliseconds before attempting to connect to the JMX
+ * server
+ */
+ public static final long DEFAULT_INITIAL_SCHEDULE_DELAY = 3 * 1000;
+
+ /**
+ * The JMX connection descriptor
+ */
+ private final JMXServiceDescriptor connection;
+
+ /**
+ * The time between connection retries
+ */
+ private long rescheduleDelay = DEFAULT_RESCHEDULE_DELAY;
+
+ /**
+ * The JMX environment used for passing credentials to the JMX connection
+ */
+ private final Hashtable<String, String[]> environment = new Hashtable<String, String[]>();
+
+ /**
+ * Determines if this {@link Job} has been canceled
+ */
+ private volatile boolean cancel = false;
+
+ /**
+ * The JMX MBeanServer client
+ */
+ private JMXConnector jmxClient;
+
+ /**
+ * Constructs a {@link Job} that will connect to the JMX MBeanServer on a
+ * remote (or local) Karaf instance.
+ *
+ * @param name
+ * the friendly name of this job as displayed to the user
+ * @param connection
+ * the {@link JMXServiceDescriptor} that represents
+ * the JMX MBeanServer this {@link Job} will connect to
+ */
+ public MBeanServerConnectionJob(final String name, final JMXServiceDescriptor connection) {
+ super(name);
+
+ this.connection = connection;
+
+ String[] credentials;
+ if (hasCredentials()) {
+ credentials = new String[] { connection.getUsername(), connection.getPassword() };
+ environment.put(JMXConnector.CREDENTIALS, credentials);
+ }
+ }
+
+ public JMXConnector getJmxClient() {
+ return jmxClient;
+ }
+
+ public JMXServiceDescriptor getMBeanServerConnectionDescriptor() {
+ return connection;
+ }
+
+ public final long getRescheduleDelay() {
+ return rescheduleDelay;
+ }
+
+ /**
+ * Determines if this job successfully connected to the MBeanServer
+ *
+ * @return true if connected to the MBeanServer, false otherwise
+ */
+ public final boolean isConnected() {
+ return jmxClient != null;
+ }
+
+ /**
+ * @param rescheduleDelay
+ * the rescheduleDelay to set
+ */
+ public final void setRescheduleDelay(final long rescheduleDelay) {
+ this.rescheduleDelay = rescheduleDelay;
+ }
+
+ @Override
+ protected void canceling() {
+ cancel = true;
+ }
+
+ @Override
+ protected IStatus run(final IProgressMonitor monitor) {
+
+ IStatus status;
+
+ try {
+ jmxClient = JMXConnectorFactory.connect(connection.getUrl(), environment);
+
+ monitor.worked(5);
+
+ status = new Status(
+ IStatus.OK,
+ KarafWorkbenchActivator.PLUGIN_ID,
+ "Successfully connected to JMX MBeanServer for: " + getName());
+
+ } catch (final IOException ex) {
+ status = new Status(
+ IStatus.WARNING,
+ KarafWorkbenchActivator.PLUGIN_ID,
+ "Retrying connection for for: " + getName(), ex);
+
+ if (!cancel) {
+ schedule(rescheduleDelay);
+ }
+ }
+
+ return status;
+ }
+
+ /**
+ * Determines if the {@link JMXServiceDescriptor} has
+ * authentication information provided
+ *
+ * @return true if there is authentication information, false otherwise
+ */
+ private boolean hasCredentials() {
+ if (connection.getUsername() != null && connection.getUsername().length() > 0) {
+ return true;
+ }
+
+ return false;
+ }
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/MBeanServiceItem.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/MBeanServiceItem.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/MBeanServiceItem.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/MBeanServiceItem.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2010 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.internal;
+
+import info.evanchik.eclipse.karaf.workbench.MBeanProvider;
+import info.evanchik.eclipse.karaf.workbench.provider.BundleItem;
+import info.evanchik.eclipse.karaf.workbench.provider.ServiceItem;
+
+import java.util.Collections;
+import java.util.Map;
+
+import javax.management.openmbean.CompositeData;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class MBeanServiceItem extends ServiceItem {
+
+ private final Map<Long, BundleItem> bundleCache;
+
+ @SuppressWarnings("unused")
+ private final MBeanProvider mbeanProvider;
+
+ public MBeanServiceItem(final CompositeData compositeData, final MBeanProvider mbeanProvider, final Map<Long, BundleItem> bundleCache) {
+ super(compositeData);
+
+ this.mbeanProvider = mbeanProvider;
+ this.bundleCache = Collections.synchronizedMap(bundleCache);
+ }
+
+ @Override
+ public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
+ Object o;
+ if (adapter == null) {
+ o = null;
+ } else {
+ o = super.getAdapter(adapter);
+ if (o == null && adapter.equals(BundleItem.class)) {
+ if (bundleCache.containsKey(Long.valueOf(getBundleId()))) {
+ o = bundleCache.get(Long.valueOf(getBundleId()));
+ } else {
+ // TODO: Fetch this data from the remote source
+ o = null;
+ }
+ }
+ }
+
+ return o;
+ }
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/RuntimeDataProviderManager.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/RuntimeDataProviderManager.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/RuntimeDataProviderManager.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/RuntimeDataProviderManager.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) 2011 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.internal;
+
+import info.evanchik.eclipse.karaf.workbench.provider.RuntimeDataProvider;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class RuntimeDataProviderManager extends AbstractWorkbenchServiceManager<RuntimeDataProvider> {
+
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/WorkbenchActionProvider.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/WorkbenchActionProvider.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/WorkbenchActionProvider.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/WorkbenchActionProvider.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,72 @@
+/**
+ * Copyright (c) 2011 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.internal;
+
+import info.evanchik.eclipse.karaf.ui.IKarafProject;
+import info.evanchik.eclipse.karaf.workbench.KarafWorkbenchActivator;
+import info.evanchik.eclipse.karaf.workbench.ui.editor.KarafPlatformEditorInput;
+import info.evanchik.eclipse.karaf.workbench.ui.editor.KarafPlatformEditorPart;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.navigator.CommonActionProvider;
+import org.eclipse.ui.navigator.ICommonActionExtensionSite;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class WorkbenchActionProvider extends CommonActionProvider {
+
+ @Override
+ public void init(final ICommonActionExtensionSite aSite) {
+ super.init(aSite);
+
+ aSite.getStructuredViewer().addDoubleClickListener(new IDoubleClickListener() {
+
+ @Override
+ public void doubleClick(final DoubleClickEvent event) {
+ // TODO: This method is a mess: clean it up!
+ if (!(event.getSelection() instanceof IStructuredSelection)) {
+ return;
+ }
+
+ final IStructuredSelection structuredSelection = (IStructuredSelection) event.getSelection();
+ if (structuredSelection.size() > 1) {
+ return;
+ }
+
+ final Object element = structuredSelection.getFirstElement();
+ if (!(element instanceof IProject)) {
+ return;
+ }
+
+ final IProject project = (IProject) element;
+ final IKarafProject karafProject = (IKarafProject) project.getAdapter(IKarafProject.class);
+ final IEditorInput editorInput = new KarafPlatformEditorInput(karafProject);
+
+ try {
+ final IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
+ page.openEditor(editorInput, KarafPlatformEditorPart.ID);
+ } catch (final PartInitException e) {
+ KarafWorkbenchActivator.getLogger().error("Unable to open editor for " + karafProject.getName(), e);
+ }
+ }
+ });
+ }
+
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/eclipse/EclipseRuntimeDataProvider.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/eclipse/EclipseRuntimeDataProvider.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/eclipse/EclipseRuntimeDataProvider.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/internal/eclipse/EclipseRuntimeDataProvider.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,254 @@
+/**
+ * Copyright (c) 2009 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.internal.eclipse;
+
+import info.evanchik.eclipse.karaf.workbench.KarafWorkbenchActivator;
+import info.evanchik.eclipse.karaf.workbench.provider.AbstractRuntimeDataProvider;
+import info.evanchik.eclipse.karaf.workbench.provider.BundleItem;
+import info.evanchik.eclipse.karaf.workbench.provider.RuntimeDataProvider;
+import info.evanchik.eclipse.karaf.workbench.provider.RuntimeDataProviderListener;
+import info.evanchik.eclipse.karaf.workbench.provider.ServiceItem;
+
+import java.util.EnumSet;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.osgi.framework.AllServiceListener;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.service.startlevel.StartLevel;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class EclipseRuntimeDataProvider extends AbstractRuntimeDataProvider implements RuntimeDataProvider {
+
+ private final BundleContext context;
+
+ private final BundleListener eclipseBundleListener;
+
+ private final AllServiceListener eclipseAllServiceListener;
+
+ private ServiceReference packageAdminReference;
+
+ private PackageAdmin packageAdmin;
+
+ private ServiceReference startLevelReference;
+
+ private StartLevel startLevel;
+
+ /**
+ *
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+ private final class EclipseBundleListener implements BundleListener {
+
+ @Override
+ public void bundleChanged(BundleEvent event) {
+ final BundleItem wrappedBundle = new BundleItem(event.getBundle(), startLevel, packageAdmin);
+
+ EnumSet<RuntimeDataProviderListener.EventType> events = EnumSet.noneOf(RuntimeDataProviderListener.EventType.class);
+
+ switch (event.getType()) {
+ case BundleEvent.INSTALLED:
+ synchronized (bundleSet) {
+ if (!bundleSet.contains(wrappedBundle)) {
+ bundleSet.add(wrappedBundle);
+
+ events = EnumSet.of(RuntimeDataProviderListener.EventType.ADD);
+ }
+ }
+ break;
+ case BundleEvent.UNINSTALLED:
+ synchronized (bundleSet) {
+ if (bundleSet.contains(wrappedBundle)) {
+ bundleSet.remove(wrappedBundle);
+
+ events = EnumSet.of(RuntimeDataProviderListener.EventType.REMOVE);
+ }
+ }
+ break;
+ default:
+ events = EnumSet.of(RuntimeDataProviderListener.EventType.CHANGE);
+ break;
+ }
+
+ fireProviderChangeEvent(events);
+ }
+ };
+
+ /**
+ *
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+ private final class EclipseAllServiceListener implements AllServiceListener {
+
+ @Override
+ public void serviceChanged(ServiceEvent event) {
+ final ServiceReference reference = event.getServiceReference();
+
+ final ServiceItem ri = new ServiceItem(reference);
+
+ EnumSet<RuntimeDataProviderListener.EventType> events = EnumSet.noneOf(RuntimeDataProviderListener.EventType.class);
+
+ switch (event.getType()) {
+ case ServiceEvent.REGISTERED:
+ synchronized (serviceSet) {
+ if (serviceSet.contains(ri)) {
+ serviceSet.add(ri);
+ events = EnumSet.of(RuntimeDataProviderListener.EventType.ADD);
+ }
+ }
+ break;
+ case ServiceEvent.UNREGISTERING:
+ synchronized (serviceSet) {
+ if (serviceSet.contains(ri)) {
+ serviceSet.remove(ri);
+ events = EnumSet.of(RuntimeDataProviderListener.EventType.REMOVE);
+ }
+ }
+ break;
+ case ServiceEvent.MODIFIED:
+ default:
+ events = EnumSet.of(RuntimeDataProviderListener.EventType.CHANGE);
+ break;
+ }
+
+ fireProviderChangeEvent(events);
+ }
+ };
+
+ public EclipseRuntimeDataProvider(BundleContext context) {
+ super();
+
+ this.context = context;
+
+ this.eclipseBundleListener = new EclipseBundleListener();
+ this.eclipseAllServiceListener = new EclipseAllServiceListener();
+
+ this.packageAdminReference = context.getServiceReference(PackageAdmin.class.getName());
+ this.packageAdmin = (PackageAdmin) context.getService(packageAdminReference);
+
+ this.startLevelReference = context.getServiceReference(StartLevel.class.getName());
+ this.startLevel = (StartLevel) context.getService(startLevelReference);
+ }
+
+ public String getName() {
+ return "Eclipse Workbench";
+ }
+
+ public void start() {
+ context.addBundleListener(eclipseBundleListener);
+ context.addServiceListener(eclipseAllServiceListener);
+
+ final Job initializeJob = new Job("Populating OSGi Runtime view data for: Eclipse Workbench") {
+ @Override
+ public IStatus run(IProgressMonitor monitor) {
+ if (monitor == null) {
+ monitor = new NullProgressMonitor();
+ }
+
+ final Bundle[] bundles;
+ final ServiceReference[] services;
+
+ try {
+ bundles = context.getBundles();
+ services = context.getAllServiceReferences(null, null);
+ } catch (InvalidSyntaxException e) {
+ // TODO: Log something?
+ return new Status(IStatus.ERROR, KarafWorkbenchActivator.PLUGIN_ID,
+ "Unable to get service references for running Eclipse Workbench", e);
+ }
+
+ int servicesLength = 0;
+ if (services != null) {
+ servicesLength = services.length;
+ }
+
+ monitor.worked(10);
+
+ monitor.beginTask("Populating view data set", bundles.length + servicesLength);
+
+ monitor.subTask("OSGi Bundles");
+
+ for (Bundle b : bundles) {
+ /*
+ * This bundle can't be added because it does not have a
+ * context
+ */
+ if (b == null || b.getBundleContext() == null) {
+ continue;
+ }
+
+ synchronized (bundleSet) {
+ bundleSet.add(new BundleItem(b, startLevel, packageAdmin));
+ }
+
+ monitor.worked(1);
+ }
+
+ // If there are no services then this is null
+ if (services != null) {
+ monitor.subTask("OSGi Services");
+
+ for (ServiceReference r : services) {
+ synchronized (serviceSet) {
+ serviceSet.add(new ServiceItem(r));
+ }
+
+ monitor.worked(1);
+ }
+ }
+
+ monitor.done();
+
+ return Status.OK_STATUS;
+ }
+ };
+
+ initializeJob.setPriority(Job.LONG);
+ initializeJob.schedule();
+
+ fireStartEvent();
+ }
+
+ public void stop() {
+ context.removeBundleListener(eclipseBundleListener);
+ context.removeServiceListener(eclipseAllServiceListener);
+
+ context.ungetService(startLevelReference);
+ startLevel = null;
+ startLevelReference = null;
+
+ context.ungetService(packageAdminReference);
+ packageAdmin = null;
+ packageAdminReference = null;
+
+ synchronized (bundleSet) {
+ bundleSet.clear();
+ serviceSet.clear();
+ }
+
+ fireStopEvent();
+ }
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/IJMXTransportListener.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/IJMXTransportListener.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/IJMXTransportListener.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/IJMXTransportListener.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2009 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.jmx;
+
+import info.evanchik.eclipse.karaf.workbench.WorkbenchServiceListener;
+
+import javax.management.remote.JMXConnectorProvider;
+
+/**
+ * A {@code IJMXTransportListener} is notified when a
+ * {@link JMXConnectorProvider} is added or removed from a
+ * {@link IJMXTransportRegistry}.
+ *
+ * @see IJMXTransportRegistry
+ *
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public interface IJMXTransportListener extends WorkbenchServiceListener<JMXConnectorProvider> {
+
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/IJMXTransportRegistry.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/IJMXTransportRegistry.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/IJMXTransportRegistry.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/IJMXTransportRegistry.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,82 @@
+/**
+ * Copyright (c) 2009 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.jmx;
+
+import java.util.Set;
+
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorProvider;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public interface IJMXTransportRegistry {
+
+ /**
+ * Adds a {@link IJMXTransportListener} to the list of listeners for this
+ * registry. The listener will be notified whenever a
+ * {@link JMXConnectorProvider} is added or removed from the registry.<br>
+ * <br>
+ * Adding the same listener multiple times has no effect.
+ *
+ * @param listener the {@code IJMXTransportListener} to add
+ */
+ public void addJMXTransportListener(IJMXTransportListener listener);
+
+ /**
+ * Returns a {@link Set} of names representing
+ * {@link JMXConnectorProvider}s
+ *
+ * @return
+ * a {@code Set} of names representing {@link JMXConnectorProvider}s
+ */
+ public Set<String> getConnectorNames();
+
+ /**
+ * Getter for a {@link JMXConnectorProvider} using its name as a retrieval
+ * key
+ *
+ * @param name the name of the {@code JMXConnectorProvider}
+ *
+ * @return
+ * the {@code JMXConnectorProvider} for the given name, or null if it
+ * does not exist
+ */
+ public JMXConnectorProvider getConnectorProvider(String name);
+
+ /**
+ * Gets a {@link JMXConnector} for a {@link JMXServiceDescriptor} making use
+ * of the {@code JMXConnectorProvider} registered with the transport
+ * registry
+ *
+ * @param serviceDescriptor the {@code JMXServiceDescriptor} for which the
+ * {@code JMXConnector} is requested
+ *
+ * @return
+ * the {@code JMXConnector} used to connect to the service
+ * represented by the {@code JMXServiceDescriptor}
+ */
+ public JMXConnector getJMXConnector(JMXServiceDescriptor serviceDescriptor);
+
+ /**
+ * Removes the given {@link IJMXTransportListener} from the registry.<br>
+ * <br>
+ * If the {@code JMXConnectorProvider} is not registered with the registry,
+ * this method has no effect.
+ *
+ * @param listener the {@code IJMXTransportListener} to remove
+ */
+ public void removeJMXTransportListner(IJMXTransportListener listener);
+
+ // TODO: This should not be here
+ public void loadTransportExtensions();
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/JMXServiceDescriptor.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/JMXServiceDescriptor.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/JMXServiceDescriptor.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/JMXServiceDescriptor.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,206 @@
+/**
+ * Copyright (c) 2009 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.jmx;
+
+import java.io.Serializable;
+import java.net.MalformedURLException;
+
+import javax.management.remote.JMXServiceURL;
+
+import org.eclipse.core.runtime.PlatformObject;
+
+/**
+ * A {@code JMXServiceDescriptor} contains all of the elements necessary to
+ * describe a connection to a JMX endpoint:<br>
+ * <br>
+ * <ol>
+ * <li>A human readable name - Suitable for displaying via the UI</li>
+ * <li>A {@link JMXServiceURL} - Used to connect to the MBeanServer</li>
+ * <li>Credentials - A username and password credential pair</li>
+ * </ol>
+ * <br>
+ * These elements form the necessary descriptive information to use in the JMX
+ * Client UI.
+ *
+ * @see JMXServiceURL
+ *
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class JMXServiceDescriptor extends PlatformObject implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String name;
+
+ private final String username;
+
+ private final String password;
+
+ private final String domain;
+
+ /**
+ * The {@link JMXServiceURL} of the JMX server
+ */
+ private final JMXServiceURL jmxServiceUrl;
+
+ /**
+ * Constructor that creates a {@link JMXServiceURL} connection description
+ * using a preexisting {@code JMXServiceURL} instance.
+ *
+ * @param name
+ * the name for this connection descriptor
+ * @param url
+ * the {@code JMXServiceURL} to use
+ * @param username
+ * the username or null if authentication is not necessary
+ * @param password
+ * the password or null if authentication is not necessary
+ * @param domain
+ * the JMX domain used in {@code url}
+ */
+ public JMXServiceDescriptor(
+ final String name,
+ final JMXServiceURL url,
+ final String username,
+ final String password,
+ final String domain)
+ {
+ this.name = name;
+ this.username = username;
+ this.password = password;
+ this.domain = domain;
+
+ this.jmxServiceUrl = url;
+ }
+
+ /**
+ * Constructor that creates a {@link JMXServiceURL} connection description
+ * using a String URL as the primary means of connecting.
+ *
+ * @param name
+ * the name for this connection descriptor
+ * @param url
+ * a URL to the MBeanServer, similar to {@code
+ * service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi}
+ * @param username
+ * the username or null if authentication is not necessary
+ * @param password
+ * the password or null if authentication is not necessary
+ * @param domain
+ * the JMX domain to use
+ * @throws MalformedURLException if the given string URL is not well formed
+ */
+ public JMXServiceDescriptor(
+ final String name,
+ final String url,
+ final String username,
+ final String password,
+ final String domain) throws MalformedURLException
+ {
+ this(name, new JMXServiceURL(url), username, password, domain);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public JMXServiceURL getUrl() {
+ return jmxServiceUrl;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getDomain() {
+ return domain;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (domain == null ? 0 : domain.hashCode());
+ result = prime * result + (jmxServiceUrl == null ? 0 : jmxServiceUrl.hashCode());
+ result = prime * result + (name == null ? 0 : name.hashCode());
+ result = prime * result + (password == null ? 0 : password.hashCode());
+ result = prime * result + (username == null ? 0 : username.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+
+ final JMXServiceDescriptor other = (JMXServiceDescriptor) obj;
+ if (domain == null) {
+ if (other.domain != null) {
+ return false;
+ }
+ } else if (!domain.equals(other.domain)) {
+ return false;
+ }
+
+ if (jmxServiceUrl == null) {
+ if (other.jmxServiceUrl != null) {
+ return false;
+ }
+ } else if (!jmxServiceUrl.equals(other.jmxServiceUrl)) {
+ return false;
+ }
+
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+
+ if (password == null) {
+ if (other.password != null) {
+ return false;
+ }
+ } else if (!password.equals(other.password)) {
+ return false;
+ }
+
+ if (username == null) {
+ if (other.username != null) {
+ return false;
+ }
+ } else if (!username.equals(other.username)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return name + "[" + username + "@" + jmxServiceUrl.toString() + "]";
+ }
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/LocalJMXServiceDescriptor.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/LocalJMXServiceDescriptor.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/LocalJMXServiceDescriptor.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/LocalJMXServiceDescriptor.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,115 @@
+/**
+ * Copyright (c) 2011 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.jmx;
+
+import info.evanchik.eclipse.karaf.core.KarafPlatformModel;
+
+import java.net.MalformedURLException;
+
+import javax.management.remote.JMXServiceURL;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class LocalJMXServiceDescriptor extends JMXServiceDescriptor {
+
+ private static final long serialVersionUID = 1L;
+
+ private final KarafPlatformModel karafPlatformModel;
+
+ /**
+ * @param name
+ * @param karafPlatformModel
+ * @param url
+ * @param username
+ * @param password
+ * @param domain
+ */
+ public LocalJMXServiceDescriptor(
+ final String name,
+ final KarafPlatformModel karafPlatformModel,
+ final JMXServiceURL url,
+ final String username,
+ final String password,
+ final String domain)
+ {
+ super(name, url, username, password, domain);
+
+ this.karafPlatformModel = karafPlatformModel;
+ }
+
+ /**
+ * @param name
+ * @param karafPlatformModel
+ * @param url
+ * @param username
+ * @param password
+ * @param domain
+ * @throws MalformedURLException
+ */
+ public LocalJMXServiceDescriptor(
+ final String name,
+ final KarafPlatformModel karafPlatformModel,
+ final String url,
+ final String username,
+ final String password,
+ final String domain)
+ throws MalformedURLException
+ {
+ super(name, url, username, password, domain);
+
+ this.karafPlatformModel = karafPlatformModel;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!super.equals(obj)) {
+ return false;
+ }
+
+ if (!(obj instanceof LocalJMXServiceDescriptor)) {
+ return false;
+ }
+
+ final LocalJMXServiceDescriptor other = (LocalJMXServiceDescriptor) obj;
+ if (karafPlatformModel == null) {
+ if (other.karafPlatformModel != null) {
+ return false;
+ }
+ } else if (!karafPlatformModel.equals(other.karafPlatformModel)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public Object getAdapter(@SuppressWarnings("rawtypes") final Class adapter) {
+ if (KarafPlatformModel.class.equals(adapter)) {
+ return karafPlatformModel;
+ }
+
+ return super.getAdapter(adapter);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + (karafPlatformModel == null ? 0 : karafPlatformModel.hashCode());
+ return result;
+ }
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/internal/JMXServiceManager.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/internal/JMXServiceManager.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/internal/JMXServiceManager.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/internal/JMXServiceManager.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2009 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.jmx.internal;
+
+import info.evanchik.eclipse.karaf.workbench.internal.AbstractWorkbenchServiceManager;
+import info.evanchik.eclipse.karaf.workbench.jmx.JMXServiceDescriptor;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class JMXServiceManager extends AbstractWorkbenchServiceManager<JMXServiceDescriptor>{
+
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/internal/JMXTransportRegistry.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/internal/JMXTransportRegistry.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/internal/JMXTransportRegistry.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/internal/JMXTransportRegistry.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,228 @@
+/**
+ * Copyright (c) 2009 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.jmx.internal;
+
+import info.evanchik.eclipse.karaf.workbench.KarafWorkbenchActivator;
+import info.evanchik.eclipse.karaf.workbench.jmx.IJMXTransportListener;
+import info.evanchik.eclipse.karaf.workbench.jmx.IJMXTransportRegistry;
+import info.evanchik.eclipse.karaf.workbench.jmx.JMXServiceDescriptor;
+
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorProvider;
+import javax.management.remote.JMXServiceURL;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.ISafeRunnable;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.ListenerList;
+import org.eclipse.core.runtime.RegistryFactory;
+import org.eclipse.core.runtime.SafeRunner;
+import org.eclipse.core.runtime.Status;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class JMXTransportRegistry implements IJMXTransportRegistry {
+
+ private final Map<String, JMXConnectorProvider> transports;
+
+ protected final ListenerList jmxTransportListeners;
+
+ private static enum EventType {
+ ADDED,
+ REMOVED;
+ }
+
+ private class JMXTransportNotifier implements ISafeRunnable {
+
+ private EventType event;
+
+ private IJMXTransportListener listener;
+
+ private JMXConnectorProvider jmxConnectorProvider;
+
+ public JMXTransportNotifier() {
+ // Intentionally left blank
+ }
+
+ @Override
+ public void handleException(Throwable exception) {
+ final IStatus status =
+ new Status(
+ IStatus.ERROR,
+ KarafWorkbenchActivator.PLUGIN_ID,
+ 120,
+ "An exception occurred during breakpoint change notification.", exception); //$NON-NLS-1$
+ KarafWorkbenchActivator.getDefault().getLog().log(status);
+ }
+
+ @Override
+ public void run() throws Exception {
+ switch (event) {
+ case ADDED:
+ listener.serviceAdded(jmxConnectorProvider);
+ break;
+ case REMOVED:
+ listener.serviceRemoved(jmxConnectorProvider);
+ break;
+ }
+ }
+
+ /**
+ * Notifies the listeners of the add/remove
+ *
+ * @param jmxConnectorProviders
+ * the {@link JMXConnectorProvider}s that changed
+ * @param event
+ * the type of change
+ */
+ public void notify(List<JMXConnectorProvider> jmxConnectorProviders, EventType e) {
+ this.event = e;
+
+ Object[] copiedListeners = jmxTransportListeners.getListeners();
+ for (int i= 0; i < copiedListeners.length; i++) {
+ listener = (IJMXTransportListener)copiedListeners[i];
+ for(JMXConnectorProvider connector : jmxConnectorProviders) {
+ jmxConnectorProvider = connector;
+ SafeRunner.run(this);
+ }
+ }
+
+ listener = null;
+ jmxConnectorProvider = null;
+ }
+ }
+
+ public JMXTransportRegistry() {
+ transports = Collections.synchronizedMap(new HashMap<String, JMXConnectorProvider>());
+ jmxTransportListeners = new ListenerList();
+ }
+
+ @Override
+ public void addJMXTransportListener(IJMXTransportListener listener) {
+ jmxTransportListeners.add(listener);
+ }
+
+ @Override
+ public Set<String> getConnectorNames() {
+ return Collections.unmodifiableSet(transports.keySet());
+ }
+
+ @Override
+ public JMXConnectorProvider getConnectorProvider(String key) {
+ final JMXConnectorProvider connector = transports.get(key);
+
+ // TODO: Add logging
+
+ return connector;
+ }
+
+ @Override
+ public JMXConnector getJMXConnector(JMXServiceDescriptor serviceDescriptor) {
+ try {
+ final String transport = serviceDescriptor.getUrl().getProtocol();
+
+ final JMXConnectorProvider connectorProvider = getConnectorProvider(transport);
+
+ final JMXServiceURL url = getJMXServiceURL(
+ serviceDescriptor.getUrl().getHost(),
+ serviceDescriptor.getUrl().getPort(),
+ serviceDescriptor.getUrl().getProtocol(),
+ serviceDescriptor.getDomain());
+
+ Map<String, Object> environment = null;
+ if (serviceDescriptor.getUsername() != null) {
+ environment = new HashMap<String, Object>();
+ String[] credentials = new String[] {
+ serviceDescriptor.getUsername(),
+ serviceDescriptor.getPassword()
+ };
+ environment.put(JMXConnector.CREDENTIALS, credentials);
+ }
+
+ return connectorProvider.newJMXConnector(url, environment);
+ } catch (Exception e) {
+ KarafWorkbenchActivator.getLogger().error(e.getMessage(), e);
+ return null;
+ }
+ }
+
+ @Override
+ public void removeJMXTransportListner(IJMXTransportListener listener) {
+ jmxTransportListeners.remove(listener);
+ }
+
+ private JMXTransportNotifier getJMXTransportrNotifier() {
+ return new JMXTransportNotifier();
+ }
+
+ @Override
+ public void loadTransportExtensions() {
+ final IExtensionPoint point =
+ RegistryFactory.getRegistry().getExtensionPoint(
+ KarafWorkbenchActivator.PLUGIN_ID,
+ KarafWorkbenchActivator.JMX_CONNECTOR_PROVIDER_EXTENSION_ID);
+
+ final IExtension[] types = point.getExtensions();
+
+ for (int i = 0; i < types.length; i++) {
+ loadTransportConfigurationElements(types[i].getConfigurationElements());
+ }
+ }
+
+ private void loadTransportConfigurationElements(IConfigurationElement[] configElems) {
+ for (int j = 0; j < configElems.length; j++) {
+ final IConfigurationElement element = configElems[j];
+ final String elementName = element.getName();
+ String transport;
+ if (elementName.equals("transport") //$NON-NLS-1$
+ && null != element.getAttribute("class") //$NON-NLS-1$
+ && null != (transport = element.getAttribute("protocol"))) //$NON-NLS-1$
+ {
+ try {
+ Object obj = element.createExecutableExtension("class"); //$NON-NLS-1$
+ if (obj instanceof JMXConnectorProvider) {
+ transports.put(transport, (JMXConnectorProvider)obj);
+ }
+ } catch (CoreException e) {
+ KarafWorkbenchActivator.getLogger().error(e.getMessage(), e);
+ }
+ }
+ }
+
+ final List<JMXConnectorProvider> transportsAdded = new ArrayList<JMXConnectorProvider>();
+ transportsAdded.addAll(transports.values());
+
+ getJMXTransportrNotifier().notify(transportsAdded, EventType.ADDED);
+ }
+
+ private static JMXServiceURL getJMXServiceURL(
+ String host,
+ int port,
+ String protocol,
+ String domain)
+ throws MalformedURLException
+ {
+ return new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + host + ":" + port + "/" + domain);
+ }
+}
Added: karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/internal/RMIConnectionProvider.java
URL: http://svn.apache.org/viewvc/karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/internal/RMIConnectionProvider.java?rev=1227144&view=auto
==============================================================================
--- karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/internal/RMIConnectionProvider.java (added)
+++ karaf/eik/trunk/plugins/info.evanchik.eclipse.karaf.workbench/src/main/java/info/evanchik/eclipse/karaf/workbench/jmx/internal/RMIConnectionProvider.java Wed Jan 4 13:22:10 2012
@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2010 Stephen Evanchik
+ * 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:
+ * Stephen Evanchik - initial implementation
+ */
+package info.evanchik.eclipse.karaf.workbench.jmx.internal;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorProvider;
+import javax.management.remote.JMXServiceURL;
+
+/**
+ * @author Stephen Evanchik (evanchsa@gmail.com)
+ *
+ */
+public class RMIConnectionProvider implements JMXConnectorProvider {
+
+ @Override
+ public JMXConnector newJMXConnector(JMXServiceURL serviceURL, Map<String, ?> environment)
+ throws IOException
+ {
+ return JMXConnectorFactory.newJMXConnector(serviceURL, environment);
+ }
+}