/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.util;
import java.net.URL;
import java.net.URLClassLoader;
import com.tc.object.bytecode.hook.impl.ClassProcessorHelper;
import com.tc.object.loaders.NamedClassLoader;
public class ExtendableURLClassLoader extends URLClassLoader
{
public ExtendableURLClassLoader(URL[] urls, ClassLoader parent, String nameSuffix)
{
super(urls, parent);
registerClassLoaderInClusterIfNeeded(nameSuffix);
}
// TODO a better idea I think would be to create a Servoy TIM for this kind of things (if possible)
private void registerClassLoaderInClusterIfNeeded(String nameSuffix)
{
try
{
// if this class can be found it means application server was started under Terracotta
Class.forName("com.tc.object.loaders.NamedClassLoader"); //$NON-NLS-1$
// although this class is not actually an instance of NamedClassLoader, when running clustered it is (URLClassLoader is injected by terracotta);
// we need to register this classloader with terracotta so that plugins/beans/lafs/drivers can add clustering behavior;
// the class loader name decided which named classloaders can share terracotta roots between JVM; each name should be unique within that JVM
// (currently you are not allowed to have multiple instances of the same terracotta root in the same JVM if loaded by different classloaders - thus the names
// have to be unique (also to avoid ambiguity))
((NamedClassLoader)this).__tc_setClassLoaderName(getCurrentClassLoaderName() + nameSuffix);
ClassProcessorHelper.registerGlobalLoader(((NamedClassLoader)this), null); // null web app. name (war deployment) for now - we build the name based on parent classloaders
}
catch (ClassNotFoundException e)
{
// we are not running inside a Terracotta cluster; np, nothing to register
}
catch (ClassCastException e)
{
// we are not running inside a Terracotta cluster; np, nothing to register
}
}
private String getCurrentClassLoaderName()
{
// try to find the named classloader name of the classloader loading this classloader's class :) (when running under Terracotta)
// - not the parent's that could be another (in case of beans for example)
ClassLoader currentClassLoader = getClass().getClassLoader();
String currentClassLoaderName = ""; //$NON-NLS-1$
if (currentClassLoader instanceof NamedClassLoader) currentClassLoaderName = ((NamedClassLoader)currentClassLoader).__tc_getClassLoaderName();
return currentClassLoaderName;
}
@Override
public void addURL(URL url)
{
super.addURL(url);
}
private boolean urlsVisible = false;
public void setURLsVisible(boolean b)
{
urlsVisible = b;
}
/**
* if disabled ,we never want that RMI starts loading classes from the developer
*/
@Override
public URL[] getURLs()
{
Debug.trace("ExtendableURLClassLoader.getURLs is invoked!"); //$NON-NLS-1$
if (urlsVisible)
{
return super.getURLs();
}
else
{
return new URL[0];
}
}
@Override
public String toString()
{
return "ExtendableURLClassLoader: " + getURLs();
}
}