PageRenderTime 24ms CodeModel.GetById 15ms app.highlight 6ms RepoModel.GetById 1ms app.codeStats 0ms

/testability-explorer/src/main/java/com/google/test/metric/JavaClassRepository.java

http://testability-explorer.googlecode.com/
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