aboutsummaryrefslogtreecommitdiffstats
path: root/app/src/fil/libre/repwifiapp/fwproxies/FrameworkProxy.java
blob: a468a1cd72f122cc11fdc39b9f8be58179a045fc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
//
// Copyright 2017, 2018 Filippo "Fil" Bergamo <fil.bergamo@riseup.net>
// 
// This file is part of RepWifiApp.
//
// RepWifiApp is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// RepWifiApp is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with RepWifiApp.  If not, see <http://www.gnu.org/licenses/>.
// 
// ********************************************************************

package fil.libre.repwifiapp.fwproxies;

import fil.libre.repwifiapp.helpers.Logger;
import java.lang.reflect.Constructor;

/**
 * Provides a base class for creating "proxy" classes that wrap up classes from
 * the Android Application Framework via reflection, exposing them outside the
 * framework itself.
 */
public abstract class FrameworkProxy {

    protected Object inner;

    protected abstract String getInnerClassName();

    protected static String getStaticInnerClassName() {
        return "Object";
    }

    protected static Class<?> getClassFromName(String className) {

        try {
            return Class.forName(className);
        } catch (ClassNotFoundException e) {
            Logger.logError(null, e);
            return null;
        }

    }

    protected Class<?> getInnerClass() {
        return getClassFromName(getInnerClassName());
    }

    protected Class<?>[] getTypesArray(Class<?>... args) {
        Class<?>[] types = new Class<?>[args.length];
        for (int i = 0; i < args.length; i++) {
            types[i] = args[i];
        }
        return types;
    }

    protected Object createInnerObject(Class<?> argType, Object arg) {
        return createInnerObject(getTypesArray(argType), arg);
    }

    protected Object createInnerObject(Class<?>[] argumentTypes, Object... args) {
        try {
            Class<?> cls = getClassFromName(getInnerClassName());
            Constructor<?> c = cls.getConstructor(argumentTypes);
            this.inner = c.newInstance(getRealArgs(args));
            return this.inner;
        } catch (Exception e) {
            Logger.logError("Exception while creating inner object via reflection.", e);
            return null;
        }
    }

    protected Object invokeMethodGetResult(String methodName, Class<?> argumentType, Object arg) {
        return invokeMethodGetResult(methodName, getTypesArray(argumentType), arg);
    }

    protected Object invokeMethodGetResult(String methodName, Class<?>[] argumentTypes,
                    Object... args) {
        try {
            return getClassFromName(getInnerClassName()).getMethod(methodName, argumentTypes)
                            .invoke(inner, getRealArgs(args));
        } catch (Exception e) {
            Logger.logError("Exception while invoking method via reflection.", e);
            return null;
        }
    }

    protected void invokeMethod(String methodName, Class<?> argumentType, Object arg) {
        invokeMethod(methodName, getTypesArray(argumentType), arg);
    }

    protected void invokeMethod(String methodName, Class<?>[] argumentTypes, Object... args) {
        try {
            getClassFromName(getInnerClassName()).getMethod(methodName, argumentTypes).invoke(
                            inner, getRealArgs(args));
        } catch (Exception e) {
            Logger.logError("Exception while invoking method via reflection.", e);
        }
    }

    private Object[] getRealArgs(Object[] args) {

        if (args == null || args.length == 0) {
            return new Object[] {};
        }

        // if the object is just a proxy, use the inner object as an argument to
        // the call.
        for (int i = 0; i < args.length; i++) {
            if (args[i] instanceof FrameworkProxy) {
                args[i] = ((FrameworkProxy) args[i]).inner;
            }
        }

        return args;

    }

}