org.parallelj.launching.transport.jmx.DynamicLegacyProgram.java Source code

Java tutorial

Introduction

Here is the source code for org.parallelj.launching.transport.jmx.DynamicLegacyProgram.java

Source

/*
 *     ParallelJ, framework for parallel computing
 *
 *     Copyright (C) 2010, 2011, 2012 Atos Worldline or third-party contributors as
 *     indicated by the @author tags or express copyright attribution
 *     statements applied by the authors.
 *
 *     This library is free software; you can redistribute it and/or
 *     modify it under the terms of the GNU Lesser General Public
 *     License as published by the Free Software Foundation; either
 *     version 2.1 of the License.
 *
 *     This library 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
 *     Lesser General Public License for more details.
 *
 *     You should have received a copy of the GNU Lesser General Public
 *     License along with this library; if not, write to the Free Software
 *     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */
package org.parallelj.launching.transport.jmx;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.ReflectionException;

import org.apache.commons.lang3.ArrayUtils;
import org.parallelj.launching.Launch;
import org.parallelj.launching.LaunchException;
import org.parallelj.launching.Launcher;
import org.parallelj.launching.LaunchingMessageKind;
import org.parallelj.launching.inout.Argument;
import org.parallelj.launching.parser.NopParser;
import org.parallelj.launching.remote.RemoteProgram;

/**
 * Dynamic MBean to register a Program as a MBean
 * 
 */
public class DynamicLegacyProgram implements DynamicMBean {
    /**
     * The adapter class
     */
    private RemoteProgram remoteProgram;

    private JmxCommand[] cmds;
    private MBeanOperationInfo[] operations;

    /**
     * Default constructor
     * 
     * @param adapterClass
     *            the Program's adapter type
     * @param adapterArgs
     */
    public DynamicLegacyProgram(RemoteProgram remoteProgram) {
        this.remoteProgram = remoteProgram;

        // Get all available Commands
        this.cmds = JmxCommands.getCommands().values().toArray(new JmxCommand[] {});
        Arrays.sort(this.cmds);

        this.operations = new MBeanOperationInfo[this.cmds.length];
        int opIndex = 0;
        for (JmxCommand cmd : this.cmds) {
            final List<MBeanParameterInfo> parameters = new ArrayList<MBeanParameterInfo>();
            for (JmxOption option : JmxOptions.getOptions()) {
                // Options "id" and "args" doesn't have to be shown using Jmx
                final MBeanParameterInfo param = new MBeanParameterInfo(option.getName(), "java.lang.String",
                        option.getDescription());
                parameters.add(param);
            }
            final MBeanOperationInfo operation = new MBeanOperationInfo(cmd.getType(), cmd.getUsage(),
                    ArrayUtils.addAll(parameters.toArray(new MBeanParameterInfo[] {}), createMBeanParameterInfos()),
                    "java.lang.String", MBeanOperationInfo.INFO);
            operations[opIndex++] = operation;
        }
    }

    /**
     * Initialize the JobDataMap with the Program arguments
     * 
     * @param job
     *            The JobDetail for the JobDataMap initialization
     * @param params
     *            The parameters Objects for the Program
     * @param signature
     *            The parameters type
     * @throws MBeanException
     *             If an error appends when initializing the JobDataMap
     */
    protected Map<String, Object> buildJobDataMap(final JmxCommand jmxCommand, final Object[] params)
            throws MBeanException {
        final Map<String, Object> jobDataMap = new HashMap<String, Object>();

        try {
            int ind = 0;

            // Options are before the AdapterArguments
            for (JmxOption option : JmxOptions.getOptions()) {
                option.process(jobDataMap, String.valueOf(params[ind++]));
            }

            for (Argument arg : this.remoteProgram.getArguments()) {
                arg.setValueUsingParser(String.valueOf(params[ind++]));
            }
        } catch (Exception e) {
            throw new MBeanException(e);
        }
        return jobDataMap;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.management.DynamicMBean#invoke(java.lang.String,
     * java.lang.Object[], java.lang.String[])
     */
    @Override
    public final Object invoke(final String actionName, final Object[] params, final String[] signature)
            throws MBeanException, ReflectionException {
        // Get the JmxCommand
        JmxCommand curCmd = null;
        for (JmxCommand cmd : this.cmds) {
            if (cmd.getType().equals(actionName)) {
                curCmd = cmd;
                break;
            }
        }

        final boolean isSync = actionName.startsWith("sync");
        try {
            // initialize arguments for lunching (using Quartz)
            final Map<String, Object> jobDataMap = buildJobDataMap(curCmd, params);

            final Launch<?> launch = Launcher.getLauncher().newLaunch((Class<?>) remoteProgram.getAdapterClass())
                    .addParameters(jobDataMap);
            if (isSync) {
                // Launch and wait until terminated
                launch.synchLaunch();
                return LaunchingMessageKind.ILAUNCH0003.getFormatedMessage(
                        remoteProgram.getAdapterClass().getCanonicalName(), launch.getLaunchId(),
                        launch.getLaunchResult().getStatusCode(), launch.getLaunchResult().getReturnCode());
            } else {
                // Launch and continue
                launch.aSynchLaunch();
                return LaunchingMessageKind.ILAUNCH0002.getFormatedMessage(
                        remoteProgram.getAdapterClass().getCanonicalName(), launch.getLaunchId());
            }
        } catch (LaunchException e) {
            LaunchingMessageKind.ELAUNCH0003.format(actionName, e);
        }

        return null;
    }

    /**
     * Generate the available methods description for each Program registered as
     * a MBean with this dynamic MBean
     * 
     * @return an array of MBeanOperationInfo
     */
    private MBeanOperationInfo[] createMBeanOperationInfo() {
        return this.operations;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.management.DynamicMBean#getMBeanInfo()
     */
    @Override
    public final MBeanInfo getMBeanInfo() {
        final MBeanOperationInfo[] opers = createMBeanOperationInfo();
        return new MBeanInfo(remoteProgram.getAdapterClass().getCanonicalName(), null, null, null, opers, null);
    }

    /**
     * Generate MBean parameter info for all Program field annotated with @In
     * 
     * @return an array of MBeanParameterInfo
     */
    private MBeanParameterInfo[] createMBeanParameterInfos() {
        final int lenght = this.remoteProgram.getArguments() != null ? this.remoteProgram.getArguments().size() : 0;
        int cpt = 0;
        MBeanParameterInfo[] result = new MBeanParameterInfo[lenght];
        if (this.remoteProgram.getArguments() != null) {
            for (Argument arg : this.remoteProgram.getArguments()) {
                // Only simple Type are authorized for JMX
                String type = null;

                String descriptionWithParserFormat = "Parser  '%s' will be used to set this parameter as it is defined in @In annotation for this field.";
                String descriptionWithoutParserFormat = "No parser will be used for this field as it is a primitive one.";
                String descriptionValueValue = descriptionWithoutParserFormat;
                if (!arg.getParser().getCanonicalName().equals(NopParser.class.getCanonicalName())) {
                    descriptionValueValue = String.format(descriptionWithParserFormat,
                            arg.getParser().getCanonicalName());
                }
                if (!arg.getType().equals(String.class) && !arg.getType().equals(int.class)
                        && !arg.getType().equals(long.class) && !arg.getType().equals(boolean.class)) {
                    type = String.class.getCanonicalName();
                } else {
                    type = arg.getType().getCanonicalName();
                }

                result[cpt++] = new MBeanParameterInfo(arg.getName(), type, descriptionValueValue);
            }
        }
        return result;
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.management.DynamicMBean#getAttribute(java.lang.String)
     */
    @Override
    public final Object getAttribute(final String attribute)
            throws AttributeNotFoundException, MBeanException, ReflectionException {
        // Do Nothing
        return null;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * javax.management.DynamicMBean#setAttribute(javax.management.Attribute)
     */
    @Override
    public void setAttribute(final Attribute attribute)
            throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
        // Do Nothing
    }

    /*
     * (non-Javadoc)
     * 
     * @see javax.management.DynamicMBean#getAttributes(java.lang.String[])
     */
    @Override
    public final AttributeList getAttributes(final String[] attributes) {
        return new AttributeList();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * javax.management.DynamicMBean#setAttributes(javax.management.AttributeList
     * )
     */
    @Override
    public final AttributeList setAttributes(final AttributeList attributes) {
        return new AttributeList();
    }
}