/* * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package com.sun.tools.jconsole;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import java.util.ArrayList;import java.util.List;import javax.swing.JPanel;import javax.swing.SwingWorker;/** * A JConsole plugin class. JConsole uses the * <a href="{@docRoot}/../../../../api/java/util/ServiceLoader.html"> * service provider</a> mechanism to search the JConsole plugins. * Users can provide their JConsole plugins in a jar file * containing a file named * * <blockquote><pre> * META-INF/services/com.sun.tools.jconsole.JConsolePlugin</pre></blockquote> * * <p> This file contains one line for each plugin, for example, * * <blockquote><pre> * com.sun.example.JTop</pre></blockquote> * <p> which is the fully qualified class name of the class implementing * {@code JConsolePlugin}. * * <p> To load the JConsole plugins in JConsole, run: * * <blockquote><pre> * jconsole -pluginpath <plugin-path> </pre></blockquote> * * <p> where <tt><plugin-path></tt> specifies the paths of JConsole * plugins to look up which can be a directory or a jar file. Multiple * paths are separated by the path separator character of the platform. * * <p> When a new JConsole window is created for a connection, * an instance of each {@code JConsolePlugin} will be created. * The {@code JConsoleContext} object is not available at its * construction time. * JConsole will set the {@link JConsoleContext} object for * a plugin after the plugin object is created. It will then * call its {@link #getTabs getTabs} method and add the returned * tabs to the JConsole window. * * @see <a href="{@docRoot}/../../../../api/java/util/ServiceLoader.html"> * java.util.ServiceLoader</a> * * @since 1.6 */public abstract class JConsolePlugin { private volatile JConsoleContext context = null; private List<PropertyChangeListener> listeners = null; /** * Constructor. */ protected JConsolePlugin() { } /** * Sets the {@link JConsoleContext JConsoleContext} object representing * the connection to an application. This method will be called * only once after the plugin is created and before the {@link #getTabs} * is called. The given {@code context} can be in any * {@link JConsoleContext#getConnectionState connection state} when * this method is called. * * @param context a {@code JConsoleContext} object */ public final synchronized void setContext(JConsoleContext context) { this.context = context; if (listeners != null) { for (PropertyChangeListener l : listeners) { context.addPropertyChangeListener(l); } // throw away the listener list listeners = null; } } /** * Returns the {@link JConsoleContext JConsoleContext} object representing * the connection to an application. This method may return <tt>null</tt> * if it is called before the {@link #setContext context} is initialized. * * @return the {@link JConsoleContext JConsoleContext} object representing * the connection to an application. */ public final JConsoleContext getContext() { return context; } /** * Returns the tabs to be added in JConsole window. * <p> * The returned map contains one entry for each tab * to be added in the tabbed pane in a JConsole window with * the tab name as the key * and the {@link JPanel} object as the value. * This method returns an empty map if no tab is added by this plugin. * This method will be called from the <i>Event Dispatch Thread</i> * once at the new connection time. * * @return a map of a tab name and a {@link JPanel} object * representing the tabs to be added in the JConsole window; * or an empty map. */ public abstract java.util.Map<String, JPanel> getTabs(); /** * Returns a {@link SwingWorker} to perform * the GUI update for this plugin at the same interval * as JConsole updates the GUI. * <p> * JConsole schedules the GUI update at an interval specified * for a connection. This method will be called at every * update to obtain a {@code SwingWorker} for each plugin. * <p> * JConsole will invoke the {@link SwingWorker#execute execute()} * method to schedule the returned {@code SwingWorker} for execution * if: * <ul> * <li> the <tt>SwingWorker</tt> object has not been executed * (i.e. the {@link SwingWorker#getState} method * returns {@link javax.swing.SwingWorker.StateValue#PENDING PENDING} * state); and</li> * <li> the <tt>SwingWorker</tt> object returned in the previous * update has completed the task if it was not <tt>null</tt> * (i.e. the {@link SwingWorker#isDone SwingWorker.isDone} method * returns <tt>true</tt>).</li> * </ul> * <br> * Otherwise, <tt>SwingWorker</tt> object will not be scheduled to work. * * <p> * A plugin can schedule its own GUI update and this method * will return <tt>null</tt>. * * @return a <tt>SwingWorker</tt> to perform the GUI update; or * <tt>null</tt>. */ public abstract SwingWorker<?,?> newSwingWorker(); /** * Dispose this plugin. This method is called by JConsole to inform * that this plugin will be discarded and that it should free * any resources that it has allocated. * The {@link #getContext JConsoleContext} can be in any * {@link JConsoleContext#getConnectionState connection state} when * this method is called. */ public void dispose() { // Default nop implementation } /** * Adds a {@link PropertyChangeListener PropertyChangeListener} * to the {@link #getContext JConsoleContext} object for this plugin. * This method is a convenient method for this plugin to register * a listener when the {@code JConsoleContext} object may or * may not be available. * * <p>For example, a plugin constructor can * call this method to register a listener to listen to the * {@link JConsoleContext.ConnectionState connectionState} * property changes and the listener will be added to the * {@link JConsoleContext#addPropertyChangeListener JConsoleContext} * object when it is available. * * @param listener The {@code PropertyChangeListener} to be added * * @throws NullPointerException if {@code listener} is {@code null}. */ public final void addContextPropertyChangeListener(PropertyChangeListener listener) { if (listener == null) { throw new NullPointerException("listener is null"); } if (context == null) { // defer registration of the listener until setContext() is called synchronized (this) { // check again if context is not set if (context == null) { // maintain a listener list to be added later if (listeners == null) { listeners = new ArrayList<PropertyChangeListener>(); } listeners.add(listener); return; } } } context.addPropertyChangeListener(listener); } /** * Removes a {@link PropertyChangeListener PropertyChangeListener} * from the listener list of the {@link #getContext JConsoleContext} * object for this plugin. * If {@code listener} was never added, no exception is * thrown and no action is taken. * * @param listener the {@code PropertyChangeListener} to be removed * * @throws NullPointerException if {@code listener} is {@code null}. */ public final void removeContextPropertyChangeListener(PropertyChangeListener listener) { if (listener == null) { throw new NullPointerException("listener is null"); } if (context == null) { // defer registration of the listener until setContext() is called synchronized (this) { // check again if context is not set if (context == null) { if (listeners != null) { listeners.remove(listener); } return; } } } context.removePropertyChangeListener(listener); }}
/*
* Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.tools.jconsole;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
/**
* A JConsole plugin class. JConsole uses the
* <a href="{@docRoot}/../../../../api/java/util/ServiceLoader.html">
* service provider</a> mechanism to search the JConsole plugins.
* Users can provide their JConsole plugins in a jar file
* containing a file named
*
* <blockquote><pre>
* META-INF/services/com.sun.tools.jconsole.JConsolePlugin</pre></blockquote>
*
* <p> This file contains one line for each plugin, for example,
*
* <blockquote><pre>
* com.sun.example.JTop</pre></blockquote>
* <p> which is the fully qualified class name of the class implementing
* {@code JConsolePlugin}.
*
* <p> To load the JConsole plugins in JConsole, run:
*
* <blockquote><pre>
* jconsole -pluginpath <plugin-path> </pre></blockquote>
*
* <p> where <tt><plugin-path></tt> specifies the paths of JConsole
* plugins to look up which can be a directory or a jar file. Multiple
* paths are separated by the path separator character of the platform.
*
* <p> When a new JConsole window is created for a connection,
* an instance of each {@code JConsolePlugin} will be created.
* The {@code JConsoleContext} object is not available at its
* construction time.
* JConsole will set the {@link JConsoleContext} object for
* a plugin after the plugin object is created. It will then
* call its {@link #getTabs getTabs} method and add the returned
* tabs to the JConsole window.
*
* @see <a href="{@docRoot}/../../../../api/java/util/ServiceLoader.html">
* java.util.ServiceLoader</a>
*
* @since 1.6
*/
public abstract class JConsolePlugin {
private volatile JConsoleContext context = null;
private List<PropertyChangeListener> listeners = null;
/**
* Constructor.
*/
protected JConsolePlugin() {
}
/**
* Sets the {@link JConsoleContext JConsoleContext} object representing
* the connection to an application. This method will be called
* only once after the plugin is created and before the {@link #getTabs}
* is called. The given {@code context} can be in any
* {@link JConsoleContext#getConnectionState connection state} when
* this method is called.
*
* @param context a {@code JConsoleContext} object
*/
public final synchronized void setContext(JConsoleContext context) {
this.context = context;
if (listeners != null) {
for (PropertyChangeListener l : listeners) {
context.addPropertyChangeListener(l);
}
// throw away the listener list
listeners = null;
}
}
/**
* Returns the {@link JConsoleContext JConsoleContext} object representing
* the connection to an application. This method may return <tt>null</tt>
* if it is called before the {@link #setContext context} is initialized.
*
* @return the {@link JConsoleContext JConsoleContext} object representing
* the connection to an application.
*/
public final JConsoleContext getContext() {
return context;
}
/**
* Returns the tabs to be added in JConsole window.
* <p>
* The returned map contains one entry for each tab
* to be added in the tabbed pane in a JConsole window with
* the tab name as the key
* and the {@link JPanel} object as the value.
* This method returns an empty map if no tab is added by this plugin.
* This method will be called from the <i>Event Dispatch Thread</i>
* once at the new connection time.
*
* @return a map of a tab name and a {@link JPanel} object
* representing the tabs to be added in the JConsole window;
* or an empty map.
*/
public abstract java.util.Map<String, JPanel> getTabs();
/**
* Returns a {@link SwingWorker} to perform
* the GUI update for this plugin at the same interval
* as JConsole updates the GUI.
* <p>
* JConsole schedules the GUI update at an interval specified
* for a connection. This method will be called at every
* update to obtain a {@code SwingWorker} for each plugin.
* <p>
* JConsole will invoke the {@link SwingWorker#execute execute()}
* method to schedule the returned {@code SwingWorker} for execution
* if:
* <ul>
* <li> the <tt>SwingWorker</tt> object has not been executed
* (i.e. the {@link SwingWorker#getState} method
* returns {@link javax.swing.SwingWorker.StateValue#PENDING PENDING}
* state); and</li>
* <li> the <tt>SwingWorker</tt> object returned in the previous
* update has completed the task if it was not <tt>null</tt>
* (i.e. the {@link SwingWorker#isDone SwingWorker.isDone} method
* returns <tt>true</tt>).</li>
* </ul>
* <br>
* Otherwise, <tt>SwingWorker</tt> object will not be scheduled to work.
*
* <p>
* A plugin can schedule its own GUI update and this method
* will return <tt>null</tt>.
*
* @return a <tt>SwingWorker</tt> to perform the GUI update; or
* <tt>null</tt>.
*/
public abstract SwingWorker<?,?> newSwingWorker();
/**
* Dispose this plugin. This method is called by JConsole to inform
* that this plugin will be discarded and that it should free
* any resources that it has allocated.
* The {@link #getContext JConsoleContext} can be in any
* {@link JConsoleContext#getConnectionState connection state} when
* this method is called.
*/
public void dispose() {
// Default nop implementation
}
/**
* Adds a {@link PropertyChangeListener PropertyChangeListener}
* to the {@link #getContext JConsoleContext} object for this plugin.
* This method is a convenient method for this plugin to register
* a listener when the {@code JConsoleContext} object may or
* may not be available.
*
* <p>For example, a plugin constructor can
* call this method to register a listener to listen to the
* {@link JConsoleContext.ConnectionState connectionState}
* property changes and the listener will be added to the
* {@link JConsoleContext#addPropertyChangeListener JConsoleContext}
* object when it is available.
*
* @param listener The {@code PropertyChangeListener} to be added
*
* @throws NullPointerException if {@code listener} is {@code null}.
*/
public final void addContextPropertyChangeListener(PropertyChangeListener listener) {
if (listener == null) {
throw new NullPointerException("listener is null");
}
if (context == null) {
// defer registration of the listener until setContext() is called
synchronized (this) {
// check again if context is not set
if (context == null) {
// maintain a listener list to be added later
if (listeners == null) {
listeners = new ArrayList<PropertyChangeListener>();
}
listeners.add(listener);
return;
}
}
}
context.addPropertyChangeListener(listener);
}
/**
* Removes a {@link PropertyChangeListener PropertyChangeListener}
* from the listener list of the {@link #getContext JConsoleContext}
* object for this plugin.
* If {@code listener} was never added, no exception is
* thrown and no action is taken.
*
* @param listener the {@code PropertyChangeListener} to be removed
*
* @throws NullPointerException if {@code listener} is {@code null}.
*/
public final void removeContextPropertyChangeListener(PropertyChangeListener listener) {
if (listener == null) {
throw new NullPointerException("listener is null");
}
if (context == null) {
// defer registration of the listener until setContext() is called
synchronized (this) {
// check again if context is not set
if (context == null) {
if (listeners != null) {
listeners.remove(listener);
}
return;
}
}
}
context.removePropertyChangeListener(listener);
}
}