Home | History | Annotate | Download | only in create
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      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 com.android.tools.layoutlib.create;
     18 
     19 import java.util.HashMap;
     20 
     21 /**
     22  * Allows stub methods from LayoutLib to be overriden at runtime.
     23  * <p/>
     24  * Implementation note: all types required by this class(inner/outer classes & interfaces)
     25  * must be referenced by the injectClass argument to {@link AsmGenerator} in Main.java;
     26  * Otherwise they won't be accessible in layoutlib.jar at runtime.
     27  */
     28 public final class OverrideMethod {
     29 
     30     /** Map of method overridden. */
     31     private static HashMap<String, MethodListener> sMethods = new HashMap<>();
     32     /** Default listener for all method not listed in sMethods. Nothing if null. */
     33     private static MethodListener sDefaultListener = null;
     34 
     35     /**
     36      * Sets the default listener for all methods not specifically handled.
     37      * Null means to do nothing.
     38      */
     39     @SuppressWarnings("UnusedDeclaration") // Used by Bridge by reflection for debug purposes.
     40     public static void setDefaultListener(MethodListener listener) {
     41         sDefaultListener = listener;
     42     }
     43 
     44     /**
     45      * Defines or reset a listener for the given method signature.
     46      *
     47      * @param signature The signature of the method being invoked, composed of the
     48      *                  binary class name followed by the method descriptor (aka argument
     49      *                  types). Example: "com/foo/MyClass/InnerClass/printInt(I)V"
     50      * @param listener The new listener. Removes it if null.
     51      */
     52     public static void setMethodListener(String signature, MethodListener listener) {
     53         if (listener == null) {
     54             sMethods.remove(signature);
     55         } else {
     56             sMethods.put(signature, listener);
     57         }
     58     }
     59 
     60     /**
     61      * Invokes the specific listener for the given signature or the default one if defined.
     62      * <p/>
     63      * This version invokes the method listener for the void return type.
     64      * <p/>
     65      * Note: this is not intended to be used by the LayoutLib Bridge. It is intended to be called
     66      * by the stubbed methods generated by the LayoutLib_create tool.
     67      *
     68      * @param signature The signature of the method being invoked, composed of the
     69      *                  binary class name followed by the method descriptor (aka argument
     70      *                  types). Example: "com/foo/MyClass/InnerClass/printInt(I)V".
     71      * @param isNative True if the method was a native method.
     72      * @param caller The calling object. Null for static methods, "this" for instance methods.
     73      */
     74     public static void invokeV(String signature, boolean isNative, Object caller) {
     75         MethodListener i = sMethods.get(signature);
     76         if (i != null) {
     77             i.onInvokeV(signature, isNative, caller);
     78         } else if (sDefaultListener != null) {
     79             sDefaultListener.onInvokeV(signature, isNative, caller);
     80         }
     81     }
     82 
     83     /**
     84      * Invokes the specific listener for the int return type.
     85      * @see #invokeV(String, boolean, Object)
     86      */
     87     public static int invokeI(String signature, boolean isNative, Object caller) {
     88         MethodListener i = sMethods.get(signature);
     89         if (i != null) {
     90             return i.onInvokeI(signature, isNative, caller);
     91         } else if (sDefaultListener != null) {
     92             return sDefaultListener.onInvokeI(signature, isNative, caller);
     93         }
     94         return 0;
     95     }
     96 
     97     /**
     98      * Invokes the specific listener for the long return type.
     99      * @see #invokeV(String, boolean, Object)
    100      */
    101     public static long invokeL(String signature, boolean isNative, Object caller) {
    102         MethodListener i = sMethods.get(signature);
    103         if (i != null) {
    104             return i.onInvokeL(signature, isNative, caller);
    105         } else if (sDefaultListener != null) {
    106             return sDefaultListener.onInvokeL(signature, isNative, caller);
    107         }
    108         return 0;
    109     }
    110 
    111     /**
    112      * Invokes the specific listener for the float return type.
    113      * @see #invokeV(String, boolean, Object)
    114      */
    115     public static float invokeF(String signature, boolean isNative, Object caller) {
    116         MethodListener i = sMethods.get(signature);
    117         if (i != null) {
    118             return i.onInvokeF(signature, isNative, caller);
    119         } else if (sDefaultListener != null) {
    120             return sDefaultListener.onInvokeF(signature, isNative, caller);
    121         }
    122         return 0;
    123     }
    124 
    125     /**
    126      * Invokes the specific listener for the double return type.
    127      * @see #invokeV(String, boolean, Object)
    128      */
    129     public static double invokeD(String signature, boolean isNative, Object caller) {
    130         MethodListener i = sMethods.get(signature);
    131         if (i != null) {
    132             return i.onInvokeD(signature, isNative, caller);
    133         } else if (sDefaultListener != null) {
    134             return sDefaultListener.onInvokeD(signature, isNative, caller);
    135         }
    136         return 0;
    137     }
    138 
    139     /**
    140      * Invokes the specific listener for the object return type.
    141      * @see #invokeV(String, boolean, Object)
    142      */
    143     public static Object invokeA(String signature, boolean isNative, Object caller) {
    144         MethodListener i = sMethods.get(signature);
    145         if (i != null) {
    146             return i.onInvokeA(signature, isNative, caller);
    147         } else if (sDefaultListener != null) {
    148             return sDefaultListener.onInvokeA(signature, isNative, caller);
    149         }
    150         return null;
    151     }
    152 }
    153