org.fusesource.cloudmix.agent.mop.MopProcess.java Source code

Java tutorial

Introduction

Here is the source code for org.fusesource.cloudmix.agent.mop.MopProcess.java

Source

/**************************************************************************************
 * Copyright (C) 2009 Progress Software, Inc. All rights reserved.                    *
 * http://fusesource.com                                                              *
 * ---------------------------------------------------------------------------------- *
 * The software in this package is published under the terms of the AGPL license      *
 * a copy of which has been included with this distribution in the license.txt file.  *
 **************************************************************************************/
package org.fusesource.cloudmix.agent.mop;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean;

import com.google.common.collect.Lists;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.fusesource.cloudmix.common.GridClient;
import org.fusesource.cloudmix.common.dto.ProvisioningAction;
import org.fusesource.cloudmix.common.util.FileUtils;
import org.fusesource.cloudmix.common.util.Strings;
import org.fusesource.mop.MOP;
import org.fusesource.mop.ProcessRunner;

/**
 * @version $Revision: 1.1 $
 */
public class MopProcess {
    private static final transient Log LOG = LogFactory.getLog(MopProcess.class);

    private MopAgent mopAgent;
    private ProvisioningAction action;
    private String credentials;
    private String commandLine;
    private ClassLoader mopClassLoader;
    private MOP mop = new MOP();
    private int statusCode = -1;
    private Thread thread;
    private AtomicBoolean completed = new AtomicBoolean(false);
    private File workDirectory;
    private String featureId;

    public MopProcess(MopAgent mopAgent, ProvisioningAction action, String credentials, String commandLine,
            ClassLoader mopClassLoader) {
        this.mopAgent = mopAgent;
        this.action = action;
        this.featureId = action.getFeature();
        this.credentials = credentials;
        this.commandLine = commandLine;
        this.mopClassLoader = mopClassLoader;
        this.workDirectory = mopAgent.createProcessDirectory(action);
    }

    public String getFeatureId() {
        return featureId;
    }

    public String getId() {
        return action.getFeature();
    }

    public ProvisioningAction getAction() {
        return action;
    }

    public String getCommandLine() {
        return commandLine;
    }

    public String getCredentials() {
        return credentials;
    }

    public File getWorkDirectory() {
        return workDirectory;
    }

    public void start() throws Exception {
        final List<String> argList = Lists.newArrayList();
        if (commandLine != null) {
            StringTokenizer iter = new StringTokenizer(commandLine);
            while (iter.hasMoreTokens()) {
                argList.add(iter.nextToken());
            }
        }
        if (argList.isEmpty()) {
            throw new IllegalArgumentException("No arguments specified");
        }

        // Propagate the profile properties to the forked process...
        String profile = mopAgent.getProfileFor(action);
        if (profile == null) {
            LOG.warn("Could not find profile ID for action " + action);
        } else {
            GridClient gridClient = mopAgent.getClient();
            Properties properties = gridClient.getProperties(profile);
            if (properties == null) {
                LOG.warn("No properties available for profile: " + profile);
            } else {
                for (Entry<Object, Object> entry : properties.entrySet()) {
                    mop.setSystemProperty(Strings.asString(entry.getKey()), Strings.asString(entry.getValue()));
                }
            }
        }

        // Propagate repository props to the forked process:
        for (Entry<String, String> entry : mop.getRepository().getRepositorySystemProps().entrySet()) {
            mop.setSystemProperty(entry.getKey(), entry.getValue());
        }

        // lets ensure the command will spin off to another process:
        if (!(argList.contains("fork") || argList.contains("exec"))) {
            LOG.info("Adding Fork To MopProcess: " + argList);
            argList.add(0, "fork");
        }

        // lets transform the class loader to exclude the parent (to avoid maven & jetty plugin dependencies)
        // lets run in a background thread
        thread = new Thread("Feature: " + getId() + "MOP " + argList) {
            @Override
            public void run() {
                LOG.debug("Using class loader: " + mopClassLoader + " of type: " + mopClassLoader.getClass());
                dumpClassLoader(mopClassLoader);

                File dir = getWorkDirectory();
                FileUtils.createDirectory(dir);
                try {
                    LOG.info("Created working directory " + dir.getCanonicalPath() + " for feature " + getId());
                } catch (IOException e1) {
                    LOG.error("Problem with working directory for " + dir + " for feature " + getId());
                }

                mop.setWorkingDirectory(dir);

                Thread.currentThread().setContextClassLoader(mopClassLoader);

                LOG.info("Starting feature: " + getId() + " via MOP: " + argList);
                String[] args = argList.toArray(new String[argList.size()]);
                try {
                    statusCode = mop.executeAndWait(args);
                    LOG.info("Stopped feature: " + getId() + " with status code: " + statusCode);
                } catch (Exception e) {
                    LOG.error("Failed running feature: " + getId() + ". Reason: " + e, e);
                } finally {
                    clear();
                }
            }
        };
        thread.setContextClassLoader(mopClassLoader);
        thread.start();
    }

    void dumpClassLoader(ClassLoader cl) {
        if (LOG.isDebugEnabled()) {
            if (cl instanceof URLClassLoader) {
                URLClassLoader urlClassLoader = (URLClassLoader) cl;
                URL[] urls = urlClassLoader.getURLs();
                for (URL url : urls) {
                    LOG.debug("ClassLoader URL: " + url);
                }
            }
            ClassLoader parent = cl.getParent();
            if (parent != null) {
                LOG.debug("Parent Class Loader: " + parent);
                dumpClassLoader(parent);
            }
        }
    }

    public void stop() throws Exception {
        if (mop != null) {
            ProcessRunner processRunner = mop.getProcessRunner();
            if (processRunner != null) {
                processRunner.kill();
            }
        }
        clear();
    }

    public boolean isCompleted() {
        return completed.get();
    }

    private void clear() {
        completed.set(true);
        mop = null;
        thread = null;
    }
}