StructureLoader.java revision 1643:133ea8746b37
1/*
2 * Copyright (c) 2010, 2013, 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 jdk.nashorn.internal.runtime;
27
28import static jdk.nashorn.internal.codegen.Compiler.SCRIPTS_PACKAGE;
29import static jdk.nashorn.internal.codegen.Compiler.binaryName;
30import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_DUAL_FIELD_PREFIX;
31import static jdk.nashorn.internal.codegen.CompilerConstants.JS_OBJECT_SINGLE_FIELD_PREFIX;
32
33import java.lang.reflect.Module;
34import java.security.ProtectionDomain;
35import jdk.nashorn.internal.codegen.ObjectClassGenerator;
36
37/**
38 * Responsible for on the fly construction of structure classes.
39 */
40final class StructureLoader extends NashornLoader {
41    private static final String SINGLE_FIELD_PREFIX = binaryName(SCRIPTS_PACKAGE) + '.' + JS_OBJECT_SINGLE_FIELD_PREFIX.symbolName();
42    private static final String DUAL_FIELD_PREFIX   = binaryName(SCRIPTS_PACKAGE) + '.' + JS_OBJECT_DUAL_FIELD_PREFIX.symbolName();
43
44    private final Module structuresModule;
45
46    /**
47     * Constructor.
48     */
49    StructureLoader(final ClassLoader parent) {
50        super(parent);
51
52        // new structures module, it's exports, read edges
53        structuresModule = defineModule("jdk.scripting.nashorn.structures", this);
54        addModuleExports(structuresModule, SCRIPTS_PKG, nashornModule);
55        addReadsModule(structuresModule, nashornModule);
56        addReadsModule(structuresModule, Object.class.getModule());
57
58        // specific exports from nashorn to the structures module
59        nashornModule.addExports(SCRIPTS_PKG, structuresModule);
60        nashornModule.addExports(RUNTIME_PKG, structuresModule);
61
62        // nashorn has to read fields from classes of the new module
63        nashornModule.addReads(structuresModule);
64    }
65
66    /**
67     * Returns true if the class name represents a structure object with dual primitive/object fields.
68     * @param name a class name
69     * @return true if a dual field structure class
70     */
71    private static boolean isDualFieldStructure(final String name) {
72        return name.startsWith(DUAL_FIELD_PREFIX);
73    }
74
75    /**
76     * Returns true if the class name represents a structure object with single object-only fields.
77     * @param name a class name
78     * @return true if a single field structure class
79     */
80    static boolean isSingleFieldStructure(final String name) {
81        return name.startsWith(SINGLE_FIELD_PREFIX);
82    }
83
84    /**
85     * Returns true if the class name represents a Nashorn structure object.
86     * @param name a class name
87     * @return true if a structure class
88     */
89    static boolean isStructureClass(final String name) {
90        return isDualFieldStructure(name) || isSingleFieldStructure(name);
91    }
92
93    protected Module getModule() {
94        return structuresModule;
95    }
96
97    @Override
98    protected Class<?> findClass(final String name) throws ClassNotFoundException {
99        if (isDualFieldStructure(name)) {
100            return generateClass(name, name.substring(DUAL_FIELD_PREFIX.length()), true);
101        } else if (isSingleFieldStructure(name)) {
102            return generateClass(name, name.substring(SINGLE_FIELD_PREFIX.length()), false);
103        }
104        return super.findClass(name);
105    }
106
107    /**
108     * Generate a layout class.
109     * @param name       Name of class.
110     * @param descriptor Layout descriptor.
111     * @return Generated class.
112     */
113    private Class<?> generateClass(final String name, final String descriptor, final boolean dualFields) {
114        final Context context = Context.getContextTrusted();
115
116        final byte[] code = new ObjectClassGenerator(context, dualFields).generate(descriptor);
117        return defineClass(name, code, 0, code.length, new ProtectionDomain(null, getPermissions(null)));
118    }
119}
120