/* neon - Embeddable HTTP Server based on jdk.httpserver Copyright (C) 2024 Ulrich Hilger This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package de.uhilger.neon; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; import java.util.Enumeration; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; /** * Die Klasse JarScanner enthaelt Methoden, um fuer eine Klasse zu bestimmen, in * welcher JAR-Datei sie liegt und diese JAR-Datei nach Klassen zu durchsuchen. * * @author Ulrich Hilger * @version 0.1, 30.11.2024 */ public class JarScanner { public void processZipContent(ClassLoader urlCL, File archive, String packageName, JarScannerListener l, Handler h, String contextName) { try { ZipFile zipfile = new ZipFile(archive); Enumeration en = zipfile.entries(); while (en.hasMoreElements()) { ZipEntry zipentry = (ZipEntry) en.nextElement(); if (!zipentry.isDirectory()) { processZipEntry(urlCL, zipentry, packageName, l, h, contextName); } else { // ZIP-Dir muss nicht bearbeitet werden } } zipfile.close(); } catch (IOException ex) { log(Level.SEVERE, ex.getLocalizedMessage()); } } private void processZipEntry(ClassLoader urlCL, ZipEntry zipentry, String packageName, JarScannerListener l, Handler h, String contextName) { log(Level.FINEST, zipentry.getName()); String zName = zipentry.getName(); if (zName.toLowerCase().endsWith(".class")) { int pos = zName.indexOf(".class"); String fullClassName = zName.substring(0, pos); log(Level.FINEST, "full class name: " + zName); String fullClassNameDots = fullClassName.replace('/', '.'); log(Level.FINEST, "full class name dots: " + fullClassNameDots); String pkgName = getPackageName(fullClassNameDots); log(Level.FINEST, " -- package name: " + pkgName); if (null != urlCL && pkgName.toLowerCase().startsWith(packageName)) { Class c = null; try { c = urlCL.loadClass(fullClassNameDots); if (c != null) { if (c.isAnnotationPresent(Actor.class)) { log(Level.FINER, " ---- ACTOR ---- " + fullClassNameDots); l.actorFound(c, h, contextName); } else { log(Level.FINER, "kein Actor " + fullClassNameDots); } } else { log(Level.FINER, "class NOT loaded: " + zName); } } catch (ClassNotFoundException ex) { log(Level.FINER, " +++++ Class not found: " + ex.getMessage()); } } } } private String getPackageName(String fullClassName) { String packageName; int pos = fullClassName.lastIndexOf("."); if (pos > 0) { packageName = fullClassName.substring(0, pos); } else { packageName = fullClassName; } return packageName; } public ClassLoader getUrlClassLoader(Class c) { URL url; ClassLoader urlCL = null; try { url = getPath(c).toURL(); log(Level.FINER, "url: " + url.getPath()); urlCL = new URLClassLoader(new URL[]{url}); } catch (URISyntaxException ex) { log(Level.SEVERE, ex.getMessage()); } catch (MalformedURLException ex) { log(Level.SEVERE, ex.getMessage()); } finally { return urlCL; } } public URI getPath(Class c) throws URISyntaxException { //Class c = this.getClass(); String className = c.getName(); finer("this name: " + className); int pos = className.indexOf(".class"); if(pos > -1) { String classNameWoExt = className.substring(0, pos); } String classNameWoPkg = className.substring(className.lastIndexOf(".") + 1); finer("Class name: " + classNameWoPkg); String classPath = c.getResource(classNameWoPkg + ".class").getPath(); pos = classPath.indexOf("!"); String jarPath; if(pos > -1) { jarPath = /*"jar:" + */ classPath.substring(0, pos); } else { jarPath = classPath; } finer("path: " + jarPath); return new URI(jarPath); } private void finer(String msg) { log(Level.FINER, msg); } private void log(Level l, String msg) { Logger.getLogger(JarScanner.class.getName()).log(l, msg); } public interface JarScannerListener { public void actorFound(Class actorClass, Handler h, String contextName); } }