}
SystemInstance.get().setComponent(EjbResolver.class, globalResolver);
Context globalContext = containerSystem.getJNDIContext();
UndeployException undeployException = new UndeployException(messages.format("destroyApplication.failed", appInfo.path));
WebAppBuilder webAppBuilder = SystemInstance.get().getComponent(WebAppBuilder.class);
if (webAppBuilder != null) {
try {
webAppBuilder.undeployWebApps(appInfo);
} catch (Exception e) {
undeployException.getCauses().add(new Exception("App: " + appInfo.path + ": " + e.getMessage(), e));
}
}
// get all of the ejb deployments
List<BeanContext> deployments = new ArrayList<BeanContext>();
for (EjbJarInfo ejbJarInfo : appInfo.ejbJars) {
for (EnterpriseBeanInfo beanInfo : ejbJarInfo.enterpriseBeans) {
String deploymentId = beanInfo.ejbDeploymentId;
BeanContext beanContext = containerSystem.getBeanContext(deploymentId);
if (beanContext == null) {
undeployException.getCauses().add(new Exception("deployment not found: " + deploymentId));
} else {
deployments.add(beanContext);
}
}
}
// Just as with startup we need to get things in an
// order that respects the singleton @DependsOn information
// Theoreticlly if a Singleton depends on something in its
// @PostConstruct, it can depend on it in its @PreDestroy.
// Therefore we want to make sure that if A dependsOn B,
// that we destroy A first then B so that B will still be
// usable in the @PreDestroy method of A.
// Sort them into the original starting order
deployments = sort(deployments);
// reverse that to get the stopping order
Collections.reverse(deployments);
// stop
for (BeanContext deployment : deployments) {
String deploymentID = deployment.getDeploymentID() + "";
try {
Container container = deployment.getContainer();
container.stop(deployment);
} catch (Throwable t) {
undeployException.getCauses().add(new Exception("bean: " + deploymentID + ": " + t.getMessage(), t));
}
}
// undeploy
for (BeanContext bean : deployments) {
String deploymentID = bean.getDeploymentID() + "";
try {
Container container = bean.getContainer();
container.undeploy(bean);
bean.setContainer(null);
} catch (Throwable t) {
undeployException.getCauses().add(new Exception("bean: " + deploymentID + ": " + t.getMessage(), t));
} finally {
bean.setDestroyed(true);
}
}
// get the client ids
List<String> clientIds = new ArrayList<String>();
for (ClientInfo clientInfo : appInfo.clients) {
clientIds.add(clientInfo.moduleId);
for (String className : clientInfo.localClients) {
clientIds.add(className);
}
for (String className : clientInfo.remoteClients) {
clientIds.add(className);
}
}
if (appContext != null) for (WebContext webContext : appContext.getWebContexts()) {
containerSystem.removeWebContext(webContext);
}
// Clear out naming for all components first
for (BeanContext deployment : deployments) {
String deploymentID = deployment.getDeploymentID() + "";
try {
containerSystem.removeBeanContext(deployment);
} catch (Throwable t) {
undeployException.getCauses().add(new Exception(deploymentID, t));
}
JndiBuilder.Bindings bindings = deployment.get(JndiBuilder.Bindings.class);
if (bindings != null) for (String name : bindings.getBindings()) {
try {
globalContext.unbind(name);
} catch (Throwable t) {
undeployException.getCauses().add(new Exception("bean: " + deploymentID + ": " + t.getMessage(), t));
}
}
}
for (PersistenceUnitInfo unitInfo : appInfo.persistenceUnits) {
try {
Object object = globalContext.lookup(PERSISTENCE_UNIT_NAMING_CONTEXT + unitInfo.id);
globalContext.unbind(PERSISTENCE_UNIT_NAMING_CONTEXT + unitInfo.id);
// close EMF so all resources are released
ReloadableEntityManagerFactory remf = ((ReloadableEntityManagerFactory) object);
remf.close();
persistenceClassLoaderHandler.destroy(unitInfo.id);
remf.unregister();
} catch (Throwable t) {
undeployException.getCauses().add(new Exception("persistence-unit: " + unitInfo.id + ": " + t.getMessage(), t));
}
}
for (String sId : moduleIds) {
try {
globalContext.unbind(VALIDATOR_FACTORY_NAMING_CONTEXT + sId);
globalContext.unbind(VALIDATOR_NAMING_CONTEXT + sId);
} catch (NamingException e) {
undeployException.getCauses().add(new Exception("validator: " + sId + ": " + e.getMessage(), e));
}
}
moduleIds.clear();
try {
if (globalContext instanceof IvmContext) {
IvmContext ivmContext = (IvmContext) globalContext;
ivmContext.prune("openejb/Deployment");
ivmContext.prune("openejb/local");
ivmContext.prune("openejb/remote");
ivmContext.prune("openejb/global");
}
} catch (NamingException e) {
undeployException.getCauses().add(new Exception("Unable to prune openejb/Deployments and openejb/local namespaces, this could cause future deployments to fail.", e));
}
deployments.clear();
for (String clientId : clientIds) {
try {
globalContext.unbind("/openejb/client/" + clientId);
} catch (Throwable t) {
undeployException.getCauses().add(new Exception("client: " + clientId + ": " + t.getMessage(), t));
}
}
// mbeans
MBeanServer server = LocalMBeanServer.get();
for (String objectName : appInfo.jmx) {
try {
ObjectName on = new ObjectName(objectName);
if (server.isRegistered(on)) {
server.unregisterMBean(on);
}
} catch (InstanceNotFoundException e) {
logger.warning("can't unregister " + objectName + " because the mbean was not found", e);
} catch (MBeanRegistrationException e) {
logger.warning("can't unregister " + objectName, e);
} catch (MalformedObjectNameException mone) {
logger.warning("can't unregister because the ObjectName is malformed: " + objectName, mone);
}
}
containerSystem.removeAppContext(appInfo.appId);
ClassLoaderUtil.destroyClassLoader(appInfo.path);
if (undeployException.getCauses().size() > 0) {
throw undeployException;
}
logger.debug("destroyApplication.success", appInfo.path);
}