Package org.maltparserx.core.plugin

Source Code of org.maltparserx.core.plugin.JarLoader

package org.maltparserx.core.plugin;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
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.security.SecureClassLoader;
import java.util.HashMap;
import java.util.Set;
import java.util.TreeSet;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import java.util.regex.PatternSyntaxException;

import org.maltparserx.core.exception.MaltChainedException;
import org.maltparserx.core.helper.HashSet;
import org.maltparserx.core.options.OptionManager;


/**
The jar class loader loads the content of a jar file that complies with a MaltParser Plugin.

@author Johan Hall
*/
public class JarLoader extends SecureClassLoader {
  private HashMap<String, byte[]> classByteArrays;
  private HashMap<String, Class<?>> classes;
 
  /**
   * Creates a new class loader that is specialized for loading jar files.
   *
   * @param parent The parent class loader
   */
  public JarLoader(ClassLoader parent) {
    super(parent);
    classByteArrays = new HashMap<String, byte[]>();
    classes = new HashMap<String, Class<?>>();
  }
 
  /* (non-Javadoc)
   * @see java.lang.ClassLoader#findClass(java.lang.String)
   */
  protected Class<?> findClass(String name) {
    String urlName = name.replace('.', '/');
    byte buf[];

    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
      int i = name.lastIndexOf('.');
      if (i >= 0) {
        sm.checkPackageDefinition(name.substring(0, i));
      }
    }

    buf = (byte[]) classByteArrays.get(urlName);
    if (buf != null) {
      return defineClass(null, buf, 0, buf.length);
    }
    return null;
  }

  /**
   * Loads the content of a jar file that comply with a MaltParser Plugin 
   *
   * @param jarUrl The URL to the jar file
   * @throws PluginException
   */
  public boolean readJarFile(URL jarUrl) throws MaltChainedException {
    JarInputStream jis;
    JarEntry je;
    Set<URL> pluginXMLs = new HashSet<URL>();
   
    /*if (logger.isDebugEnabled()) {
      logger.debug("Loading jar " + jarUrl+"\n");
    }*/
    JarFile jarFile;
    try {
      jarFile = new JarFile(jarUrl.getFile());
    } catch (IOException e) {
      throw new PluginException("Could not open jar file " + jarUrl+". ", e);
    }
    try {
          Manifest manifest = jarFile.getManifest();
          if (manifest != null) {
            Attributes manifestAttributes = manifest.getMainAttributes();
            if (!(manifestAttributes.getValue("MaltParser-Plugin") != null && manifestAttributes.getValue("MaltParser-Plugin").equals("true"))) {
              return false;
            }
            if (manifestAttributes.getValue("Class-Path") != null) {
              String[] classPathItems = manifestAttributes.getValue("Class-Path").split(" ");
              for (int i=0; i < classPathItems.length; i++) {
                URL u;
                try {
                  u = new URL(jarUrl.getProtocol()+":"+new File(jarFile.getName()).getParentFile().getPath()+"/"+classPathItems[i]);
                } catch (MalformedURLException e) {
                  throw new PluginException("The URL to the plugin jar-class-path '"+jarUrl.getProtocol()+":"+new File(jarFile.getName()).getParentFile().getPath()+"/"+classPathItems[i]+"' is wrong. ", e);
                }
              URLClassLoader sysloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
              Class<?> sysclass = URLClassLoader.class;
              Method method = sysclass.getDeclaredMethod("addURL",new Class[]{URL.class});
              method.setAccessible(true);
              method.invoke(sysloader,new Object[]{u });
              }
            }
          }
    } catch (PatternSyntaxException e) {
      throw new PluginException("Could not split jar-class-path entries in the jar-file '"+jarFile.getName()+"'. ", e);
    } catch (IOException e) {
      throw new PluginException("Could not read the manifest file in the jar-file '"+jarFile.getName()+"'. ", e);
    } catch (NoSuchMethodException e) {
      throw new PluginException("", e);
    } catch (IllegalAccessException e) {
      throw new PluginException("", e);
    } catch (InvocationTargetException e) {
      throw new PluginException("", e);
    }
   
        try {
      jis = new JarInputStream(jarUrl.openConnection().getInputStream());

      while ((je = jis.getNextJarEntry()) != null) {
        String jarName = je.getName();
        if (jarName.endsWith(".class")) {
          /* if (logger.isDebugEnabled()) {
            logger.debug("  Loading class: " + jarName+"\n");
          }*/
          loadClassBytes(jis, jarName);
          Class<?> clazz = findClass(jarName.substring(0, jarName.length() - 6));
          classes.put(jarName.substring(0, jarName.length() - 6).replace('/','.'), clazz);
          loadClass(jarName.substring(0, jarName.length() - 6).replace('/', '.'));
        }
        if (jarName.endsWith("plugin.xml")) {
          pluginXMLs.add(new URL("jar:"+jarUrl.getProtocol()+":"+jarUrl.getPath()+"!/"+jarName));
        }
        jis.closeEntry();
      }
      for (URL url : pluginXMLs) {
        /* if (logger.isDebugEnabled()) {
          logger.debug("  Loading "+url+"\n");
        }*/
        OptionManager.instance().loadOptionDescriptionFile(url);
      }
    } catch (MalformedURLException e) {
      throw new PluginException("The URL to the plugin.xml is wrong. ", e);
    } catch (IOException e) {
      throw new PluginException("cannot open jar file " + jarUrl+". ", e);
    } catch (ClassNotFoundException e) {
      throw new PluginException("The class "+e.getMessage() +" can't be found. ", e);
    }
    return true;
  }

  /**
   * Returns the Class object for the class with the specified name.
   *
   * @param classname the fully qualified name of the desired class
   * @return the Class object for the class with the specified name.
   */
  public Class<?> getClass(String classname) {
    return (Class<?>)classes.get(classname);
  }
 
  /**
   * Reads a jar file entry into a byte array.
   *
   * @param jis The jar input stream
   * @param jarName The name of a jar file entry
   * @throws PluginException
   */
  private void loadClassBytes(JarInputStream jis, String jarName) throws MaltChainedException {
    BufferedInputStream jarBuf = new BufferedInputStream(jis);
    ByteArrayOutputStream jarOut = new ByteArrayOutputStream();
    int b;
    try {
      while ((b = jarBuf.read()) != -1) {
        jarOut.write(b);
      }
      classByteArrays.put(jarName.substring(0, jarName.length() - 6), jarOut.toByteArray());
    } catch (IOException e) {
      throw new PluginException("Error reading entry " + jarName+". ", e);
    }
  }

  /**
   * Checks package access
   *
   * @param name  the package name
   */
  protected void checkPackageAccess(String name) {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null) {
      sm.checkPackageAccess(name);
    }
  }
 
  /* (non-Javadoc)
   * @see java.lang.Object#toString()
   */
  public String toString() {
    StringBuilder sb = new StringBuilder();
   
    sb.append("The MaltParser Plugin Loader (JarLoader)\n");
    sb.append("---------------------------------------------------------------------\n");
    for (String entry : new TreeSet<String>(classes.keySet())) {
      sb.append("   "+entry+"\n");
    }
    return sb.toString();
  }
}
TOP

Related Classes of org.maltparserx.core.plugin.JarLoader

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.