blob: ee36e9f1d42e18d9dfe62bfd7b92581bf016c278 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005-2014 Obeo
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.query.legacy.tools.classloaders;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecore.EObject;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
/**
* A class loader that combines plugins, acceleo services, and metamodels.
*
*/
public class AcceleoClassLoader extends URLClassLoader {
/**
* The preferred class loader.
*/
protected static ClassLoader preferredClassLoader = null;
/**
* The preferred class loader cache class name -> Class.
*/
protected static Map preferedCache = new HashMap();
/**
* Updates the preferred class loader with the given model object.
*
* @param object
* is the model object
*/
public static void setPreferredLoader(EObject object) {
if (object != null) {
ClassLoader loader = object.getClass().getClassLoader();
if (AcceleoClassLoader.preferredClassLoader != loader) {
AcceleoClassLoader.preferedCache = new HashMap();
}
AcceleoClassLoader.preferredClassLoader = loader;
} else {
AcceleoClassLoader.preferedCache = new HashMap();
AcceleoClassLoader.preferredClassLoader = null;
}
}
/**
* @param loader
* is the preferred class loader
*/
public static void setPreferredClassLoader(ClassLoader loader) {
if (AcceleoClassLoader.preferredClassLoader != loader) {
AcceleoClassLoader.preferedCache = new HashMap();
}
AcceleoClassLoader.preferredClassLoader = loader;
}
/**
* @return the preferred class loader
*/
public static ClassLoader getPreferredClassLoader() {
return AcceleoClassLoader.preferredClassLoader;
}
/**
* The optional bundle that contains the classes.
*/
private Bundle bundle;
/**
* Constructor.
*
* @param urls
* are the specific URLs of the classloader
* @param parent
* is the parent classloader
*/
public AcceleoClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent);
this.bundle = null;
}
/**
* Constructor.
*
* @param bundle
* is the optional bundle that contains the generator
* @param parent
* is the parent classloader
*/
public AcceleoClassLoader(Bundle bundle, ClassLoader parent) {
super(new URL[] {}, parent);
this.bundle = bundle;
}
/* (non-Javadoc) */
@Override
public Class loadClass(String name) throws ClassNotFoundException {
try {
if (bundle != null) {
Class c = loadClassInBundle(bundle, name, true);
if (c != null) {
return c;
} else {
return loadClassInPreferredLoader(name);
}
} else {
return loadClassInPreferredLoader(name);
}
} catch (ClassNotFoundException e) {
return loadClassInPreferredLoader(name);
} catch (NoClassDefFoundError e) {
return loadClassInPreferredLoader(name);
}
}
private Class loadClassInBundle(Bundle bundle, String name, boolean requiredSearch) {
try {
return bundle.loadClass(name);
} catch (ClassNotFoundException e) {
if (requiredSearch) {
return loadClassInRequiredBundles(bundle, name);
}
} catch (NoClassDefFoundError e) {
if (requiredSearch) {
return loadClassInRequiredBundles(bundle, name);
}
}
return null;
}
private Class loadClassInRequiredBundles(Bundle bundle, String name) {
String requiredBundles = bundle.getHeaders().get(Constants.REQUIRE_BUNDLE);
if (requiredBundles != null) {
StringTokenizer st = new StringTokenizer(requiredBundles, ","); //$NON-NLS-1$
while (st.hasMoreTokens()) {
String id = st.nextToken().trim();
int iDot = id.indexOf(';');
if (iDot > -1) {
id = id.substring(0, iDot).trim();
}
if (id.length() > 0) {
Bundle requiredBundle = Platform.getBundle(id);
if (requiredBundle != null) {
Class c = loadClassInBundle(requiredBundle, name, false);
if (c != null) {
return c;
}
}
}
}
}
return null;
}
private Class loadClassInPreferredLoader(String name) throws ClassNotFoundException {
Class res = (Class) AcceleoClassLoader.preferedCache.get(name);
if (res == null) {
try {
if (AcceleoClassLoader.preferredClassLoader != null && AcceleoClassLoader.preferredClassLoader != this && AcceleoClassLoader.preferredClassLoader != getParent()) {
res = AcceleoClassLoader.preferredClassLoader.loadClass(name);
}
} catch (ClassNotFoundException e) {
// continue
} catch (NoClassDefFoundError e) {
// continue
}
if (res == null) {
try {
res = getParent().loadClass(name);
} catch (ClassNotFoundException e) {
res = super.loadClass(name);
} catch (NoClassDefFoundError e) {
res = super.loadClass(name);
}
}
if (res != null) {
AcceleoClassLoader.preferedCache.put(name, res);
}
}
return res;
}
}