/testability-explorer/src/main/java/com/google/test/metric/JavaClassRepository.java
Java | 111 lines | 78 code | 14 blank | 19 comment | 16 complexity | 99c31401a4e26a9ca83e6325f8010a72 MD5 | raw file
1/* 2 * Copyright 2007 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16package com.google.test.metric; 17 18import java.io.IOException; 19import java.io.InputStream; 20import java.util.HashMap; 21import java.util.Map; 22 23import org.objectweb.asm.ClassReader; 24 25import com.google.classpath.ClassPath; 26import com.google.test.metric.asm.ClassInfoBuilderVisitor; 27 28public class JavaClassRepository implements ClassRepository { 29 30 private final Map<String, ClassInfo> classes = new HashMap<String, ClassInfo>(); 31 private ClassPath classpathRoots; 32 33 public JavaClassRepository() { 34 } 35 36 public JavaClassRepository(ClassPath classpathRoots) { 37 this.classpathRoots = classpathRoots; 38 } 39 40 public ClassInfo getClass(String name) { 41 if (name.startsWith("[")) { 42 return getClass(Object.class.getCanonicalName()); 43 } 44 if (name.contains("$") || name.contains("/")) { 45 throw new IllegalStateException("Class name can not contain '$' or '/' in a name: " + name); 46 } 47 ClassInfo classInfo = classes.get(name); 48 if (classInfo == null) { 49 try { 50 classInfo = parseClass(inputStreamForClass(name)); 51 } catch (ArrayIndexOutOfBoundsException e) { 52 throw new ClassNotFoundException(name); 53 } catch (ClassNotFoundException e) { 54 throw new ClassNotFoundException(name, e); 55 } 56 } 57 return classInfo; 58 } 59 60 private InputStream inputStreamForClass(String clazzName) { 61 String resource = clazzName.replace(".", "/"); 62 InputStream classBytes = null; 63 while (true) { 64 classBytes = getResource(resource + ".class"); 65 if (classBytes != null) { 66 return classBytes; 67 } 68 int index = resource.lastIndexOf('/'); 69 if (index == -1) { 70 throw new ClassNotFoundException(clazzName); 71 } 72 resource = resource.substring(0, index) + "$" + resource.substring(index + 1); 73 } 74 } 75 76 private InputStream getResource(String classResource) { 77 InputStream classBytes = null; 78 if (classpathRoots != null) { 79 classBytes = classpathRoots.getResourceAsStream(classResource); 80 } 81 if (classBytes == null) { 82 //Perhaps it is a JDK Class 83 classBytes = ClassLoader.getSystemResourceAsStream(classResource); 84 } 85 return classBytes; 86 } 87 88 private ClassInfo parseClass(InputStream classBytes) { 89 try { 90 ClassReader classReader = new ClassReader(classBytes); 91 ClassInfoBuilderVisitor visitor = new ClassInfoBuilderVisitor(this); 92 classReader.accept(visitor, 0); 93 return visitor.getClassInfo(); 94 } catch (IOException e) { 95 throw new RuntimeException(e); 96 } 97 } 98 99 /* (non-Javadoc) 100 * @see com.google.test.metric.ClassRepository#addClass(com.google.test.metric.ClassInfo) 101 */ 102 public void addClass(ClassInfo classInfo) { 103 String name = classInfo.getName(); 104 if (name.contains("$") || name.contains("/")) { 105 throw new IllegalStateException(); 106 } 107 classes.put(name, classInfo); 108 } 109 110} 111