1 /* 2 * Copyright (c) 2006, 2012, 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 */ 25 26 package com.sun.tools.javac.sym; 27 28 import com.sun.tools.javac.api.JavacTaskImpl; 29 import com.sun.tools.javac.code.Kinds; 30 import com.sun.tools.javac.code.Scope; 31 import com.sun.tools.javac.code.Symbol.*; 32 import com.sun.tools.javac.code.Symbol; 33 import com.sun.tools.javac.code.Attribute; 34 import com.sun.tools.javac.code.Symtab; 35 import com.sun.tools.javac.code.Type; 36 import com.sun.tools.javac.code.Types; 37 import com.sun.tools.javac.jvm.ClassWriter; 38 import com.sun.tools.javac.jvm.Pool; 39 import com.sun.tools.javac.processing.JavacProcessingEnvironment; 40 import com.sun.tools.javac.util.List; 41 import com.sun.tools.javac.util.Names; 42 import com.sun.tools.javac.util.Pair; 43 44 import java.io.File; 45 import java.io.IOException; 46 import java.util.ArrayList; 47 import java.util.EnumSet; 48 import java.util.Enumeration; 49 import java.util.HashSet; 50 import java.util.Map; 51 import java.util.ResourceBundle; 52 import java.util.Set; 53 54 import javax.annotation.processing.AbstractProcessor; 55 import javax.annotation.processing.RoundEnvironment; 56 import javax.annotation.processing.SupportedAnnotationTypes; 57 import javax.annotation.processing.SupportedOptions; 58 import javax.lang.model.SourceVersion; 59 import javax.lang.model.element.ElementKind; 60 import javax.lang.model.element.TypeElement; 61 import javax.tools.Diagnostic; 62 import javax.tools.JavaCompiler; 63 import javax.tools.JavaFileManager.Location; 64 import javax.tools.JavaFileObject; 65 import static javax.tools.JavaFileObject.Kind.CLASS; 66 import javax.tools.StandardJavaFileManager; 67 import javax.tools.StandardLocation; 68 import javax.tools.ToolProvider; 69 70 /** 71 * Used to generate a "symbol file" representing rt.jar that only 72 * includes supported or legacy proprietary API. Valid annotation 73 * processor options: 74 * 75 * <dl> 76 * <dt>com.sun.tools.javac.sym.Jar</dt> 77 * <dd>Specifies the location of rt.jar.</dd> 78 * <dt>com.sun.tools.javac.sym.Dest</dt> 79 * <dd>Specifies the destination directory.</dd> 80 * </dl> 81 * 82 * <p><b>This is NOT part of any supported API. 83 * If you write code that depends on this, you do so at your own 84 * risk. This code and its internal interfaces are subject to change 85 * or deletion without notice.</b></p> 86 * 87 * @author Peter von der Ah\u00e9 88 */ 89 @SupportedOptions({ 90 "com.sun.tools.javac.sym.Jar", 91 "com.sun.tools.javac.sym.Dest", 92 "com.sun.tools.javac.sym.Profiles"}) 93 @SupportedAnnotationTypes("*") 94 public class CreateSymbols extends AbstractProcessor { 95 96 static Set<String> getLegacyPackages() { 97 ResourceBundle legacyBundle 98 = ResourceBundle.getBundle("com.sun.tools.javac.resources.legacy"); 99 Set<String> keys = new HashSet<String>(); 100 for (Enumeration<String> e = legacyBundle.getKeys(); e.hasMoreElements(); ) 101 keys.add(e.nextElement()); 102 return keys; 103 } 104 105 public boolean process(Set<? extends TypeElement> tes, RoundEnvironment renv) { 106 try { 107 if (renv.processingOver()) 108 createSymbols(); 109 } catch (IOException e) { 110 processingEnv.getMessager() 111 .printMessage(Diagnostic.Kind.ERROR, e.getLocalizedMessage()); 112 } catch (Throwable t) { 113 t.printStackTrace(); 114 Throwable cause = t.getCause(); 115 if (cause == null) 116 cause = t; 117 processingEnv.getMessager() 118 .printMessage(Diagnostic.Kind.ERROR, cause.getLocalizedMessage()); 119 } 120 return true; 121 } 122 123 void createSymbols() throws IOException { 124 Set<String> legacy = getLegacyPackages(); 125 Set<String> legacyProprietary = getLegacyPackages(); 126 Set<String> documented = new HashSet<String>(); 127 Set<PackageSymbol> packages = 128 ((JavacProcessingEnvironment)processingEnv).getSpecifiedPackages(); 129 Map<String,String> pOptions = processingEnv.getOptions(); 130 String jarName = pOptions.get("com.sun.tools.javac.sym.Jar"); 131 if (jarName == null) 132 throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Jar=LOCATION_OF_JAR"); 133 String destName = pOptions.get("com.sun.tools.javac.sym.Dest"); 134 if (destName == null) 135 throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Dest=LOCATION_OF_JAR"); 136 String profileSpec=pOptions.get("com.sun.tools.javac.sym.Profiles"); 137 if (profileSpec == null) 138 throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Profiles=PROFILES_SPEC"); 139 Profiles profiles = Profiles.read(new File(profileSpec)); 140 141 for (PackageSymbol psym : packages) { 142 String name = psym.getQualifiedName().toString(); 143 legacyProprietary.remove(name); 144 documented.add(name); 145 } 146 147 JavaCompiler tool = ToolProvider.getSystemJavaCompiler(); 148 StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null); 149 Location jarLocation = StandardLocation.locationFor(jarName); 150 File jarFile = new File(jarName); 151 fm.setLocation(jarLocation, List.of(jarFile)); 152 fm.setLocation(StandardLocation.CLASS_PATH, List.<File>nil()); 153 fm.setLocation(StandardLocation.SOURCE_PATH, List.<File>nil()); 154 { 155 ArrayList<File> bootClassPath = new ArrayList<File>(); 156 bootClassPath.add(jarFile); 157 for (File path : fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH)) { 158 if (!new File(path.getName()).equals(new File("rt.jar"))) 159 bootClassPath.add(path); 160 } 161 System.err.println("Using boot class path = " + bootClassPath); 162 fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath); 163 } 164 // System.out.println(fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH)); 165 File destDir = new File(destName); 166 if (!destDir.exists()) 167 if (!destDir.mkdirs()) 168 throw new RuntimeException("Could not create " + destDir); 169 fm.setLocation(StandardLocation.CLASS_OUTPUT, List.of(destDir)); 170 Set<String> hiddenPackages = new HashSet<String>(); 171 Set<String> crisp = new HashSet<String>(); 172 List<String> options = List.of("-XDdev"); 173 // options = options.prepend("-doe"); 174 // options = options.prepend("-verbose"); 175 JavacTaskImpl task = (JavacTaskImpl) 176 tool.getTask(null, fm, null, options, null, null); 177 com.sun.tools.javac.main.JavaCompiler compiler = 178 com.sun.tools.javac.main.JavaCompiler.instance(task.getContext()); 179 ClassWriter writer = ClassWriter.instance(task.getContext()); 180 Symtab syms = Symtab.instance(task.getContext()); 181 Names names = Names.instance(task.getContext()); 182 Attribute.Compound proprietaryAnno = 183 new Attribute.Compound(syms.proprietaryType, 184 List.<Pair<Symbol.MethodSymbol,Attribute>>nil()); 185 Attribute.Compound[] profileAnnos = new Attribute.Compound[profiles.getProfileCount() + 1]; 186 Symbol.MethodSymbol profileValue = (MethodSymbol) syms.profileType.tsym.members().lookup(names.value).sym; 187 for (int i = 1; i < profileAnnos.length; i++) { 188 profileAnnos[i] = new Attribute.Compound(syms.profileType, 189 List.<Pair<Symbol.MethodSymbol, Attribute>>of( 190 new Pair<Symbol.MethodSymbol, Attribute>(profileValue, new Attribute.Constant(syms.intType, i)))); 191 } 192 193 Type.moreInfo = true; 194 Types types = Types.instance(task.getContext()); 195 Pool pool = new Pool(types); 196 for (JavaFileObject file : fm.list(jarLocation, "", EnumSet.of(CLASS), true)) { 197 String className = fm.inferBinaryName(jarLocation, file); 198 int index = className.lastIndexOf('.'); 199 String pckName = index == -1 ? "" : className.substring(0, index); 200 boolean addLegacyAnnotation = false; 201 if (documented.contains(pckName)) { 202 if (!legacy.contains(pckName)) 203 crisp.add(pckName); 204 // System.out.println("Documented: " + className); 205 } else if (legacyProprietary.contains(pckName)) { 206 addLegacyAnnotation = true; 207 // System.out.println("Legacy proprietary: " + className); 208 } else { 209 // System.out.println("Hidden " + className); 210 hiddenPackages.add(pckName); 211 continue; 212 } 213 TypeSymbol sym = (TypeSymbol)compiler.resolveIdent(className); 214 if (sym.kind != Kinds.TYP) { 215 if (className.indexOf('$') < 0) { 216 System.err.println("Ignoring (other) " + className + " : " + sym); 217 System.err.println(" " + sym.getClass().getSimpleName() + " " + sym.type); 218 } 219 continue; 220 } 221 sym.complete(); 222 if (sym.getEnclosingElement().getKind() != ElementKind.PACKAGE) { 223 System.err.println("Ignoring (bad) " + sym.getQualifiedName()); 224 continue; 225 } 226 ClassSymbol cs = (ClassSymbol) sym; 227 if (addLegacyAnnotation) { 228 cs.annotations.prepend(List.of(proprietaryAnno)); 229 } 230 int p = profiles.getProfile(cs.fullname.toString().replace(".", "/")); 231 if (0 < p && p < profileAnnos.length) 232 cs.annotations.prepend(List.of(profileAnnos[p])); 233 writeClass(pool, cs, writer); 234 } 235 236 if (false) { 237 for (String pckName : crisp) 238 System.out.println("Crisp: " + pckName); 239 for (String pckName : hiddenPackages) 240 System.out.println("Hidden: " + pckName); 241 for (String pckName : legacyProprietary) 242 System.out.println("Legacy proprietary: " + pckName); 243 for (String pckName : documented) 244 System.out.println("Documented: " + pckName); 245 } 246 } 247 248 void writeClass(final Pool pool, final ClassSymbol cs, final ClassWriter writer) 249 throws IOException 250 { 251 try { 252 pool.reset(); 253 cs.pool = pool; 254 writer.writeClass(cs); 255 for (Scope.Entry e = cs.members().elems; e != null; e = e.sibling) { 256 if (e.sym.kind == Kinds.TYP) { 257 ClassSymbol nestedClass = (ClassSymbol)e.sym; 258 nestedClass.complete(); 259 writeClass(pool, nestedClass, writer); 260 } 261 } 262 } catch (ClassWriter.StringOverflow ex) { 263 throw new RuntimeException(ex); 264 } catch (ClassWriter.PoolOverflow ex) { 265 throw new RuntimeException(ex); 266 } 267 } 268 269 public SourceVersion getSupportedSourceVersion() { 270 return SourceVersion.latest(); 271 } 272 273 // used for debugging 274 public static void main(String... args) { 275 String rt_jar = args[0]; 276 String dest = args[1]; 277 args = new String[] { 278 "-Xbootclasspath:" + rt_jar, 279 "-XDprocess.packages", 280 "-proc:only", 281 "-processor", 282 "com.sun.tools.javac.sym.CreateSymbols", 283 "-Acom.sun.tools.javac.sym.Jar=" + rt_jar, 284 "-Acom.sun.tools.javac.sym.Dest=" + dest, 285 // <editor-fold defaultstate="collapsed"> 286 "java.applet", 287 "java.awt", 288 "java.awt.color", 289 "java.awt.datatransfer", 290 "java.awt.dnd", 291 "java.awt.event", 292 "java.awt.font", 293 "java.awt.geom", 294 "java.awt.im", 295 "java.awt.im.spi", 296 "java.awt.image", 297 "java.awt.image.renderable", 298 "java.awt.print", 299 "java.beans", 300 "java.beans.beancontext", 301 "java.io", 302 "java.lang", 303 "java.lang.annotation", 304 "java.lang.instrument", 305 "java.lang.management", 306 "java.lang.ref", 307 "java.lang.reflect", 308 "java.math", 309 "java.net", 310 "java.nio", 311 "java.nio.channels", 312 "java.nio.channels.spi", 313 "java.nio.charset", 314 "java.nio.charset.spi", 315 "java.rmi", 316 "java.rmi.activation", 317 "java.rmi.dgc", 318 "java.rmi.registry", 319 "java.rmi.server", 320 "java.security", 321 "java.security.acl", 322 "java.security.cert", 323 "java.security.interfaces", 324 "java.security.spec", 325 "java.sql", 326 "java.text", 327 "java.text.spi", 328 "java.util", 329 "java.util.concurrent", 330 "java.util.concurrent.atomic", 331 "java.util.concurrent.locks", 332 "java.util.jar", 333 "java.util.logging", 334 "java.util.prefs", 335 "java.util.regex", 336 "java.util.spi", 337 "java.util.zip", 338 "javax.accessibility", 339 "javax.activation", 340 "javax.activity", 341 "javax.annotation", 342 "javax.annotation.processing", 343 "javax.crypto", 344 "javax.crypto.interfaces", 345 "javax.crypto.spec", 346 "javax.imageio", 347 "javax.imageio.event", 348 "javax.imageio.metadata", 349 "javax.imageio.plugins.jpeg", 350 "javax.imageio.plugins.bmp", 351 "javax.imageio.spi", 352 "javax.imageio.stream", 353 "javax.jws", 354 "javax.jws.soap", 355 "javax.lang.model", 356 "javax.lang.model.element", 357 "javax.lang.model.type", 358 "javax.lang.model.util", 359 "javax.management", 360 "javax.management.loading", 361 "javax.management.monitor", 362 "javax.management.relation", 363 "javax.management.openmbean", 364 "javax.management.timer", 365 "javax.management.modelmbean", 366 "javax.management.remote", 367 "javax.management.remote.rmi", 368 "javax.naming", 369 "javax.naming.directory", 370 "javax.naming.event", 371 "javax.naming.ldap", 372 "javax.naming.spi", 373 "javax.net", 374 "javax.net.ssl", 375 "javax.print", 376 "javax.print.attribute", 377 "javax.print.attribute.standard", 378 "javax.print.event", 379 "javax.rmi", 380 "javax.rmi.CORBA", 381 "javax.rmi.ssl", 382 "javax.script", 383 "javax.security.auth", 384 "javax.security.auth.callback", 385 "javax.security.auth.kerberos", 386 "javax.security.auth.login", 387 "javax.security.auth.spi", 388 "javax.security.auth.x500", 389 "javax.security.cert", 390 "javax.security.sasl", 391 "javax.sound.sampled", 392 "javax.sound.sampled.spi", 393 "javax.sound.midi", 394 "javax.sound.midi.spi", 395 "javax.sql", 396 "javax.sql.rowset", 397 "javax.sql.rowset.serial", 398 "javax.sql.rowset.spi", 399 "javax.swing", 400 "javax.swing.border", 401 "javax.swing.colorchooser", 402 "javax.swing.filechooser", 403 "javax.swing.event", 404 "javax.swing.table", 405 "javax.swing.text", 406 "javax.swing.text.html", 407 "javax.swing.text.html.parser", 408 "javax.swing.text.rtf", 409 "javax.swing.tree", 410 "javax.swing.undo", 411 "javax.swing.plaf", 412 "javax.swing.plaf.basic", 413 "javax.swing.plaf.metal", 414 "javax.swing.plaf.multi", 415 "javax.swing.plaf.synth", 416 "javax.tools", 417 "javax.transaction", 418 "javax.transaction.xa", 419 "javax.xml.parsers", 420 "javax.xml.bind", 421 "javax.xml.bind.annotation", 422 "javax.xml.bind.annotation.adapters", 423 "javax.xml.bind.attachment", 424 "javax.xml.bind.helpers", 425 "javax.xml.bind.util", 426 "javax.xml.soap", 427 "javax.xml.ws", 428 "javax.xml.ws.handler", 429 "javax.xml.ws.handler.soap", 430 "javax.xml.ws.http", 431 "javax.xml.ws.soap", 432 "javax.xml.ws.spi", 433 "javax.xml.transform", 434 "javax.xml.transform.sax", 435 "javax.xml.transform.dom", 436 "javax.xml.transform.stax", 437 "javax.xml.transform.stream", 438 "javax.xml", 439 "javax.xml.crypto", 440 "javax.xml.crypto.dom", 441 "javax.xml.crypto.dsig", 442 "javax.xml.crypto.dsig.dom", 443 "javax.xml.crypto.dsig.keyinfo", 444 "javax.xml.crypto.dsig.spec", 445 "javax.xml.datatype", 446 "javax.xml.validation", 447 "javax.xml.namespace", 448 "javax.xml.xpath", 449 "javax.xml.stream", 450 "javax.xml.stream.events", 451 "javax.xml.stream.util", 452 "org.ietf.jgss", 453 "org.omg.CORBA", 454 "org.omg.CORBA.DynAnyPackage", 455 "org.omg.CORBA.ORBPackage", 456 "org.omg.CORBA.TypeCodePackage", 457 "org.omg.stub.java.rmi", 458 "org.omg.CORBA.portable", 459 "org.omg.CORBA_2_3", 460 "org.omg.CORBA_2_3.portable", 461 "org.omg.CosNaming", 462 "org.omg.CosNaming.NamingContextExtPackage", 463 "org.omg.CosNaming.NamingContextPackage", 464 "org.omg.SendingContext", 465 "org.omg.PortableServer", 466 "org.omg.PortableServer.CurrentPackage", 467 "org.omg.PortableServer.POAPackage", 468 "org.omg.PortableServer.POAManagerPackage", 469 "org.omg.PortableServer.ServantLocatorPackage", 470 "org.omg.PortableServer.portable", 471 "org.omg.PortableInterceptor", 472 "org.omg.PortableInterceptor.ORBInitInfoPackage", 473 "org.omg.Messaging", 474 "org.omg.IOP", 475 "org.omg.IOP.CodecFactoryPackage", 476 "org.omg.IOP.CodecPackage", 477 "org.omg.Dynamic", 478 "org.omg.DynamicAny", 479 "org.omg.DynamicAny.DynAnyPackage", 480 "org.omg.DynamicAny.DynAnyFactoryPackage", 481 "org.w3c.dom", 482 "org.w3c.dom.events", 483 "org.w3c.dom.bootstrap", 484 "org.w3c.dom.ls", 485 "org.xml.sax", 486 "org.xml.sax.ext", 487 "org.xml.sax.helpers", 488 "com.sun.java.browser.dom", 489 "org.w3c.dom", 490 "org.w3c.dom.bootstrap", 491 "org.w3c.dom.ls", 492 "org.w3c.dom.ranges", 493 "org.w3c.dom.traversal", 494 "org.w3c.dom.html", 495 "org.w3c.dom.stylesheets", 496 "org.w3c.dom.css", 497 "org.w3c.dom.events", 498 "org.w3c.dom.views", 499 "com.sun.management", 500 "com.sun.security.auth", 501 "com.sun.security.auth.callback", 502 "com.sun.security.auth.login", 503 "com.sun.security.auth.module", 504 "com.sun.security.jgss", 505 "com.sun.net.httpserver", 506 "com.sun.net.httpserver.spi", 507 "javax.smartcardio" 508 // </editor-fold> 509 }; 510 com.sun.tools.javac.Main.compile(args); 511 } 512 513 }