From 675190608e81f38a713c965071c36b49b0ef8027 Mon Sep 17 00:00:00 2001
From: ulrich
Date: Sun, 01 Dec 2024 09:52:46 +0000
Subject: [PATCH] Test fuer getResourceAsStream ergaenzt

---
 src/de/uhilger/neon/Factory.java |  150 +++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 124 insertions(+), 26 deletions(-)

diff --git a/src/de/uhilger/neon/Factory.java b/src/de/uhilger/neon/Factory.java
index 14015d5..ba46730 100644
--- a/src/de/uhilger/neon/Factory.java
+++ b/src/de/uhilger/neon/Factory.java
@@ -23,6 +23,7 @@
 import com.sun.net.httpserver.HttpContext;
 import com.sun.net.httpserver.HttpHandler;
 import com.sun.net.httpserver.HttpServer;
+import de.uhilger.neon.JarScanner.JarScannerListener;
 import de.uhilger.neon.entity.ContextDescriptor;
 import de.uhilger.neon.entity.NeonDescriptor;
 import de.uhilger.neon.entity.ServerDescriptor;
@@ -35,6 +36,9 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.net.InetSocketAddress;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -42,6 +46,8 @@
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.Executors;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 /**
  * Einen Neon-Server aus einer Beschreibungsdatei herstellen
@@ -59,7 +65,7 @@
  * @author Ulrich Hilger
  * @version 1, 6.2.2024
  */
-public class Factory {
+public class Factory implements JarScannerListener {
 
   public Factory() {
     listeners = new ArrayList<>();
@@ -89,16 +95,16 @@
     return gson.fromJson(sb.toString(), NeonDescriptor.class);
   }
   
-  public void runInstance(NeonDescriptor d) 
+  public void runInstance(Class c, NeonDescriptor d) 
           throws ClassNotFoundException, NoSuchMethodException, InstantiationException, 
           IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
-    this.runInstance(d, null, new ArrayList<>());
+    this.runInstance(c, d, null, new ArrayList<>());
   }
 
-  public void runInstance(NeonDescriptor d, List<String> packageNames) 
+  public void runInstance(Class c, NeonDescriptor d, List<String> packageNames) 
           throws ClassNotFoundException, NoSuchMethodException, InstantiationException, 
           IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
-    this.runInstance(d, packageNames, new ArrayList<>());
+    this.runInstance(c, d, packageNames, new ArrayList<>());
   }
   /**
    * Einen Neon-Server gemaess einem Serverbeschreibungsobjekt herstellen und starten
@@ -115,9 +121,20 @@
    * @throws InvocationTargetException
    * @throws IOException
    */
-  public void runInstance(NeonDescriptor d, List<String> packageNames, List<DataProvider> sdp) 
+  public void runInstance(Class c, NeonDescriptor d, List<String> packageNames, List<DataProvider> sdp) 
           throws ClassNotFoundException, NoSuchMethodException, InstantiationException, 
           IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
+
+    Logger.getLogger(Factory.class.getName()).log(Level.FINER, System.getProperty("java.class.path"));
+    Class pingClass = c.getClassLoader().loadClass("de.uhilger.neonbaselokal.actor.Ping");
+    if(pingClass != null) {
+      Logger.getLogger(Factory.class.getName()).log(Level.FINER, 
+              pingClass.getName() + " " + pingClass.getPackageName() + 
+                      " " + pingClass.getSimpleName());
+    } else {
+      Logger.getLogger(Factory.class.getName()).log(Level.FINER, "pingClass not found");
+    }
+    
     List serverList = d.server;
     Iterator<ServerDescriptor> serverIterator = serverList.iterator();
     while (serverIterator.hasNext()) {
@@ -128,7 +145,7 @@
       if(packageNames == null) {
         packageNames = d.actorPackages;
       }
-      addContexts(d, server, sd.contexts, packageNames, sdp);
+      addContexts(c, d, server, sd.contexts, packageNames, sdp);
 
       server.setExecutor(Executors.newFixedThreadPool(10));
       server.start();
@@ -156,7 +173,7 @@
     return auth;
   }
 
-  private void addContexts(NeonDescriptor d, HttpServer server, List contextList, List<String> packageNames, 
+  private void addContexts(Class c, NeonDescriptor d, HttpServer server, List contextList, List<String> packageNames, 
           List<DataProvider> sdp) 
           throws ClassNotFoundException, NoSuchMethodException, InstantiationException, 
           IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
@@ -176,7 +193,7 @@
         ctxAttrs.putAll(cd.attributes);        
         if (h instanceof Handler) {         
           for (String packageName : packageNames) {
-            wireActors(
+            wireActors(c, 
                     packageName, Actor.class, (Handler) h, 
                     cd.attributes.get("contextName"));
               ctx.getAttributes().put("serverDataProviderList", sdp);
@@ -254,29 +271,103 @@
     }
   }
 
-  private void wireActors(String packageName, Class annotation, Handler h, String contextName) {
-    ClassLoader cl = ClassLoader.getSystemClassLoader();
-    InputStream stream = cl
-            .getResourceAsStream(packageName.replaceAll("[.]", "/"));
-    BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
-    Iterator i = reader.lines().iterator();
-    while (i.hasNext()) {
-      String line = i.next().toString();
-      if (line.endsWith(".class")) {
-        try {
-          Class actorClass = Class.forName(packageName + "."
-                  + line.substring(0, line.lastIndexOf('.')));
-          if (actorClass != null && actorClass.isAnnotationPresent(annotation)) {
-            wire(h, actorClass, contextName);
+  private void wireActors(Class c, String packageName, Class annotation, Handler h, String contextName) {
+    JarScanner js = new JarScanner();
+    URI path;
+    try {
+      path = js.getPath(c);
+      if(path.toString().endsWith(".class")) {
+        ClassLoader cl = c.getClassLoader();
+        InputStream stream = cl
+                .getResourceAsStream(packageName.replaceAll("[.]", "/"));
+        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+        Iterator i = reader.lines().iterator();
+        while (i.hasNext()) {
+          String line = i.next().toString();
+          if (line.endsWith(".class")) {
+            try {
+              Class actorClass = cl.loadClass(packageName + "."
+                      + line.substring(0, line.lastIndexOf('.')));
+              if (actorClass != null && actorClass.isAnnotationPresent(annotation)) {
+                wire(h, actorClass, contextName);
+              }
+            } catch (ClassNotFoundException ex) {
+              // Klasse nicht gefunden. Muss das geloggt oder sonstwie behandel werden?
+            }
+          } else {
+            wireActors(c, packageName + "." + line, annotation, h, contextName);
           }
-        } catch (ClassNotFoundException ex) {
-          // Klasse nicht gefunden. Muss das geloggt oder sonstwie behandel werden?
         }
       } else {
-        wireActors(packageName + "." + line, annotation, h, contextName);
+        ClassLoader cl = js.getUrlClassLoader(c);
+        js.processZipContent(cl, new File(path), packageName, this, h, contextName);
       }
+      //listClasses(c, packageName);
+    } catch (URISyntaxException ex) {
+      Logger.getLogger(Factory.class.getName()).log(Level.SEVERE, ex.getMessage(), ex);
     }
   }
+  
+  /**
+   * Diese Testmethode zeigt, dass die Methode getResourceAsStream nicht funktioniert wie 
+   * dokumentiert. 
+   * 
+   * 1. Sie liefert den Inhalt einer gegebenen Package mitsamt Unterpackages als 
+   * Stream, wenn sie auf eine Packagestruktur angewendet wird, die unverpackt in einem 
+   * Verzeichnis des Dateisystems liegt.
+   * 
+   * 2. Sie liefert - faelschlicherweise - null bzw. einen leeren Stream, wenn die Packagestruktur 
+   * in einem Jar verpackt ist.
+   * 
+   * Saemtliche Versuche, ueber den ClassPath oder die Pfadangabe der Package das Verhalten zu 
+   * aendern, gehen bislang fehl (z.B. / oder . als Separator, 
+   * / oder . zu Beginn enthalten oder nicht, realative oder absolute packagepfadangabe). 
+   * Es ist auch unerheblich, ob 
+   * Class.getResourceAsStream oder Class.getClassLoader().getResourceAsStream verwendet wird.
+   * 
+   * Unabhaengig davon, ob und wie letztlich im Fall 2. oben die Methode getResourceAsStream 
+   * dazu zu bringen waere, eine Inhaltsliste fuer eine Package zu liefern ist allein die 
+   * Tatsache, dass sich die Methode unterschiedlich verhaelt bereits ein 
+   * schwerer Bug.
+   * 
+   * @param c
+   * @param packageName 
+   */
+  private void listClasses(Class c, String packageName) {
+        Logger.getLogger(Factory.class.getName()).log(Level.FINER, "packageName: " + packageName);
+        //ClassLoader cl = c.getClassLoader();
+        String newPackageName = packageName.replaceAll("[.]", "/");
+        Logger.getLogger(Factory.class.getName()).log(Level.FINER, "newPackageName: " + newPackageName);
+        InputStream stream = c
+                .getResourceAsStream(newPackageName);
+        if(stream != null) {
+        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
+        Iterator i = reader.lines().iterator();
+        Logger.getLogger(Factory.class.getName()).log(Level.FINER, Long.toString(reader.lines().count()));
+        while (i.hasNext()) {
+          String line = i.next().toString();
+          Logger.getLogger(Factory.class.getName()).log(Level.FINER, "class to inspect: " + line);
+          if (line.endsWith(".class")) {
+            try {
+              Class actorClass = c.getClassLoader().loadClass(packageName + "."
+                      + line.substring(0, line.lastIndexOf('.')));
+              if (actorClass != null && actorClass.isAnnotationPresent(Actor.class)) {
+                Logger.getLogger(Factory.class.getName()).log(Level.FINER, "ACTOR");
+              } else {
+                Logger.getLogger(Factory.class.getName()).log(Level.FINER, "no actor");
+              }
+            } catch (ClassNotFoundException ex) {
+              Logger.getLogger(Factory.class.getName()).log(Level.FINER, "Klasse nicht gefunden");
+            }
+          } else {
+            listClasses(c, packageName + "." + line);
+          }
+        }
+        } else {
+         Logger.getLogger(Factory.class.getName()).log(Level.FINER, "stream ist null"); 
+        }
+  }
+  
   
   /*
     Eine Action-Annotation enthaelt gewoehnlich die Route, 
@@ -346,4 +437,11 @@
       l.instanceStarted();
     }
   }
+
+  /* -------------- JarScannerListener Implementierung --------------- */
+    
+  @Override
+  public void actorFound(Class actorClass, Handler h, String contextName) {
+    wire(h, actorClass, contextName);
+  }
 }

--
Gitblit v1.9.3