/*
* Copyright to the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.rioproject.cybernode.service;
import net.jini.config.ConfigurationException;
import org.rioproject.impl.config.AggregateConfig;
import org.rioproject.config.GroovyConfig;
import org.rioproject.impl.servicebean.DefaultServiceBeanContext;
import org.rioproject.servicebean.ServiceBeanContext;
import org.rioproject.log.LoggerConfig;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* Service termination helper.
*/
public class ServiceTerminationHelper {
/**
* Cleanup resources that may cause memory leaks
*
* @param context The <code>ServiceBeanContext</code> to use
*/
public static void cleanup(ServiceBeanContext context) {
if (context != null) {
/* Release any created Handlers */
LoggerConfig[] loggerConfigs = context.getServiceBeanConfig().getLoggerConfigs();
if (loggerConfigs != null) {
for (LoggerConfig loggerConfig : loggerConfigs) {
loggerConfig.close();
}
}
/* If we have a groovy configuration, clean the configuration, clearing
* the class cache and setting the embedded groovy classloader to null */
try {
if (context.getConfiguration() instanceof AggregateConfig) {
AggregateConfig ac = (AggregateConfig) context.getConfiguration();
if (ac.getOuterConfiguration() instanceof GroovyConfig) {
((GroovyConfig) ac.getOuterConfiguration()).clear();
}
if (context instanceof DefaultServiceBeanContext)
((DefaultServiceBeanContext) context).setConfiguration(null);
}
} catch (ConfigurationException e) {
/* */
}
}
/* Services using groovy leak memory on undeployment. The object retaining a reference to the
* GroovyClassLoader (that has as it's parent the ServiceClassLoader) is a static
* org.codehaus.groovy.control.CompilationUnit field in the
* org.codehaus.groovy.transform.ASTTransformationVisitor class */
try {
final Class clazz = loadClass("org.codehaus.groovy.transform.ASTTransformationVisitor");
final Field compUnit = clazz.getDeclaredField("compUnit");
compUnit.setAccessible(true);
// static field
compUnit.set(null, null);
} catch (Throwable t) {
// ignore
}
}
static Class loadClass(final String className) {
return AccessController.doPrivileged(new PrivilegedAction<Class>() {
public Class run() {
try {
return Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
return null;
}
}
});
}
}