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