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