NashornLoader.java revision 1350:3cb11f4d617e
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 java.io.File;
29import java.io.IOException;
30import java.net.MalformedURLException;
31import java.net.URL;
32import java.net.URLClassLoader;
33import java.security.CodeSource;
34import java.security.Permission;
35import java.security.PermissionCollection;
36import java.security.Permissions;
37import java.security.SecureClassLoader;
38import jdk.nashorn.tools.Shell;
39
40/**
41 * Superclass for Nashorn class loader classes.
42 */
43abstract class NashornLoader extends SecureClassLoader {
44    private static final String OBJECTS_PKG        = "jdk.nashorn.internal.objects";
45    private static final String RUNTIME_PKG        = "jdk.nashorn.internal.runtime";
46    private static final String RUNTIME_ARRAYS_PKG = "jdk.nashorn.internal.runtime.arrays";
47    private static final String RUNTIME_LINKER_PKG = "jdk.nashorn.internal.runtime.linker";
48    private static final String SCRIPTS_PKG        = "jdk.nashorn.internal.scripts";
49
50    private static final Permission[] SCRIPT_PERMISSIONS;
51
52    static {
53        /*
54         * Generated classes get access to runtime, runtime.linker, objects, scripts packages.
55         * Note that the actual scripts can not access these because Java.type, Packages
56         * prevent these restricted packages. And Java reflection and JSR292 access is prevented
57         * for scripts. In other words, nashorn generated portions of script classes can access
58         * classes in these implementation packages.
59         */
60        SCRIPT_PERMISSIONS = new Permission[] {
61                new RuntimePermission("accessClassInPackage." + RUNTIME_PKG),
62                new RuntimePermission("accessClassInPackage." + RUNTIME_LINKER_PKG),
63                new RuntimePermission("accessClassInPackage." + OBJECTS_PKG),
64                new RuntimePermission("accessClassInPackage." + SCRIPTS_PKG),
65                new RuntimePermission("accessClassInPackage." + RUNTIME_ARRAYS_PKG)
66        };
67    }
68
69    NashornLoader(final ClassLoader parent) {
70        super(parent);
71    }
72
73    protected static void checkPackageAccess(final String name) {
74        final int i = name.lastIndexOf('.');
75        if (i != -1) {
76            final SecurityManager sm = System.getSecurityManager();
77            if (sm != null) {
78                final String pkgName = name.substring(0, i);
79                switch (pkgName) {
80                    case RUNTIME_PKG:
81                    case RUNTIME_ARRAYS_PKG:
82                    case RUNTIME_LINKER_PKG:
83                    case OBJECTS_PKG:
84                    case SCRIPTS_PKG:
85                        // allow it.
86                        break;
87                    default:
88                        sm.checkPackageAccess(pkgName);
89                }
90            }
91        }
92    }
93
94    @Override
95    protected PermissionCollection getPermissions(final CodeSource codesource) {
96        final Permissions permCollection = new Permissions();
97        for (final Permission perm : SCRIPT_PERMISSIONS) {
98            permCollection.add(perm);
99        }
100        return permCollection;
101    }
102
103    /**
104     * Create a secure URL class loader for the given classpath
105     * @param classPath classpath for the loader to search from
106     * @return the class loader
107     */
108    static ClassLoader createClassLoader(final String classPath) {
109        final ClassLoader parent = Shell.class.getClassLoader();
110        final URL[] urls = pathToURLs(classPath);
111        return URLClassLoader.newInstance(urls, parent);
112    }
113
114    /*
115     * Utility method for converting a search path string to an array
116     * of directory and JAR file URLs.
117     *
118     * @param path the search path string
119     * @return the resulting array of directory and JAR file URLs
120     */
121    private static URL[] pathToURLs(final String path) {
122        final String[] components = path.split(File.pathSeparator);
123        URL[] urls = new URL[components.length];
124        int count = 0;
125        while(count < components.length) {
126            final URL url = fileToURL(new File(components[count]));
127            if (url != null) {
128                urls[count++] = url;
129            }
130        }
131        if (urls.length != count) {
132            final URL[] tmp = new URL[count];
133            System.arraycopy(urls, 0, tmp, 0, count);
134            urls = tmp;
135        }
136        return urls;
137    }
138
139    /*
140     * Returns the directory or JAR file URL corresponding to the specified
141     * local file name.
142     *
143     * @param file the File object
144     * @return the resulting directory or JAR file URL, or null if unknown
145     */
146    private static URL fileToURL(final File file) {
147        String name;
148        try {
149            name = file.getCanonicalPath();
150        } catch (final IOException e) {
151            name = file.getAbsolutePath();
152        }
153        name = name.replace(File.separatorChar, '/');
154        if (!name.startsWith("/")) {
155            name = "/" + name;
156        }
157        // If the file does not exist, then assume that it's a directory
158        if (!file.isFile()) {
159            name += "/";
160        }
161        try {
162            return new URL("file", "", name);
163        } catch (final MalformedURLException e) {
164            throw new IllegalArgumentException("file");
165        }
166    }
167}
168
169