Encore des modifications

This commit is contained in:
Mysaa
2021-05-23 02:31:16 +02:00
parent 42ad4335b2
commit 3640b97dde
5 changed files with 133 additions and 80 deletions
+5
View File
@@ -9,6 +9,9 @@
// Apply the java-library plugin to add support for Java Library // Apply the java-library plugin to add support for Java Library
apply plugin: 'java-library' apply plugin: 'java-library'
apply plugin: 'eclipse' apply plugin: 'eclipse'
apply plugin: 'java'
compileJava.options.encoding = 'UTF-8'
// In this section you declare where to find the dependencies of your project // In this section you declare where to find the dependencies of your project
repositories { repositories {
@@ -74,6 +77,8 @@ dependencies {
compile 'com.thedeanda:lorem:2.1' compile 'com.thedeanda:lorem:2.1'
compile 'commons-io:commons-io:2.6'
// https://mvnrepository.com/artifact/mysql/mysql-connector-java // https://mvnrepository.com/artifact/mysql/mysql-connector-java
compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.15' compile group: 'mysql', name: 'mysql-connector-java', version: '8.0.15'
+2 -10
View File
@@ -1,18 +1,10 @@
/* /*
* This settings file was generated by the Gradle 'init' task. * This file was generated by the Gradle 'init' task.
* *
* The settings file is used to specify which projects to include in your build. * The settings file is used to specify which projects to include in your build.
* In a single project build this file can be empty or even removed.
* *
* Detailed information about configuring a multi-project build in Gradle can be found * Detailed information about configuring a multi-project build in Gradle can be found
* in the user guide at https://docs.gradle.org/4.3/userguide/multi_project_builds.html * in the user guide at https://docs.gradle.org/4.8.1/userguide/multi_project_builds.html
*/
/*
// To declare projects as part of a multi-project build use the 'include' method
include 'shared'
include 'api'
include 'services:webservice'
*/ */
rootProject.name = 'Juliabot' rootProject.name = 'Juliabot'
@@ -1007,7 +1007,7 @@ public class EcouteurDEvents implements EventListener{
case "HttpRequestEvent": case "HttpRequestEvent":
System.err.println("EN attente d'un dev assez motivé pour coder ce foutu HttpRequestEvent !!!"); //TODO System.err.println("EN attente d'un dev assez motivé pour coder ce foutu HttpRequestEvent !!!");
return; return;
default: default:
throw new IllegalStateException("Cette méthode n'est pas a jour avec le JDA ... je gère pas "+event.getClass().getName()); throw new IllegalStateException("Cette méthode n'est pas a jour avec le JDA ... je gère pas "+event.getClass().getName());
+82 -43
View File
@@ -8,6 +8,8 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.commons.io.output.TeeOutputStream;
import com.bernard.juliabot.JuliaAddon.JarWithMultipleAddonsException; import com.bernard.juliabot.JuliaAddon.JarWithMultipleAddonsException;
import com.bernard.juliabot.JuliaAddon.JuliaClassLoader; import com.bernard.juliabot.JuliaAddon.JuliaClassLoader;
import com.bernard.juliabot.api.*; import com.bernard.juliabot.api.*;
@@ -41,6 +43,8 @@ public class Julia {
Connection eventDatabase; Connection eventDatabase;
Connection juliaDatabase; Connection juliaDatabase;
JuliaErrPrintStream syserr;
public Julia() { public Julia() {
@@ -62,37 +66,49 @@ public class Julia {
connectionProps.put("useSSL", "true"); connectionProps.put("useSSL", "true");
connectionProps.put("requireSSL", "true"); connectionProps.put("requireSSL", "true");
try { try {
Class.forName("com.mysql.jdbc.Driver");
eventDatabase = DriverManager.getConnection("jdbc:mysql://192.168.1.41:3306/juliaEvents", connectionProps); eventDatabase = DriverManager.getConnection("jdbc:mysql://192.168.1.41:3306/juliaEvents", connectionProps);
juliaDatabase = DriverManager.getConnection("jdbc:mysql://192.168.1.41:3306/julia", connectionProps); juliaDatabase = DriverManager.getConnection("jdbc:mysql://192.168.1.41:3306/julia", connectionProps);
} catch (SQLException | ClassNotFoundException e) { } catch (SQLException e) {
System.err.println("Impossible de se connecter a la BDD, ca ne sers a rien de lancer JuL'IA du coup ... Bonne nuit"); System.err.println("Impossible de se connecter a la BDD, ca ne sers a rien de lancer JuL'IA du coup ... Bonne nuit");
e.printStackTrace(); e.printStackTrace();
syserr.flush();
return; return;
} }
System.out.println("La BDD est charge" + eventDatabase+","+juliaDatabase); System.out.println("La BDD est chargée" + eventDatabase+","+juliaDatabase);
// Dmarrage de JDA et du Bot // Démarrage de JDA et du Bot
try { try {
lecouteur = new EcouteurDEvents(this); lecouteur = new EcouteurDEvents(this);
jda = new JDABuilder(AccountType.BOT).setToken(token).addEventListener(lecouteur).build(); jda = new JDABuilder(AccountType.BOT).setToken(token).addEventListener(lecouteur).build();
jda.awaitReady(); jda.awaitReady();
} catch(Exception e) { } catch(Exception e) {
System.err.println("Impossible de dmarrer JuL'IA"); System.err.println("Impossible de démarrer JuL'IA");
e.printStackTrace(); e.printStackTrace();
syserr.flush();
return; return;
} }
jda.getGuildById(222947179017404416L).getTextChannelById(460935684669046784L).sendMessage(LoremIpsum.getInstance().getWords(10, 15)).complete(); jda.getGuildById(222947179017404416L).getTextChannelById(460935684669046784L).sendMessage(LoremIpsum.getInstance().getWords(10, 15)).complete();
syserr = new JuliaErrPrintStream(jda.getGuildById(222947179017404416L).getTextChannelById(576469792735756309L));
TeeOutputStream tos = new TeeOutputStream(System.err, syserr.printStream());
System.setErr(new PrintStream(tos));
Timer syserrtimer = new Timer("Syserr-refresh", true);
syserrtimer.schedule(new TimerTask() {
@Override
public void run() {Julia.theJulia().syserr.flushMessage();}
} , 0, 1000);
//Launch update to see every addon in juliaddon/ //Launch update to see every addon in juliaddon/
update();//Va remplir la map avalivableAddons update();//Va remplir la map avalivableAddons
//Dmarrage du sysin //Démarrage du sysin
sysinator = new ReadLoop(); sysinator = new ReadLoop();
Thread sysinThread = new Thread(sysinator, "sysin-reader"); Thread sysinThread = new Thread(sysinator, "sysin-reader");
sysinThread.start(); sysinThread.start();
@@ -101,7 +117,7 @@ public class Julia {
//Loader l'internalddon (hard-coded) //Loader l'internalddon (hard-coded)
//laboratoires.get('#').loadAddon("com.bernard.juliabot.internaddon", "beta", false);//Pas besoin d'update, il viens d'etre fait //laboratoires.get('#').loadAddon("com.bernard.juliabot.internaddon", "beta", false);//Pas besoin d'update, il viens d'etre fait
//Load addons in # and in $ (rcupere ce qu'il faut dans la BDD) //Load addons in # and in $ (récupere ce qu'il faut dans la BDD)
Set<String> toLoad = new HashSet<>(); Set<String> toLoad = new HashSet<>();
try { try {
Statement statement = juliaDatabase.createStatement(); Statement statement = juliaDatabase.createStatement();
@@ -115,13 +131,15 @@ public class Julia {
} catch (SQLException e) { } catch (SQLException e) {
System.err.println("Impossible de charger les plugins, vous aurez tout a faire a la main !"); System.err.println("Impossible de charger les plugins, vous aurez tout a faire a la main !");
e.printStackTrace(); e.printStackTrace();
syserr.flush();
} }
System.out.println("Les addons charger : "+toLoad); System.out.println("Les addons à charger : "+toLoad);
try { try {
juliaDatabase.createStatement().executeUpdate("DELETE FROM loadedJuliaddons"); juliaDatabase.createStatement().executeUpdate("DELETE FROM loadedJuliaddons");
} catch (SQLException e) { } catch (SQLException e) {
System.err.println("Je n'ai pas pu vider la table ... atention aux doublons !"); System.err.println("Je n'ai pas pu vider la table ... atention aux doublons !");
e.printStackTrace(); e.printStackTrace();
syserr.flush();
} }
for(String l : toLoad) { for(String l : toLoad) {
@@ -134,12 +152,13 @@ public class Julia {
} }
public synchronized void update() { public synchronized void update() {
Map<String,JuliaAddon> avalivableAddons = new HashMap<>(); Map<String,JuliaAddon> avalivableAddons = new HashMap<>();
File juliaddonFolder = new File(juliaddonsFolder); File juliaddonFolder = new File(juliaddonsFolder);
for(File f : juliaddonFolder.listFiles((parent,name)->name.toLowerCase().endsWith(".jar"))){ for(File f : juliaddonFolder.listFiles((parent,name)->name.toLowerCase().endsWith(".jar"))){
if(fileTrack.containsKey(f.getName()) && fileTrack.get(f.getName()) == f.lastModified()) if(fileTrack.containsKey(f.getName()) && fileTrack.get(f.getName()) == f.lastModified())
continue;//Le fichier n'a pas boug, pas besoin de le relire continue;//Le fichier n'a pas bougé, pas besoin de le relire
fileTrack.put(f.getName(), f.lastModified()); fileTrack.put(f.getName(), f.lastModified());
try { try {
JarFile jar = new JarFile(f); JarFile jar = new JarFile(f);
@@ -147,7 +166,7 @@ public class Julia {
JuliaAddon addon = new JuliaAddon(jar); JuliaAddon addon = new JuliaAddon(jar);
String id = addon.pkg+":"+addon.version; String id = addon.pkg+":"+addon.version;
if(avalivableAddons.containsKey(id)) if(avalivableAddons.containsKey(id))
System.err.println("L'addon "+id+" a dj t charg dans les fichiers "+avalivableAddons.get(id).jarFile.getName()+" et "+jar.getName()+", je garde que le deuxime !"); System.err.println("L'addon "+id+" a déjà été chargée dans les fichiers "+avalivableAddons.get(id).jarFile.getName()+" et "+jar.getName()+", je garde que le deuxime !");
avalivableAddons.put(id, addon); avalivableAddons.put(id, addon);
}catch(JarWithMultipleAddonsException e) { }catch(JarWithMultipleAddonsException e) {
Set<Set<JarEntry>> addonsEntries = e.getAddonsEntries(); Set<Set<JarEntry>> addonsEntries = e.getAddonsEntries();
@@ -156,26 +175,38 @@ public class Julia {
JuliaAddon addon = new JuliaAddon(jar, entry); JuliaAddon addon = new JuliaAddon(jar, entry);
String id = addon.pkg+":"+addon.version; String id = addon.pkg+":"+addon.version;
if(avalivableAddons.containsKey(id)) if(avalivableAddons.containsKey(id))
System.err.println("L'addon "+id+" a dj t charg dans les fichiers "+avalivableAddons.get(id).jarFile.getName()+" et "+jar.getName()+", je garde que le deuxime !"); System.err.println("L'addon "+id+" a déjà été chargée dans les fichiers "+avalivableAddons.get(id).jarFile.getName()+" et "+jar.getName()+", je garde que le deuxime !");
avalivableAddons.put(id, addon); avalivableAddons.put(id, addon);
} catch (JarWithMultipleAddonsException e1) { } catch (JarWithMultipleAddonsException e1) {
System.err.println("THIS SHOULD NOT HAPPEN"); System.err.println("THIS SHOULD NOT HAPPEN");
System.err.println("TOUT EST CASS ALERTE ROUGE !"); System.err.println("TOUT EST CASSÉ ALERTE ROUGE !");
System.err.println("C'est problematique, j'teint tout, c'est mieux"); System.err.println("C'est problematique, j'éteint tout, c'est mieux");
syserr.flush();
System.exit(31415926); System.exit(31415926);
} }
} }
}catch(IllegalStateException e) { }catch(IllegalStateException e) {
System.err.println(e.getMessage()); System.err.println(e.getMessage());
syserr.flush();
} }
} catch (IOException e) { } catch (IOException e) {
System.err.println("Impossible de lire le fichier jar "+f.getName()); System.err.println("Impossible de lire le fichier jar "+f.getName());
e.printStackTrace(); e.printStackTrace();
syserr.flush();
} }
syserr.flush();
} }
this.avalivableAddons = avalivableAddons; this.avalivableAddons = avalivableAddons;
} }
public Connection getJuliaDatabase() {
return juliaDatabase;
}
public class ReadLoop implements Runnable{ public class ReadLoop implements Runnable{
boolean running = false; boolean running = false;
@@ -189,8 +220,8 @@ public class Julia {
while(running) { while(running) {
String request = sc.nextLine(); String request = sc.nextLine();
System.out.println("Je suis cens avoir lu la commande "+request); System.out.println("Je suis censée avoir lu la commande "+request);
//TODO ragir ... //TODO réagir ...
@@ -200,6 +231,7 @@ public class Julia {
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
System.err.println("Erreur de lecture du sysin, je deviens sourd"); System.err.println("Erreur de lecture du sysin, je deviens sourd");
e.printStackTrace(); e.printStackTrace();
syserr.flush();
running=false; running=false;
} }
} }
@@ -210,11 +242,11 @@ public class Julia {
public class Laboratory{ public class Laboratory{
char laboratory; char laboratory;
Map<String,JuliaAddon> loadedAddons;//<pkg,JuliaAddon> : les addons chargs dans ce laboratoire Map<String,JuliaAddon> loadedAddons;//<pkg,JuliaAddon> : les addons chargés dans ce laboratoire
Map<String,CommandeSurchargee> loadedCommands;//<commandName,Calling method> : les commandes charges Map<String,CommandeSurchargee> loadedCommands;//<commandName,Calling method> : les commandes chargées
Map<Class<?>,Object> callerObjects; // <Classe, objet de cette classe> : Les objets instancis dans ce laboratoire Map<Class<?>,Object> callerObjects; // <Classe, objet de cette classe> : Les objets instanciés dans ce laboratoire
Map<String,String> aliases;// <alias, vrainom> Map<String,String> aliases;// <alias, vrainom>
Map<Class<? extends Event>,Set<Method>> loadedEvents;// Les mthodes appeler quand un event de cette classe est lanc Map<Class<? extends Event>,Set<Method>> loadedEvents;// Les méthodes à appeler quand un event de cette classe est lancé
Map<String,JuliaClassLoader> clazzTrack;//<className,JuliaClassLoader which loaded ths class in this laboratory> Map<String,JuliaClassLoader> clazzTrack;//<className,JuliaClassLoader which loaded ths class in this laboratory>
@@ -245,7 +277,7 @@ public class Julia {
public synchronized void loadAddon(String pkg,String version,boolean update) { public synchronized void loadAddon(String pkg,String version,boolean update) {
if(update)Julia.this.update(); if(update)Julia.this.update();
if(loadedAddons.containsKey(pkg)) if(loadedAddons.containsKey(pkg))
throw new IllegalStateException("Impossible de charger le juliaddon "+pkg+" dans le laboratoire "+laboratory+", il est dj charg"); throw new IllegalStateException("Impossible de charger le juliaddon "+pkg+" dans le laboratoire "+laboratory+", il est dj charg");
try { try {
PreparedStatement s = juliaDatabase.prepareStatement("INSERT INTO loadedJuliaddons (ID,laboratory,pkg,version) VALUES (NULL,?,?,?)"); PreparedStatement s = juliaDatabase.prepareStatement("INSERT INTO loadedJuliaddons (ID,laboratory,pkg,version) VALUES (NULL,?,?,?)");
s.setString(1, Character.toString(laboratory)); s.setString(1, Character.toString(laboratory));
@@ -255,6 +287,7 @@ public class Julia {
} catch (SQLException e) { } catch (SQLException e) {
System.err.println("Je ne peux pas notifier la BDD que je load le plugin, je le load pas du coup ..."); System.err.println("Je ne peux pas notifier la BDD que je load le plugin, je le load pas du coup ...");
e.printStackTrace(); e.printStackTrace();
syserr.flush();
return; return;
} }
@@ -268,17 +301,18 @@ public class Julia {
public synchronized void unloadAddon(String pkg) { public synchronized void unloadAddon(String pkg) {
if(!loadedAddons.containsKey(pkg)) if(!loadedAddons.containsKey(pkg))
return;//SI l'addon n'est pas charg, on a rien besoin de faire return;//SI l'addon n'est pas chargé, on a rien besoin de faire
try { try {
PreparedStatement s = juliaDatabase.prepareStatement("DELETE FROM juliaddons WHERE laboratory=? AND pkg=?"); PreparedStatement s = juliaDatabase.prepareStatement("DELETE FROM juliaddons WHERE laboratory=? AND pkg=?");
s.setString(1, Character.toString(laboratory)); s.setString(1, Character.toString(laboratory));
s.setString(2, pkg); s.setString(2, pkg);
if(s.executeUpdate() != 1) { if(s.executeUpdate() != 1) {
System.err.println("Ce juliaddon n'tait pas charg dans la BDD ... trs bizzare"); System.err.println("Ce juliaddon n'était pas chargé dans la BDD ... très bizzare");
} }
} catch (SQLException e) { } catch (SQLException e) {
System.err.println("Je ne peux pas notifier la BDD que je unload le plugin, je l'unload mais vous risquez d'avoir des problemes ..."); System.err.println("Je ne peux pas notifier la BDD que je unload le plugin, je l'unload mais vous risquez d'avoir des problemes ...");
e.printStackTrace(); e.printStackTrace();
syserr.flush();
return; return;
} }
JuliaAddon addon = loadedAddons.get(pkg); JuliaAddon addon = loadedAddons.get(pkg);
@@ -292,17 +326,17 @@ public class Julia {
//Verify that commands asks for good argument //Verify that commands asks for good argument
if(!Arrays.stream(m.getParameterTypes()).map(CCommande.class::isAssignableFrom).reduce(Boolean::logicalAnd).get()) if(!Arrays.stream(m.getParameterTypes()).map(CCommande.class::isAssignableFrom).reduce(Boolean::logicalAnd).get())
throw new IllegalArgumentException("Les paramtres d'une commande doivent tous implmenter CCommande"); throw new IllegalArgumentException("Les paramètres d'une commande doivent tous implémenter CCommande");
try { try {
m.setAccessible(true); m.setAccessible(true);
}catch(SecurityException e) { }catch(SecurityException e) {
throw new IllegalArgumentException("Impossible de me donner le droit d'xecuter "+m.toGenericString()); throw new IllegalArgumentException("Impossible de me donner le droit d'éxecuter "+m.toGenericString());
} }
// Argument OK // Argument OK
//Register aliases //Register aliases
// print un message d'erreur si un alias a dj t enregistr pour une autre commande // print un message d'erreur si un alias a déjà été enregistré pour une autre commande
Arrays.stream(c.aliases()) Arrays.stream(c.aliases())
.filter(aliases::containsKey).filter(alias -> !aliases.get(alias).equals(c.name())) .filter(aliases::containsKey).filter(alias -> !aliases.get(alias).equals(c.name()))
.forEach(alias -> System.err.println("Faut remplacer l'alias "+alias+", plus de deux addons l'utilisent")); .forEach(alias -> System.err.println("Faut remplacer l'alias "+alias+", plus de deux addons l'utilisent"));
@@ -311,7 +345,7 @@ public class Julia {
//Cration de l'objet si ca n'a pas t fait //Création de l'objet si ca n'a pas été fait
checkObject(m.getDeclaringClass()); checkObject(m.getDeclaringClass());
//Enregistre la nouvelle surcharge //Enregistre la nouvelle surcharge
@@ -323,10 +357,10 @@ public class Julia {
public synchronized void registerEvent(Method m, Discord d) { public synchronized void registerEvent(Method m, Discord d) {
Class<?>[] parameters = m.getParameterTypes(); Class<?>[] parameters = m.getParameterTypes();
if(parameters.length != 1) if(parameters.length != 1)
throw new IllegalArgumentException("Les catcheurs d'events ne doivent avoir qu'un seul paramtre, extends Event, la mthde fautive tant "+m.toGenericString()); throw new IllegalArgumentException("Les catcheurs d'events ne doivent avoir qu'un seul paramétre, extends Event, la méthode fautive étant "+m.toGenericString());
if(!Event.class.isAssignableFrom(parameters[0])) if(!Event.class.isAssignableFrom(parameters[0]))
throw new IllegalArgumentException("Les catcheur d'events ne doivent avoir qu'un paramtre, qui doit extends Event, la mthode fautive tant "+m.toGenericString()); throw new IllegalArgumentException("Les catcheur d'events ne doivent avoir qu'un paramètre, qui doit extends Event, la méthode fautive étant "+m.toGenericString());
//La mthode est vrifie //La méthode est vérifiée
if(!loadedEvents.containsKey(parameters[0])) if(!loadedEvents.containsKey(parameters[0]))
loadedEvents.put((Class<? extends Event>) parameters[0], new HashSet<>()); loadedEvents.put((Class<? extends Event>) parameters[0], new HashSet<>());
checkObject(m.getDeclaringClass()); checkObject(m.getDeclaringClass());
@@ -335,7 +369,7 @@ public class Julia {
public synchronized void unregisterCommand(Method m,Command c) { public synchronized void unregisterCommand(Method m,Command c) {
if(loadedCommands.containsKey(c.name())) if(loadedCommands.containsKey(c.name()))
throw new IllegalStateException("Une commade "+c.name()+" a dj t enregistre !"); throw new IllegalStateException("Une commade "+c.name()+" a déjà été enregistrée !");
//Unregister aliases //Unregister aliases
for(String alias:c.aliases()) for(String alias:c.aliases())
aliases.remove(alias, c.name());//Evite de supprimer les alias d'autres commandes qui auraient overwrite aliases.remove(alias, c.name());//Evite de supprimer les alias d'autres commandes qui auraient overwrite
@@ -343,10 +377,10 @@ public class Julia {
loadedCommands.remove(c.name()); loadedCommands.remove(c.name());
} }
@SuppressWarnings("unchecked")//Pour un truc qui n'ets pas cens arriver, donc bon ... @SuppressWarnings("unchecked")//Pour un truc qui n'ets pas censé arriver, donc bon ...
public synchronized void unregisterEvent(Method m, Discord d) { public synchronized void unregisterEvent(Method m, Discord d) {
Class<?>[] parameters = m.getParameterTypes(); Class<?>[] parameters = m.getParameterTypes();
if(!loadedEvents.containsKey(parameters[0]))//N'est pas cens arriver, si l'event a t load, cette HashSet devrai exister if(!loadedEvents.containsKey(parameters[0]))//N'est pas censé arriver, si l'event a été load, cette HashSet devrai exister
loadedEvents.put((Class<? extends Event>) parameters[0], new HashSet<>()); loadedEvents.put((Class<? extends Event>) parameters[0], new HashSet<>());
loadedEvents.get(parameters[0]).remove(m); loadedEvents.get(parameters[0]).remove(m);
} }
@@ -370,7 +404,7 @@ public class Julia {
case "net.dv8tion.jda.core.JDA": case "net.dv8tion.jda.core.JDA":
params[i] = Julia.this.jda; params[i] = Julia.this.jda;
break; break;
//TODO completer les paramtres //TODO completer les paramètres
default: default:
continue constLoop; continue constLoop;
@@ -384,8 +418,8 @@ public class Julia {
if(o != null)break;//Sortir de la boucle, on a notre joli objet if(o != null)break;//Sortir de la boucle, on a notre joli objet
} }
if(o == null) { if(o == null) {
System.err.println("Je ne peux pas crer l'objet, faudait mettre un costructeur valide (en mon sens :P)"); System.err.println("Je ne peux pas créer l'objet, faudait mettre un costructeur valide (en mon sens :P)");
System.err.println("Je fais tout planter du coup, votrez addon sera pas charg !"); System.err.println("Je fais tout planter du coup, votrez addon sera pas chargé !");
throw new IllegalStateException("Pas de constructeur valable"); throw new IllegalStateException("Pas de constructeur valable");
} }
callerObjects.put(clazz, o); callerObjects.put(clazz, o);
@@ -400,14 +434,15 @@ public class Julia {
try { try {
m.invoke(callable, event); m.invoke(callable, event);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
System.err.println("C'est pas joli joli, je suis cens lancer une mthode laquelle je n'ai pas accs : "+m.toGenericString()); System.err.println("C'est pas joli joli, je suis censé lancer une méthode à laquelle je n'ai pas accès : "+m.toGenericString());
throw new IllegalStateException(e); throw new IllegalStateException(e);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
System.err.println("La mthode n'est pas cense recevoir de tels erreurs, je devrai avoir chck la mthode, mais elle ne veut pas de mes arguments ... : "+m.toGenericString()); System.err.println("La méthode n'est pas censée recevoir de tels erreurs, je devrai avoir chécké la méthode, mais elle ne veut pas de mes arguments ... : "+m.toGenericString());
throw new IllegalStateException(e); throw new IllegalStateException(e);
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
System.err.println("La mthode lanc cette exception ... je la relance derrire du coup : "+m.toGenericString()); System.err.println("La méthode à lancé cette exception ... je la relance derrière du coup : "+m.toGenericString());
e.printStackTrace(); e.printStackTrace();
syserr.flush();
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
} }
@@ -427,7 +462,7 @@ public class Julia {
CommandeSurchargee scommande = loadedCommands.get(cname); CommandeSurchargee scommande = loadedCommands.get(cname);
Method m = scommande.getExecutor(content); Method m = scommande.getExecutor(content);
if(m==null) if(m==null)
throw new IllegalArgumentException("La commande "+cname+" alias "+name+" n'est pas prvue pour s'xecuter avec un "+content.getClass().getCanonicalName()); throw new IllegalArgumentException("La commande "+cname+" alias "+name+" n'est pas prévue pour s'éxecuter avec un "+content.getClass().getCanonicalName());
final Object[] parameters = new Object[m.getParameterCount()]; final Object[] parameters = new Object[m.getParameterCount()];
Arrays.fill(parameters, content); Arrays.fill(parameters, content);
final Object caller = callerObjects.get(m.getDeclaringClass()); final Object caller = callerObjects.get(m.getDeclaringClass());
@@ -442,18 +477,22 @@ public class Julia {
m.invoke(caller, parameters); m.invoke(caller, parameters);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
System.err.println("Problme d'accs la mthode "+m.toGenericString()+" ... c'est embtant"); System.err.println("Problème d'accès à la méthode "+m.toGenericString()+" ... c'est embêtant");
e.printStackTrace(); e.printStackTrace();
syserr.flush();
called.setExitValue(e.getCause()); called.setExitValue(e.getCause());
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
System.err.println("trange, je pensais avoir check les arguments"); System.err.println("Étrange, je pensais avoir check les arguments");
e.printStackTrace(); e.printStackTrace();
syserr.flush();
called.setExitValue(e.getCause()); called.setExitValue(e.getCause());
} catch (InvocationTargetException e) { } catch (InvocationTargetException e) {
//Lui a plant //Lui a planté
called.setExitValue(e.getCause()); called.setExitValue(e.getCause());
System.err.println("L'appel a la commande a planté ...");
e.getCause().printStackTrace();
} }
syserr.flush();
called.ended(); called.ended();
}, "commande-"+cname+".aka."+name+"-"+System.nanoTime()); }, "commande-"+cname+".aka."+name+"-"+System.nanoTime());
@@ -8,6 +8,7 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
@@ -15,9 +16,9 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.bernard.juliabot.Julia.Laboratory;
import com.bernard.juliabot.api.Command; import com.bernard.juliabot.api.Command;
import com.bernard.juliabot.api.Discord; import com.bernard.juliabot.api.Discord;
import com.bernard.juliabot.Julia.Laboratory;
import com.bernard.juliabot.api.JuLIAddon; import com.bernard.juliabot.api.JuLIAddon;
public class JuliaAddon { public class JuliaAddon {
@@ -58,12 +59,12 @@ public class JuliaAddon {
//String jarExtra = jarMatcher.group(3); //String jarExtra = jarMatcher.group(3);
version = jarVersion; version = jarVersion;
//Sets addon,pkg,version(si redefini) et addonClass //Sets addon,pkg,version(si redefini) et addonClass
unassignedClassLoader = new JuliaClassLoader(jar, entriesToRead,new DummyLaboratory()); unassignedClassLoader = new JuliaClassLoader(jar, entriesToRead,new DummyLaboratory());
} }
public synchronized JuliaClassLoader newClassLoader(Laboratory laboratory) { public synchronized JuliaClassLoader newClassLoader(Laboratory laboratory) {
if(unassignedClassLoader==null) if(unassignedClassLoader==null)
try { try {
@@ -97,6 +98,8 @@ public class JuliaAddon {
public class JuliaClassLoader extends ClassLoader { public class JuliaClassLoader extends ClassLoader {
Map<String,Class<?>> loadedClasses; Map<String,Class<?>> loadedClasses;
Set<JarEntry> entries;
JarFile jar;
Laboratory laboratory = null; Laboratory laboratory = null;
HashSet<Method> registeredCommands; HashSet<Method> registeredCommands;
@@ -104,6 +107,8 @@ public class JuliaAddon {
public JuliaClassLoader(JarFile jar,Set<JarEntry> entriesToRead,Laboratory labo) throws JarWithMultipleAddonsException { public JuliaClassLoader(JarFile jar,Set<JarEntry> entriesToRead,Laboratory labo) throws JarWithMultipleAddonsException {
super(); super();
entries = entriesToRead;
this.jar = jar;
loadedClasses = new HashMap<>(); loadedClasses = new HashMap<>();
this.laboratory = labo; this.laboratory = labo;
Set<Class<?>> readClasses = new HashSet<>(); Set<Class<?>> readClasses = new HashSet<>();
@@ -116,11 +121,12 @@ public class JuliaAddon {
//Le fichier est un .class //Le fichier est un .class
try { try {
String className = entry.getName().replaceAll("/", ".").substring(0, entry.getName().length()-".class".length()); String className = entry.getName().replaceAll("/", ".").substring(0, entry.getName().length()-".class".length());
byte[] classData = new byte[(int) entry.getSize()]; Class<?> clazz;
InputStream reader = jar.getInputStream(entry); try {
reader.read(classData); clazz = loadClass(className);
reader.close(); } catch (ClassNotFoundException e) {
Class<?> clazz = defineClass(className,classData,0,(int) entry.getSize()); throw new IllegalStateException("J'ai demandé a charger une classe sachant que je l'ai dans le jar, mais j'ai quand meme pas réussi à la charger ...", e);
}
readClasses.add(clazz); readClasses.add(clazz);
//Instantiated class //Instantiated class
@@ -131,7 +137,7 @@ public class JuliaAddon {
throw new IllegalArgumentException("Le nom de la classe est invalide pour un Juliaddon (il faut au moins trois de profondeur dans le package) : "+clazz.getName()); throw new IllegalArgumentException("Le nom de la classe est invalide pour un Juliaddon (il faut au moins trois de profondeur dans le package) : "+clazz.getName());
String pkg = m.group(1); String pkg = m.group(1);
if(juliaddons.containsKey(pkg)) if(juliaddons.containsKey(pkg))
throw new IllegalArgumentException("Il existe deja un juliaddon dans le package "+pkg+" , déplacez "+clazz.getName()+" ou "+juliaddons.get(pkg).getName()); throw new IllegalArgumentException("Il existe deja un juliaddon dans le package "+pkg+" , dplacez "+clazz.getName()+" ou "+juliaddons.get(pkg).getName());
juliaddons.put(pkg, entry); juliaddons.put(pkg, entry);
//If overwritten, will JarWithMultipleAddonsException //If overwritten, will JarWithMultipleAddonsException
JuliaAddon.this.addon = clazz.getAnnotation(JuLIAddon.class); JuliaAddon.this.addon = clazz.getAnnotation(JuLIAddon.class);
@@ -148,18 +154,14 @@ public class JuliaAddon {
System.err.println("Vous essayez de mettre cette classe dans un package interdit ! Honte a vous"); System.err.println("Vous essayez de mettre cette classe dans un package interdit ! Honte a vous");
e.printStackTrace(); e.printStackTrace();
continue; continue;
} catch (IOException e) {
System.err.println("Impossible de lire les données du fichier "+entry.getName()+" dans le jar "+jar.getName());
e.printStackTrace();
continue;
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
System.err.println("Le fichier "+entry.getName()+" ne décris pas un Juliaddon valide, il n'a donc pas été chargé, mais faites attention !"); System.err.println("Le fichier "+entry.getName()+" ne dcris pas un Juliaddon valide, il n'a donc pas t charg, mais faites attention !");
e.printStackTrace(); e.printStackTrace();
continue; continue;
} }
} }
//Toutes les classes du Jar ont été lues : Si plusieurs addons, on rentre //Toutes les classes du Jar ont t lues : Si plusieurs addons, on rentre
//dans le if pour lever l'exception, sinon, on initialise le JuliaClassLoader //dans le if pour lever l'exception, sinon, on initialise le JuliaClassLoader
if(juliaddons.size() > 1) { if(juliaddons.size() > 1) {
Set<Set<JarEntry>> addonsEntries = new HashSet<>();//<pkg,Enum of classes associated with this plugin> Set<Set<JarEntry>> addonsEntries = new HashSet<>();//<pkg,Enum of classes associated with this plugin>
@@ -179,7 +181,7 @@ public class JuliaAddon {
while((lastPoint = pkg.lastIndexOf(".")) != -1) {//Il y a encore des dossier a monter while((lastPoint = pkg.lastIndexOf(".")) != -1) {//Il y a encore des dossier a monter
pkg = pkg.substring(0, lastPoint+1);//Recule de un dossier pkg = pkg.substring(0, lastPoint+1);//Recule de un dossier
if(addonsEntriesVector.containsKey(pkg)) { if(addonsEntriesVector.containsKey(pkg)) {
//Pas besoin de tester la validite du pkg car si invalide il ne serai pas rentré dans le Set juliaddons //Pas besoin de tester la validite du pkg car si invalide il ne serai pas rentr dans le Set juliaddons
addonsEntriesVector.get(pkg).add(entry); addonsEntriesVector.get(pkg).add(entry);
continue eLoop; continue eLoop;
} }
@@ -193,9 +195,7 @@ public class JuliaAddon {
} }
//Initialisation du JuliaClassloader //Initialisation du JuliaClassloader
//Les parametres addon, pkg,version et addonCLass ont déjà été initialisés lors de l'itération des fichiers du jar //Les parametres addon, pkg,version et addonCLass ont dj t initialiss lors de l'itration des fichiers du jar
for(Class<?> clazz : readClasses)
loadedClasses.put(clazz.getName(), clazz);
} }
@@ -204,13 +204,30 @@ public class JuliaAddon {
public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
if(loadedClasses.containsKey(name)) if(loadedClasses.containsKey(name))
return loadedClasses.get(name); return loadedClasses.get(name);
//System.out.println("I was asked to load "+name); ///Recherche d'une entry qui collerai
String fileName = name.replaceAll("\\.", "/")+".class";
Optional<JarEntry> oentry = entries.stream().filter(je -> je.getName().equals(fileName)).findAny();
if(oentry.isPresent()) {
try {
JarEntry entry = oentry.get();
byte[] classData = new byte[(int) entry.getSize()];
InputStream reader = jar.getInputStream(entry);
reader.read(classData);
reader.close();
Class<?> clazz = defineClass(name,classData,0,(int) entry.getSize());
loadedClasses.put(name, clazz);
return clazz;
} catch (IOException e) {
System.err.println("Impossible de lire les donnes du fichier "+oentry.get().getName()+" dans le jar "+jar.getName()+" je peux vous dire adieu je pense");
e.printStackTrace();
}
}
JuliaClassLoader cl = laboratory.findClassLoader(name); JuliaClassLoader cl = laboratory.findClassLoader(name);
if(cl != null) if(cl != null)
try { try {
return cl.loadClass(name, resolve); return cl.loadClass(name, resolve);
}catch(ClassNotFoundException e) { }catch(ClassNotFoundException e) {
throw new ClassNotFoundException("J'ai délégué le chargement de la classe mais j'aurais pas du ... cette classe ne doit pas exister dans l'addon "+cl.getAddon().getName(),e); throw new ClassNotFoundException("J'ai dlgu le chargement de la classe mais j'aurais pas du ... cette classe ne doit pas exister dans l'addon "+cl.getAddon().getName(),e);
} }
else else
try { try {
@@ -231,7 +248,7 @@ public class JuliaAddon {
Collections.addAll(toWatch, loadClass(clazz.getName()).getMethods());//loadClass(clazz.getName()) poir eviter les references cassees par les classloaders Collections.addAll(toWatch, loadClass(clazz.getName()).getMethods());//loadClass(clazz.getName()) poir eviter les references cassees par les classloaders
} catch (SecurityException | ClassNotFoundException e) { } catch (SecurityException | ClassNotFoundException e) {
e.printStackTrace(); e.printStackTrace();
System.err.println("L'addon "+JuliaAddon.this.addonClass.getName()+" spécifie la classe "+clazz.getName()); System.err.println("L'addon "+JuliaAddon.this.addonClass.getName()+" spcifie la classe "+clazz.getName());
} }
for(Method m : toWatch) { for(Method m : toWatch) {
Command c = m.getAnnotation(Command.class); Command c = m.getAnnotation(Command.class);