All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.admin.amx.impl.mbean.MBeanImplBase Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * 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));
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy