• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / httpunit / 755

14 Feb 2026 07:14PM UTC coverage: 80.526%. Remained the same
755

push

github

hazendaz
[ci] Fix badge

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8245 of 10124 relevant lines covered (81.44%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.11
/src/main/java/com/meterware/httpunit/dom/ScriptingSupport.java
1
/*
2
 * SPDX-License-Identifier: MIT
3
 * See LICENSE file for details.
4
 *
5
 * Copyright 2000-2026 Russell Gold
6
 * Copyright 2021-2000 hazendaz
7
 */
8
package com.meterware.httpunit.dom;
9

10
import java.lang.reflect.InvocationTargetException;
11
import java.lang.reflect.Method;
12
import java.util.Hashtable;
13

14
import org.mozilla.javascript.FunctionObject;
15
import org.mozilla.javascript.Scriptable;
16

17
/**
18
 * Utilities to support scripting.
19
 */
20
class ScriptingSupport {
×
21

22
    /** A non-null method value to be used to indicate that we have already looked up and failed to find one. **/
23
    private static final Method NO_SUCH_PROPERTY = ScriptingSupport.class.getDeclaredMethods()[0];
1✔
24

25
    /** The Constant NO_ARGS. */
26
    private static final Object[] NO_ARGS = {};
1✔
27

28
    /** map of classes to maps of string to function objects. **/
29
    private static Hashtable _classFunctionMaps = new Hashtable<>();
1✔
30

31
    /** map of classes to maps of string to getter methods. **/
32
    private static Hashtable _classGetterMaps = new Hashtable<>();
1✔
33

34
    /** map of classes to maps of string to setter methods. **/
35
    private static Hashtable _classSetterMaps = new Hashtable<>();
1✔
36

37
    /**
38
     * Checks for named property.
39
     *
40
     * @param element
41
     *            the element
42
     * @param javaPropertyName
43
     *            the java property name
44
     * @param scriptable
45
     *            the scriptable
46
     *
47
     * @return true, if successful
48
     */
49
    static boolean hasNamedProperty(Object element, String javaPropertyName, Scriptable scriptable) {
50
        Method getter = getPropertyGetter(element.getClass(), javaPropertyName);
1✔
51
        if (getter != NO_SUCH_PROPERTY) {
1!
52
            return true;
1✔
53
        }
54
        Object function = getFunctionObject(element.getClass(), javaPropertyName, scriptable);
×
55
        return function != null;
×
56
    }
57

58
    /**
59
     * Gets the named property.
60
     *
61
     * @param element
62
     *            the element
63
     * @param javaPropertyName
64
     *            the java property name
65
     * @param scriptable
66
     *            the scriptable
67
     *
68
     * @return the named property
69
     */
70
    static Object getNamedProperty(Object element, String javaPropertyName, Scriptable scriptable) {
71
        Method getter = getPropertyGetter(element.getClass(), javaPropertyName);
1✔
72
        if (getter == NO_SUCH_PROPERTY) {
1✔
73
            Object function = getFunctionObject(element.getClass(), javaPropertyName, scriptable);
1✔
74
            return function == null ? Scriptable.NOT_FOUND : function;
1✔
75
        }
76
        try {
77
            return getter.invoke(element, NO_ARGS);
1✔
78
        } catch (IllegalAccessException | InvocationTargetException e) {
×
79
            return Scriptable.NOT_FOUND;
×
80
        }
81
    }
82

83
    /**
84
     * Gets the function object.
85
     *
86
     * @param aClass
87
     *            the a class
88
     * @param methodName
89
     *            the method name
90
     * @param scriptable
91
     *            the scriptable
92
     *
93
     * @return the function object
94
     */
95
    private static FunctionObject getFunctionObject(Class aClass, String methodName, Scriptable scriptable) {
96
        Hashtable functionMap = (Hashtable) _classFunctionMaps.get(aClass);
1✔
97
        if (functionMap == null) {
1✔
98
            _classFunctionMaps.put(aClass, functionMap = new Hashtable<>());
1✔
99
        }
100

101
        Object result = functionMap.get(methodName);
1✔
102
        if (result == NO_SUCH_PROPERTY) {
1✔
103
            return null;
1✔
104
        }
105
        if (result != null) {
1!
106
            return (FunctionObject) result;
×
107
        }
108

109
        Method[] methods = aClass.getMethods();
1✔
110
        for (Method method : methods) {
1✔
111
            if (method.getName().equalsIgnoreCase(methodName)) {
1✔
112
                FunctionObject function = new FunctionObject(methodName, method, scriptable);
1✔
113
                functionMap.put(methodName, function);
1✔
114
                return function;
1✔
115
            }
116
        }
117
        functionMap.put(methodName, NO_SUCH_PROPERTY);
1✔
118
        return null;
1✔
119
    }
120

121
    /**
122
     * Gets the property getter.
123
     *
124
     * @param aClass
125
     *            the a class
126
     * @param propertyName
127
     *            the property name
128
     *
129
     * @return the property getter
130
     */
131
    private static Method getPropertyGetter(Class aClass, String propertyName) {
132
        Hashtable methodMap = (Hashtable) _classGetterMaps.get(aClass);
1✔
133
        if (methodMap == null) {
1✔
134
            _classGetterMaps.put(aClass, methodMap = new Hashtable<>());
1✔
135
        }
136

137
        Method result = (Method) methodMap.get(propertyName);
1✔
138
        if (result != null) {
1✔
139
            return result;
1✔
140
        }
141

142
        Method[] methods = aClass.getMethods();
1✔
143
        for (Method method : methods) {
1✔
144
            if (method.getParameterTypes().length > 0) {
1✔
145
                continue;
1✔
146
            }
147
            if (method.getName().equalsIgnoreCase("is" + propertyName)
1!
148
                    || method.getName().equalsIgnoreCase("get" + propertyName)) {
1✔
149
                methodMap.put(propertyName, method);
1✔
150
                return method;
1✔
151
            }
152
        }
153
        methodMap.put(propertyName, NO_SUCH_PROPERTY);
1✔
154
        return NO_SUCH_PROPERTY;
1✔
155
    }
156

157
    /**
158
     * Sets the named property.
159
     *
160
     * @param element
161
     *            the element
162
     * @param javaPropertyName
163
     *            the java property name
164
     * @param value
165
     *            the value
166
     */
167
    static void setNamedProperty(AbstractDomComponent element, String javaPropertyName, Object value) {
168
        Method setter = getPropertySetter(element.getClass(), javaPropertyName, value);
1✔
169
        if (setter == NO_SUCH_PROPERTY) {
1!
170
            return;
×
171
        }
172

173
        try {
174
            setter.invoke(element, adjustedForSetter(value, setter));
1✔
175
        } catch (IllegalAccessException | InvocationTargetException e) { /* do nothing */
×
176
        }
1✔
177
    }
1✔
178

179
    /**
180
     * Adjusted for setter.
181
     *
182
     * @param value
183
     *            the value
184
     * @param setter
185
     *            the setter
186
     *
187
     * @return the object
188
     */
189
    private static Object adjustedForSetter(Object value, Method setter) {
190
        if (value == null) {
1!
191
            return null;
×
192
        }
193
        Class targetValueClass = setter.getParameterTypes()[0];
1✔
194
        if (targetValueClass.equals(String.class)) {
1✔
195
            return value.toString();
1✔
196
        }
197
        if (!(value instanceof Number) || !isNumericParameter(targetValueClass)) {
1!
198
            return value;
×
199
        }
200

201
        if (targetValueClass.getName().equals("int")) {
1!
202
            return Integer.valueOf(((Number) value).intValue());
1✔
203
        }
204
        if (targetValueClass.getName().equals("byte")) {
×
205
            return Byte.valueOf(((Number) value).byteValue());
×
206
        }
207
        if (targetValueClass.getName().equals("long")) {
×
208
            return Long.valueOf(((Number) value).longValue());
×
209
        }
210
        if (targetValueClass.getName().equals("short")) {
×
211
            return Short.valueOf(((Number) value).shortValue());
×
212
        }
213
        if (targetValueClass.getName().equals("float")) {
×
214
            return Float.valueOf(((Number) value).intValue());
×
215
        }
216
        if (targetValueClass.getName().equals("double")) {
×
217
            return Double.valueOf(((Number) value).intValue());
×
218
        }
219
        return value;
×
220
    }
221

222
    /**
223
     * Gets the property setter.
224
     *
225
     * @param aClass
226
     *            the a class
227
     * @param propertyName
228
     *            the property name
229
     * @param value
230
     *            the value
231
     *
232
     * @return the property setter
233
     */
234
    static Method getPropertySetter(Class aClass, String propertyName, Object value) {
235
        Hashtable methodMap = (Hashtable) _classSetterMaps.get(aClass);
1✔
236
        if (methodMap == null) {
1✔
237
            _classSetterMaps.put(aClass, methodMap = new Hashtable<>());
1✔
238
        }
239

240
        Method result = (Method) methodMap.get(propertyName);
1✔
241
        if (result != null) {
1✔
242
            return result;
1✔
243
        }
244

245
        String setterName = "set" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
1✔
246
        Method[] methods = aClass.getMethods();
1✔
247
        for (Method method : methods) {
1!
248
            if (method.getName().equalsIgnoreCase(setterName) && method.getParameterTypes().length == 1
1!
249
                    && isConvertableTo(value.getClass(), method.getParameterTypes()[0])) {
1!
250
                methodMap.put(propertyName, method);
1✔
251
                return method;
1✔
252
            }
253
        }
254
        methodMap.put(propertyName, NO_SUCH_PROPERTY);
×
255
        return NO_SUCH_PROPERTY;
×
256
    }
257

258
    /**
259
     * check whether the valueType is convertable to the parameterType.
260
     *
261
     * @param valueType
262
     *            the value type
263
     * @param parameterType
264
     *            the parameter type
265
     *
266
     * @return true, if is convertable to
267
     */
268
    public static boolean isConvertableTo(Class valueType, Class parameterType) {
269
        if (valueType.equals(parameterType) || parameterType.equals(String.class)
1✔
270
                || valueType.equals(String.class) && isNumericParameter(parameterType)) {
1✔
271
            return true;
1✔
272
        }
273
        if (Number.class.isAssignableFrom(valueType) && isNumericParameter(parameterType)
1!
274
                || valueType.equals(Boolean.class) && parameterType.equals(boolean.class)) {
1!
275
            return true;
1✔
276
        }
277
        return valueType.equals(String.class) && parameterType.equals(Boolean.class);
1!
278
    }
279

280
    /**
281
     * Checks if is numeric parameter.
282
     *
283
     * @param parameterType
284
     *            the parameter type
285
     *
286
     * @return true, if is numeric parameter
287
     */
288
    private static boolean isNumericParameter(Class parameterType) {
289
        if (parameterType.isPrimitive() && !parameterType.equals(boolean.class)) {
1!
290
            return true;
1✔
291
        }
292
        return Number.class.isAssignableFrom(parameterType);
1✔
293
    }
294
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc