org.glassfish.admin.amx.impl.mbean.MBeanImplBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of payara-micro Show documentation
Show all versions of payara-micro Show documentation
Micro Distribution of the Payara Project
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 1997-2012 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
// Portions Copyright [2019] Payara Foundation and/or affiliates
package org.glassfish.admin.amx.impl.mbean;
import org.glassfish.admin.amx.util.AMXDebug;
import org.glassfish.admin.amx.util.jmx.AttributeChangeNotificationBuilder;
import org.glassfish.admin.amx.util.jmx.NotificationBuilder;
import org.glassfish.admin.amx.util.jmx.NotificationEmitterSupport;
import org.glassfish.admin.amx.util.jmx.NotificationSender;
import org.glassfish.admin.amx.util.Output;
import org.glassfish.admin.amx.util.StringUtil;
import org.glassfish.admin.amx.util.stringifier.SmartStringifier;
import javax.management.*;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Absolute base impl class. Should contain only core functionality,
* nothing to do with appserver specifics.
*/
public abstract class MBeanImplBase
implements MBeanRegistration, NotificationSender {
protected static final String[] EMPTY_STRING_ARRAY = new String[0];
/**
The MBeanServer in which this object is registered (if any)
*/
protected volatile MBeanServer mServer;
/**
The ObjectName by which this object is registered (if registered).
Multiple registrations, which are possible, overwrite this; the last registration
wins. If the MBean has not been registered, this name will be null.
*/
protected volatile ObjectName mSelfObjectName;
private volatile NotificationEmitterSupport mNotificationEmitter;
private volatile Map mNotificationBuilders;
/**
We need debugging before the MBean is registered, so our
only choice is to use an ID based on something other than
the as-yet-unknown ObjectName, namely the classname.
*/
private final Output mDebug = AMXDebug.getInstance().getOutput(getDebugID());
public MBeanImplBase() {
}
/**
Some subclasses need the MBeanServer set in advance.
*/
public MBeanImplBase(final MBeanServer mbeanServer) {
mServer = mbeanServer;
}
public final int getListenerCount() {
return (getNotificationEmitter().getListenerCount());
}
public final int getNotificationTypeListenerCount(final String type) {
return (getNotificationEmitter().getNotificationTypeListenerCount(type));
}
/**
@return an empty array
Subclass may wish to override this.
*/
protected final synchronized NotificationEmitterSupport getNotificationEmitter() {
if (mNotificationEmitter == null) {
mNotificationEmitter = new NotificationEmitterSupport(true);
}
return (mNotificationEmitter);
}
public synchronized void addNotificationListener(
final NotificationListener listener) {
getNotificationEmitter().addNotificationListener(listener, null, null);
}
public synchronized void addNotificationListener(
final NotificationListener listener,
final NotificationFilter filter,
final Object handback) {
getNotificationEmitter().addNotificationListener(listener, filter, handback);
}
public synchronized void removeNotificationListener(final NotificationListener listener)
throws ListenerNotFoundException {
getNotificationEmitter().removeNotificationListener(listener);
}
public synchronized void removeNotificationListener(
final NotificationListener listener,
final NotificationFilter filter,
final Object handback)
throws ListenerNotFoundException {
getNotificationEmitter().removeNotificationListener(listener, filter, handback);
}
@Override
public void sendNotification(final Notification notification) {
getNotificationEmitter().sendNotification(notification);
}
protected NotificationBuilder createNotificationBuilder(final String notificationType) {
NotificationBuilder builder = null;
if (notificationType.equals(AttributeChangeNotification.ATTRIBUTE_CHANGE)) {
builder = new AttributeChangeNotificationBuilder(getObjectName());
} else {
builder = new NotificationBuilder(notificationType, getObjectName());
}
return (builder);
}
/**
Get a NotificationBuilder for the specified type of Notification
whose source is this object.
*/
protected synchronized NotificationBuilder getNotificationBuilder(final String notificationType) {
if (mNotificationBuilders == null) {
mNotificationBuilders = new HashMap();
}
NotificationBuilder builder = mNotificationBuilders.get(notificationType);
if (builder == null) {
builder = createNotificationBuilder(notificationType);
mNotificationBuilders.put(notificationType, builder);
}
return (builder);
}
/**
Send a Notification of the specified type containing no data.
*/
protected void sendNotification(final String notificationType) {
sendNotification(notificationType, notificationType, null, null);
}
/**
Send a Notification of the specified type containing a single
key/value pair for data.
*/
protected void sendNotification(
final String notificationType,
final String key,
final Serializable value) {
final String message = "no message specified";
sendNotification(notificationType, message, key, value);
}
/**
Send a Notification of the specified type containing a single
key/value pair for data.
*/
protected void sendNotification(
final String notificationType,
final String message,
final String key,
final Serializable value) {
final NotificationBuilder builder =
getNotificationBuilder(notificationType);
final Notification notif = builder.buildNew(message);
NotificationBuilder.putMapData(notif, key, value);
sendNotification(notif);
}
public final ObjectName getObjectName() {
return (mSelfObjectName);
}
public String getJMXDomain() {
return (getObjectName().getDomain());
}
public final MBeanServer getMBeanServer() {
return (mServer);
}
protected static String toString(Object o) {
if (o == null) {
return ("");
}
return (SmartStringifier.toString(o));
}
protected final void trace(Object o) {
debug(o);
}
protected final void logSevere(Object o) {
final String msg = toString(o);
debug(msg);
if (getMBeanLogLevelInt() <= Level.SEVERE.intValue()) {
getMBeanLogger().severe(msg);
}
}
protected final void logWarning(Object o) {
final String msg = toString(o);
debug(msg);
if (getMBeanLogLevelInt() <= Level.WARNING.intValue()) {
getMBeanLogger().warning(msg);
}
}
protected final void logInfo(Object o) {
final String msg = toString(o);
debug(msg);
if (getMBeanLogLevelInt() <= Level.INFO.intValue()) {
getMBeanLogger().info(msg);
}
}
protected final void logFine(Object o) {
final String msg = toString(o);
debug(msg);
if (getMBeanLogLevelInt() <= Level.FINE.intValue()) {
getMBeanLogger().fine(msg);
}
}
protected final void logFiner(Object o) {
final String msg = toString(o);
debug(msg);
if (getMBeanLogLevelInt() <= Level.FINER.intValue()) {
getMBeanLogger().finer(msg);
}
}
protected final void logFinest(Object o) {
final String msg = toString(o);
debug(msg);
if (getMBeanLogLevelInt() <= Level.FINEST.intValue()) {
getMBeanLogger().finest(msg);
}
}
protected final Logger getMBeanLogger() {
return Logger.getLogger("MBeans");
}
protected final Level _getMBeanLogLevel() {
Logger logger = getMBeanLogger();
assert (logger != null);
Level level = logger.getLevel();
while (level == null) {
logger = logger.getParent();
level = logger.getLevel();
}
return (level);
}
public final String getMBeanLogLevel() {
return "" + _getMBeanLogLevel();
}
public final void setMBeanLogLevel(final String level) {
getMBeanLogger().setLevel(Level.parse(level));
}
protected final int getMBeanLogLevelInt() {
return (_getMBeanLogLevel().intValue());
}
public final String getMBeanLoggerName() {
return (getMBeanLogger().getName());
}
protected static String quote(final Object o) {
return (StringUtil.quote("" + o));
}
@Override
public ObjectName preRegister(final MBeanServer server, final ObjectName nameIn) throws Exception {
assert (nameIn != null);
mServer = server;
mSelfObjectName = nameIn;
// ObjectName could still be modified by subclass
return (mSelfObjectName);
}
protected void postRegisterHook(final Boolean registrationSucceeded) {
}
@Override
public final void postRegister(final Boolean registrationSucceeded) {
if (registrationSucceeded) {
getMBeanLogger().log(Level.FINEST, "postRegister: {0}", getObjectName());
} else {
getMBeanLogger().log(Level.FINEST, "postRegister: FAILURE: {0}", getObjectName());
}
postRegisterHook(registrationSucceeded);
}
protected void preDeregisterHook()
throws Exception {
}
@Override
public final void preDeregister()
throws Exception {
getMBeanLogger().log(Level.FINEST, "preDeregister: {0}", getObjectName());
preDeregisterHook();
}
protected void postDeregisterHook() {
}
@Override
public final void postDeregister() {
getMBeanLogger().log(Level.FINEST, "postDeregister: {0}", getObjectName());
postDeregisterHook();
if (mNotificationEmitter != null) {
mNotificationEmitter.cleanup();
mNotificationEmitter = null;
}
if (mNotificationBuilders != null) {
mNotificationBuilders.clear();
mNotificationBuilders = null;
}
// Leave these variables set, they may be desired after unregistration by some subclasses
//mServer = null;
//mSelfObjectName = null;
}
protected String getDebugID() {
return this.getClass().getName();
}
/**
Although unusual, a subclass may override the debug state.
Generally it is faster to NOT call getAMXDebug() before calling
debug( x ) if 'x' is just a string. If it is expensive to
construct 'x', then preflighting with getAMXDebug() may
be worthwhile.
*/
public final boolean getAMXDebug() {
return AMXDebug.getInstance().getDebug(getDebugID());
}
public boolean enableAMXDebug(final boolean enabled) {
final boolean formerValue = getAMXDebug();
if (formerValue != enabled) {
setAMXDebug(enabled);
}
return formerValue;
}
protected Output getDebugOutput() {
return AMXDebug.getInstance().getOutput(getDebugID());
}
public final void setAMXDebug(final boolean debug) {
AMXDebug.getInstance().setDebug(getDebugID(), debug);
}
protected boolean shouldOmitObjectNameForDebug() {
return mSelfObjectName == null;
}
protected final void debug(final Object o) {
if (getAMXDebug() && mDebug != null) {
final String newline = System.getProperty("line.separator");
if (shouldOmitObjectNameForDebug()) {
mDebug.println(o);
} else {
mDebug.println(mSelfObjectName.toString());
mDebug.println("===> " + o);
}
mDebug.println(newline);
}
}
protected void debugMethod(final String methodName, final Object... args) {
if (getAMXDebug()) {
debug(AMXDebug.methodString(methodName, args));
}
}
protected void debugMethod(
final String msg,
final String methodName,
final Object... args) {
if (getAMXDebug()) {
debug(AMXDebug.methodString(methodName, args) + ": " + msg);
}
}
protected void debug(final Object... args) {
if (getAMXDebug()) {
debug(StringUtil.toString("", args));
}
}
}