SecurityUtils.java revision f6c387128427e121477c1b32ad35cdcaa5101ba3
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 23package org.apache.harmony.security.fortress; 24 25import java.security.AccessControlContext; 26import java.util.WeakHashMap; 27 28import org.apache.harmony.security.internal.nls.Messages; 29 30//FIXME: move this class under umbrella of protected packages - 31// see lib/java.security: property 'package.access', 32// so only trusted classes like Thread and AccessController will 33// have an access to this class. 34// This is to remove dependency on VMStack, to reduce number 35// of VM2API-dependent classes. 36 37/** 38 * The class is used to perform an exchange of information between 39 * java.lang.Thread and java.security.AccessController.<br> 40 * The data to exchange is inherited contexts for the Thread-s. 41 * 42 */ 43public final class SecurityUtils { 44 45 // A map used to store inherited contexts.<br> 46 // A thread is used as a key for the map and AccessControlContext 47 // passed to the putContext is used as a value. 48 private static final WeakHashMap<Thread, AccessControlContext> ACC_CACHE = new WeakHashMap<Thread, AccessControlContext>(); 49 50 /** 51 * This method to be invoked in the Thread's constructor. The first argument 52 * (thread) must be Thread's this and the second must be a snapshot of the 53 * current AccessControlContext: 54 * <p> 55 * <code> 56 * Thread() {<br> 57 * SecurityUtils.putContext(this,AccessController.getContext());<br> 58 * ...do the stuff you need...<br> 59 * }<br> 60 * </code> 61 * 62 * The method throws SecurityException if the method is called more than 63 * once for a given thread. The first call to <code>putContext</code> is 64 * always performed in the Thread's constructor so this effectively means 65 * that no one can replace the snapshot taken. 66 * 67 * @throws SecurityException if a context for the passed 68 * <code>thread</code> already exists in the map. 69 * @throws NullPointerException if thread is null 70 * @throws Error if context is null AND if null context is already stored 71 * in the map 72 */ 73 public static void putContext(Thread thread, AccessControlContext context) 74 throws SecurityException { 75 if (thread == null) { 76 throw new NullPointerException(Messages.getString("security.140")); //$NON-NLS-1$ 77 } 78 synchronized (ACC_CACHE) { 79 if (ACC_CACHE.containsKey(thread)) { 80 throw new SecurityException(Messages.getString("security.141")); //$NON-NLS-1$ 81 } 82 if (context == null) { 83 // this only allowed once - for the very first thread. 84 if (ACC_CACHE.containsValue(null)) { 85 throw new Error(Messages.getString("security.142")); //$NON-NLS-1$ 86 } 87 } 88 ACC_CACHE.put(thread, context); 89 } 90 } 91 92 /** 93 * Returns the AccessControlContext stored for a given thread.<br> 94 * The method may return null - for the very first thread created 95 * by the VM which does not have inherited context.<br> 96 * It may also return null if no Thread found in the map - that seems 97 * possible during VM startup process. 98 */ 99 public static AccessControlContext getContext(Thread thread) 100 throws SecurityException { 101 102 // ~fixme: see 'fixme' at the top of the file 103 /* 104 Class cl = VMStack.getCallerClass(0); 105 if (cl != AccessController.class) { 106 throw new SecurityException("You ["+cl+"] do not have access to this resource."); 107 } 108 */ 109 110 synchronized (ACC_CACHE) { 111 return ACC_CACHE.get(thread); 112 } 113 } 114} 115