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 */ putContext(Thread thread, AccessControlContext context)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 */ getContext(Thread thread)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