Home | History | Annotate | Download | only in fortress
      1 /*
      2  *  Licensed to the Apache Software Foundation (ASF) under one or more
      3  *  contributor license agreements.  See the NOTICE file distributed with
      4  *  this work for additional information regarding copyright ownership.
      5  *  The ASF licenses this file to You under the Apache License, Version 2.0
      6  *  (the "License"); you may not use this file except in compliance with
      7  *  the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  *  Unless required by applicable law or agreed to in writing, software
     12  *  distributed under the License is distributed on an "AS IS" BASIS,
     13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  *  See the License for the specific language governing permissions and
     15  *  limitations under the License.
     16  */
     17 
     18 /**
     19 * @author Alexander V. Astapchuk
     20 * @version $Revision$
     21 */
     22 
     23 package org.apache.harmony.security.fortress;
     24 
     25 import java.security.AccessControlContext;
     26 import java.util.WeakHashMap;
     27 
     28 //FIXME: move this class under umbrella of protected packages -
     29 // see lib/java.security: property 'package.access',
     30 // so only trusted classes like Thread and AccessController will
     31 // have an access to this class.
     32 // This is to remove dependency on VMStack, to reduce number
     33 // of VM2API-dependent classes.
     34 
     35 /**
     36  * The class is used to perform an exchange of information between
     37  * java.lang.Thread and java.security.AccessController.<br>
     38  * The data to exchange is inherited contexts for the Thread-s.
     39  *
     40  */
     41 public final class SecurityUtils {
     42 
     43     // A map used to store inherited contexts.<br>
     44     // A thread is used as a key for the map and AccessControlContext
     45     // passed to the putContext is used as a value.
     46     private static final WeakHashMap<Thread, AccessControlContext> ACC_CACHE = new WeakHashMap<Thread, AccessControlContext>();
     47 
     48     /**
     49      * This method to be invoked in the Thread's constructor. The first argument
     50      * (thread) must be Thread's this and the second must be a snapshot of the
     51      * current AccessControlContext:
     52      * <p>
     53      * <code>
     54      * Thread() {<br>
     55      * SecurityUtils.putContext(this,AccessController.getContext());<br>
     56      *  ...do the stuff you need...<br>
     57      * }<br>
     58      * </code>
     59      *
     60      * The method throws SecurityException if the method is called more than
     61      * once for a given thread. The first call to <code>putContext</code> is
     62      * always performed in the Thread's constructor so this effectively means
     63      * that no one can replace the snapshot taken.
     64      *
     65      * @throws SecurityException if a context for the passed
     66      *     <code>thread</code> already exists in the map.
     67      * @throws NullPointerException if thread is null
     68      * @throws Error if context is null AND if null context is already stored
     69      *     in the map
     70      */
     71     public static void putContext(Thread thread, AccessControlContext context)
     72             throws SecurityException {
     73         if (thread == null) {
     74             throw new NullPointerException();
     75         }
     76         synchronized (ACC_CACHE) {
     77             if (ACC_CACHE.containsKey(thread)) {
     78                 throw new SecurityException("You can not modify this map");
     79             }
     80             if (context == null) {
     81                 // this only allowed once - for the very first thread.
     82                 if (ACC_CACHE.containsValue(null)) {
     83                     throw new Error("null context may be stored only once");
     84                 }
     85             }
     86             ACC_CACHE.put(thread, context);
     87         }
     88     }
     89 
     90     /**
     91      * Returns the AccessControlContext stored for a given thread.<br>
     92      * The method may return null - for the very first thread created
     93      * by the VM which does not have inherited context.<br>
     94      * It may also return null if no Thread found in the map - that seems
     95      * possible during VM startup process.
     96      */
     97     public static AccessControlContext getContext(Thread thread)
     98             throws SecurityException {
     99 
    100         // ~fixme: see 'fixme' at the top of the file
    101         /*
    102          Class cl = VMStack.getCallerClass(0);
    103          if (cl != AccessController.class) {
    104          throw new SecurityException("You ["+cl+"] do not have access to this resource.");
    105          }
    106          */
    107 
    108         synchronized (ACC_CACHE) {
    109             return ACC_CACHE.get(thread);
    110         }
    111     }
    112 }
    113