org.jolokia.detector.GlassfishDetector.java Source code

Java tutorial

Introduction

Here is the source code for org.jolokia.detector.GlassfishDetector.java

Source

package org.jolokia.detector;

/*
 * Copyright 2009-2013 Roland Huss
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.management.*;

import org.jolokia.backend.executor.MBeanServerExecutor;
import org.jolokia.config.Configuration;
import org.jolokia.request.JmxRequest;
import org.jolokia.util.LogHandler;
import org.json.simple.JSONObject;

/**
 * Detector for Glassfish servers
 *
 * @author roland
 * @since 04.12.10
 */
public class GlassfishDetector extends AbstractServerDetector {

    private static final Pattern GLASSFISH_VERSION = Pattern.compile("^.*(?:Glassfish|Payara).*\\sv?(.*?)$",
            Pattern.CASE_INSENSITIVE);
    private static final Pattern GLASSFISH_FULL_VERSION = Pattern
            .compile("^.*(?:Glassfish|Payara).*?\\sv?([.\\d]+).*$", Pattern.CASE_INSENSITIVE);

    /** {@inheritDoc}
     * @param pMBeanServerExecutor*/
    public ServerHandle detect(MBeanServerExecutor pMBeanServerExecutor) {
        String version = detectVersion(pMBeanServerExecutor);
        if (version != null) {
            return new GlassfishServerHandle(version, new HashMap<String, String>());
        } else {
            return null;
        }
    }

    private String detectVersion(MBeanServerExecutor pMBeanServerExecutor) {
        String fullVersion = getSingleStringAttribute(pMBeanServerExecutor, "com.sun.appserv:j2eeType=J2EEServer,*",
                "serverVersion");
        String version = extractVersionFromFullVersion(fullVersion);
        if (fullVersion == null || "3".equals(version)) {
            String versionFromAmx = getSingleStringAttribute(pMBeanServerExecutor, "amx:type=domain-root,*",
                    "ApplicationServerFullVersion");
            version = getVersionFromFullVersion(version,
                    versionFromAmx != null ? versionFromAmx : System.getProperty("glassfish.version"));
        } else if (mBeanExists(pMBeanServerExecutor, "com.sun.appserver:type=Host,*")) {
            // Last desperate try to get hold of Glassfish MBean
            version = "3";
        }
        return version;
    }

    private String extractVersionFromFullVersion(String pFullVersion) {
        if (pFullVersion != null) {
            Matcher matcher = GLASSFISH_VERSION.matcher(pFullVersion);
            if (matcher.matches()) {
                return matcher.group(1);
            }
        }
        return null;
    }

    private boolean isAmxBooted(MBeanServerExecutor pServerManager) {
        return mBeanExists(pServerManager, "amx:type=domain-root,*");
    }

    // Return true if AMX could be booted, false otherwise
    private synchronized boolean bootAmx(MBeanServerExecutor pServers, final LogHandler pLoghandler) {
        ObjectName bootMBean = null;
        try {
            bootMBean = new ObjectName("amx-support:type=boot-amx");
        } catch (MalformedObjectNameException e) {
            // Cannot happen ....
        }
        try {
            pServers.call(bootMBean, new MBeanServerExecutor.MBeanAction<Void>() {
                /** {@inheritDoc} */
                public Void execute(MBeanServerConnection pConn, ObjectName pName, Object... extraArgs)
                        throws ReflectionException, InstanceNotFoundException, IOException, MBeanException {
                    pConn.invoke(pName, "bootAMX", null, null);
                    return null;
                }
            });
            return true;
        } catch (InstanceNotFoundException e) {
            pLoghandler.error("No bootAmx MBean found: " + e, e);
            // Can happen, when a call to bootAmx comes to early before the bean
            // is registered
            return false;
        } catch (IllegalArgumentException e) {
            pLoghandler.error("Exception while booting AMX: " + e, e);
            // We dont try it again
            return true;
        } catch (Exception e) {
            pLoghandler.error("Exception while executing bootAmx: " + e, e);
            // dito
            return true;
        }
    }

    private String getVersionFromFullVersion(String pOriginalVersion, String pFullVersion) {
        if (pFullVersion == null) {
            return pOriginalVersion;
        }
        Matcher v3Matcher = GLASSFISH_FULL_VERSION.matcher(pFullVersion);
        if (v3Matcher.matches()) {
            return v3Matcher.group(1);
        } else {
            return pOriginalVersion;
        }
    }

    private class GlassfishServerHandle extends ServerHandle {
        private boolean amxShouldBeBooted = false;
        private LogHandler logHandler;

        /**
         * Server handle for a glassfish server
         *
         * @param version Glassfish version
         * @param extraInfo extra infos
         */
        public GlassfishServerHandle(String version, Map<String, String> extraInfo) {
            super("Oracle", "glassfish", version, extraInfo);
        }

        @Override
        /** {@inheritDoc} */
        public Map<String, String> getExtraInfo(MBeanServerExecutor pServerManager) {
            Map<String, String> extra = super.getExtraInfo(pServerManager);
            if (pServerManager != null && extra != null && getVersion().startsWith("3")) {
                extra.put("amxBooted", Boolean.toString(isAmxBooted(pServerManager)));
            }
            return extra;
        }

        @Override
        /** {@inheritDoc} */
        public void preDispatch(MBeanServerExecutor pMBeanServerExecutor, JmxRequest pJmxReq) {
            if (amxShouldBeBooted) {
                // Clear flag only of bootAMX succeed or fails with an unrecoverable error
                amxShouldBeBooted = !bootAmx(pMBeanServerExecutor, logHandler);
            }
        }

        @Override
        /** {@inheritDoc} */
        public void postDetect(MBeanServerExecutor pServerManager, Configuration pConfig, LogHandler pLoghandler) {
            JSONObject opts = getDetectorOptions(pConfig, pLoghandler);
            amxShouldBeBooted = (opts == null || opts.get("bootAmx") == null || (Boolean) opts.get("bootAmx"))
                    && !isAmxBooted(pServerManager);
            logHandler = pLoghandler;
        }
    }

}