blob: 7726450c6da360b8a30d056c87cfb6fa8c5d4c73 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @author Alexander V. Astapchuk
*/
package org.apache.harmony.security.fortress;
import java.security.AccessControlContext;
import java.util.WeakHashMap;
/**
* The class is used to perform an exchange of information between
* java.lang.Thread and java.security.AccessController.<br>
* The data to excnahge is inherited contexts for the Thread-s.
*
*/
public final class SecurityUtils {
// A map used to store inherited contexts.<br>
// A thread is used as a key for the map and AccessControlContext
// passed to the putContext is used as a value.
private static final WeakHashMap<Thread, AccessControlContext> ACC_CACHE =
new WeakHashMap<Thread, AccessControlContext>();
/**
* This method to be invoked in the Thread's constructor. The first argument
* (thread) must be Thread's this and the second must be a snapshot of the
* current AccessControlContext:
* <p>
* <code>
* Thread() {<br>
* SecurityUtils.putContext(this,AccessController.getContext());<br>
* ...do the stuff you need...<br>
* }<br>
* </code>
*
* The method throws SecurityException if the method is called more than
* once for a given thread. The first call to <code>putContext</code> is
* always performed in the Thread's constructor so this effectively means
* that no one can replace the snapshot taken.
*
* @throws SecurityException if a context for the passed
* <code>thread</code> already exists in the map.
* @throws NullPointerException if thread is null
* @throws Error if context is null AND if null context is already stored
* in the map
*/
public static void putContext(Thread thread, AccessControlContext context)
throws SecurityException {
if (thread == null) {
throw new NullPointerException("thread can not be null");
}
synchronized (ACC_CACHE) {
if (ACC_CACHE.containsKey(thread)) {
throw new SecurityException("You can not modify this map.");
}
if (context == null) {
// this only allowed once - for the very first thread.
if (ACC_CACHE.containsValue(null)) {
throw new Error("null context may be stored only once.");
}
}
ACC_CACHE.put(thread, context);
}
}
/**
* Returns the AccessControlContext stored for a given thread.<br>
* The method may return null - for the very first thread created
* by the VM which does not have inherited context.<br>
* It may also return null if no Thread found in the map - that seems
* possible during VM startup process.
*/
public static AccessControlContext getContext(Thread thread)
throws SecurityException {
// ~fixme: see 'fixme' at the top of the file
/*
Class cl = VMStack.getCallerClass(0);
if (cl != AccessController.class) {
throw new SecurityException("You ["+cl+"] do not have access to this resource.");
}
*/
synchronized (ACC_CACHE) {
return ACC_CACHE.get(thread);
}
}
}