/* * 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 com.addthis.hydra.task.run; import java.io.DataInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; public class ResourceClassLoader extends ClassLoader { /** * Parent ClassLoader passed to this constructor * will be used if this ClassLoader can not resolve a * particular class. * * @param parent Parent ClassLoader * (may be from getClass().getClassLoader()) */ public ResourceClassLoader(ClassLoader parent) { super(parent); } /** * Loads a given class from .class file just like * the default ClassLoader. This method could be * changed to load the class over network from some * other server or from the database. * * @param name Full class name */ private Class<?> getClass(String name) throws ClassNotFoundException { // We are getting a name that looks like // javablogging.package.ClassToLoad // and we have to convert it into the .class file name // like javablogging/package/ClassToLoad.class String file = name.replace('.', File.separatorChar) + ".class"; byte[] b = null; try { // This loads the byte code data from the file b = loadClassData(file); // defineClass is inherited from the ClassLoader class // and converts the byte array into a Class Class<?> c = defineClass(name, b, 0, b.length); resolveClass(c); return c; } catch (IOException e) { e.printStackTrace(); return null; } } /** * Every request for a class passes through this method. * If the requested class is in "javablogging" package, * it will load it using the * {@link ResourceClassLoader#getClass()} method. * If not, it will use the super.loadClass() method * which in turn will pass the request to the parent. * * @param name Full class name */ @Override public Class<?> loadClass(String name) throws ClassNotFoundException { System.out.println("loading class '" + name + "'"); if (name.startsWith("javablogging.")) { return getClass(name); } return super.loadClass(name); } /** * Loads a given file (presumably .class) into a byte array. * The file should be accessible as a resource, for example * it could be located on the classpath. * * @param name File name to load * @return Byte array read from the file * @throws IOException Is thrown when there * was some problem reading the file */ private byte[] loadClassData(String name) throws IOException { // Opening the file InputStream stream = getClass().getClassLoader() .getResourceAsStream(name); int size = stream.available(); byte[] buff = new byte[size]; DataInputStream in = new DataInputStream(stream); // Reading the binary data in.readFully(buff); in.close(); return buff; } }