Package eu.bibl.bio.jfile.classloader

Source Code of eu.bibl.bio.jfile.classloader.JarClassLoader

package eu.bibl.bio.jfile.classloader;

import java.net.URL;
import java.util.HashMap;
import java.util.Set;

import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.tree.ClassNode;

import sun.misc.URLClassPath;
import eu.bibl.banalysis.storage.classes.ClassContainer;

/**
* Specific {@link ClassLoader} for loading things from external JarFiles, caching loaded classes as it goes along. <br>
*
* @author Bibl
*/
public class JarClassLoader extends ClassLoader {

  /** Associated path for classes **/
  protected ClassContainer container;
  /** Previously loaded classes **/
  protected HashMap<String, Class<?>> cache;
  /** Resource class path **/
  protected URLClassPath ucp;

  /**
   * @param contents Reference to the JarContents object.
   */
  public JarClassLoader(ClassContainer container) {
    this.container = container;
    cache = new HashMap<String, Class<?>>();
    Set<URL> urlSet = container.resources.keySet();
    URL[] urls = urlSet.toArray(new URL[urlSet.size()]);
    ucp = new URLClassPath(urls);
  }

  /**
   * Add a resource URL to the class path by force.
   * @param url URL to add.
   */
  public void addJar(URL url) {
    ucp.addURL(url);
  }

  /**
   * Adds the class contents of the {@link ClassContainer} as well as the resource locations.
   * @param contents Contents to add.
   */
  public void addJar(ClassContainer container) {
    this.container.add(container);
    for (URL url : container.resources.keySet())
      ucp.addURL(url);
  }

  @Override
  public URL findResource(final String name) {
    return ucp.findResource(name, true);
  }

  /**
   * @param cn ClassNode to define
   * @return Defined Class.
   */
  public Class<?> defineNode(ClassNode cn) {
    ClassWriter cw = new ClassWriter(0);
    return defineNode(cn, cw);
  }

  /**
   * Defines a ClassNode with a custom {@link ClassWriter}
   *
   * @param cn ClassNode to define
   * @param cw ClassWriter to define with
   * @return Defined Class.
   */
  public Class<?> defineNode(ClassNode cn, ClassWriter cw) {
    cn.accept(cw);
    byte[] bytes = cw.toByteArray();
    Class<?> c = defineClass(null, bytes, 0, bytes.length);
    if (c != null)
      cache.put(cn.name, c);
    return c;
  }

  // @Override
  // public Class<?> loadClass(String name) throws ClassNotFoundException {
  // return findClass(name.replace(".", "/"));
  // }

  @Override
  protected Class<?> findClass(String name) throws ClassNotFoundException {
    name = name.replace(".", "/");
    if (cache.containsKey(name))
      return cache.get(name);
    ClassNode node = container.getNodes().get(name);
    if (node != null)
      return defineNode(node);
    // Class<?> c = super.loadClass(name);
    // if (c != null) {
    // cacheClass(name, c);
    // return c;
    // }
    Class<?> c = getSystemClassLoader().loadClass(name);
    if (c != null)
      cacheClass(name, c);
    return c;
  }

  /**
   * Forces the class to be put into the cache overwriting the previously loaded one.
   * @param name Fully qualified name of the class.
   * @param c Class to add.
   */
  public void cacheClass(String name, Class<?> c) {
    if ((c != null) && !c.getName().startsWith("java"))
      cache.put(name, c);
  }
}
TOP

Related Classes of eu.bibl.bio.jfile.classloader.JarClassLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.