JavaAnalyzer.java revision fead9ca09b117136b35bc5bf137340a754f9eddd
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * http://www.apache.org/licenses/LICENSE-2.0 7 * Unless required by applicable law or agreed to in writing, software 8 * distributed under the License is distributed on an "AS IS" BASIS, 9 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 * See the License for the specific language governing permissions and 11 * limitations under the License. 12 */ 13 14package android.databinding.tool.reflection.java; 15 16import com.google.common.collect.ImmutableMap; 17 18import android.databinding.tool.reflection.ModelAnalyzer; 19import android.databinding.tool.reflection.ModelClass; 20import android.databinding.tool.reflection.SdkUtil; 21import android.databinding.tool.reflection.TypeUtil; 22import android.databinding.tool.util.L; 23 24import java.io.File; 25import java.net.MalformedURLException; 26import java.net.URL; 27import java.net.URLClassLoader; 28import java.util.HashMap; 29import java.util.Map; 30 31public class JavaAnalyzer extends ModelAnalyzer { 32 public static final Map<String, Class> PRIMITIVE_TYPES = 33 new ImmutableMap.Builder<String, Class>() 34 .put("boolean", boolean.class) 35 .put("byte", byte.class) 36 .put("short", short.class) 37 .put("char", char.class) 38 .put("int", int.class) 39 .put("long", long.class) 40 .put("float", float.class) 41 .put("double", double.class) 42 .build(); 43 44 private HashMap<String, JavaClass> mClassCache = new HashMap<String, JavaClass>(); 45 46 private final ClassLoader mClassLoader; 47 48 public JavaAnalyzer(ClassLoader classLoader) { 49 setInstance(this); 50 mClassLoader = classLoader; 51 } 52 53 @Override 54 public JavaClass loadPrimitive(String className) { 55 Class clazz = PRIMITIVE_TYPES.get(className); 56 if (clazz == null) { 57 return null; 58 } else { 59 return new JavaClass(clazz); 60 } 61 } 62 63 @Override 64 public ModelClass findClass(String className, Map<String, String> imports) { 65 // TODO handle imports 66 JavaClass loaded = mClassCache.get(className); 67 if (loaded != null) { 68 return loaded; 69 } 70 L.d("trying to load class %s from %s", className, mClassLoader.toString()); 71 loaded = loadPrimitive(className); 72 if (loaded == null) { 73 try { 74 if (className.startsWith("[") && className.contains("L")) { 75 int indexOfL = className.indexOf('L'); 76 JavaClass baseClass = (JavaClass) findClass( 77 className.substring(indexOfL + 1, className.length() - 1), null); 78 String realClassName = className.substring(0, indexOfL + 1) + 79 baseClass.mClass.getCanonicalName() + ';'; 80 loaded = new JavaClass(Class.forName(realClassName, false, mClassLoader)); 81 mClassCache.put(className, loaded); 82 } else { 83 loaded = loadRecursively(className); 84 mClassCache.put(className, loaded); 85 } 86 87 } catch (Throwable t) { 88// L.e(t, "cannot load class " + className); 89 } 90 } 91 // expr visitor may call this to resolve statics. Sometimes, it is OK not to find a class. 92 if (loaded == null) { 93 return null; 94 } 95 L.d("loaded class %s", loaded.mClass.getCanonicalName()); 96 return loaded; 97 } 98 99 @Override 100 public ModelClass findClass(Class classType) { 101 return new JavaClass(classType); 102 } 103 104 @Override 105 public TypeUtil createTypeUtil() { 106 return new JavaTypeUtil(); 107 } 108 109 private JavaClass loadRecursively(String className) throws ClassNotFoundException { 110 try { 111 L.d("recursively checking %s", className); 112 return new JavaClass(mClassLoader.loadClass(className)); 113 } catch (ClassNotFoundException ex) { 114 int lastIndexOfDot = className.lastIndexOf("."); 115 if (lastIndexOfDot == -1) { 116 throw ex; 117 } 118 return loadRecursively(className.substring(0, lastIndexOfDot) + "$" + className 119 .substring(lastIndexOfDot + 1)); 120 } 121 } 122 123 public static void initForTests() { 124 Map<String, String> env = System.getenv(); 125 for (Map.Entry<String, String> entry : env.entrySet()) { 126 L.d("%s %s", entry.getKey(), entry.getValue()); 127 } 128 String androidHome = env.get("ANDROID_HOME"); 129 if (androidHome == null) { 130 throw new IllegalStateException( 131 "you need to have ANDROID_HOME set in your environment" 132 + " to run compiler tests"); 133 } 134 File androidJar = new File(androidHome + "/platforms/android-21/android.jar"); 135 if (!androidJar.exists() || !androidJar.canRead()) { 136 throw new IllegalStateException( 137 "cannot find android jar at " + androidJar.getAbsolutePath()); 138 } 139 // now load android data binding library as well 140 141 try { 142 ClassLoader classLoader = new URLClassLoader(new URL[]{androidJar.toURI().toURL()}, 143 ModelAnalyzer.class.getClassLoader()); 144 new JavaAnalyzer(classLoader); 145 } catch (MalformedURLException e) { 146 throw new RuntimeException("cannot create class loader", e); 147 } 148 149 SdkUtil.initialize(8, new File(androidHome)); 150 } 151} 152