SecurityUtils.java revision 89c1feb0a69a7707b271086e749975b3f7acacf7
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