2015-10-17 1 views
0

Я делаю загрузчик классов, который может принимать банку, и на основании этого он может принимать имя пакета и ему разрешено загружать только классы, находящиеся в этом пакете. Когда я пытаюсь загрузить класс оттуда, я получаю сообщение об ошибке:NullPointerException в пользовательском ClassLoader - не удается найти zipEntry

Exception in thread "main" java.lang.NullPointerException 
at com.classloader.CustomClassLoader.getClassBytes(CustomClassLoader.java:64) 
at com.classloader.CustomClassLoader.getClass(CustomClassLoader.java:48) 
at com.classloader.CustomClassLoader.loadClass(CustomClassLoader.java:89) 
at com.classloader.TestJar.main(TestJar.java:46) 

Несмотря на то, что имя пакета и имя входа верны. Любые идеи, где проблема и как ее исправить? Код ниже, и я считаю, что это довольно понятно.

CustomLoader

package com.classloader; 

import java.io.ByteArrayOutputStream; 
import java.io.DataInputStream; 
import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.util.Enumeration; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.LinkedHashMap; 
import java.util.LinkedHashSet; 
import java.util.List; 
import java.util.Map; 
import java.util.Set; 
import java.util.zip.ZipEntry; 
import java.util.zip.ZipException; 
import java.util.zip.ZipFile; 

public class CustomClassLoader extends ClassLoader implements LoaderConstraints { 

private Map<String, Class> loaded = new HashMap<String, Class>(); 
private Map<String, String> available = new LinkedHashMap<String, String>(); 
private Set<String> allowed = new LinkedHashSet<String>(); 

public Set<String> getPermited() { 
    return allowed; 
} 

public Map<String, String> getAvailable() { 
    return available; 
} 

public Map<String, Class> getLoaded() { 
    return loaded; 
} 

public CustomClassLoader() { 
    super(CustomClassLoader.class.getClassLoader()); 
} 

private Class<?> getClass(String className, String pack) throws ClassNotFoundException { 

    Class<?> c = null; 
    String classPath = className.replace('.', File.separatorChar) + ".class"; 
    byte[] b = null; 
    try { 
     b = getClassBytes(classPath, pack); 

     c = defineClass(className, b, 0, b.length); 
     resolveClass(c); 

     return c; 
    } catch (IOException e) { 
     e.printStackTrace(); 

    } 
    return c; 
} 

private byte[] getClassBytes(String classPath, String pack) throws IOException { 
     ZipFile zip = new ZipFile(pack); 
     // System.out.println(classPath); classPath is right , as well as pack 
     ZipEntry entry = zip.getEntry(classPath);//This return null, for some reason ???  
     InputStream in = zip.getInputStream(zip.getEntry(classPath));  
     long size = entry.getSize(); 
     byte buff[] = new byte[(int)size]; 
     in.read(buff); 
     in.close(); 
     return buff; 
} 

    @Override 
    public Class<?> loadClass(String className) throws ClassNotFoundException { 



     Class<?> found = null; 

     if(loaded.get(className) != null){ 
         return loaded.get(className); 
       } 

     if(available.get(className) != null){ 
       if(allowed.contains(className) == true){ 
           found = getClass(className, available.get(className)); 
           if(found != null) 
             loaded.put(className, found); 
       } 
     } 
     else{ 
         found = super.loadClass(className); 
         if(found != null) 
           loaded.put(className, found); 
     } 

     return found; 
    } 

public void files(ZipFile zip, Map<String,String> list) throws ZipException, IOException{ 

    Enumeration<? extends ZipEntry> entries = zip.entries(); 

    while(entries.hasMoreElements()) { 
     ZipEntry entry = entries.nextElement(); 
     if (!entry.isDirectory() && entry.getName().endsWith(".class")) { 
      String className = entry.getName().replace('/', '.'); 
      list.put(className.substring(0, className.length() - ".class".length()) 
           ,zip.getName()); 
     }    
    } 

} 

public void addJar (File jarFile) { 
    try { 
     files(new ZipFile(jarFile), available); 
    } catch (ZipException e) { 

     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 

} 

public void deleteJar(File jarFile) { 
    Map<String,String> removes = new HashMap<String, String>(); 
    try { 
     files(new ZipFile(jarFile), removes); 
    } catch (ZipException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    available.keySet().removeAll(removes.keySet()); 

} 

public void allowPackage(final String p) { 
    for(String s : available.keySet()){ 
     if(s.startsWith(p)) 
      allowed.add(new String(s)); 
    } 

} 

public void denyPackage(final String p) { 
    Set<String> newPermited = new HashSet<String>(); 
    for(String s : allowed){ 
     if(!s.startsWith(p)) 
      newPermited.add(new String(s)); 
    } 
    allowed = newPermited; 

} 

} 

Тест

public static void main(String[] args) throws ZipException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException { 

CustomClassLoader ccl = new CustomClassLoader(); 
    ccl.addJar(new File("derby.jar")); 

    ccl.allowPackage("org.apache.derby.jdbc"); 

    //System.out.println(ccl.getAvailable().get("org.apache.derby.jdbc.EmbeddedDriver")); --> returns "derby.jar" 

    Class<?> clazz = ccl.loadClass("org.apache.derby.jdbc.EmbeddedDriver");//Gives exception , line 46 
    System.out.println(clazz.getClass()); 
    Object instance = clazz.newInstance(); 
    System.out.println(instance.getClass()); 
} 

derby.jar находится в папке проекта. Любая помощь приветствуется :)

ответ

0

Попробуйте заменить File.separatorChar на '/'