PageRenderTime 38ms CodeModel.GetById 24ms 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
Possible License(s): Apache-2.0
  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. */
  16. package com.google.test.metric;
  17. import java.io.IOException;
  18. import java.io.InputStream;
  19. import java.util.HashMap;
  20. import java.util.Map;
  21. import org.objectweb.asm.ClassReader;
  22. import com.google.classpath.ClassPath;
  23. import com.google.test.metric.asm.ClassInfoBuilderVisitor;
  24. public class JavaClassRepository implements ClassRepository {
  25. private final Map<String, ClassInfo> classes = new HashMap<String, ClassInfo>();
  26. private ClassPath classpathRoots;
  27. public JavaClassRepository() {
  28. }
  29. public JavaClassRepository(ClassPath classpathRoots) {
  30. this.classpathRoots = classpathRoots;
  31. }
  32. public ClassInfo getClass(String name) {
  33. if (name.startsWith("[")) {
  34. return getClass(Object.class.getCanonicalName());
  35. }
  36. if (name.contains("$") || name.contains("/")) {
  37. throw new IllegalStateException("Class name can not contain '$' or '/' in a name: " + name);
  38. }
  39. ClassInfo classInfo = classes.get(name);
  40. if (classInfo == null) {
  41. try {
  42. classInfo = parseClass(inputStreamForClass(name));
  43. } catch (ArrayIndexOutOfBoundsException e) {
  44. throw new ClassNotFoundException(name);
  45. } catch (ClassNotFoundException e) {
  46. throw new ClassNotFoundException(name, e);
  47. }
  48. }
  49. return classInfo;
  50. }
  51. private InputStream inputStreamForClass(String clazzName) {
  52. String resource = clazzName.replace(".", "/");
  53. InputStream classBytes = null;
  54. while (true) {
  55. classBytes = getResource(resource + ".class");
  56. if (classBytes != null) {
  57. return classBytes;
  58. }
  59. int index = resource.lastIndexOf('/');
  60. if (index == -1) {
  61. throw new ClassNotFoundException(clazzName);
  62. }
  63. resource = resource.substring(0, index) + "$" + resource.substring(index + 1);
  64. }
  65. }
  66. private InputStream getResource(String classResource) {
  67. InputStream classBytes = null;
  68. if (classpathRoots != null) {
  69. classBytes = classpathRoots.getResourceAsStream(classResource);
  70. }
  71. if (classBytes == null) {
  72. //Perhaps it is a JDK Class
  73. classBytes = ClassLoader.getSystemResourceAsStream(classResource);
  74. }
  75. return classBytes;
  76. }
  77. private ClassInfo parseClass(InputStream classBytes) {
  78. try {
  79. ClassReader classReader = new ClassReader(classBytes);
  80. ClassInfoBuilderVisitor visitor = new ClassInfoBuilderVisitor(this);
  81. classReader.accept(visitor, 0);
  82. return visitor.getClassInfo();
  83. } catch (IOException e) {
  84. throw new RuntimeException(e);
  85. }
  86. }
  87. /* (non-Javadoc)
  88. * @see com.google.test.metric.ClassRepository#addClass(com.google.test.metric.ClassInfo)
  89. */
  90. public void addClass(ClassInfo classInfo) {
  91. String name = classInfo.getName();
  92. if (name.contains("$") || name.contains("/")) {
  93. throw new IllegalStateException();
  94. }
  95. classes.put(name, classInfo);
  96. }
  97. }