001    /*
002     * Copyright 2006-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    package com.sun.tools.javac.sym;
027    
028    import com.sun.tools.javac.api.JavacTaskImpl;
029    import com.sun.tools.javac.code.Kinds;
030    import com.sun.tools.javac.code.Scope;
031    import com.sun.tools.javac.code.Symbol.*;
032    import com.sun.tools.javac.code.Symbol;
033    import com.sun.tools.javac.code.Attribute;
034    import com.sun.tools.javac.code.Symtab;
035    import com.sun.tools.javac.code.Type;
036    import com.sun.tools.javac.jvm.ClassReader;
037    import com.sun.tools.javac.jvm.ClassWriter;
038    import com.sun.tools.javac.jvm.Pool;
039    import com.sun.tools.javac.processing.JavacProcessingEnvironment;
040    import com.sun.tools.javac.util.List;
041    import com.sun.tools.javac.util.Pair;
042    
043    import java.io.File;
044    import java.io.IOException;
045    import java.util.ArrayList;
046    import java.util.EnumSet;
047    import java.util.Enumeration;
048    import java.util.HashSet;
049    import java.util.ResourceBundle;
050    import java.util.Set;
051    
052    import javax.annotation.processing.AbstractProcessor;
053    import javax.annotation.processing.RoundEnvironment;
054    import javax.annotation.processing.SupportedAnnotationTypes;
055    import javax.annotation.processing.SupportedOptions;
056    import javax.lang.model.SourceVersion;
057    import javax.lang.model.element.ElementKind;
058    import javax.lang.model.element.TypeElement;
059    import javax.tools.Diagnostic;
060    import javax.tools.JavaCompiler;
061    import javax.tools.JavaFileManager.Location;
062    import javax.tools.JavaFileObject;
063    import static javax.tools.JavaFileObject.Kind.CLASS;
064    import javax.tools.StandardJavaFileManager;
065    import javax.tools.StandardLocation;
066    import javax.tools.ToolProvider;
067    
068    /**
069     * Used to generate a "symbol file" representing rt.jar that only
070     * includes supported or legacy proprietary API.  Valid annotation
071     * processor options:
072     *
073     * <dl>
074     * <dt>com.sun.tools.javac.sym.Jar</dt>
075     * <dd>Specifies the location of rt.jar.</dd>
076     * <dt>com.sun.tools.javac.sym.Dest</dt>
077     * <dd>Specifies the destination directory.</dd>
078     * </dl>
079     *
080     * <p><b>This is NOT part of any API supported by Sun Microsystems.
081     * If you write code that depends on this, you do so at your own
082     * risk.  This code and its internal interfaces are subject to change
083     * or deletion without notice.</b></p>
084     *
085     * @author Peter von der Ah\u00e9
086     */
087    @SupportedOptions({"com.sun.tools.javac.sym.Jar","com.sun.tools.javac.sym.Dest"})
088    @SupportedAnnotationTypes("*")
089    public class CreateSymbols extends AbstractProcessor {
090    
091        static Set<String> getLegacyPackages() {
092            ResourceBundle legacyBundle
093                = ResourceBundle.getBundle("com.sun.tools.javac.resources.legacy");
094            Set<String> keys = new HashSet<String>();
095            for (Enumeration<String> e = legacyBundle.getKeys(); e.hasMoreElements(); )
096                keys.add(e.nextElement());
097            return keys;
098        }
099    
100        public boolean process(Set<? extends TypeElement> tes, RoundEnvironment renv) {
101            try {
102                if (renv.processingOver())
103                    createSymbols();
104            } catch (IOException e) {
105                processingEnv.getMessager()
106                    .printMessage(Diagnostic.Kind.ERROR, e.getLocalizedMessage());
107            } catch (Throwable t) {
108                Throwable cause = t.getCause();
109                if (cause == null)
110                    cause = t;
111                processingEnv.getMessager()
112                    .printMessage(Diagnostic.Kind.ERROR, cause.getLocalizedMessage());
113            }
114            return true;
115        }
116    
117        void createSymbols() throws IOException {
118            Set<String> legacy = getLegacyPackages();
119            Set<String> legacyProprietary = getLegacyPackages();
120            Set<String> documented = new HashSet<String>();
121            Set<PackageSymbol> packages =
122                ((JavacProcessingEnvironment)processingEnv).getSpecifiedPackages();
123            String jarName = processingEnv.getOptions().get("com.sun.tools.javac.sym.Jar");
124            if (jarName == null)
125                throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Jar=LOCATION_OF_JAR");
126            String destName = processingEnv.getOptions().get("com.sun.tools.javac.sym.Dest");
127            if (destName == null)
128                throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Dest=LOCATION_OF_JAR");
129    
130            for (PackageSymbol psym : packages) {
131                String name = psym.getQualifiedName().toString();
132                legacyProprietary.remove(name);
133                documented.add(name);
134            }
135    
136            JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
137            StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
138            Location jarLocation = StandardLocation.locationFor(jarName);
139            File jarFile = new File(jarName);
140            fm.setLocation(jarLocation, List.of(jarFile));
141            fm.setLocation(StandardLocation.CLASS_PATH, List.<File>nil());
142            fm.setLocation(StandardLocation.SOURCE_PATH, List.<File>nil());
143            {
144                ArrayList<File> bootClassPath = new ArrayList<File>();
145                bootClassPath.add(jarFile);
146                for (File path : fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH)) {
147                    if (!new File(path.getName()).equals(new File("rt.jar")))
148                        bootClassPath.add(path);
149                }
150                System.err.println("Using boot class path = " + bootClassPath);
151                fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath);
152            }
153            // System.out.println(fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH));
154            File destDir = new File(destName);
155            if (!destDir.exists())
156                if (!destDir.mkdirs())
157                    throw new RuntimeException("Could not create " + destDir);
158            fm.setLocation(StandardLocation.CLASS_OUTPUT, List.of(destDir));
159            Set<String> hiddenPackages = new HashSet<String>();
160            Set<String> crisp = new HashSet<String>();
161            List<String> options = List.of("-XDdev");
162            // options = options.prepend("-doe");
163            // options = options.prepend("-verbose");
164            JavacTaskImpl task = (JavacTaskImpl)
165                tool.getTask(null, fm, null, options, null, null);
166            com.sun.tools.javac.main.JavaCompiler compiler =
167                com.sun.tools.javac.main.JavaCompiler.instance(task.getContext());
168            ClassReader reader = ClassReader.instance(task.getContext());
169            ClassWriter writer = ClassWriter.instance(task.getContext());
170            Symtab syms = Symtab.instance(task.getContext());
171            Attribute.Compound proprietary =
172                new Attribute.Compound(syms.proprietaryType,
173                                       List.<Pair<Symbol.MethodSymbol,Attribute>>nil());
174    
175            Type.moreInfo = true;
176            Pool pool = new Pool();
177            for (JavaFileObject file : fm.list(jarLocation, "", EnumSet.of(CLASS), true)) {
178                String className = fm.inferBinaryName(jarLocation, file);
179                int index = className.lastIndexOf('.');
180                String pckName = index == -1 ? "" : className.substring(0, index);
181                boolean addLegacyAnnotation = false;
182                if (documented.contains(pckName)) {
183                    if (!legacy.contains(pckName))
184                        crisp.add(pckName);
185                    // System.out.println("Documented: " + className);
186                } else if (legacyProprietary.contains(pckName)) {
187                    addLegacyAnnotation = true;
188                    // System.out.println("Legacy proprietary: " + className);
189                } else {
190                    // System.out.println("Hidden " + className);
191                    hiddenPackages.add(pckName);
192                    continue;
193                }
194                TypeSymbol sym = (TypeSymbol)compiler.resolveIdent(className);
195                if (sym.kind != Kinds.TYP) {
196                    if (className.indexOf('$') < 0) {
197                        System.err.println("Ignoring (other) " + className + " : " + sym);
198                        System.err.println("   " + sym.getClass().getSimpleName() + " " + sym.type);
199                    }
200                    continue;
201                }
202                sym.complete();
203                if (sym.getEnclosingElement().getKind() != ElementKind.PACKAGE) {
204                    System.err.println("Ignoring (bad) " + sym.getQualifiedName());
205                    continue;
206                }
207                ClassSymbol cs = (ClassSymbol) sym;
208                if (addLegacyAnnotation) {
209                    cs.attributes_field = (cs.attributes_field == null)
210                        ? List.of(proprietary)
211                        : cs.attributes_field.prepend(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    }