Ultrakompakter HTTP Server
ulrich
2024-12-01 7456da964add0d6e8530ab731d5e8837dcfb8a54
commit | author | age
f4025a 1 /*
c2e8cf 2   neon - Embeddable HTTP Server based on jdk.httpserver
U 3   Copyright (C) 2024  Ulrich Hilger
f4025a 4
c2e8cf 5   This program is free software: you can redistribute it and/or modify
U 6   it under the terms of the GNU Affero General Public License as
7   published by the Free Software Foundation, either version 3 of the
8   License, or (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU Affero General Public License for more details.
14
15   You should have received a copy of the GNU Affero General Public License
16   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  */
f4025a 18 package de.uhilger.neon;
U 19
20 import java.io.File;
21 import java.io.IOException;
22 import java.net.MalformedURLException;
23 import java.net.URI;
24 import java.net.URISyntaxException;
25 import java.net.URL;
26 import java.net.URLClassLoader;
27 import java.util.Enumeration;
28 import java.util.logging.Level;
29 import java.util.logging.Logger;
30 import java.util.zip.ZipEntry;
31 import java.util.zip.ZipFile;
32
33 /**
34  * Die Klasse JarScanner enthaelt Methoden, um fuer eine Klasse zu bestimmen, in 
35  * welcher JAR-Datei sie liegt und diese JAR-Datei nach Klassen zu durchsuchen.
36  * 
37  * @author Ulrich Hilger
38  * @version 0.1, 30.11.2024
39  */
40 public class JarScanner {
41   
42   
43   public void processZipContent(ClassLoader urlCL, File archive, String packageName, JarScannerListener l, Handler h, String contextName) {
44     try {
45       ZipFile zipfile = new ZipFile(archive);
46       Enumeration en = zipfile.entries();
47       while (en.hasMoreElements()) {
48         ZipEntry zipentry = (ZipEntry) en.nextElement();
49         if (!zipentry.isDirectory()) {
50           processZipEntry(urlCL, zipentry, packageName, l, h, contextName);
51         } else {
52           // ZIP-Dir muss nicht bearbeitet werden
53         }
54       }
55       zipfile.close();
56     } catch (IOException ex) {
57       log(Level.SEVERE, ex.getLocalizedMessage());
58     }
59   }
60
61   private void processZipEntry(ClassLoader urlCL, ZipEntry zipentry, String packageName, JarScannerListener l, Handler h, String contextName) {
7456da 62     finest(zipentry.getName());
f4025a 63     String zName = zipentry.getName();
U 64     if (zName.toLowerCase().endsWith(".class")) {
65       int pos = zName.indexOf(".class");
66       String fullClassName = zName.substring(0, pos);
7456da 67       finest("full class name: " + zName);
f4025a 68       String fullClassNameDots = fullClassName.replace('/', '.');
7456da 69       finest("full class name dots: " + fullClassNameDots);
f4025a 70       String pkgName = getPackageName(fullClassNameDots);
7456da 71       finest(" -- package name: " + pkgName);
f4025a 72       if (null != urlCL && pkgName.toLowerCase().startsWith(packageName)) {
U 73         Class c = null;
74         try {
75           c = urlCL.loadClass(fullClassNameDots);
76           if (c != null) {
77             if (c.isAnnotationPresent(Actor.class)) {
7456da 78               finest(" ---- ACTOR ---- " + fullClassNameDots);
f4025a 79               l.actorFound(c, h, contextName);
U 80             } else {
7456da 81               finest("kein Actor " + fullClassNameDots);
f4025a 82             }
U 83           } else {
7456da 84             finest("class NOT loaded: " + zName);
f4025a 85           }
U 86         } catch (ClassNotFoundException ex) {
7456da 87           finest(" +++++ Class not found: " + ex.getMessage());
f4025a 88         }
U 89       }
90     }
91   }
92   
93   private String getPackageName(String fullClassName) {
94     String packageName;
95     int pos = fullClassName.lastIndexOf(".");
96     if (pos > 0) {
97       packageName = fullClassName.substring(0, pos);
98     } else {
99       packageName = fullClassName;
100     }
101     return packageName;
102   }
103   
104   public ClassLoader getUrlClassLoader(Class c) {
105     URL url;
106     ClassLoader urlCL = null;
107     try {
108       url = getPath(c).toURL();
7456da 109       finer("url: " + url.getPath());
f4025a 110       urlCL = new URLClassLoader(new URL[]{url});
U 111     } catch (URISyntaxException ex) {
112       log(Level.SEVERE, ex.getMessage());
113     } catch (MalformedURLException ex) {
114       log(Level.SEVERE, ex.getMessage());
115     } finally {
116       return urlCL;
117     }
118   }
119   
120   public URI getPath(Class c) throws URISyntaxException {
121     //Class c = this.getClass();
122     String className = c.getName();
7456da 123     finest("this name: " + className);
f4025a 124     
U 125     int pos = className.indexOf(".class");
126     if(pos > -1) {
127       String classNameWoExt = className.substring(0, pos);
128     }
129     String classNameWoPkg = className.substring(className.lastIndexOf(".") + 1);
7456da 130     finest("Class name: " + classNameWoPkg);
f4025a 131     String classPath = c.getResource(classNameWoPkg + ".class").getPath();
U 132     pos = classPath.indexOf("!");
133     String jarPath;
134     if(pos > -1) {
135       jarPath = /*"jar:" + */ classPath.substring(0, pos);
136     } else {
137       jarPath = classPath;
138     }
7456da 139     finest("path: " + jarPath);
f4025a 140     return new URI(jarPath);
U 141   }
142   
7456da 143   private void finest(String msg) {
U 144     log(Level.FINEST, msg);
145   }
146   
f4025a 147   private void finer(String msg) {
U 148     log(Level.FINER, msg);
149   }
150   
151   private void log(Level l, String msg) {
152     Logger.getLogger(JarScanner.class.getName()).log(l, msg);
153   }
154   
155   
156   public interface JarScannerListener {
157     public void actorFound(Class actorClass, Handler h, String contextName);
158   }
159   
160 }