org.hyperic.hq.product.ClientPluginDeployer.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.product.ClientPluginDeployer.java

Source

/*
 * NOTE: This copyright does *not* cover user programs that use HQ
 * program services by normal system calls through the application
 * program interfaces provided as part of the Hyperic Plug-in Development
 * Kit or the Hyperic Client Development Kit - this is merely considered
 * normal use of the program, and does *not* fall under the heading of
 * "derived work".
 * 
 * Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
 * This file is part of HQ.
 * 
 * HQ is free software; you can redistribute it and/or modify
 * it under the terms version 2 of the GNU General Public License as
 * published by the Free Software Foundation. This program 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 General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 */

package org.hyperic.hq.product;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.agent.AgentConfig;

/**
 * Deployment of embedded plugin files.
 * Plugins can embed scripts, jars, native libraries, etc.
 * This class deploys such files on the agent-side only to
 * pdk/work/$type/$plugin/
 * Where type is "scripts", "lib", etc., plugin is the plugin name.
 * The pdk/$type directory must exist otherwise deployment is skipped.
 */
public class ClientPluginDeployer {

    private static final Log log = LogFactory.getLog(ClientPluginDeployer.class.getName());

    private String plugin;
    private String pdk;

    private static HashMap handlers = new HashMap();

    private static final String[] EX_DIRS = { "scripts", "lib" };

    private static final String[] DIRS = { "tmp" };

    static {
        addHandlers(EX_DIRS, true);
        addHandlers(DIRS, false);
    }

    public ClientPluginDeployer(String pdk, String type) {
        this.pdk = pdk;
        this.plugin = type;
    }

    public static void addHandler(String dir, boolean isExecutable) {
        Handler handler = new Handler(dir);
        handlers.put(handler.getName(), handler);
        handler.setExecutable(isExecutable);
    }

    public static void addHandlers(String[] dirs, boolean isExecutable) {

        for (int i = 0; i < dirs.length; i++) {
            addHandler(dirs[i], isExecutable);
        }
    }

    public Handler getHandler(String name) {
        Handler handler = (Handler) handlers.get(name);
        if (handler != null) {
            return handler;
        }
        //e.g. "script" -> "scripts"
        return (Handler) handlers.get(name + 's');
    }

    public static File getSubDirectory(String root, String name, String plugin) {

        String subdir = "";
        if (!new File(root).getName().equals(AgentConfig.WORK_DIR)) {
            subdir += AgentConfig.WORK_DIR + File.separator;
        }
        subdir += name + File.separator + plugin;

        File dir = new File(root, subdir);

        if (!dir.exists()) {
            if (!dir.mkdirs()) {
                log.error("mkdir(" + dir + ") failed for plugin: " + plugin);
                return null;
            } else {
                log.debug("mkdir(" + dir + ") succeeded for plugin: " + plugin);
            }
        }

        return dir;
    }

    public static class Handler {
        private String name;
        private boolean isExecutable;

        Handler(String name) {
            this.name = name;
        }

        public String getName() {
            return this.name;
        }

        public boolean isExecutable() {
            return this.isExecutable;
        }

        public void setExecutable(boolean value) {
            this.isExecutable = value;
        }

        public File getSubDirectory(ClientPluginDeployer deployer) {
            return ClientPluginDeployer.getSubDirectory(deployer.pdk, this.name, deployer.plugin);
        }
    }

    public List unpackJar(String jar) throws IOException {

        ArrayList jars = new ArrayList();

        ZipFile zipfile = new ZipFile(jar);
        for (Enumeration e = zipfile.entries(); e.hasMoreElements();) {
            ZipEntry entry = (ZipEntry) e.nextElement();
            String name = entry.getName();

            if (entry.isDirectory()) {
                continue;
            }

            int ix = name.indexOf('/');
            if (ix == -1) {
                continue;
            }

            String prefix = name.substring(0, ix);
            name = name.substring(ix + 1);

            File file = getFile(prefix, name);
            if (file == null) {
                continue;
            }

            if (name.endsWith(".jar")) {
                jars.add(file.toString());
            }

            if (upToDate(entry, file)) {
                continue;
            }

            InputStream is = zipfile.getInputStream(entry);
            try {
                write(is, file);
            } catch (IOException ioe) {
                zipfile.close();
                throw ioe;
            } finally {
                is.close();
            }
        }

        zipfile.close();

        return jars;
    }

    public class PluginFile extends File {
        //shutup eclipse warning
        static final long serialVersionUID = 0xff;

        Handler handler;

        public PluginFile(String pathname) {
            super(pathname);
        }

        public PluginFile(File parent, String child) {
            super(parent, child);
        }

        public PluginFile(String parent, String child) {
            super(parent, child);
        }
    }

    public boolean isDeployableType(String type) {
        return getHandler(type) != null;
    }

    public File getFile(String type, String file) {

        Handler handler = getHandler(type);

        if (handler == null) {
            return null;
        }

        File dir = handler.getSubDirectory(this);

        if (dir == null) {
            log.debug("Unable to determine subdirectory to write: " + file);
            return null;
        }

        PluginFile pluginFile = new PluginFile(dir, file);
        pluginFile.handler = handler;
        return pluginFile;
    }

    public boolean upToDate(long source, long target) {
        return source < target;
    }

    public boolean upToDate(ZipEntry source, File target) {
        boolean upToDate = upToDate(source.getTime(), target.lastModified());

        if (upToDate) {
            log.debug("Unchanged file: " + target);
        }

        return upToDate;
    }

    public boolean upToDate(File source, File target) {
        boolean upToDate = upToDate(source.lastModified(), target.lastModified());

        if (upToDate) {
            log.debug("Unchanged file: " + target);
        }

        return upToDate;
    }

    public void write(String data, File file) throws IOException {

        write(new ByteArrayInputStream(data.getBytes()), file);
    }

    public void write(InputStream is, File file) throws IOException {

        if (file == null) {
            return;
        }

        boolean exists = file.exists();
        FileOutputStream os;

        try {
            os = new FileOutputStream(file);
            log.debug((exists ? "Updated" : "Created") + " file: " + file);
        } catch (IOException e) {
            if (file.exists() && (file.length() > 0)) {
                //e.g. on win32, agent running w/ dll loaded
                //PluginDumper cannot overwrite file inuse.
                return;
            } else {
                String msg = "Error writing " + file + ": " + e.getMessage();
                throw new IOException(msg);
            }
        }

        byte[] buffer = new byte[1024];
        int len;
        while ((len = is.read(buffer)) > 0) {
            os.write(buffer, 0, len);
        }
        os.close();

        if (file instanceof PluginFile) {
            Handler handler = ((PluginFile) file).handler;
            if (handler.isExecutable()) {
                chmodx(file);
            }
        }

    }

    public boolean chmod(File file, String mode) {

        if (GenericPlugin.isWin32()) {
            return false;
        }

        try {
            //XXX lame.
            String cmd = "chmod " + mode + " " + file;
            Process process = Runtime.getRuntime().exec(cmd);

            try {
                return process.waitFor() == 0;
            } catch (InterruptedException e) {
                return false;
            }
        } catch (IOException e) {
            return false;
        }
    }

    public boolean chmodx(File file) {
        return chmod(file, "+x");
    }
}