1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package org.apache.harmony.luni.internal.reflect;
19
20import java.lang.reflect.Method;
21
22import org.apache.harmony.luni.util.Msg;
23
24class ProxyMethod {
25    Method method;
26
27    Class[] commonExceptions;
28
29    ProxyMethod(Method method) {
30        this.method = method;
31        this.commonExceptions = method.getExceptionTypes();
32    }
33
34    Class[] getCheckedExceptions() {
35        Class[] newExceptions = commonExceptions.clone();
36        int cLength = newExceptions.length;
37        for (int c = 0, cL = cLength; c < cL; c++) {
38            Class<?> ex = newExceptions[c];
39            if (Throwable.class == ex) {
40                // if Throwable is included then treat as if no exceptions are
41                // checked
42                return new Class[0];
43            }
44            if (Error.class.isAssignableFrom(ex) || RuntimeException.class.isAssignableFrom(ex)) {
45                newExceptions[c] = null;
46                cLength--;
47            }
48        }
49
50        // All errors & runtime exceptions are passed back without being wrapped
51        Class[] result = new Class[cLength + 2];
52        int index = 0;
53        result[index++] = Error.class;
54        result[index++] = RuntimeException.class;
55        for (Class<?> ex : newExceptions) {
56            if (ex != null) {
57                result[index++] = ex;
58            }
59        }
60        return result;
61    }
62
63    boolean matchMethod(Method otherMethod) {
64        if (!method.getName().equals(otherMethod.getName())) {
65            return false;
66        }
67
68        Class[] params1 = method.getParameterTypes();
69        Class[] params2 = otherMethod.getParameterTypes();
70        int p = params1.length;
71        if (p != params2.length) {
72            return false;
73        }
74        while (--p >= 0) {
75            if (params1[p] != params2[p]) {
76                return false;
77            }
78        }
79
80        Class<?> thisMethodReturnType = method.getReturnType();
81        Class<?> otherMethodReturnType = otherMethod.getReturnType();
82        if (!thisMethodReturnType.isAssignableFrom(otherMethodReturnType)) {
83            if (otherMethodReturnType.isAssignableFrom(thisMethodReturnType)) {
84                // substitute returnType of method with that of otherMethod
85                method = otherMethod;
86            } else {
87                throw new IllegalArgumentException(Msg.getString("K00f2",
88                        method.getName()));
89            }
90        }
91
92        if (commonExceptions.length != 0) {
93            Class[] otherExceptions = otherMethod.getExceptionTypes();
94            if (otherExceptions.length == 0) {
95                commonExceptions = otherExceptions;
96            } else {
97                int cLength = commonExceptions.length;
98                nextException: for (int c = 0, cL = cLength, oL = otherExceptions.length; c < cL; c++) {
99                    Class<?> cException = commonExceptions[c];
100                    for (int o = 0; o < oL; o++) {
101                        Class<?> oException = otherExceptions[o];
102                        if (cException == oException) {
103                            continue nextException;
104                        }
105                        if (oException.isAssignableFrom(cException)) {
106                            continue nextException; // cException is a subclass
107                        }
108                        if (cException.isAssignableFrom(oException)) {
109                            // oException is a subclass, keep it instead
110                            commonExceptions[c] = cException = oException;
111                            continue nextException;
112                        }
113                    }
114                    commonExceptions[c] = null;
115                    cLength--;
116                }
117                if (cLength != commonExceptions.length) {
118                    Class[] newExceptions = new Class[cLength];
119                    for (int i = 0, j = 0, length = commonExceptions.length; i < length; i++) {
120                        Class<?> ex = commonExceptions[i];
121                        if (ex != null) {
122                            newExceptions[j++] = ex;
123                        }
124                    }
125                    commonExceptions = newExceptions;
126                }
127            }
128        }
129        return true;
130    }
131
132}
133