1 /*
2 * Copyright 2008-2009 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package impl.java.dyn;
27
28 import java.dyn.MethodHandles;
29 import sun.reflect.Reflection;
30
31 /**
32 * Access control to this package.
33 * Classes in other packages can attempt to acquire the access token,
34 * but will fail if they are not recognized as friends.
35 * Certain methods in this package, although public, require a non-null
36 * access token in order to proceed; they act like package-private methods.
37 * @author jrose
38 */
39
40 public class Access {
41 private Access() { }
42
43 /**
44 * The heart of this pattern: The list of classes which are
45 * permitted to acquire the access token, and become honorary
46 * members of this package.
47 */
48 static private final String[] FRIENDS = {
49 "java.dyn.", "impl.java.dyn."
50 };
51
52 /**
53 * The following object is NOT public. That's the point of the pattern.
54 * It is package-private, so that any member of this package
55 * can acquire the access token, and give it away to trusted friends.
56 */
57 static final Access TOKEN = new Access();
58
59 /**
60 * @return Access.TOKEN, if the caller is a friend of this package
61 */
62 public static Access getToken() {
63 Class<?> callc = Reflection.getCallerClass(2);
64 if (callc.getClassLoader() == Access.class.getClassLoader()) {
65 String callcName = callc.getName();
66 for (String friend : FRIENDS) {
67 if (callcName.startsWith(friend))
68 return TOKEN;
69 }
70 }
71 throw new IllegalAccessError("bad caller: " + callc);
72 }
73
74 /**
75 * Throw an IllegalAccessError if the caller does not possess
76 * the Access.TOKEN.
77 * @param must be Access.TOKEN
78 */
79 public static void check(Access token) {
80 if (token == null)
81 fail();
82 // else it must be the unique Access.TOKEN
83 assert(token == Access.TOKEN);
84 }
85 private static void fail() {
86 Class<?> callc = Reflection.getCallerClass(3);
87 throw new IllegalAccessError("bad caller: " + callc);
88 }
89
90 static {
91 //sun.reflect.Reflection.registerMethodsToFilter(MH.class, "getToken");
92 }
93 }