alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (ArgTypeCompilerFactory.java)

This example Java source code file (ArgTypeCompilerFactory.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

argtypediagnosticformatter, backdoorcompiler, context, file, jsr199compiler, list, log, main, object, override, set, simplecompiler, string, stringbuilder, util

The ArgTypeCompilerFactory.java Java example source code

/*
 * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import java.io.*;
import java.util.*;
import java.util.List;
import javax.tools.*;

import com.sun.tools.javac.api.*;
import com.sun.tools.javac.api.DiagnosticFormatter.Configuration.DiagnosticPart;
import com.sun.tools.javac.api.Formattable.LocalizedString;
import com.sun.tools.javac.code.Flags.Flag;
import com.sun.tools.javac.code.Kinds.KindName;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.file.*;
import com.sun.tools.javac.main.Main;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.parser.Tokens.TokenKind;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.AbstractDiagnosticFormatter.SimpleConfiguration;
import javax.lang.model.SourceVersion;

/**
 * Compiler factory for instances of Example.Compiler that use custom
 * DiagnosticFormatter and Messages objects to track the types of args
 * when when localizing diagnostics.
 * The compiler objects only support "output" mode, not "check" mode.
 */
class ArgTypeCompilerFactory implements Example.Compiler.Factory {
    // Same code as Example.Compiler.DefaultFactory, but the names resolve differently
    public Example.Compiler getCompiler(List<String> opts, boolean verbose) {
        String first;
        String[] rest;
        if (opts == null || opts.isEmpty()) {
            first = null;
            rest = new String[0];
        } else {
            first = opts.get(0);
            rest = opts.subList(1, opts.size()).toArray(new String[opts.size() - 1]);
        }
        if (first == null || first.equals("jsr199"))
            return new Jsr199Compiler(verbose, rest);
        else if (first.equals("simple"))
            return new SimpleCompiler(verbose);
        else if (first.equals("backdoor"))
            return new BackdoorCompiler(verbose);
        else
            throw new IllegalArgumentException(first);
    }

    /**
     * Compile using the JSR 199 API.  The diagnostics generated are
     * scanned for resource keys.   Not all diagnostic keys are generated
     * via the JSR 199 API -- for example, rich diagnostics are not directly
     * accessible, and some diagnostics generated by the file manager may
     * not be generated (for example, the JSR 199 file manager does not see
     * -Xlint:path).
     */
    static class Jsr199Compiler extends Example.Compiler {
        List<String> fmOpts;

        Jsr199Compiler(boolean verbose, String... args) {
            super(verbose);
            for (int i = 0; i < args.length; i++) {
                String arg = args[i];
                if (arg.equals("-filemanager") && (i + 1 < args.length)) {
                    fmOpts = Arrays.asList(args[++i].split(","));
                } else
                    throw new IllegalArgumentException(arg);
            }
        }

        @Override
        boolean run(PrintWriter out, Set<String> keys, boolean raw, List opts, List files) {
            assert out != null && keys == null;

            if (verbose)
                System.err.println("run_jsr199: " + opts + " " + files);

            JavacTool tool = JavacTool.create();

            StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
            if (fmOpts != null)
                fm = new FileManager(fm, fmOpts);

            Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files);

            Context c = new Context();
            ArgTypeMessages.preRegister(c);
            ArgTypeJavaCompiler.preRegister(c);
            JavacTaskImpl t = (JavacTaskImpl) tool.getTask(out, fm, null, opts, null, fos, c);
            return t.call();
        }
    }

    /**
     * Run the test using the standard simple entry point.
     */
    static class SimpleCompiler extends Example.Compiler {
        SimpleCompiler(boolean verbose) {
            super(verbose);
        }

        @Override
        boolean run(PrintWriter out, Set<String> keys, boolean raw, List opts, List files) {
            assert out != null && keys == null;

            if (verbose)
                System.err.println("run_simple: " + opts + " " + files);

            List<String> args = new ArrayList();

            args.addAll(opts);
            for (File f: files)
                args.add(f.getPath());

            Main main = new Main("javac", out);
            Context c = new Context() {
                @Override public void clear() {
                    ((JavacFileManager) get(JavaFileManager.class)).close();
                    super.clear();
                }
            };
            JavacFileManager.preRegister(c); // can't create it until Log has been set up
            ArgTypeJavaCompiler.preRegister(c);
            ArgTypeMessages.preRegister(c);
            Main.Result result = main.compile(args.toArray(new String[args.size()]), c);

            return result.isOK();
        }
    }

    static class BackdoorCompiler extends Example.Compiler {
        BackdoorCompiler(boolean verbose) {
            super(verbose);
        }

        @Override
        boolean run(PrintWriter out, Set<String> keys, boolean raw, List opts, List files) {
            assert out != null && keys == null;

            if (verbose)
                System.err.println("run_simple: " + opts + " " + files);

            List<String> args = new ArrayList(opts);
            for (File f: files)
                args.add(f.getPath());

            Context c = new Context();
            JavacFileManager.preRegister(c); // can't create it until Log has been set up
            ArgTypeJavaCompiler.preRegister(c);
            ArgTypeMessages.preRegister(c);
            Main m = new Main("javac", out);
            Main.Result result = m.compile(args.toArray(new String[args.size()]), c);

            return result.isOK();
        }

    }


    // <editor-fold defaultstate="collapsed" desc="Custom Javac components">

    /**
     * Diagnostic formatter which reports formats a diag as a series of lines
     * containing a key, and a possibly empty set of descriptive strings for the
     * arg types.
     */
    static class ArgTypeDiagnosticFormatter extends AbstractDiagnosticFormatter {

        ArgTypeDiagnosticFormatter(Options options) {
            super(null, new SimpleConfiguration(options,
                    EnumSet.of(DiagnosticPart.SUMMARY,
                    DiagnosticPart.DETAILS,
                    DiagnosticPart.SUBDIAGNOSTICS)));
        }

        @Override
        protected String formatDiagnostic(JCDiagnostic d, Locale locale) {
            return formatMessage(d, locale);
        }

        @Override
        public String formatMessage(JCDiagnostic d, Locale l) {
            StringBuilder buf = new StringBuilder();
            formatMessage(d, buf);
            return buf.toString();
        }

        private void formatMessage(JCDiagnostic d, StringBuilder buf) {
            String key = d.getCode();
            Object[] args = d.getArgs();
            // report the primary arg types, without recursing into diag fragments
            buf.append(getKeyArgsString(key, args));
            // report details for any diagnostic fragments
            for (Object arg: args) {
                if (arg instanceof JCDiagnostic) {
                    buf.append("\n");
                    formatMessage((JCDiagnostic) arg, buf);
                }
            }
            // report details for any subdiagnostics
            for (String s: formatSubdiagnostics(d, null)) {
                buf.append("\n");
                buf.append(s);
            }
        }

        @Override
        public boolean isRaw() {
            return true;
        }
    }

    /**
     * Trivial subtype of JavaCompiler to get access to the protected compilerKey field.
     * The factory is used to ensure that the log is initialized with an instance of
     * ArgTypeDiagnosticFormatter before we create the required JavaCompiler.
     */
    static class ArgTypeJavaCompiler extends JavaCompiler {
        static void preRegister(Context context) {
            context.put(compilerKey, new Context.Factory<JavaCompiler>() {
                public JavaCompiler make(Context c) {
                    Log log = Log.instance(c);
                    Options options = Options.instance(c);
                    log.setDiagnosticFormatter(new ArgTypeDiagnosticFormatter(options));
                    return new JavaCompiler(c);
                }
            });
        }

        // not used
        private ArgTypeJavaCompiler() {
            super(null);
        }
    }

    /**
     * Diagnostic formatter which "localizes" a message as a line
     * containing a key, and a possibly empty set of descriptive strings for the
     * arg types.
     */
    static class ArgTypeMessages extends JavacMessages {
        static void preRegister(Context context) {
            context.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() {
                public JavacMessages make(Context c) {
                    return new ArgTypeMessages(c) {
                        @Override
                        public String getLocalizedString(Locale l, String key, Object... args) {
                            return getKeyArgsString(key, args);
                        }
                    };
                }
            });
        }

        ArgTypeMessages(Context context) {
            super(context);
        }
    }

    /**
     * Utility method to generate a string for key and args
     */
    static String getKeyArgsString(String key, Object... args) {
        StringBuilder buf = new StringBuilder();
        buf.append(key);
        String sep = ": ";
        for (Object o : args) {
            buf.append(sep);
            buf.append(getArgTypeOrStringValue(o));
            sep = ", ";
        }
        return buf.toString();
    }

    static boolean showStringValues = false;

    static String getArgTypeOrStringValue(Object o) {
        if (showStringValues && o instanceof String)
            return "\"" + o + "\"";
        return getArgType(o);
    }

    static String getArgType(Object o) {
        if (o == null)
            return "null";
        if (o instanceof Name)
            return "name";
        if (o instanceof Boolean)
            return "boolean";
        if (o instanceof Integer)
            return "number";
        if (o instanceof String)
            return "string";
        if (o instanceof Flag)
            return "modifier";
        if (o instanceof KindName)
            return "symbol kind";
        if (o instanceof TokenKind)
            return "token";
        if (o instanceof Symbol)
            return "symbol";
        if (o instanceof Type)
            return "type";
        if (o instanceof List) {
            List<?> l = (List) o;
            if (l.isEmpty())
                return "list";
            else
                return "list of " + getArgType(l.get(0));
        }
        if (o instanceof ListBuffer)
            return getArgType(((ListBuffer) o).toList());
        if (o instanceof Set) {
            Set<?> s = (Set) o;
            if (s.isEmpty())
                return "set";
            else
                return "set of " + getArgType(s.iterator().next());
        }
        if (o instanceof SourceVersion)
            return "source version";
        if (o instanceof FileObject || o instanceof File)
            return "file name";
        if (o instanceof JCDiagnostic)
            return "message segment";
        if (o instanceof LocalizedString)
            return "message segment";  // only instance is "no arguments"
        String s = o.getClass().getSimpleName();
        return (s.isEmpty() ? o.getClass().getName() : s);
    }

    // </editor-fold>

}

Other Java examples (source code examples)

Here is a short list of links related to this Java ArgTypeCompilerFactory.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.