1 /* 2 * Copyright (c) 2010, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package com.sun.classanalyzer; 24 25 import java.io.BufferedReader; 26 import java.io.File; 27 import java.io.FileNotFoundException; 28 import java.io.FileReader; 29 import java.io.IOException; 30 31 import java.util.Collection; 32 import java.util.Deque; 33 import java.util.LinkedList; 34 import java.util.Properties; 35 import java.util.Set; 36 import java.util.TreeSet; 37 import static com.sun.classanalyzer.Module.*; 38 39 /** 40 * Platform module. 41 * 42 * The name of the platform modules starts with either "jdk." or "sun.". 43 * All sun.* and jdk.boot are local modules. Any requesting module 44 * of a local module has to be explicitly permitted. 45 * 46 * The input module config files can define "sun.*" and "jdk.*" 47 * modules. For any sun.* module, it will have a corresponding 48 * non-local platform module that is defined for application modules 49 * to require. 50 * 51 * The tool will create the following platform modules: 52 * 1) jdk.<name> for each sun.<name> module 53 * 2) jdk module - represents the entire JDK 54 * 3) jdk.jre module - represents the entire JRE 55 * 56 */ 57 public class Platform { 58 59 static final String DEFAULT_BOOT_MODULE = "jdk.boot"; 60 static final String JDK_BASE_MODULE = "jdk.base"; 61 // platform modules created but not defined in the input module configs. 62 static final String JDK_MODULE = "jdk"; 63 static final String JRE_MODULE = "jdk.jre"; 64 static final String LEGACY_MODULE = "jdk.legacy"; 65 // the following modules are expected to be defined in 66 // the input module config files. 67 static final String JDK_TOOLS = "jdk.tools"; 68 static final String JRE_TOOLS = "jdk.tools.jre"; 69 static final String JDK_BASE_TOOLS = "jdk.tools.base"; 70 static final String JDK_LANGTOOLS = "jdk.langtools"; 71 72 static boolean isBootModule(String name) { 73 return name.equals(DEFAULT_BOOT_MODULE); 74 } 75 private static BootModule bootModule; 76 77 static Module createBootModule(ModuleConfig config) { 78 bootModule = new BootModule(config); 79 return bootModule; 80 } 81 82 static Module bootModule() { 83 return bootModule; 84 } 85 private static Module jdkBaseModule; 86 87 static Module jdkBaseModule() { 88 if (jdkBaseModule == null) { 89 jdkBaseModule = findModule(JDK_BASE_MODULE); 90 } 91 return jdkBaseModule; 92 } 93 private static Module jdkBaseToolModule; 94 95 static Module jdkBaseToolModule() { 96 if (jdkBaseToolModule == null) { 97 jdkBaseToolModule = findModule(JDK_BASE_TOOLS); 98 } 99 return jdkBaseToolModule; 100 } 101 private static Module jdkModule; 102 private static Module jreModule; 103 private static Module legacyModule; 104 105 static Module jdkModule() { 106 return jdkModule; 107 } 108 109 static Module jreModule() { 110 return jreModule; 111 } 112 113 static Module legacyModule() { 114 return legacyModule; 115 } 116 117 private static Module addPlatformModule(String name, String mainClass) { 118 ModuleConfig config = null; 119 try { 120 config = new ModuleConfig(name, mainClass); 121 return Module.addModule(config); 122 } catch (IOException ex) { 123 throw new RuntimeException(ex); 124 } 125 } 126 127 static boolean isAggregator(String name) { 128 return name.equals(JDK_MODULE) || 129 name.equals(JRE_MODULE) || 130 name.equals(JDK_TOOLS) || 131 name.equals(JRE_TOOLS) || 132 name.equals(JDK_BASE_TOOLS) || 133 name.equals(LEGACY_MODULE) || 134 name.startsWith(JDK_LANGTOOLS); 135 } 136 137 // returns the module that is used by the requires statement 138 // in other module's module-info 139 static Module toRequiresModule(Module m) { 140 Module moduleForRequires = m; 141 if (m == bootModule()) { 142 moduleForRequires = jdkBaseModule(); 143 } else if (m.name().startsWith("sun.")) { 144 // create an aggregate module for each sun.* module 145 String mn = m.name().replaceFirst("sun", "jdk"); 146 String mainClassName = m.mainClass() == null ? null : m.mainClass().getClassName(); 147 148 Module rm = findModule(mn); 149 if (rm != null) { 150 if (rm.mainClass() != m.mainClass()) { 151 throw new RuntimeException(mn + 152 " module already exists but mainClass not matched"); 153 } 154 return rm; 155 } 156 157 if (m.hasPlatformAPIs()) { 158 ModuleConfig config = null; 159 try { 160 config = new ModuleConfig(mn, mainClassName); 161 } catch (IOException ex) { 162 throw new RuntimeException(ex); 163 } 164 moduleForRequires = Module.addModule(config); 165 moduleForRequires.addRequiresModule(m); 166 } 167 } 168 return moduleForRequires; 169 } 170 171 static void fixupPlatformModules() { 172 // Create the full jdk and jre modules 173 jdkModule = addPlatformModule(JDK_MODULE, null /* no main class */); 174 jreModule = addPlatformModule(JRE_MODULE, null /* no main class */); 175 176 Module jreTools = findModule(JRE_TOOLS); 177 Module jdkTools = findModule(JDK_TOOLS); 178 Module jdkBaseTools = findModule(JDK_BASE_TOOLS); 179 180 for (Module m : getTopLevelModules()) { 181 String mn = m.name(); 182 183 // initialize module-info 184 m.fixupModuleInfo(); 185 186 // set up the jdk, jdk.jre and jdk.legacy modules 187 if (mn.startsWith("jdk.") || mn.startsWith("sun.")) { 188 Module req = m.toRequiredModule(); 189 190 if (!m.isAggregator() && !mn.equals(JDK_MODULE) && !mn.equals(JRE_MODULE)) { 191 // all platform modules are required jdk module 192 jdkModule.addRequiresModule(req); 193 if (m.isBootConnected() || mn.equals(JRE_TOOLS)) { 194 // add all modules that are strongly connected to jdk.boot to JRE 195 jreModule.addRequiresModule(req); 196 } 197 } 198 } else { 199 Trace.trace("Non-platform module: %s%n", m.name()); 200 } 201 } 202 // fixup the base module to include optional dependences from boot 203 // ## It adds jndi, logging, and xml optional dependences 204 // bootModule.fixupBase(); 205 } 206 private static String[] corePkgs = new String[]{ 207 "java", "javax", 208 "org.omg", "org.w3c.dom", 209 "org.xml.sax", "org.ietf.jgss" 210 }; 211 private static Set<String> nonCorePkgs = new TreeSet<String>(); 212 213 static void addNonCorePkgs(String file) throws FileNotFoundException, IOException { 214 File f = new File(file); 215 Properties props = new Properties(); 216 BufferedReader reader = null; 217 218 try { 219 reader = new BufferedReader(new FileReader(f)); 220 props.load(reader); 221 String s = props.getProperty("NON_CORE_PKGS"); 222 String[] ss = s.split("\\s+"); 223 Deque<String> values = new LinkedList<String>(); 224 225 for (String v : ss) { 226 values.add(v.trim()); 227 } 228 229 String pval; 230 while ((pval = values.poll()) != null) { 231 if (pval.startsWith("$(") && pval.endsWith(")")) { 232 String key = pval.substring(2, pval.length() - 1); 233 String value = props.getProperty(key); 234 if (value == null) { 235 throw new RuntimeException("key " + key + " not found"); 236 } 237 ss = value.split("\\s+"); 238 for (String v : ss) { 239 values.add(v.trim()); 240 } 241 continue; 242 } 243 if (pval.startsWith("java.") || pval.startsWith("javax") || 244 pval.startsWith("com.") || pval.startsWith("org.")) { 245 nonCorePkgs.add(pval); 246 } else { 247 throw new RuntimeException("Invalid non core package: " + pval); 248 } 249 } 250 } finally { 251 if (reader != null) { 252 reader.close(); 253 } 254 } 255 } 256 257 static boolean isPlatformAPI(String classname) { 258 for (String pkg : corePkgs) { 259 if (classname.startsWith(pkg + ".")) { 260 return true; 261 } 262 } 263 return false; 264 } 265 266 static boolean isNonCoreAPI(String pkgName) { 267 for (String pkg : nonCorePkgs) { 268 if (pkgName.startsWith(pkg)) { 269 return true; 270 } 271 } 272 return false; 273 } 274 275 static class BootModule extends Module { 276 277 BootModule(ModuleConfig config) { 278 super(config); 279 } 280 281 Collection<Dependency> dependences() { 282 Set<Dependency> result = new TreeSet<Dependency>(); 283 for (Dependency d : dependents()) { 284 // filter out optional dependences from jdk.boot module 285 if (!d.optional) { 286 result.add(d); 287 } 288 } 289 return result; 290 } 291 292 Module toRequiresModule() { 293 return jdkBaseModule(); 294 } 295 296 boolean isBootConnected() { 297 return true; 298 } 299 300 boolean requirePermits() { 301 return true; 302 } 303 304 void fixupBase() { 305 // fixup jdk.boot optional dependences 306 for (Dependency d : dependents()) { 307 if (d.optional) { 308 Module m = d.module().toRequiredModule(); 309 jdkBaseModule().addRequiresModule(m); 310 Trace.trace("add requires %s to %s%n", m, jdkBaseModule().name()); 311 if (m != d.module()) { 312 m.permits().remove(this); 313 } 314 315 } 316 } 317 318 } 319 } 320 }