void add(ModuleDescriptor... descriptors) { for (ModuleDescriptor descriptor: descriptors) { String name = descriptor.name(); if (!namesToReference.containsKey(name)) { //modules.add(descriptor); URI uri = URI.create("module:/" + descriptor.name()); ModuleReference mref = new ModuleReference(descriptor, uri) { @Override public ModuleReader open() { throw new UnsupportedOperationException(); } }; namesToReference.put(name, mref); } } }
/** * Defines the given binary class name to the VM, loading the class * bytes from the given module. * * @return the resulting Class or {@code null} if an I/O error occurs */ private Class<?> defineClass(String cn, LoadedModule loadedModule) { ModuleReader reader = moduleReaderFor(loadedModule.mref()); try { // read class file String rn = cn.replace('.', '/').concat(".class"); ByteBuffer bb = reader.read(rn).orElse(null); if (bb == null) { // class not found return null; } try { return defineClass(cn, bb, loadedModule.codeSource()); } finally { reader.release(bb); } } catch (IOException ioe) { // TBD on how I/O errors should be propagated return null; } }
/** * Returns the ModuleReader for the given module, creating it if needed */ private ModuleReader moduleReaderFor(ModuleReference mref) { ModuleReader reader = moduleToReader.get(mref); if (reader == null) { // avoid method reference during startup Function<ModuleReference, ModuleReader> create = new Function<>() { public ModuleReader apply(ModuleReference moduleReference) { try { return mref.open(); } catch (IOException e) { // Return a null module reader to avoid a future class // load attempting to open the module again. return new NullModuleReader(); } } }; reader = moduleToReader.computeIfAbsent(mref, create); } return reader; }
/** * Creates a ModuleReference to a possibly-patched module */ private static ModuleReference newModule(ModuleInfo.Attributes attrs, URI uri, Supplier<ModuleReader> supplier, ModulePatcher patcher, HashSupplier hasher) { ModuleReference mref = new ModuleReferenceImpl(attrs.descriptor(), uri, supplier, null, attrs.target(), attrs.recordedHashes(), hasher, attrs.moduleResolution()); if (patcher != null) mref = patcher.patchIfNeeded(mref); return mref; }
/** * Constructs a new instance of this class. */ public ModuleReferenceImpl(ModuleDescriptor descriptor, URI location, Supplier<ModuleReader> readerSupplier, ModulePatcher patcher, ModuleTarget target, ModuleHashes recordedHashes, ModuleHashes.HashSupplier hasher, ModuleResolution moduleResolution) { super(descriptor, Objects.requireNonNull(location)); this.location = location; this.readerSupplier = readerSupplier; this.patcher = patcher; this.target = target; this.recordedHashes = recordedHashes; this.hasher = hasher; this.moduleResolution = moduleResolution; }
public static void main(String[] args) throws Exception { String mn = args[0]; ModuleReference mref = ModuleLayer.boot() .configuration() .findModule(mn) .map(ResolvedModule::reference) .orElseThrow(() -> new RuntimeException(mn + " not resolved!!")); try (ModuleReader reader = mref.open()) { reader.list().forEach(name -> { testFindUnchecked(name); // if the resource is a directory then find without trailing slash if (name.endsWith("/")) { testFindUnchecked(name.substring(0, name.length() - 1)); } }); } }
/** * Test ModuleReader#find */ void testFind(ModuleReader reader, String name, byte[] expectedBytes) throws IOException { Optional<URI> ouri = reader.find(name); assertTrue(ouri.isPresent()); URL url = ouri.get().toURL(); if (!url.getProtocol().equalsIgnoreCase("jmod")) { URLConnection uc = url.openConnection(); uc.setUseCaches(false); try (InputStream in = uc.getInputStream()) { byte[] bytes = in.readAllBytes(); assertTrue(Arrays.equals(bytes, expectedBytes)); } } }
/** * Test ModuleReader#read */ void testRead(ModuleReader reader, String name, byte[] expectedBytes) throws IOException { Optional<ByteBuffer> obb = reader.read(name); assertTrue(obb.isPresent()); ByteBuffer bb = obb.get(); try { int rem = bb.remaining(); assertTrue(rem == expectedBytes.length); byte[] bytes = new byte[rem]; bb.get(bytes); assertTrue(Arrays.equals(bytes, expectedBytes)); } finally { reader.release(bb); } }
void add(ModuleDescriptor... descriptors) { for (ModuleDescriptor descriptor: descriptors) { String name = descriptor.name(); if (!namesToReference.containsKey(name)) { //modules.add(descriptor); URI uri = URI.create("module:/" + descriptor.name()); Supplier<ModuleReader> supplier = () -> { throw new UnsupportedOperationException(); }; ModuleReference mref = new ModuleReference(descriptor, uri, supplier); namesToReference.put(name, mref); } } }
/** * Test ModuleReader#find */ void testFind(ModuleReader reader, String name, byte[] expectedBytes) throws Exception { Optional<URI> ouri = reader.find(name); assertTrue(ouri.isPresent()); URL url = ouri.get().toURL(); if (!url.getProtocol().equalsIgnoreCase("jmod")) { URLConnection uc = url.openConnection(); uc.setUseCaches(false); try (InputStream in = uc.getInputStream()) { byte[] bytes = in.readAllBytes(); assertTrue(Arrays.equals(bytes, expectedBytes)); } } }
/** * Test ModuleReader#read */ void testRead(ModuleReader reader, String name, byte[] expectedBytes) throws Exception { Optional<ByteBuffer> obb = reader.read(name); assertTrue(obb.isPresent()); ByteBuffer bb = obb.get(); try { int rem = bb.remaining(); assertTrue(rem == expectedBytes.length); byte[] bytes = new byte[rem]; bb.get(bytes); assertTrue(Arrays.equals(bytes, expectedBytes)); } finally { reader.release(bb); } }
public void testBasic() throws Exception { ModuleDescriptor descriptor = new ModuleDescriptor.Builder("m") .exports("p") .exports("q") .conceals("p.internal") .build(); URI uri = URI.create("module:/m"); Supplier<ModuleReader> supplier = makeSupplier(); ModuleReference mref = new ModuleReference(descriptor, uri, supplier); assertTrue(mref.descriptor().equals(descriptor)); assertTrue(mref.location().get().equals(uri)); // check that the supplier is called try { mref.open(); assertTrue(false); } catch (UnsupportedOperationException expected) { } }
public void testEqualsAndHashCode() { ModuleDescriptor descriptor1 = new ModuleDescriptor.Builder("m1") .exports("p") .build(); ModuleDescriptor descriptor2 = new ModuleDescriptor.Builder("m1") .exports("p") .build(); URI uri = URI.create("module:/m1"); Supplier<ModuleReader> supplier = makeSupplier(); ModuleReference mref1 = new ModuleReference(descriptor1, uri, supplier); ModuleReference mref2 = new ModuleReference(descriptor2, uri, supplier); ModuleReference mref3 = new ModuleReference(descriptor1, null, supplier); assertTrue(mref1.equals(mref1)); assertTrue(mref1.equals(mref1)); assertTrue(mref2.equals(mref1)); assertTrue(mref1.hashCode() == mref2.hashCode()); assertTrue(mref3.equals(mref3)); assertFalse(mref3.equals(mref1)); assertFalse(mref1.equals(mref3)); }
private static void findRequiresExportsUsesAndProvides(ModuleReference ref, Set<String> requirePackages, Set<String> exports, Set<String> uses, Map<String, Set<String>> provides) throws IOException { try(ModuleReader reader = ref.open()) { try(Stream<String> resources = reader.list()) { resources.forEach(resource -> { if (resource.endsWith(".class")) { scanJavaClass(resource, reader, requirePackages, exports, uses); } else { if (resource.startsWith("META-INF/services/")) { // skip "META-INF/services/" directory resource entry if (resource.length() == "META-INF/services/".length()) { return; } scanServiceFile(resource, reader, provides); } } }); } } requirePackages.removeAll(exports); }
/** * Creates a ModuleReader for the given module. */ private ModuleReader createModuleReader(ModuleReference mref) { try { return mref.open(); } catch (IOException e) { // Return a null module reader to avoid a future class load // attempting to open the module again. return new NullModuleReader(); } }
/** * Creates a ModuleReference to a possibly-patched module in a modular JAR. */ static ModuleReference newJarModule(ModuleInfo.Attributes attrs, ModulePatcher patcher, Path file) { URI uri = file.toUri(); Supplier<ModuleReader> supplier = () -> new JarModuleReader(file, uri); HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a); return newModule(attrs, uri, supplier, patcher, hasher); }
/** * Creates a ModuleReference to a module in a JMOD file. */ static ModuleReference newJModModule(ModuleInfo.Attributes attrs, Path file) { URI uri = file.toUri(); Supplier<ModuleReader> supplier = () -> new JModModuleReader(file, uri); HashSupplier hasher = (a) -> ModuleHashes.computeHash(file, a); return newModule(attrs, uri, supplier, null, hasher); }
/** * Creates a ModuleReference to a possibly-patched exploded module. */ static ModuleReference newExplodedModule(ModuleInfo.Attributes attrs, ModulePatcher patcher, Path dir) { Supplier<ModuleReader> supplier = () -> new ExplodedModuleReader(dir); return newModule(attrs, dir.toUri(), supplier, patcher, null); }
@Override public ModuleReader open() throws IOException { try { return readerSupplier.get(); } catch (UncheckedIOException e) { throw e.getCause(); } }
/** * Creates a ModuleReference to the system module. */ static ModuleReference toModuleReference(ModuleDescriptor descriptor, ModuleTarget target, ModuleHashes recordedHashes, HashSupplier hasher, ModuleResolution mres) { String mn = descriptor.name(); URI uri = JNUA.create("jrt", "/".concat(mn)); Supplier<ModuleReader> readerSupplier = new Supplier<>() { @Override public ModuleReader get() { return new SystemModuleReader(mn, uri); } }; ModuleReference mref = new ModuleReferenceImpl(descriptor, uri, readerSupplier, null, target, recordedHashes, hasher, mres); // may need a reference to a patched module if --patch-module specified mref = ModuleBootstrap.patcher().patchIfNeeded(mref); return mref; }
/** * Returns the ModuleReader to delegate to when the resource is not * found in a patch location. */ private ModuleReader delegate() throws IOException { ModuleReader r = delegate; if (r == null) { synchronized (this) { r = delegate; if (r == null) { delegate = r = mref.open(); } } } return r; }
private static ModuleReference moduleReference(ModuleDescriptor desc) { return new ModuleReference(desc, null) { @Override public ModuleReader open() { throw new UnsupportedOperationException(); } }; }
/** * Test ModuleReader#open */ void testOpen(ModuleReader reader, String name, byte[] expectedBytes) throws IOException { Optional<InputStream> oin = reader.open(name); assertTrue(oin.isPresent()); InputStream in = oin.get(); try (in) { byte[] bytes = in.readAllBytes(); assertTrue(Arrays.equals(bytes, expectedBytes)); } }
/** * Test ModuleReader#list */ void testList(ModuleReader reader, String name) throws IOException { List<String> list = reader.list().collect(Collectors.toList()); Set<String> names = new HashSet<>(list); assertTrue(names.size() == list.size()); // no duplicates assertTrue(names.contains("module-info.class")); assertTrue(names.contains(name)); // all resources should be locatable via find for (String e : names) { assertTrue(reader.find(e).isPresent()); } }
/** * List all modules that the finder finds and the resources in the module. */ private void listAllModules(ModuleFinder finder) throws Exception { for (ModuleReference mref : finder.findAll()) { System.out.println(mref.descriptor()); try (ModuleReader reader = mref.open()) { reader.list().forEach(name -> System.out.format(" %s%n", name)); } } }
private ModuleReference newModuleReference(ModuleDescriptor descriptor, URI uri) { return new ModuleReference(descriptor, uri) { @Override public ModuleReader open() { throw new UnsupportedOperationException(); } }; }
public static ModuleTarget read(ModuleReference modRef) throws IOException { ModuleReader reader = modRef.open(); try (InputStream in = reader.open("module-info.class").get()) { return read(in); } finally { reader.close(); } }
/** * Test ModuleReader#open */ void testOpen(ModuleReader reader, String name, byte[] expectedBytes) throws Exception { Optional<InputStream> oin = reader.open(name); assertTrue(oin.isPresent()); InputStream in = oin.get(); try (in) { byte[] bytes = in.readAllBytes(); assertTrue(Arrays.equals(bytes, expectedBytes)); } }
public void testNullLocation() { ModuleDescriptor descriptor = new ModuleDescriptor.Builder("m") .exports("p") .build(); Supplier<ModuleReader> supplier = makeSupplier(); ModuleReference mref = new ModuleReference(descriptor, null, supplier); assertTrue(!mref.location().isPresent()); }
public void testToString() { ModuleDescriptor descriptor = new ModuleDescriptor.Builder("m1").build(); URI uri = URI.create("module:/m1"); Supplier<ModuleReader> supplier = makeSupplier(); ModuleReference mref = new ModuleReference(descriptor, uri, supplier); String s = mref.toString(); assertTrue(s.contains("m1")); assertTrue(s.contains(uri.toString())); }
private static ModuleReader getReader(BundleWiring wiring) { // Pretty sure this never used, but it is possible the // jpms layer above would want to get resources out of modules // in the bundle layer. This code would provide that access. return new ModuleReader() { @Override public Optional<URI> find(String name) throws IOException { int lastSlash = name.lastIndexOf('/'); String path; String filePattern; if (lastSlash > 0) { path = name.substring(0, lastSlash); filePattern = name.substring(lastSlash + 1); } else { path = ""; filePattern = name; } Collection<String> resources = wiring.listResources(path, filePattern, BundleWiring.LISTRESOURCES_LOCAL); URI uri; try { uri = resources.isEmpty() ? null : wiring.getClassLoader().getResource(name).toURI(); } catch (URISyntaxException e) { uri = null; } return Optional.ofNullable(uri); } @Override public void close() throws IOException { } @Override public Stream<String> list() throws IOException { return Stream.empty(); } }; }
static ModuleReference moduleReference(ModuleDescriptor descriptor, URI uri, ModuleReader moduleReader) { return new ModuleReference(descriptor, uri) { @Override public ModuleReader open() throws IOException { return moduleReader; } }; }
private static void scanServiceFile(String resource, ModuleReader reader, Map<String, Set<String>> provides) { String service = resource.substring("META-INF/services/".length()); try(InputStream input = reader.open(resource).orElseThrow(() -> new IOException("resource unavailable " + resource)); InputStreamReader isr = new InputStreamReader(input, StandardCharsets.UTF_8); BufferedReader lineReader = new BufferedReader(isr)) { Set<String> providers = lineReader.lines() .map(ModuleFixerPlugin::parseProviderLine) .collect(Collectors.toSet()); provides.put(service, providers); } catch(IOException e) { throw new UncheckedIOException(e); } }
public ModuleReader open() { return null; }
/** * Returns the ModuleReader for the given module. */ private ModuleReader moduleReaderFor(ModuleReference mref) { return moduleToReader.computeIfAbsent(mref, m -> createModuleReader(mref)); }
/** * Defines the given binary class name to the VM, loading the class * bytes from the given module. * * @return the resulting Class or {@code null} if an I/O error occurs */ private Class<?> defineClass(String cn, LoadedModule loadedModule) { ModuleReference mref = loadedModule.mref(); ModuleReader reader = moduleReaderFor(mref); try { ByteBuffer bb = null; URL csURL = null; // locate class file, special handling for patched modules to // avoid locating the resource twice String rn = cn.replace('.', '/').concat(".class"); if (reader instanceof PatchedModuleReader) { Resource r = ((PatchedModuleReader)reader).findResource(rn); if (r != null) { bb = r.getByteBuffer(); csURL = r.getCodeSourceURL(); } } else { bb = reader.read(rn).orElse(null); csURL = loadedModule.codeSourceURL(); } if (bb == null) { // class not found return null; } CodeSource cs = new CodeSource(csURL, (CodeSigner[]) null); try { // define class to VM return defineClass(cn, bb, cs); } finally { reader.release(bb); } } catch (IOException ioe) { // TBD on how I/O errors should be propagated return null; } }