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 }