1/* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25package jdk.internal.module; 26 27import java.io.BufferedReader; 28import java.io.IOException; 29import java.io.InputStream; 30import java.io.InputStreamReader; 31import java.io.UncheckedIOException; 32import java.lang.module.ModuleDescriptor; 33import java.lang.module.ModuleFinder; 34import java.lang.module.ModuleReference; 35import java.util.HashMap; 36import java.util.HashSet; 37import java.util.Map; 38import java.util.Set; 39 40import static java.nio.charset.StandardCharsets.*; 41 42/** 43 * Generates the maps of concealed and exported packages to open at run-time. 44 * 45 * This is used at run-time for exploded builds, and at link-time to generate 46 * the maps for the system modules in the run-time image. 47 */ 48 49public class IllegalAccessMaps { 50 private final Map<String, Set<String>> concealedPackagesToOpen; 51 private final Map<String, Set<String>> exportedPackagesToOpen; 52 53 private IllegalAccessMaps(Map<String, Set<String>> map1, 54 Map<String, Set<String>> map2) { 55 this.concealedPackagesToOpen = map1; 56 this.exportedPackagesToOpen = map2; 57 } 58 59 /** 60 * Returns the map of concealed packages to open. The map key is the 61 * module name, the value is the set of concealed packages to open. 62 */ 63 public Map<String, Set<String>> concealedPackagesToOpen() { 64 return concealedPackagesToOpen; 65 } 66 67 /** 68 * Returns the map of exported packages to open. The map key is the 69 * module name, the value is the set of exported packages to open. 70 */ 71 public Map<String, Set<String>> exportedPackagesToOpen() { 72 return exportedPackagesToOpen; 73 } 74 75 /** 76 * Generate the maps of module to concealed and exported packages for 77 * the system modules that are observable with the given module finder. 78 */ 79 public static IllegalAccessMaps generate(ModuleFinder finder) { 80 Map<String, ModuleDescriptor> map = new HashMap<>(); 81 finder.findAll().stream() 82 .map(ModuleReference::descriptor) 83 .forEach(md -> md.packages().forEach(pn -> map.putIfAbsent(pn, md))); 84 85 Map<String, Set<String>> concealedPackagesToOpen = new HashMap<>(); 86 Map<String, Set<String>> exportedPackagesToOpen = new HashMap<>(); 87 88 String rn = "jdk8_packages.dat"; 89 InputStream in = IllegalAccessMaps.class.getResourceAsStream(rn); 90 if (in == null) { 91 throw new InternalError(rn + " not found"); 92 } 93 try (BufferedReader br = new BufferedReader(new InputStreamReader(in, UTF_8))) { 94 br.lines() 95 .filter(line -> !line.isEmpty() && !line.startsWith("#")) 96 .forEach(pn -> { 97 ModuleDescriptor descriptor = map.get(pn); 98 if (descriptor != null && !isOpen(descriptor, pn)) { 99 String name = descriptor.name(); 100 if (isExported(descriptor, pn)) { 101 exportedPackagesToOpen.computeIfAbsent(name, 102 k -> new HashSet<>()).add(pn); 103 } else { 104 concealedPackagesToOpen.computeIfAbsent(name, 105 k -> new HashSet<>()).add(pn); 106 } 107 } 108 }); 109 110 } catch (IOException ioe) { 111 throw new UncheckedIOException(ioe); 112 } 113 114 return new IllegalAccessMaps(concealedPackagesToOpen, exportedPackagesToOpen); 115 } 116 117 private static boolean isExported(ModuleDescriptor descriptor, String pn) { 118 return descriptor.exports() 119 .stream() 120 .anyMatch(e -> e.source().equals(pn) && !e.isQualified()); 121 } 122 123 private static boolean isOpen(ModuleDescriptor descriptor, String pn) { 124 return descriptor.opens() 125 .stream() 126 .anyMatch(e -> e.source().equals(pn) && !e.isQualified()); 127 } 128} 129