NashornLoader.java revision 953:221a84ef44c0
11590Srgrimes/*
21590Srgrimes * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
31590Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41590Srgrimes *
51590Srgrimes * This code is free software; you can redistribute it and/or modify it
61590Srgrimes * under the terms of the GNU General Public License version 2 only, as
71590Srgrimes * published by the Free Software Foundation.  Oracle designates this
81590Srgrimes * particular file as subject to the "Classpath" exception as provided
91590Srgrimes * by Oracle in the LICENSE file that accompanied this code.
101590Srgrimes *
111590Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT
121590Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
131590Srgrimes * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
141590Srgrimes * version 2 for more details (a copy is included in the LICENSE file that
151590Srgrimes * accompanied this code).
161590Srgrimes *
171590Srgrimes * You should have received a copy of the GNU General Public License version
181590Srgrimes * 2 along with this work; if not, write to the Free Software Foundation,
191590Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
201590Srgrimes *
211590Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
221590Srgrimes * or visit www.oracle.com if you need additional information or have any
231590Srgrimes * questions.
241590Srgrimes */
251590Srgrimes
261590Srgrimespackage jdk.nashorn.internal.runtime;
271590Srgrimes
281590Srgrimesimport java.io.File;
291590Srgrimesimport java.io.IOException;
3087628Sdwmaloneimport java.net.MalformedURLException;
3187628Sdwmaloneimport java.net.URL;
3287628Sdwmaloneimport java.net.URLClassLoader;
3387628Sdwmaloneimport java.security.CodeSource;
3487628Sdwmaloneimport java.security.Permission;
3587628Sdwmaloneimport java.security.PermissionCollection;
3687249Smarkmimport java.security.Permissions;
3787249Smarkmimport java.security.SecureClassLoader;
3887249Smarkmimport jdk.nashorn.tools.Shell;
391590Srgrimes
401590Srgrimes/**
411590Srgrimes * Superclass for Nashorn class loader classes.
421590Srgrimes */
431590Srgrimesabstract class NashornLoader extends SecureClassLoader {
441590Srgrimes    private static final String OBJECTS_PKG        = "jdk.nashorn.internal.objects";
451590Srgrimes    private static final String RUNTIME_PKG        = "jdk.nashorn.internal.runtime";
461590Srgrimes    private static final String RUNTIME_ARRAYS_PKG = "jdk.nashorn.internal.runtime.arrays";
4792920Simp    private static final String RUNTIME_LINKER_PKG = "jdk.nashorn.internal.runtime.linker";
4892920Simp    private static final String SCRIPTS_PKG        = "jdk.nashorn.internal.scripts";
491590Srgrimes
501590Srgrimes    private static final Permission[] SCRIPT_PERMISSIONS;
511590Srgrimes
521590Srgrimes    static {
531590Srgrimes        /*
541590Srgrimes         * Generated classes get access to runtime, runtime.linker, objects, scripts packages.
55100822Sdwmalone         * Note that the actual scripts can not access these because Java.type, Packages
561590Srgrimes         * prevent these restricted packages. And Java reflection and JSR292 access is prevented
571590Srgrimes         * for scripts. In other words, nashorn generated portions of script classes can access
581590Srgrimes         * classes in these implementation packages.
591590Srgrimes         */
601590Srgrimes        SCRIPT_PERMISSIONS = new Permission[] {
611590Srgrimes                new RuntimePermission("accessClassInPackage." + RUNTIME_PKG),
621590Srgrimes                new RuntimePermission("accessClassInPackage." + RUNTIME_LINKER_PKG),
631590Srgrimes                new RuntimePermission("accessClassInPackage." + OBJECTS_PKG),
641590Srgrimes                new RuntimePermission("accessClassInPackage." + SCRIPTS_PKG),
651590Srgrimes                new RuntimePermission("accessClassInPackage." + RUNTIME_ARRAYS_PKG)
661590Srgrimes        };
671590Srgrimes    }
6887750Scharnier
691590Srgrimes    NashornLoader(final ClassLoader parent) {
701590Srgrimes        super(parent);
711590Srgrimes    }
721590Srgrimes
731590Srgrimes    protected static void checkPackageAccess(final String name) {
741590Srgrimes        final int i = name.lastIndexOf('.');
7597574Stjr        if (i != -1) {
761590Srgrimes            final SecurityManager sm = System.getSecurityManager();
771590Srgrimes            if (sm != null) {
781590Srgrimes                final String pkgName = name.substring(0, i);
791590Srgrimes                switch (pkgName) {
801590Srgrimes                    case RUNTIME_PKG:
811590Srgrimes                    case RUNTIME_ARRAYS_PKG:
821590Srgrimes                    case RUNTIME_LINKER_PKG:
831590Srgrimes                    case OBJECTS_PKG:
841590Srgrimes                    case SCRIPTS_PKG:
851590Srgrimes                        // allow it.
861590Srgrimes                        break;
871590Srgrimes                    default:
881590Srgrimes                        sm.checkPackageAccess(pkgName);
891590Srgrimes                }
901590Srgrimes            }
911590Srgrimes        }
921590Srgrimes    }
931590Srgrimes
941590Srgrimes    @Override
95100822Sdwmalone    protected PermissionCollection getPermissions(final CodeSource codesource) {
961590Srgrimes        final Permissions permCollection = new Permissions();
971590Srgrimes        for (final Permission perm : SCRIPT_PERMISSIONS) {
981590Srgrimes            permCollection.add(perm);
9997581Stjr        }
1001590Srgrimes        return permCollection;
1011590Srgrimes    }
1021590Srgrimes
1031590Srgrimes    /**
1041590Srgrimes     * Create a secure URL class loader for the given classpath
1051590Srgrimes     * @param classPath classpath for the loader to search from
1061590Srgrimes     * @return the class loader
1071590Srgrimes     */
1081590Srgrimes    static ClassLoader createClassLoader(final String classPath) {
1091590Srgrimes        final ClassLoader parent = Shell.class.getClassLoader();
1101590Srgrimes        final URL[] urls = pathToURLs(classPath);
1111590Srgrimes        return URLClassLoader.newInstance(urls, parent);
1121590Srgrimes    }
1131590Srgrimes
1141590Srgrimes    /*
1151590Srgrimes     * Utility method for converting a search path string to an array
1161590Srgrimes     * of directory and JAR file URLs.
1171590Srgrimes     *
1181590Srgrimes     * @param path the search path string
1191590Srgrimes     * @return the resulting array of directory and JAR file URLs
1201590Srgrimes     */
1211590Srgrimes    private static URL[] pathToURLs(final String path) {
1221590Srgrimes        final String[] components = path.split(File.pathSeparator);
123100822Sdwmalone        URL[] urls = new URL[components.length];
1241590Srgrimes        int count = 0;
125166501Srse        while(count < components.length) {
1261590Srgrimes            final URL url = fileToURL(new File(components[count]));
1271590Srgrimes            if (url != null) {
1281590Srgrimes                urls[count++] = url;
129166501Srse            }
1301590Srgrimes        }
131166501Srse        if (urls.length != count) {
1321590Srgrimes            final URL[] tmp = new URL[count];
1331590Srgrimes            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 = 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