ModuleHelper.java revision 3294:9adfb22ff08f
1/*
2 * Copyright (c) 2015, 2016, 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
26package com.sun.tools.javac.util;
27
28import java.lang.reflect.InvocationTargetException;
29import java.lang.reflect.Method;
30
31public class ModuleHelper {
32    /** The context key for the module helper. */
33    protected static final Context.Key<ModuleHelper> moduleHelperKey = new Context.Key<>();
34
35    /** Get the JavaCompiler instance for this context. */
36    public static ModuleHelper instance(Context context) {
37        ModuleHelper instance = context.get(moduleHelperKey);
38        if (instance == null)
39            instance = new ModuleHelper(context);
40        return instance;
41    }
42
43    public ModuleHelper(Context context) {
44        context.put(moduleHelperKey, this);
45        Options options = Options.instance(context);
46        allowAccessToInternalAPI = options.isSet("accessInternalAPI");
47    }
48
49    final boolean allowAccessToInternalAPI;
50
51    private void exportPackageToModule(String packageName, Object target)
52            throws ClassNotFoundException, NoSuchMethodException, IllegalArgumentException,
53                   InvocationTargetException, IllegalAccessException {
54        if (addExportsMethod == null) {
55            Class<?> moduleClass = Class.forName("java.lang.reflect.Module");
56            addExportsMethod = moduleClass.getDeclaredMethod("addExports",
57                    new Class<?>[] { String.class, moduleClass });
58        }
59        addExportsMethod.invoke(from, new Object[] { packageName, target });
60    }
61
62    static final String[] javacInternalPackages = new String[] {
63        "com.sun.tools.javac.api",
64        "com.sun.tools.javac.code",
65        "com.sun.tools.javac.comp",
66        "com.sun.tools.javac.file",
67        "com.sun.tools.javac.jvm",
68        "com.sun.tools.javac.main",
69        "com.sun.tools.javac.model",
70        "com.sun.tools.javac.parser",
71        "com.sun.tools.javac.platform",
72        "com.sun.tools.javac.processing",
73        "com.sun.tools.javac.tree",
74        "com.sun.tools.javac.util",
75
76        "com.sun.tools.doclint",
77    };
78
79    public void addExports(ClassLoader classLoader) {
80        try {
81            if (allowAccessToInternalAPI) {
82                if (from == null) {
83                    if (getModuleMethod == null) {
84                        getModuleMethod = Class.class.getDeclaredMethod("getModule", new Class<?>[0]);
85                    }
86                    from = getModuleMethod.invoke(getClass(), new Object[0]);
87                }
88                if (getUnnamedModuleMethod == null) {
89                    getUnnamedModuleMethod = ClassLoader.class.getDeclaredMethod("getUnnamedModule", new Class<?>[0]);
90                }
91                Object target = getUnnamedModuleMethod.invoke(classLoader, new Object[0]);
92                for (String pack: javacInternalPackages) {
93                    exportPackageToModule(pack, target);
94                }
95            }
96        } catch (Exception e) {
97            // do nothing
98        }
99    }
100
101    // a module instance
102    private Object from = null;
103
104    // on java.lang.reflect.Module
105    private static Method addExportsMethod = null;
106
107    // on java.lang.ClassLoader
108    private static Method getUnnamedModuleMethod = null;
109
110    // on java.lang.Class
111    private static Method getModuleMethod = null;
112}
113