/*
* Created on Jan 28, 2005
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package com.idega.slide.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Timer;
import org.apache.slide.common.Domain;
import org.apache.slide.util.logger.Logger;
import org.apache.slide.webdav.event.NotificationTrigger;
/**
* @author thomas
*
* As long as the org.apache.slide project does not provide methods for
* unloading dirty reflection methods are used to reset some classes that cause
* problems during reloading idegaweb application.
*
* !!! Be very careful with this class !!!
* !!! Use this class only when stopping idegaweb application !!!
*
*/
public class DirtyUnloader {
java.util.logging.Logger logger = java.util.logging.Logger.getLogger(this.getClass().getName());
public void reset() {
logger.info("["+DirtyUnloader.class.getName()+"] Reset NotificationTrigger");
// is this class already loaded?
resetNotificationTrigger();
}
public void unload() {
logger.info("["+DirtyUnloader.class.getName()+"] Unload NotificationTrigger");
unloadNotificationTrigger();
logger.info("["+ DirtyUnloader.class.getName()+"] Unload Domain");
unloadDomain();
}
/**
* The NotificationTrigger and its Timer prevents tomcat from stopping.
*
*/
private void unloadNotificationTrigger() {
// first cancel Timer
cancelAndUnloadTimerOfNotificationTrigger();
// destroy static instance
unloadInstanceOfNotificationTrigger();
}
private void resetNotificationTrigger() {
// first cancel Timer
resetInstanceOfNotificationTrigger();
// destroy static instance
resetTimerOfNotificationTrigger();
}
/** The Domain, once initialized, can never initialized again.
* There are two static variables that are checked:
* namespaces and domain.
* By setting these static variables to null
* the Domain can be initialized again, that happens
* when reloading the idegaweb application.
*
* see the method isInitialized() of the Domain class:
*
* Tests if the domain has been initialized before.
*
* @return boolean True if the domain has already been initialized
*
* public static boolean isInitialized() {
*
* return ((domain != null) || (namespaces != null));
* }
*
*
*/
private void unloadDomain() {
unloadEmbeddedDomainOfDomain();
unloadNameSpacesOfDomain();
}
private void cancelAndUnloadTimerOfNotificationTrigger() {
try {
Field timerField = NotificationTrigger.class.getDeclaredField("timer");
timerField.setAccessible(true);
Object object = timerField.get(null);
Timer timer = (Timer) object;
timer.cancel();
timerField.set(null, null);
}
catch (Exception ex) {
logger.warning("[DirtyUnloader] Could not unload timer of NotificationTrigger");
}
}
private void resetTimerOfNotificationTrigger() {
try {
Field timerField = NotificationTrigger.class.getDeclaredField("timer");
timerField.setAccessible(true);
Timer timer = new Timer();
timerField.set(null, timer);
}
catch (Exception ex) {
logger.warning("[DirtyUnloader] Could not reset timer of NotificationTrigger");
}
}
private void unloadInstanceOfNotificationTrigger() {
try {
Field instanceField = NotificationTrigger.class.getDeclaredField("notificationTrigger");
instanceField.setAccessible(true);
instanceField.set(null, null);
}
catch (Exception ex) {
logger.warning("[DirtyUnloader] Could not unload instance of NotificationTrigger");
}
}
private void resetInstanceOfNotificationTrigger() {
try {
// before invoking set Logger of the Domain class (the logger is used by NotificationTrigger)
Logger logger = new org.apache.slide.util.logger.SimpleLogger();
logger.setLoggerLevel(Logger.INFO);
Field embeddedDomainField = Domain.class.getDeclaredField("logger");
embeddedDomainField.setAccessible(true);
embeddedDomainField.set(null, logger);
// invoke the default (private) constructor
Class clazz = NotificationTrigger.class;
Constructor[] constructors = clazz.getDeclaredConstructors();
Constructor constructor = constructors[0];
constructor.setAccessible(true);
NotificationTrigger trigger = (NotificationTrigger) constructor.newInstance((Object[]) null);
Field instanceField = NotificationTrigger.class.getDeclaredField("notificationTrigger");
instanceField.setAccessible(true);
instanceField.set(null, trigger);
}
catch (Exception ex) {
logger.warning("[DirtyUnloader] Could not reload NotificationTrigger");
}
}
private void unloadEmbeddedDomainOfDomain() {
try {
Field embeddedDomainField = Domain.class.getDeclaredField("domain");
embeddedDomainField.setAccessible(true);
embeddedDomainField.set(null, null);
}
catch (Exception ex) {
logger.warning("[DirtyUnloader] Could not unload embeddedDomain of Domain");
}
}
private void unloadNameSpacesOfDomain() {
try {
Field namespacesField = Domain.class.getDeclaredField("namespaces");
namespacesField.setAccessible(true);
namespacesField.set(null, null);
}
catch (Exception ex) {
logger.warning("[DirtyUnloader] Could not unload namespaces of Domain");
}
}
}