| /* |
| * Copyright (c) 2008, 2009, 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 sun.dyn; |
| |
| import sun.reflect.Reflection; |
| |
| /** |
| * Access control to this package. |
| * Classes in other packages can attempt to acquire the access token, |
| * but will fail if they are not recognized as friends. |
| * Certain methods in this package, although public, require a non-null |
| * access token in order to proceed; they act like package-private methods. |
| * @author jrose |
| */ |
| |
| public class Access { |
| |
| private Access() { } |
| |
| /** |
| * The heart of this pattern: The list of classes which are |
| * permitted to acquire the access token, and become honorary |
| * members of this package. |
| */ |
| private static final String[] FRIENDS = { |
| "java.dyn.", "sun.dyn." |
| }; |
| |
| /** |
| * The following object is NOT public. That's the point of the pattern. |
| * It is package-private, so that any member of this package |
| * can acquire the access token, and give it away to trusted friends. |
| */ |
| static final Access TOKEN = new Access(); |
| |
| /** |
| * @return Access.TOKEN, if the caller is a friend of this package |
| */ |
| public static Access getToken() { |
| Class<?> callc = Reflection.getCallerClass(2); |
| if (isFriend(callc)) |
| return TOKEN; |
| else |
| throw new IllegalAccessError("bad caller: " + callc); |
| } |
| |
| /** Is the given name the name of a class which could be our friend? */ |
| public static boolean isFriendName(String name) { |
| for (String friend : FRIENDS) { |
| if (name.startsWith(friend)) |
| return true; |
| } |
| return false; |
| } |
| |
| /** Is the given class a friend? True if {@link #isFriendName}, |
| * and the given class also shares a class loader with us. |
| */ |
| public static boolean isFriend(Class<?> c) { |
| return isFriendName(c.getName()) && c.getClassLoader() == CLASS_LOADER; |
| } |
| |
| private static final ClassLoader CLASS_LOADER = Access.class.getClassLoader(); |
| |
| /** |
| * Throw an IllegalAccessError if the caller does not possess |
| * the Access.TOKEN. |
| * @param must be Access.TOKEN |
| */ |
| public static void check(Access token) { |
| if (token == null) |
| fail(); |
| // else it must be the unique Access.TOKEN |
| assert(token == Access.TOKEN); |
| } |
| private static void fail() { |
| final int CALLER_DEPTH = 3; |
| // 0: Reflection.getCC, 1: this.fail, 2: Access.*, 3: caller |
| Class<?> callc = Reflection.getCallerClass(CALLER_DEPTH); |
| throw new IllegalAccessError("bad caller: " + callc); |
| } |
| |
| static { |
| //sun.reflect.Reflection.registerMethodsToFilter(MH.class, "getToken"); |
| } |
| } |