/*
* 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-2007], 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.hqu;
import groovy.lang.GroovyClassLoader;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.authz.server.session.AuthzSubject;
import org.hyperic.hq.authz.server.session.Resource;
import org.hyperic.hq.common.SystemException;
import org.hyperic.hq.hqu.server.session.Attachment;
import org.hyperic.hq.hqu.server.session.UIPlugin;
import org.hyperic.util.Runnee;
import org.hyperic.util.file.FileUtil;
/**
* Basically a wrapper around the classloader and associated groovy artifacts.
*
* This class sets up the rendit_sys directory as a member of the classloader
* hierarchy. In addition, any jars contained in pluginDir/lib will be added to
* the classloader.
*/
public class PluginWrapper {
private static final Log _log = LogFactory.getLog(PluginWrapper.class);
private File _pluginDir;
private final GroovyClassLoader _loader;
private IDispatcher _dispatcher;
/**
* @return A unique temporary directory for embedded jar deployments.
*/
private File getTempDir() {
String tmp = System.getProperty("java.io.tmpdir");
File tmpHquDir = new File(tmp, "hqu");
if (!tmpHquDir.exists()) {
if (!tmpHquDir.mkdirs()) {
throw new RuntimeException("Unable to create temporary directory " + tmpHquDir.getAbsolutePath());
}
}
return tmpHquDir;
}
PluginWrapper(File pluginDir, ClassLoader parentLoader) {
GroovyClassLoader groovyLoader = new GroovyClassLoader(parentLoader);
_pluginDir = pluginDir;
try {
File tmpDir = getTempDir();
File libDir = new File(_pluginDir, "lib");
if (libDir.isDirectory()) {
File[] files = libDir.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isFile() && files[i].getName().endsWith(".jar")) {
String prefix = pluginDir.getName() + "-" +
files[i].getName().substring(0, files[i].getName().length() - 4);
File tmpJar = File.createTempFile(prefix, ".jar", tmpDir);
FileUtil.copyFile(files[i], tmpJar);
tmpJar.deleteOnExit();
groovyLoader.addURL(tmpJar.toURL());
_log.info("Added url [" +tmpJar.toURL() + "] to plugin [" + pluginDir + "]");
}
}
}
} catch (MalformedURLException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
_loader = groovyLoader;
}
private Object doInContext(Runnee runnable) throws Exception {
Thread curThread = Thread.currentThread();
ClassLoader oldLoader = curThread.getContextClassLoader();
try {
curThread.setContextClassLoader(_loader);
return runnable.run();
} finally {
curThread.setContextClassLoader(oldLoader);
}
}
void loadDispatcher() throws Exception {
doInContext(new Runnee() {
public Object run() throws Exception {
try {
Class c = _loader.loadClass("org.hyperic.hq.hqu.rendit.Dispatcher");
_dispatcher = (IDispatcher) c.newInstance();
} catch (Exception e) {
_log.error("Unable to load groovy class: org.hyperic.hq.hqu.rendit.Dispatcher", e);
}
return null;
}
});
}
Properties loadPlugin() {
try {
return (Properties) doInContext(new Runnee() {
public Object run() {
return _dispatcher.loadPlugin(_pluginDir);
}
});
} catch (Exception e) {
throw new PluginLoadException("Unable to load plugin", e);
}
}
void handleRequest(final Object request) {
try {
doInContext(new Runnee() {
public Object run() {
_dispatcher.handleRequest(request);
return null;
}
});
} catch (Exception e) {
_log.warn("Error handling request from " + _pluginDir, e);
throw new SystemException(e);
}
}
void deploy(final UIPlugin p) {
try {
doInContext(new Runnee() {
public Object run() {
_dispatcher.deploy(p);
return null;
}
});
} catch (Exception e) {
_log.warn("Error deploying from " + _pluginDir, e);
}
}
AttachmentDescriptor getAttachmentDescriptor(final Attachment a, final Resource r, final AuthzSubject u) {
try {
return (AttachmentDescriptor) doInContext(new Runnee() {
public Object run() {
return _dispatcher.getAttachmentDescriptor(a, r, u);
}
});
} catch (Exception e) {
_log.warn("Error getting attachment descriptor for " + _pluginDir, e);
throw new SystemException(e);
}
}
Object invokeMethod(final InvokeMethodInvocationBindings b) {
try {
return doInContext(new Runnee() {
public Object run() {
return _dispatcher.invokeMethod(b);
}
});
} catch (Exception e) {
_log.warn("Error invoking method from " + _pluginDir, e);
throw new SystemException(e);
}
}
File getPluginDir() {
return _pluginDir;
}
}