/*******************************************************************************
* Copyright (c) 2004, 2010 BREDEX GmbH.
* 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:
* BREDEX GmbH - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.jubula.tools.internal.utils;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* Class to edit classpath in runtime
* @author BREDEX GmbH
*
*/
public class ClassPathHacker {
/**
* parameters
*/
private static final Class[] PARAMETERS = new Class[]{URL.class};
/**
* hide contructor
*
*/
private ClassPathHacker() {
//nothing
}
/**
* AddFile
* @param f file
* @throws IOException Error
*/
public static void addFile(File f) throws IOException {
addURL(f.toURL());
}
/**
* AddFile
* @param u URL
* @throws IOException Error
*/
public static void addURL(URL u) throws IOException {
URLClassLoader sysloader =
(URLClassLoader)ClassLoader.getSystemClassLoader();
Class sysclass = URLClassLoader.class;
try {
Method method = sysclass.
getDeclaredMethod("addURL", PARAMETERS); //$NON-NLS-1$
method.setAccessible(true);
method.invoke(sysloader, new Object[]{ u });
} catch (NoSuchMethodException t) {
// no log available here
throw new IOException(
"Error, could not add URL to system classloader"); //$NON-NLS-1$
} catch (IllegalAccessException t) {
// no log available here
throw new IOException(
"Error, could not add URL to system classloader"); //$NON-NLS-1$
} catch (InvocationTargetException t) {
// no log available here
throw new IOException(
"Error, could not add URL to system classloader"); //$NON-NLS-1$
}
}
/**
* Add URL to given Classloader
*
* @param u
* URL
* @param classLoader
* the Classloader
* @throws IOException
* Error
* @throws SecurityException
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static void addURL(URL u, ClassLoader classLoader)
throws IOException, NoSuchMethodException, SecurityException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException {
Class sysclass = URLClassLoader.class;
Method method = sysclass.getDeclaredMethod("addURL", PARAMETERS); //$NON-NLS-1$
method.setAccessible(true);
method.invoke(classLoader, new Object[] { u });
}
/**
* Recursive method used to find all classes in a given directory and
* subdirectories.
*
* @param directoryUrl
* The base directory
* @param packageName
* The package name for classes found inside the base directory
* @return The classes
* @throws ClassNotFoundException
* @throws MalformedURLException
*/
public static List<Class> findClasses(URL directoryUrl, String packageName)
throws ClassNotFoundException, MalformedURLException {
List<Class> classes = new ArrayList<Class>();
File directory = new File(directoryUrl.getFile());
if (!directory.exists()) {
return classes;
}
File[] files = directory.listFiles();
for (int i = 0; i < files.length; i++) {
File file = files[i];
String fileName = file.getName();
if (file.isDirectory()) {
classes.addAll(findClasses(file.toURI().toURL(),
packageName + '.' + fileName));
} else if (fileName.endsWith(".class")) { //$NON-NLS-1$
classes.add(Class.forName(packageName + '.'
+ fileName.substring(0, fileName.length() - 6)));
}
}
return classes;
}
/**
* method to find all classes in a given jar
*
* @param resource
* The URL to the jar file
* @param pkgname
* The package name for classes found inside the base directory
* @param classLoader
* the Classloader which should be used
* @return The classes
* @throws IOException
* @throws ClassNotFoundException
*/
public static List<Class> findClassesInJar(URL resource, String pkgname,
ClassLoader classLoader)
throws IOException, ClassNotFoundException {
String relPath = pkgname.replace('.', '/');
String path = resource.getPath()
.replaceFirst("[.]jar[!].*", ".jar") //$NON-NLS-1$ //$NON-NLS-2$
.replaceFirst("file:", ""); //$NON-NLS-1$ //$NON-NLS-2$
path = URLDecoder.decode(path, "utf-8"); //$NON-NLS-1$
List<Class> classes = new ArrayList<Class>();
JarFile jarFile = null;
try {
jarFile = new JarFile(path);
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String entryName = entry.getName();
String className = null;
if (entryName.endsWith(".class") //$NON-NLS-1$
&& entryName.startsWith(relPath)) {
className = entryName.replace('/', '.').replace('\\', '.')
.replaceAll(".class", ""); //$NON-NLS-1$ //$NON-NLS-2$
if (className != null) {
classes.add(Class.forName(
className, true, classLoader));
}
}
}
} finally {
if (jarFile != null) {
jarFile.close();
}
}
return classes;
}
}