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 */ SecureClassLoader()37 protected SecureClassLoader() { 38 } 39 40 /** 41 * Constructs a new instance of {@code SecureClassLoader} with the specified 42 * parent {@code ClassLoader}. 43 * 44 * @param parent 45 * the parent {@code ClassLoader}. 46 */ SecureClassLoader(ClassLoader parent)47 protected SecureClassLoader(ClassLoader parent) { 48 super(parent); 49 } 50 51 /** 52 * Returns the {@code PermissionCollection} for the specified {@code 53 * CodeSource}. 54 * 55 * @param codesource 56 * the code source. 57 * @return the {@code PermissionCollection} for the specified {@code 58 * CodeSource}. 59 */ getPermissions(CodeSource codesource)60 protected PermissionCollection getPermissions(CodeSource codesource) { 61 // Do nothing by default, ProtectionDomain will take care about 62 // permissions in dynamic 63 return new Permissions(); 64 } 65 66 /** 67 * Constructs a new class from an array of bytes containing a class 68 * definition in class file format with an optional {@code CodeSource}. 69 * 70 * @param name 71 * the name of the new class. 72 * @param b 73 * a memory image of a class file. 74 * @param off 75 * the start offset in b of the class data. 76 * @param len 77 * the length of the class data. 78 * @param cs 79 * the {@code CodeSource}, or {@code null}. 80 * @return a new class. 81 * @throws IndexOutOfBoundsException 82 * if {@code off} or {@code len} are not valid in respect to 83 * {@code b}. 84 * @throws ClassFormatError 85 * if the specified data is not valid class data. 86 * @throws SecurityException 87 * if the package to which this class is to be added, already 88 * contains classes which were signed by different certificates, 89 * or if the class name begins with "java." 90 */ defineClass(String name, byte[] b, int off, int len, CodeSource cs)91 protected final Class<?> defineClass(String name, byte[] b, int off, int len, 92 CodeSource cs) { 93 return cs == null ? defineClass(name, b, off, len) : defineClass(name, 94 b, off, len, getPD(cs)); 95 } 96 97 /** 98 * Constructs a new class from an array of bytes containing a class 99 * definition in class file format with an optional {@code CodeSource}. 100 * 101 * @param name 102 * the name of the new class. 103 * @param b 104 * a memory image of a class file. 105 * @param cs 106 * the {@code CodeSource}, or {@code null}. 107 * @return a new class. 108 * @throws ClassFormatError 109 * if the specified data is not valid class data. 110 * @throws SecurityException 111 * if the package to which this class is to be added, already 112 * contains classes which were signed by different certificates, 113 * or if the class name begins with "java." 114 */ defineClass(String name, ByteBuffer b, CodeSource cs)115 protected final Class<?> defineClass(String name, ByteBuffer b, CodeSource cs) { 116 //FIXME 1.5 - remove b.array(), call super.defineClass(,ByteBuffer,) 117 // directly 118 byte[] data = b.array(); 119 return cs == null ? defineClass(name, data, 0, data.length) 120 : defineClass(name, data, 0, data.length, getPD(cs)); 121 } 122 123 // Constructs and caches ProtectionDomain for the given CodeSource 124 // object.<br> 125 // It calls {@link getPermissions()} to get a set of permissions. 126 // 127 // @param cs CodeSource object 128 // @return ProtectionDomain for the passed CodeSource object getPD(CodeSource cs)129 private ProtectionDomain getPD(CodeSource cs) { 130 if (cs == null) { 131 return null; 132 } 133 // need to cache PDs, otherwise every class from a given CodeSource 134 // will have it's own ProtectionDomain, which does not look right. 135 ProtectionDomain pd; 136 synchronized (pds) { 137 if ((pd = pds.get(cs)) != null) { 138 return pd; 139 } 140 PermissionCollection perms = getPermissions(cs); 141 pd = new ProtectionDomain(cs, perms, this, null); 142 pds.put(cs, pd); 143 } 144 return pd; 145 } 146 } 147