1 /* 2 * Copyright 2017 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc; 18 19 import com.google.common.base.Preconditions; 20 import com.google.common.io.ByteStreams; 21 import java.io.IOException; 22 import java.io.InputStream; 23 import java.util.regex.Pattern; 24 25 /** 26 * A class loader that can be used to repeatedly trigger static initialization of a class. A new 27 * instance is required per test. 28 */ 29 public final class StaticTestingClassLoader extends ClassLoader { 30 private final Pattern classesToDefine; 31 StaticTestingClassLoader(ClassLoader parent, Pattern classesToDefine)32 public StaticTestingClassLoader(ClassLoader parent, Pattern classesToDefine) { 33 super(parent); 34 this.classesToDefine = Preconditions.checkNotNull(classesToDefine, "classesToDefine"); 35 } 36 37 @Override findClass(String name)38 protected Class<?> findClass(String name) throws ClassNotFoundException { 39 if (!classesToDefine.matcher(name).matches()) { 40 throw new ClassNotFoundException(name); 41 } 42 InputStream is = getResourceAsStream(name.replace('.', '/') + ".class"); 43 if (is == null) { 44 throw new ClassNotFoundException(name); 45 } 46 byte[] b; 47 try { 48 b = ByteStreams.toByteArray(is); 49 } catch (IOException ex) { 50 throw new ClassNotFoundException(name, ex); 51 } 52 return defineClass(name, b, 0, b.length); 53 } 54 55 @Override loadClass(String name, boolean resolve)56 protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { 57 // Reverse normal loading order; check this class loader before its parent 58 synchronized (getClassLoadingLock(name)) { 59 Class<?> klass = findLoadedClass(name); 60 if (klass == null) { 61 try { 62 klass = findClass(name); 63 } catch (ClassNotFoundException e) { 64 // This ClassLoader doesn't know a class with that name; that's part of normal operation 65 } 66 } 67 if (klass == null) { 68 klass = super.loadClass(name, false); 69 } 70 if (resolve) { 71 resolveClass(klass); 72 } 73 return klass; 74 } 75 } 76 } 77