package de.dhbwstuttgart.environment; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.*; import com.google.common.collect.Lists; import de.dhbwstuttgart.core.JavaTXCompiler; import de.dhbwstuttgart.syntaxtree.ClassOrInterface; import de.dhbwstuttgart.syntaxtree.factory.ASTFactory; import de.dhbwstuttgart.exceptions.DebugException; import de.dhbwstuttgart.exceptions.NotImplementedException; import de.dhbwstuttgart.parser.JavaTXParser; import de.dhbwstuttgart.parser.antlr.Java17Parser.SourceFileContext; import de.dhbwstuttgart.parser.antlr.Java17Parser.SrcfileContext; import de.dhbwstuttgart.parser.scope.GatherNames; import de.dhbwstuttgart.parser.scope.JavaClassRegistry; /** * Stellt die Java-Environment dar und speichert alle Binarys, Librarys und Sourcefiles im zu kompilierenden Projekt Sie erstellt anhand dieser Informationen die JavaClassNameRegistry * * TODO: Zur Initialisierung der CompilationEnvironment sollten alle SourceFiles mit ANTLR geparst werden und alle Klassen Generics und Typen herausgefunden werden */ public class CompilationEnvironment { private final List librarys; private final List sourceFiles; public final PackageCrawler packageCrawler; /** * Imitiert die Environment beim Aufruf des JavaCompilers auf einer Menge von java-Dateien Die Environment enth�lt automatisch die Java Standard Library * * @param sourceFiles die zu kompilierenden Dateien */ public CompilationEnvironment(List sourceFiles) { /** * Java 9 bringt einige Änderungen am Classloader So funktioniert der BootClassLoader nicht mehr. hier gibts ein paar Quellen zum nachlesen: http://java9.wtf/class-loading/ https://stackoverflow.com/questions/46494112/classloaders-hierarchy-in-java-9 * */ // String bootClassPath = System.getProperty("sun.boot.class.path"); // DirectoryClassLoader cl = DirectoryClassLoader.getPlatformClassLoader(); String bootClassPath = System.getProperty("java.class.path"); librarys = new ArrayList<>(); for (String path : bootClassPath.split(File.pathSeparator)) { try { librarys.add(new URL("file:" + path)); } catch (MalformedURLException e) { new DebugException("Fehler im Classpath auf diesem System"); } } // URLClassLoader loader = new URLClassLoader(new URL[0], cl); // librarys = Arrays.asList(loader.getURLs()); this.sourceFiles = sourceFiles; this.packageCrawler = new PackageCrawler(librarys); } public void addClassesToRegistry(JavaClassRegistry registry, SourceFileContext tree, File sourceFile, JavaTXCompiler compiler) throws ClassNotFoundException, IOException { Map allNames; if (tree instanceof SrcfileContext srcfile) { allNames = GatherNames.getNames((SrcfileContext) tree, packageCrawler, compiler); for (Class c : loadDefaultPackageClasses(getPackageName(srcfile), sourceFile, compiler)) { allNames.put(c.getName(), c.getTypeParameters().length); } registry.addNames(allNames); } else { throw new NotImplementedException(); } } public static List loadDefaultPackageClasses(String packageName, File sourceFile, JavaTXCompiler compiler) throws IOException, ClassNotFoundException { ClassLoader classLoader = compiler.getClassLoader(); List ret = new ArrayList<>(); // Set classLoader to include default package for this specific source file File dir = sourceFile.getAbsoluteFile().getParentFile(); String dirPath = dir.toString() + "/"; if (packageName.length() > 0) dirPath = dirPath.substring(0, dirPath.length() - packageName.length() - 1); String path = dirPath; ArrayList defaultPath = Lists.newArrayList(new File(path)); classLoader = new DirectoryClassLoader(defaultPath, classLoader); // Gather all names in the default package for this source file (classes that are imported by default) File[] files = dir.listFiles((dir1, name) -> name.endsWith(".class")); if (files != null) for (File classFile : files) { String className = classFile.getName().substring(0, classFile.getName().length() - 6); if (className.matches("Fun\\d+\\$\\$.*")) continue; ret.add(classLoader.loadClass(packageName + className)); } return ret; } private static String getPackageName(SrcfileContext forTree) { String packageName = ""; if (forTree.packageDeclaration() != null && !forTree.packageDeclaration().qualifiedName().identifier().isEmpty()) packageName = forTree.packageDeclaration().qualifiedName().getText(); return packageName; } public List getAllAvailableClasses() { List ret = new ArrayList<>(); for (Class c : new PackageCrawler(librarys).getAllAvailableClasses()) { ret.add(ASTFactory.createClass(c)); } return ret; } }