2012-10-19 14 views
8

Obecnie tworzę system wtyczek (Moja pierwsza próba), patrząc na kod innych narodów Próbuję złożyć mój własny program ładujący klasy i pobrać wtyczki z katalogu (będą to klasy pliki)Java - Dynamiczne ładowanie klas

Mój problem polega na tym, że za każdym razem, gdy próbuję załadować klasę za pomocą mojego programu ładującego klasy, żaden import wtyczki odwołującej się do programu nie zostanie znaleziony przez program ładujący klasy. (tj: MyClass rozszerza Plugin, com.mgmc.plugins noclassdeffound) Różne obszary nazw?

Niektóre przykładowy kod: classloader:

/* 


* To change this template, choose Tools | Templates 
* and open the template in the editor. 
*/ 
package com.mcgm.game.provider; 

import com.mcgm.utils.Misc; 
import com.mcgm.utils.Paths; 
import java.awt.AWTPermission; 
import java.io.*; 
import java.net.MalformedURLException; 
import java.net.SocketPermission; 
import java.net.URL; 
import java.security.CodeSigner; 
import java.security.CodeSource; 
import java.security.Permissions; 
import java.security.ProtectionDomain; 
import java.util.PropertyPermission; 
import java.util.logging.Level; 
import java.util.logging.Logger; 

/** 
* 
* @author Tom 
*/ 
public class GameClassLoader extends ClassLoader { 
private final ProtectionDomain domain; 
private final URL base; 

public GameClassLoader(final URL url) { 
    base = url; 
    final CodeSource codeSource = new CodeSource(base, (CodeSigner[]) null); 
    domain = new ProtectionDomain(codeSource, getPermissions()); 
} 

public void loadGames() { 
    for (File f : Paths.compiledFolder.listFiles()) { 
     try { 
      Class c = loadClass(f.getPath()); 
      Misc.outPrint(c.getName()); 
     } catch (ClassNotFoundException ex) { 
      Logger.getLogger(GameClassLoader.class.getName()).log(Level.SEVERE, null, ex); 
     } 
    } 
} 

private Permissions getPermissions() { 
    final Permissions ps = new Permissions(); 
    ps.add(new AWTPermission("accessEventQueue")); 
    ps.add(new PropertyPermission("user.home", "read")); 
    ps.add(new PropertyPermission("java.vendor", "read")); 
    ps.add(new PropertyPermission("java.version", "read")); 
    ps.add(new PropertyPermission("os.name", "read")); 
    ps.add(new PropertyPermission("os.arch", "read")); 
    ps.add(new PropertyPermission("os.version", "read")); 
    ps.add(new SocketPermission("*", "resolve")); 
    ps.add(new FilePermission(Paths.compiledFolder.getPath(), "read,write,delete")); 
    ps.setReadOnly(); 
    return ps; 
} 

@Override 
@SuppressWarnings("rawtypes") 
public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException { 
    Class clazz = findLoadedClass(name); 

    if (clazz == null) { 
     try { 
      byte[] bytes = loadClassData(name); 
      clazz = defineClass(name, bytes, 0, bytes.length, domain); 
      if (resolve) { 
       resolveClass(clazz); 
      } 
     } catch (final Exception e) { 
      clazz = super.loadClass(name, resolve); 
     } 
    } 

    return clazz; 
} 

public byte[] loadClassData(final String name) { 
    try { 
     final InputStream in = getResourceAsStream(name.replace('.', '/') + ".class"); 
     final byte[] buffer = new byte[4096]; 
     final ByteArrayOutputStream out = new ByteArrayOutputStream(); 
     int n; 
     while ((n = in.read(buffer, 0, 4096)) != -1) { 
      out.write(buffer, 0, n); 
     } 
     return out.toByteArray(); 
    } catch (IOException ex) { 
     Logger.getLogger(GameClassLoader.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    return null; 

} 

@Override 
public URL getResource(final String name) { 
    try { 
     return new URL(base, name); 
    } catch (final MalformedURLException e) { 
     return null; 
    } 
} 

@Override 
public InputStream getResourceAsStream(final String name) { 
    try { 
     return new URL(base, name).openStream(); 
    } catch (final IOException e) { 
     return null; 
    } 
} 
} 

Plugin wczytuję: (Adnotacja nie zostanie znaleziony albo)

import com.mcgm.GameInfo; 
import com.mcgm.game.Minigame; 
    @GameInfo(name = "RandomGame", 
description = "A really long and boring game.", 
authors = {"Tom", "Is", "The", "Greatest"}, 
version = 0.1, 
maxPlayers = 100, 
teamBased = false, 
teamAmount = -1, 
PvP = false) 
public class game extends Minigame { 
} 

Jak dzwonię klasę być załadowany :

GameClassLoader classLoader = new GameClassLoader(Paths.compiledFolder.toURI().toURL()); 
      classLoader.loadClass("game", true); 

Myślę, że to jest trywialne dla tych, którzy wiedzą, co robią!

+2

Nie jesteś człowiekiem ciężaru. Osoby w SO odpowiadają albo zadając pytania, albo odpowiadając na nie. To super. –

+0

Jestem zaskoczony: nie masz żadnych paczek? Oczekuję klasy classLoader.loadClass ("a.b.c.d.game", true); – Aubin

+0

Staram się nie dodawać pakietów, tylko ze względu na sposób, w jaki chcę, aby ludzie mogli dodawać własne minigry - wiem, że jest to sprzeczne z konwencjami, ale w ten sposób mogę mieć wszystkie minigry w jednym folderze (lub Jar) W końcu zeskanuje folder dla wszystkich plików, sprawdzi pliki .class i .jar i załaduje je (brak pakietów oznacza brak podkatalogów skanowania) –

Odpowiedz

4

WRESZCIE! Po półtora dnia poszukiwań, Vulcan wskazał mnie we właściwym kierunku: Zmieniłem GameClassLoader do:

public GameClassLoader(final URL url, ClassLoader parent) { 
    super(parent); 

a na końcu dodaje się bazowy adres URL do getResourceAsStream()

final InputStream in = getResourceAsStream(base.getFile() + "/" + name.replace('.', '/') + ".class"); 

Dzięki bardzo za twoją pomoc faceci!

+3

Cieszę się, że pomogłem! Nie zapomnij oznaczyć własnej odpowiedzi jako zaakceptowanej do przyszłego odniesienia do innych osób. – Vulcan

0

Spróbuj dodać do ścieżki prowadzącej ukośnik zasobów: final InputStream in = getResourceAsStream("/" + name.replace('.', '/') + ".class");

Jest rzeczą muszę próbować za każdym razem wzywam getResourceAsStream(). Po prostu próbowałem tego ponownie dla ciebie. Ścieżka tutaj odnosi się do pakietu klasy, który jest używany do wywoływania getResourceAsStream(), więc wiodący slash jest potrzebny, aby powiedzieć "startuj z roota".

+0

Niestety to powstrzymuje go od ładowania, problem nie ładuje klasy; ładuje zależności klas: java.lang.NoClassDefFoundError: com/mcgm/game/Minigame Klasa została znaleziona absolutnie w porządku. –

Powiązane problemy