aboutsummaryrefslogtreecommitdiff
path: root/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java')
-rw-r--r--src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java201
1 files changed, 0 insertions, 201 deletions
diff --git a/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java b/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java
deleted file mode 100644
index 6a3d933f..00000000
--- a/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2010, 2013, 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. Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package jdk.nashorn.internal.runtime.linker;
-
-import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.Permissions;
-import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A tuple of a class loader and a single class representative of the classes that can be loaded through it. Its
- * equals/hashCode is defined in terms of the identity of the class loader. The rationale for this class is that it
- * couples a class loader with a random representative class coming from that loader - this representative class is then
- * used to determine if one loader can see the other loader's classes.
- */
-final class ClassAndLoader {
- static AccessControlContext createPermAccCtxt(final String... permNames) {
- final Permissions perms = new Permissions();
- for (final String permName : permNames) {
- perms.add(new RuntimePermission(permName));
- }
- return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
- }
-
- private static final AccessControlContext GET_LOADER_ACC_CTXT = createPermAccCtxt("getClassLoader");
-
- private final Class<?> representativeClass;
- // Don't access this directly; most of the time, use getRetrievedLoader(), or if you know what you're doing,
- // getLoader().
- private ClassLoader loader;
- // We have mild affinity against eagerly retrieving the loader, as we need to do it in a privileged block. For
- // the most basic case of looking up an already-generated adapter info for a single type, we avoid it.
- private boolean loaderRetrieved;
-
- ClassAndLoader(final Class<?> representativeClass, final boolean retrieveLoader) {
- this.representativeClass = representativeClass;
- if(retrieveLoader) {
- retrieveLoader();
- }
- }
-
- Class<?> getRepresentativeClass() {
- return representativeClass;
- }
-
- boolean canSee(final ClassAndLoader other) {
- try {
- final Class<?> otherClass = other.getRepresentativeClass();
- return Class.forName(otherClass.getName(), false, getLoader()) == otherClass;
- } catch (final ClassNotFoundException e) {
- return false;
- }
- }
-
- ClassLoader getLoader() {
- if(!loaderRetrieved) {
- retrieveLoader();
- }
- return getRetrievedLoader();
- }
-
- ClassLoader getRetrievedLoader() {
- assert loaderRetrieved;
- return loader;
- }
-
- private void retrieveLoader() {
- loader = representativeClass.getClassLoader();
- loaderRetrieved = true;
- }
-
- @Override
- public boolean equals(final Object obj) {
- return obj instanceof ClassAndLoader && ((ClassAndLoader)obj).getRetrievedLoader() == getRetrievedLoader();
- }
-
- @Override
- public int hashCode() {
- return System.identityHashCode(getRetrievedLoader());
- }
-
- /**
- * Given a list of types that define the superclass/interfaces for an adapter class, returns a single type from the
- * list that will be used to attach the adapter to its ClassValue. The first type in the array that is defined in a
- * class loader that can also see all other types is returned. If there is no such loader, an exception is thrown.
- * @param types the input types
- * @return the first type from the array that is defined in a class loader that can also see all other types.
- */
- static ClassAndLoader getDefiningClassAndLoader(final Class<?>[] types) {
- // Short circuit the cheap case
- if(types.length == 1) {
- return new ClassAndLoader(types[0], false);
- }
-
- return AccessController.doPrivileged(new PrivilegedAction<ClassAndLoader>() {
- @Override
- public ClassAndLoader run() {
- return getDefiningClassAndLoaderPrivileged(types);
- }
- }, GET_LOADER_ACC_CTXT);
- }
-
- static ClassAndLoader getDefiningClassAndLoaderPrivileged(final Class<?>[] types) {
- final Collection<ClassAndLoader> maximumVisibilityLoaders = getMaximumVisibilityLoaders(types);
-
- final Iterator<ClassAndLoader> it = maximumVisibilityLoaders.iterator();
- if(maximumVisibilityLoaders.size() == 1) {
- // Fortunate case - single maximally specific class loader; return its representative class.
- return it.next();
- }
-
- // Ambiguity; throw an error.
- assert maximumVisibilityLoaders.size() > 1; // basically, can't be zero
- final StringBuilder b = new StringBuilder();
- b.append(it.next().getRepresentativeClass().getCanonicalName());
- while(it.hasNext()) {
- b.append(", ").append(it.next().getRepresentativeClass().getCanonicalName());
- }
- throw typeError("extend.ambiguous.defining.class", b.toString());
- }
-
- /**
- * Given an array of types, return a subset of their class loaders that are maximal according to the
- * "can see other loaders' classes" relation, which is presumed to be a partial ordering.
- * @param types types
- * @return a collection of maximum visibility class loaders. It is guaranteed to have at least one element.
- */
- private static Collection<ClassAndLoader> getMaximumVisibilityLoaders(final Class<?>[] types) {
- final List<ClassAndLoader> maximumVisibilityLoaders = new LinkedList<>();
- outer: for(final ClassAndLoader maxCandidate: getClassLoadersForTypes(types)) {
- final Iterator<ClassAndLoader> it = maximumVisibilityLoaders.iterator();
- while(it.hasNext()) {
- final ClassAndLoader existingMax = it.next();
- final boolean candidateSeesExisting = maxCandidate.canSee(existingMax);
- final boolean exitingSeesCandidate = existingMax.canSee(maxCandidate);
- if(candidateSeesExisting) {
- if(!exitingSeesCandidate) {
- // The candidate sees the the existing maximum, so drop the existing one as it's no longer maximal.
- it.remove();
- }
- // NOTE: there's also the anomalous case where both loaders see each other. Not sure what to do
- // about that one, as two distinct class loaders both seeing each other's classes is weird and
- // violates the assumption that the relation "sees others' classes" is a partial ordering. We'll
- // just not do anything, and treat them as incomparable; hopefully some later class loader that
- // comes along can eliminate both of them, if it can not, we'll end up with ambiguity anyway and
- // throw an error at the end.
- } else if(exitingSeesCandidate) {
- // Existing sees the candidate, so drop the candidate.
- continue outer;
- }
- }
- // If we get here, no existing maximum visibility loader could see the candidate, so the candidate is a new
- // maximum.
- maximumVisibilityLoaders.add(maxCandidate);
- }
- return maximumVisibilityLoaders;
- }
-
- private static Collection<ClassAndLoader> getClassLoadersForTypes(final Class<?>[] types) {
- final Map<ClassAndLoader, ClassAndLoader> classesAndLoaders = new LinkedHashMap<>();
- for(final Class<?> c: types) {
- final ClassAndLoader cl = new ClassAndLoader(c, true);
- if(!classesAndLoaders.containsKey(cl)) {
- classesAndLoaders.put(cl, cl);
- }
- }
- return classesAndLoaders.keySet();
- }
-}