001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Alexander V. Astapchuk
019: * @version $Revision: 1.1.6.3 $
020: */package org.apache.harmony.security.fortress;
021:
022: import java.security.AccessControlContext;
023: import java.util.WeakHashMap;
024:
025: /**
026: * The class is used to perform an exchange of information between
027: * java.lang.Thread and java.security.AccessController.<br>
028: * The data to excnahge is inherited contexts for the Thread-s.
029: *
030: */
031: public final class SecurityUtils {
032:
033: // A map used to store inherited contexts.<br>
034: // A thread is used as a key for the map and AccessControlContext
035: // passed to the putContext is used as a value.
036: private static final WeakHashMap<Thread, AccessControlContext> ACC_CACHE = new WeakHashMap<Thread, AccessControlContext>();
037:
038: /**
039: * This method to be invoked in the Thread's constructor. The first argument
040: * (thread) must be Thread's this and the second must be a snapshot of the
041: * current AccessControlContext:
042: * <p>
043: * <code>
044: * Thread() {<br>
045: * SecurityUtils.putContext(this,AccessController.getContext());<br>
046: * ...do the stuff you need...<br>
047: * }<br>
048: * </code>
049: *
050: * The method throws SecurityException if the method is called more than
051: * once for a given thread. The first call to <code>putContext</code> is
052: * always performed in the Thread's constructor so this effectively means
053: * that no one can replace the snapshot taken.
054: *
055: * @throws SecurityException if a context for the passed
056: * <code>thread</code> already exists in the map.
057: * @throws NullPointerException if thread is null
058: * @throws Error if context is null AND if null context is already stored
059: * in the map
060: */
061: public static void putContext(Thread thread,
062: AccessControlContext context) throws SecurityException {
063: if (thread == null) {
064: throw new NullPointerException("thread can not be null");
065: }
066: synchronized (ACC_CACHE) {
067: if (ACC_CACHE.containsKey(thread)) {
068: throw new SecurityException(
069: "You can not modify this map.");
070: }
071: if (context == null) {
072: // this only allowed once - for the very first thread.
073: if (ACC_CACHE.containsValue(null)) {
074: throw new Error(
075: "null context may be stored only once.");
076: }
077: }
078: ACC_CACHE.put(thread, context);
079: }
080: }
081:
082: /**
083: * Returns the AccessControlContext stored for a given thread.<br>
084: * The method may return null - for the very first thread created
085: * by the VM which does not have inherited context.<br>
086: * It may also return null if no Thread found in the map - that seems
087: * possible during VM startup process.
088: */
089: public static AccessControlContext getContext(Thread thread)
090: throws SecurityException {
091:
092: // ~fixme: see 'fixme' at the top of the file
093: /*
094: Class cl = VMStack.getCallerClass(0);
095: if (cl != AccessController.class) {
096: throw new SecurityException("You ["+cl+"] do not have access to this resource.");
097: }
098: */
099:
100: synchronized (ACC_CACHE) {
101: return ACC_CACHE.get(thread);
102: }
103: }
104: }
|