/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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, or (at your option) any later version.
*
* This software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.deployment;
import java.io.File;
import java.net.URL;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.jboss.mx.loading.RepositoryClassLoader;
import org.jboss.mx.util.MBeanProxyExt;
import org.jboss.system.ServiceControllerMBean;
/**
* A simple subdeployer that deploys a managed object after parsing the
* deployment's xml file.
*
* @author <a href="adrian@jboss.com">Adrian Brock</a>
* @version $Revision: 81033 $
*/
public abstract class SimpleSubDeployerSupport extends SubDeployerSupport
{
/** A proxy to the ServiceController. */
private ServiceControllerMBean serviceController;
/** Whether we registered the classloader */
private boolean registeredClassLoader = false;
/**
* Get the package extension for this deployment
*
* @return the package extension
*/
public abstract String getExtension();
/**
* Get the metadata url
*
* @return the meta data url
*/
public abstract String getMetaDataURL();
/**
* Get the object name for this deployment
*
* @param di the deployment info
* @return the object name
*/
public abstract String getObjectName(DeploymentInfo di) throws DeploymentException;
/**
* Get the deployment class
*
* @return the deployment class
*/
public abstract String getDeploymentClass();
public boolean accepts(DeploymentInfo di)
{
String urlStr = di.url.toString();
String extension = getExtension();
return urlStr.endsWith(extension) || urlStr.endsWith(extension + '/');
}
public void init(DeploymentInfo di) throws DeploymentException
{
URL url = getMetaDataResource(di);
parseMetaData(di, url);
resolveWatch(di, url);
super.init(di);
}
public void create(DeploymentInfo di) throws DeploymentException
{
determineObjectName(di);
ObjectName uclName = registerClassLoader(di);
try
{
registerDeployment(di, uclName);
try
{
createService(di);
try
{
super.create(di);
}
catch (Throwable t)
{
destroyService(di);
}
}
catch (Throwable t)
{
unregisterDeployment(di);
throw t;
}
}
catch (Throwable t)
{
unregisterClassLoader(di);
DeploymentException.rethrowAsDeploymentException("Error creating deployment " + di.url, t);
}
}
public void start(DeploymentInfo di) throws DeploymentException
{
startService(di);
try
{
super.start(di);
}
catch (Throwable t)
{
stopService(di);
DeploymentException.rethrowAsDeploymentException("Error in start for deployment " + di.url, t);
}
}
public void stop(DeploymentInfo di) throws DeploymentException
{
stopService(di);
super.stop(di);
}
public void destroy(DeploymentInfo di) throws DeploymentException
{
try
{
destroyService(di);
super.destroy(di);
}
finally
{
unregisterDeployment(di);
unregisterClassLoader(di);
}
}
public void postRegister(Boolean done)
{
super.postRegister(done);
if (done.booleanValue())
{
serviceController = (ServiceControllerMBean)
MBeanProxyExt.create(ServiceControllerMBean.class,
ServiceControllerMBean.OBJECT_NAME,
server);
}
}
/**
* Get the url of the meta data resource
*
* @param di the deployment info
* @return the url of the meta data resource
* @throws DeploymentException for any error
*/
protected URL getMetaDataResource(DeploymentInfo di) throws DeploymentException
{
URL url = di.localCl.findResource(getMetaDataURL());
if (url == null)
throw new DeploymentException("Could not find meta data " + getMetaDataURL() + " for deployment " + di.url);
return url;
}
/**
* Parse the meta data
*
* @param di the deployment info
* @param url the location of the meta data
* @throws DeploymentException for any error
*/
abstract protected void parseMetaData(DeploymentInfo di, URL url) throws DeploymentException;
/**
* Resolve the watch url
*
* @param di the deployment info
* @param url the location of the meta data
* @throws DeploymentException for any error
*/
protected void resolveWatch(DeploymentInfo di, URL url) throws DeploymentException
{
// Assume we watch the main deployment
di.watch = di.url;
// Unless it is an unpacked directory
if (di.url.getProtocol().equals("file"))
{
File file = new File(di.url.getFile());
if (file.isDirectory())
di.watch = url;
}
}
/**
* Determine the object name
*
* @param di the deployment info
* @throws DeploymentException for any error
*/
protected void determineObjectName(DeploymentInfo di) throws DeploymentException
{
String objectName = getObjectName(di);
try
{
di.deployedObject = new ObjectName(objectName);
}
catch (MalformedObjectNameException e)
{
throw new DeploymentException("INTERNAL ERROR: Bad object name. " + objectName);
}
}
/**
* Register the UCL classloader
*
* @param di the deployment info
* @return the object name of the classloader
* @throws DeploymentException for any error
*/
protected ObjectName registerClassLoader(DeploymentInfo di) throws DeploymentException
{
ObjectName uclName = null;
try
{
RepositoryClassLoader ucl = di.ucl;
uclName = ucl.getObjectName();
if (server.isRegistered(uclName) == false)
{
server.registerMBean(di.ucl, uclName);
registeredClassLoader = true;
}
}
catch (Throwable t)
{
DeploymentException.rethrowAsDeploymentException("Error registering classloader " + uclName, t);
}
return uclName;
}
/**
* Unregister the UCL classloader
*
* @param di the deployment info
*/
protected void unregisterClassLoader(DeploymentInfo di)
{
ObjectName uclName = null;
try
{
RepositoryClassLoader ucl = di.ucl;
if (ucl != null)
{
uclName = ucl.getObjectName();
if (registeredClassLoader && server.isRegistered(uclName))
{
server.unregisterMBean(uclName);
registeredClassLoader = false;
}
}
}
catch (Throwable t)
{
log.warn("Error unregistering classloader " + uclName, t);
}
}
/**
* Register the deployment
*
* @param di the deployment info
* @param uclName the object name of the classloader
* @throws DeploymentException for any error
*/
protected void registerDeployment(DeploymentInfo di, ObjectName uclName) throws DeploymentException
{
try
{
String deploymentClass = getDeploymentClass();
server.createMBean(deploymentClass, di.deployedObject, uclName, new Object[] { di }, new String[] { DeploymentInfo.class.getName() });
}
catch (Throwable t)
{
DeploymentException.rethrowAsDeploymentException("Error registering deployment " + di.url, t);
}
}
/**
* Unregister the deployment
*
* @param di the deployment info
*/
protected void unregisterDeployment(DeploymentInfo di)
{
try
{
if (server.isRegistered(di.deployedObject))
server.unregisterMBean(di.deployedObject);
}
catch (Throwable t)
{
log.warn("Error unregistering deployment " + di.deployedObject, t);
}
}
/**
* Do the create lifecyle for the deployment
*
* @param di the deployment info
* @throws DeploymentException for any error
*/
protected void createService(DeploymentInfo di) throws DeploymentException
{
try
{
serviceController.create(di.deployedObject);
}
catch (Throwable t)
{
DeploymentException.rethrowAsDeploymentException("Error in create for deployment " + di.url, t);
}
}
/**
* Do the start lifecyle for the deployment
*
* @param di the deployment info
* @throws DeploymentException for any error
*/
protected void startService(DeploymentInfo di) throws DeploymentException
{
try
{
serviceController.start(di.deployedObject);
}
catch (Throwable t)
{
DeploymentException.rethrowAsDeploymentException("Error in start for deployment " + di.url, t);
}
}
/**
* Do the stop lifecyle for the deployment
*
* @param di the deployment info
*/
protected void stopService(DeploymentInfo di)
{
try
{
if (di.deployedObject != null)
serviceController.stop(di.deployedObject);
}
catch (Throwable t)
{
log.warn("Error in stop for deployment " + di.url, t);
}
}
/**
* Do the destroy lifecyle for the deployment
*
* @param di the deployment info
*/
protected void destroyService(DeploymentInfo di) throws DeploymentException
{
try
{
if (di.deployedObject != null)
serviceController.destroy(di.deployedObject);
}
catch (Throwable t)
{
log.warn("Error in destroy for deployment " + di.url, t);
}
try
{
if (di.deployedObject != null)
serviceController.remove(di.deployedObject);
}
catch (Throwable t)
{
log.warn("Error in remove for deployment " + di.url, t);
}
}
}