private void findModuleInfo(ModuleSymbol msym) { try { JavaFileObject src_fo = (msym.sourceLocation == null) ? null : fileManager.getJavaFileForInput( msym.sourceLocation, names.module_info.toString(), Kind.SOURCE); JavaFileObject class_fo = (msym.classLocation == null) ? null : fileManager.getJavaFileForInput( msym.classLocation, names.module_info.toString(), Kind.CLASS); JavaFileObject fo = (src_fo == null) ? class_fo : (class_fo == null) ? src_fo : classFinder.preferredFileObject(src_fo, class_fo); if (fo == null) { String moduleName = msym.sourceLocation == null && msym.classLocation != null ? fileManager.inferModuleName(msym.classLocation) : null; if (moduleName != null) { msym.module_info.classfile = null; msym.flags_field |= Flags.AUTOMATIC_MODULE; } else { msym.kind = ERR; } } else { msym.module_info.classfile = fo; msym.module_info.completer = new Symbol.Completer() { @Override public void complete(Symbol sym) throws CompletionFailure { classFinder.fillIn(msym.module_info); } @Override public String toString() { return "ModuleInfoCompleter"; } }; } } catch (IOException e) { msym.kind = ERR; } }
@Override public ClassLoader getClassLoader(Location location) { if (location == StandardLocation.PLATFORM_CLASS_PATH) { return standardJavaFileManager.getClassLoader(location); } return classLoader; }
private List<ModuleSymbol> scanModulePath(ModuleSymbol toFind) { ListBuffer<ModuleSymbol> results = new ListBuffer<>(); Map<Name, Location> namesInSet = new HashMap<>(); while (moduleLocationIterator.hasNext()) { Set<Location> locns = (moduleLocationIterator.next()); namesInSet.clear(); for (Location l : locns) { try { Name n = names.fromString(fileManager.inferModuleName(l)); if (namesInSet.put(n, l) == null) { ModuleSymbol msym = syms.enterModule(n); if (msym.sourceLocation != null || msym.classLocation != null) { // module has already been found, so ignore this instance continue; } if (moduleLocationIterator.outer == StandardLocation.MODULE_SOURCE_PATH) { msym.sourceLocation = l; if (fileManager.hasLocation(StandardLocation.CLASS_OUTPUT)) { msym.classLocation = fileManager.getLocationForModule( StandardLocation.CLASS_OUTPUT, msym.name.toString()); } } else { msym.classLocation = l; } if (moduleLocationIterator.outer == StandardLocation.SYSTEM_MODULES || moduleLocationIterator.outer == StandardLocation.UPGRADE_MODULE_PATH) { msym.flags_field |= Flags.SYSTEM_MODULE; } if (toFind == msym || toFind == null) { // Note: cannot return msym directly, because we must finish // processing this set first results.add(msym); } } else { log.error( Errors.DuplicateModuleOnPath(getDescription(moduleLocationIterator.outer), n)); } } catch (IOException e) { // skip location for now? log error? } } if (toFind != null && results.nonEmpty()) return results.toList(); } return results.toList(); }
private void initProcessorIterator(Context context, Iterable<? extends Processor> processors) { Log log = Log.instance(context); Iterator<? extends Processor> processorIterator; if (options.isSet(XPRINT)) { try { Processor processor = PrintingProcessor.class.newInstance(); processorIterator = List.of(processor).iterator(); } catch (Throwable t) { AssertionError assertError = new AssertionError("Problem instantiating PrintingProcessor."); assertError.initCause(t); throw assertError; } } else if (processors != null) { processorIterator = processors.iterator(); } else { String processorNames = options.get(PROCESSOR); JavaFileManager fileManager = context.get(JavaFileManager.class); try { // If processorpath is not explicitly set, use the classpath. processorClassLoader = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH) ? fileManager.getClassLoader(ANNOTATION_PROCESSOR_PATH) : fileManager.getClassLoader(CLASS_PATH); /* * If the "-processor" option is used, search the appropriate * path for the named class. Otherwise, use a service * provider mechanism to create the processor iterator. */ if (processorNames != null) { processorIterator = new NameProcessIterator(processorNames, processorClassLoader, log); } else { processorIterator = new ServiceIterator(processorClassLoader, log); } } catch (SecurityException e) { /* * A security exception will occur if we can't create a classloader. * Ignore the exception if, with hindsight, we didn't need it anyway * (i.e. no processor was specified either explicitly, or implicitly, * in service configuration file.) Otherwise, we cannot continue. */ processorIterator = handleServiceLoaderUnavailability("proc.cant.create.loader", e); } } discoveredProcs = new DiscoveredProcessors(processorIterator); }
@Override public void visitTopLevel(JCCompilationUnit tree) { JavaFileObject prev = log.useSource(tree.sourcefile); boolean addEnv = false; boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE); if (tree.pid != null) { tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid)); if (tree.packageAnnotations.nonEmpty() || pkginfoOpt == PkgInfo.ALWAYS) { if (isPkgInfo) { addEnv = true; } else { log.error(tree.packageAnnotations.head.pos(), "pkg.annotations.sb.in.package-info.java"); } } } else { tree.packge = syms.unnamedPackage; } tree.packge.complete(); // Find all classes in package. Env<AttrContext> topEnv = topLevelEnv(tree); // Save environment of package-info.java file. if (isPkgInfo) { Env<AttrContext> env0 = typeEnvs.get(tree.packge); if (env0 == null) { typeEnvs.put(tree.packge, topEnv); } else { JCCompilationUnit tree0 = env0.toplevel; if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) { log.warning( tree.pid != null ? tree.pid.pos() : null, "pkg-info.already.seen", tree.packge); if (addEnv || (tree0.packageAnnotations.isEmpty() && tree.docComments != null && tree.docComments.get(tree) != null)) { typeEnvs.put(tree.packge, topEnv); } } } for (Symbol q = tree.packge; q != null && q.kind == PCK; q = q.owner) q.flags_field |= EXISTS; Name name = names.package_info; ClassSymbol c = reader.enterClass(name, tree.packge); c.flatname = names.fromString(tree.packge + "." + name); c.sourcefile = tree.sourcefile; c.completer = null; c.members_field = new Scope(c); tree.packge.package_info = c; } classEnter(tree.defs, topEnv); if (addEnv) { todo.append(topEnv); } log.useSource(prev); result = null; }
/** * Returns an empty processor iterator if no processors are on the relevant path, otherwise if * processors are present, logs an error. Called when a service loader is unavailable for some * reason, either because a service loader class cannot be found or because a security policy * prevents class loaders from being created. * * @param key The resource key to use to log an error message * @param e If non-null, pass this exception to Abort */ private Iterator<Processor> handleServiceLoaderUnavailability(String key, Exception e) { JavaFileManager fileManager = context.get(JavaFileManager.class); if (fileManager instanceof JavacFileManager) { StandardJavaFileManager standardFileManager = (JavacFileManager) fileManager; Iterable<? extends File> workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH) ? standardFileManager.getLocation(ANNOTATION_PROCESSOR_PATH) : standardFileManager.getLocation(CLASS_PATH); if (needClassLoader(options.get(PROCESSOR), workingPath)) handleException(key, e); } else { handleException(key, e); } java.util.List<Processor> pl = Collections.emptyList(); return pl.iterator(); }
@Override public String inferBinaryName(Location location, JavaFileObject file) { if (file instanceof LocalFileObject) { return ((LocalFileObject) file).binaryName(); } if (file instanceof ZipJavaFileObject) { return ((ZipJavaFileObject) file).binaryName(); } return standardJavaFileManager.inferBinaryName(location, file); }
public void visitTopLevel(JCCompilationUnit tree) { JavaFileObject prev = log.useSource(tree.sourcefile); boolean addEnv = false; boolean isPkgInfo = tree.sourcefile.isNameCompatible("package-info", JavaFileObject.Kind.SOURCE); if (tree.pid != null) { tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid)); if (tree.packageAnnotations.nonEmpty()) { if (isPkgInfo) { addEnv = true; } else { log.error(tree.packageAnnotations.head.pos(), "pkg.annotations.sb.in.package-info.java"); } } } else { tree.packge = syms.unnamedPackage; } tree.packge.complete(); // Find all classes in package. Env<AttrContext> env = topLevelEnv(tree); // Save environment of package-info.java file. if (isPkgInfo) { Env<AttrContext> env0 = typeEnvs.get(tree.packge); if (env0 == null) { typeEnvs.put(tree.packge, env); } else { JCCompilationUnit tree0 = env0.toplevel; if (!fileManager.isSameFile(tree.sourcefile, tree0.sourcefile)) { log.warning( tree.pid != null ? tree.pid.pos() : null, "pkg-info.already.seen", tree.packge); if (addEnv || (tree0.packageAnnotations.isEmpty() && tree.docComments != null && tree.docComments.get(tree) != null)) { typeEnvs.put(tree.packge, env); } } } } classEnter(tree.defs, env); if (addEnv) { todo.append(env); } log.useSource(prev); result = null; }
private JavaFileObject getModuleInfoFromLocation(Location location, Kind kind) throws IOException { if (!fileManager.hasLocation(location)) return null; return fileManager.getJavaFileForInput(location, names.module_info.toString(), kind); }
/** * Save a compiled class and associated classes to a jar file. * * <p>With a packageName = "" and recursive = false, it will save clazz and any classes compiled * from the same source (I think); this is probably what you want. * * @param packageName package name prefix to search for classes, or "" for all * @param clazz a class that has been previously compiled by this bridge * @param mainClazz a class that will be installed as the "Main-Class" of a runnable jar * @param outStream output stream * @param recursive whether to retrieve classes from rest of the the JavaFileManager hierarchy * @throws FileNotFoundException * @throws IOException */ public void saveToJar( String packageName, Class<?> clazz, Class<?> mainClazz, OutputStream outStream, boolean recursive) throws IOException { JavaFileManager manager = fileManagerCache.get(clazz); List<JavaFileObject> list = new ArrayList<JavaFileObject>(); for (JavaFileObject obj : manager.list( StandardLocation.CLASS_PATH, packageName, Collections.singleton(JavaFileObject.Kind.CLASS), false)) list.add(obj); if (list.iterator().hasNext()) { Manifest manifest = new Manifest(); manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0"); if (mainClazz != null) { manifest.getMainAttributes().put(Attributes.Name.MAIN_CLASS, mainClazz.getName()); } manifest .getMainAttributes() .put(new Attributes.Name("X-Rascal-Saved-Class"), clazz.getName()); JarOutputStream target = new JarOutputStream(outStream, manifest); JarEntry entry = new JarEntry("META-INF/"); target.putNextEntry(entry); Collection<String> dirs = new ArrayList<String>(); for (JavaFileObject o : list) { String path = o.toUri().getPath().replace(".", "/"); makeJarDirs(target, dirs, path); entry = new JarEntry(path + ".class"); entry.setTime(o.getLastModified()); target.putNextEntry(entry); try (InputStream stream = o.openInputStream()) { byte[] buffer = new byte[8192]; int c = stream.read(buffer); while (c > -1) { target.write(buffer, 0, c); c = stream.read(buffer); } } target.closeEntry(); } if (mainClazz != null) { String name = mainClazz.getName(); String path = name.replace(".", "/") + ".class"; String dir = path.substring(0, path.lastIndexOf('/')); StringBuilder dirTmp = new StringBuilder(dir.length()); for (String d : dir.split("/")) { dirTmp.append(d); dirTmp.append("/"); String tmp = dirTmp.toString(); if (!dirs.contains(tmp)) { dirs.add(tmp); entry = new JarEntry(tmp); target.putNextEntry(entry); } } entry = new JarEntry(path); target.putNextEntry(entry); try (InputStream stream = mainClazz.getClassLoader().getResourceAsStream(path)) { byte[] buffer = new byte[8192]; int c = stream.read(buffer); while (c > -1) { target.write(buffer, 0, c); c = stream.read(buffer); } } target.closeEntry(); } target.close(); } }
@Override public Iterable<JavaFileObject> list( Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException { if (location == StandardLocation.PLATFORM_CLASS_PATH) { return standardJavaFileManager.list(location, packageName, kinds, recurse); } List<JavaFileObject> ret = new ArrayList<>(); if (kinds.contains(Kind.CLASS) && location.equals(StandardLocation.CLASS_PATH)) { if (classLoader instanceof ModuleClassLoader) { ModuleClassLoader mcl = (ModuleClassLoader) classLoader; final String packageWithSlashes = packageName.replace(".", "/"); try { Iterator<Resource> resources = mcl.getModule() .iterateResources( new PathFilter() { @Override public boolean accept(String path) { if (recurse) { return path.startsWith(packageWithSlashes); } else { return path.equals(packageWithSlashes); } } }); while (resources.hasNext()) { Resource res = resources.next(); if (!res.getName().endsWith(".class")) { continue; } String binaryName = res.getName().replace("/", ".").substring(0, res.getName().length() - 6); try { ret.add( new ZipJavaFileObject( org.fakereplace.util.FileReader.readFileBytes(res.openStream()), binaryName, res.getURL().toURI())); } catch (URISyntaxException e) { e.printStackTrace(); } } } catch (ModuleLoadException e) { e.printStackTrace(); } } else { URL res = classLoader.getResource(packageName.replace(".", "/")); if (res != null) { if (res.getProtocol().equals("file")) { Path dirPath = Paths.get(res.getFile()); listDir(packageName, dirPath, recurse, ret); } else if (res.getProtocol().equals("jar")) { JarURLConnection connection = (JarURLConnection) res.openConnection(); Enumeration<JarEntry> entryEnum = connection.getJarFile().entries(); while (entryEnum.hasMoreElements()) { JarEntry entry = entryEnum.nextElement(); String name = entry.getName(); if (name.endsWith(".class") && !entry.isDirectory()) { if (name.startsWith(packageName.replace(".", "/"))) { String rem = name.substring(packageName.length()); if (rem.startsWith("/")) { rem = rem.substring(1); } if (!recurse) { if (rem.contains("/")) { continue; } } String binaryName = entry .getName() .replace("/", ".") .substring(0, entry.getName().length() - 6); try { URI uri = new URI(res.toExternalForm() + "/" + rem); ret.add( new ZipJavaFileObject( org.fakereplace.util.FileReader.readFileBytes( uri.toURL().openStream()), binaryName, uri)); } catch (Exception e) { e.printStackTrace(); } } } } } else { System.err.println( "Could not find package " + packageName + " in " + classLoader + " unknown protocol " + res.getProtocol()); } } else { return standardJavaFileManager.list(location, packageName, kinds, recurse); } } } else { return standardJavaFileManager.list(location, packageName, kinds, recurse); } return ret; }