OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / java / security / SecureClassLoader.java
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 package java.security;
19
20 import java.nio.ByteBuffer;
21 import java.util.HashMap;
22
23 /**
24  * {@code SecureClassLoader} represents a {@code ClassLoader} which associates
25  * the classes it loads with a code source and provide mechanisms to allow the
26  * relevant permissions to be retrieved.
27  */
28 public class SecureClassLoader extends ClassLoader {
29
30     // A cache of ProtectionDomains for a given CodeSource
31     private HashMap<CodeSource, ProtectionDomain> pds = new HashMap<CodeSource, ProtectionDomain>();
32
33     /**
34      * Constructs a new instance of {@code SecureClassLoader}. The default
35      * parent {@code ClassLoader} is used.
36      * <p>
37      * If a {@code SecurityManager} is installed, code calling this constructor
38      * needs the {@code SecurityPermission} {@code checkCreateClassLoader} to be
39      * granted, otherwise a {@code SecurityException} will be thrown.
40      *
41      * @throws SecurityException
42      *             if a {@code SecurityManager} is installed and the caller does
43      *             not have permission to invoke this constructor.
44      */
45     protected SecureClassLoader() {
46         super();
47     }
48
49     /**
50      * Constructs a new instance of {@code SecureClassLoader} with the specified
51      * parent {@code ClassLoader}.
52      * <p>
53      * If a {@code SecurityManager} is installed, code calling this constructor
54      * needs the {@code SecurityPermission} {@code checkCreateClassLoader} to be
55      * granted, otherwise a {@code SecurityException} will be thrown.
56      *
57      * @param parent
58      *            the parent {@code ClassLoader}.
59      * @throws SecurityException
60      *             if a {@code SecurityManager} is installed and the caller does
61      *             not have permission to invoke this constructor.
62      */
63     protected SecureClassLoader(ClassLoader parent) {
64         super(parent);
65     }
66
67     /**
68      * Returns the {@code PermissionCollection} for the specified {@code
69      * CodeSource}.
70      *
71      * @param codesource
72      *            the code source.
73      * @return the {@code PermissionCollection} for the specified {@code
74      *         CodeSource}.
75      */
76     protected PermissionCollection getPermissions(CodeSource codesource) {
77         // Do nothing by default, ProtectionDomain will take care about
78         // permissions in dynamic
79         return new Permissions();
80     }
81
82     /**
83      * Constructs a new class from an array of bytes containing a class
84      * definition in class file format with an optional {@code CodeSource}.
85      *
86      * @param name
87      *            the name of the new class.
88      * @param b
89      *            a memory image of a class file.
90      * @param off
91      *            the start offset in b of the class data.
92      * @param len
93      *            the length of the class data.
94      * @param cs
95      *            the {@code CodeSource}, or {@code null}.
96      * @return a new class.
97      * @throws IndexOutOfBoundsException
98      *             if {@code off} or {@code len} are not valid in respect to
99      *             {@code b}.
100      * @throws ClassFormatError
101      *             if the specified data is not valid class data.
102      * @throws SecurityException
103      *             if the package to which this class is to be added, already
104      *             contains classes which were signed by different certificates,
105      *             or if the class name begins with "java."
106      */
107     protected final Class<?> defineClass(String name, byte[] b, int off, int len,
108             CodeSource cs) {
109         return cs == null ? defineClass(name, b, off, len) : defineClass(name,
110                 b, off, len, getPD(cs));
111     }
112
113     /**
114      * Constructs a new class from an array of bytes containing a class
115      * definition in class file format with an optional {@code CodeSource}.
116      *
117      * @param name
118      *            the name of the new class.
119      * @param b
120      *            a memory image of a class file.
121      * @param cs
122      *            the {@code CodeSource}, or {@code null}.
123      * @return a new class.
124      * @throws ClassFormatError
125      *             if the specified data is not valid class data.
126      * @throws SecurityException
127      *             if the package to which this class is to be added, already
128      *             contains classes which were signed by different certificates,
129      *             or if the class name begins with "java."
130      */
131     protected final Class<?> defineClass(String name, ByteBuffer b, CodeSource cs) {
132         //FIXME 1.5 - remove b.array(), call super.defineClass(,ByteBuffer,)
133         // directly
134         byte[] data = b.array();
135         return cs == null ? defineClass(name, data, 0, data.length)
136                 : defineClass(name, data, 0, data.length, getPD(cs));
137     }
138
139     // Constructs and caches ProtectionDomain for the given CodeSource
140     // object.<br>
141     // It calls {@link getPermissions()} to get a set of permissions.
142     //
143     // @param cs CodeSource object
144     // @return ProtectionDomain for the passed CodeSource object
145     private ProtectionDomain getPD(CodeSource cs) {
146         if (cs == null) {
147             return null;
148         }
149         // need to cache PDs, otherwise every class from a given CodeSource
150         // will have it's own ProtectionDomain, which does not look right.
151         ProtectionDomain pd;
152         synchronized (pds) {
153             if ((pd = pds.get(cs)) != null) {
154                 return pd;
155             }
156             PermissionCollection perms = getPermissions(cs);
157             pd = new ProtectionDomain(cs, perms, this, null);
158             pds.put(cs, pd);
159         }
160         return pd;
161     }
162 }