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

aspectran / aspectran / #4075

19 Feb 2025 12:58PM CUT coverage: 35.181% (-0.004%) from 35.185%
#4075

push

github

topframe
Update

20 of 155 new or added lines in 9 files covered. (12.9%)

5 existing lines in 3 files now uncovered.

14252 of 40510 relevant lines covered (35.18%)

0.35 hits per line

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

57.59
/core/src/main/java/com/aspectran/core/context/asel/token/TokenEvaluation.java
1
/*
2
 * Copyright (c) 2008-2025 The Aspectran 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
package com.aspectran.core.context.asel.token;
17

18
import com.aspectran.core.activity.Activity;
19
import com.aspectran.core.activity.ActivityPerformException;
20
import com.aspectran.core.activity.InstantActivity;
21
import com.aspectran.core.component.bean.NoSuchBeanException;
22
import com.aspectran.core.component.bean.NoUniqueBeanException;
23
import com.aspectran.core.context.rule.type.TokenDirectiveType;
24
import com.aspectran.core.context.rule.type.TokenType;
25
import com.aspectran.utils.BeanTypeUtils;
26
import com.aspectran.utils.BeanUtils;
27
import com.aspectran.utils.PropertiesLoaderUtils;
28
import com.aspectran.utils.ReflectionUtils;
29
import com.aspectran.utils.SystemUtils;
30
import com.aspectran.utils.annotation.jsr305.NonNull;
31
import com.aspectran.utils.logging.Logger;
32
import com.aspectran.utils.logging.LoggerFactory;
33
import org.jasypt.exceptions.EncryptionInitializationException;
34
import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
35

36
import java.io.IOException;
37
import java.io.Writer;
38
import java.lang.reflect.Field;
39
import java.lang.reflect.InvocationTargetException;
40
import java.lang.reflect.Method;
41
import java.lang.reflect.Modifier;
42
import java.util.ArrayList;
43
import java.util.Arrays;
44
import java.util.HashSet;
45
import java.util.LinkedHashMap;
46
import java.util.List;
47
import java.util.Map;
48
import java.util.Properties;
49
import java.util.Set;
50

51
/**
52
 * The Class TokenEvaluation.
53
 *
54
 * <p>Created: 2008. 03. 29 AM 12:59:16</p>
55
 */
56
public class TokenEvaluation implements TokenEvaluator {
57

58
    private static final Logger logger = LoggerFactory.getLogger(TokenEvaluation.class);
1✔
59

60
    private final Activity activity;
61

62
    /**
63
     * Instantiates a new TokenEvaluation.
64
     * @param activity the current Activity
65
     */
66
    public TokenEvaluation(Activity activity) {
1✔
67
        if (activity == null) {
1✔
68
            throw new IllegalArgumentException("activity must not be null");
×
69
        }
70
        this.activity = activity;
1✔
71
    }
1✔
72

73
    @Override
74
    public Activity getActivity() {
75
        return activity;
1✔
76
    }
77

78
    @Override
79
    public Object evaluate(Token token) {
80
        try {
81
            TokenType tokenType = token.getType();
1✔
82
            Object value = null;
1✔
83
            if (tokenType == TokenType.TEXT) {
1✔
84
                value = token.getDefaultValue();
1✔
85
            } else if (tokenType == TokenType.BEAN) {
1✔
86
                value = getBean(token);
1✔
87
            } else if (tokenType == TokenType.TEMPLATE) {
1✔
88
                value = getTemplate(token);
1✔
89
            } else if (tokenType == TokenType.PARAMETER) {
1✔
90
                String[] values = getParameterValues(token.getName());
1✔
91
                if (values == null || values.length == 0) {
1✔
92
                    value = token.getDefaultValue();
1✔
93
                } else if (values.length > 1 && token.getDefaultValue() == null) {
1✔
94
                    value = values;
1✔
95
                } else {
96
                    value = (values[0] != null ? values[0] : token.getDefaultValue());
1✔
97
                }
98
            } else if (tokenType == TokenType.ATTRIBUTE) {
1✔
99
                value = getAttribute(token);
1✔
100
            } else if (tokenType == TokenType.PROPERTY) {
1✔
101
                value = getProperty(token);
1✔
102
            }
103
            return value;
1✔
104
        } catch (Exception e) {
×
105
            throw new TokenEvaluationException(token, e);
×
106
        }
107
    }
108

109
    @Override
110
    public Object evaluate(Token[] tokens) {
111
        if (tokens == null || tokens.length == 0) {
1✔
112
            return null;
×
113
        }
114
        if (tokens.length > 1) {
1✔
115
            StringBuilder sb = new StringBuilder();
1✔
116
            for (Token t : tokens) {
1✔
117
                Object value = evaluate(t);
1✔
118
                if (value != null) {
1✔
119
                    if (value instanceof Object[]) {
1✔
120
                        sb.append(Arrays.toString((Object[])value));
1✔
121
                    } else {
122
                        sb.append(value);
1✔
123
                    }
124
                }
125
            }
126
            return sb.toString();
1✔
127
        } else {
128
            return evaluate(tokens[0]);
1✔
129
        }
130
    }
131

132
    @Override
133
    public void evaluate(Token[] tokens, Writer writer) throws IOException {
134
        if (tokens == null || tokens.length == 0) {
1✔
135
            return;
×
136
        }
137
        for (Token t : tokens) {
1✔
138
            Object value = evaluate(t);
1✔
139
            if (value != null) {
1✔
140
                writer.write(value.toString());
1✔
141
            }
142
        }
143
        writer.flush();
1✔
144
    }
1✔
145

146
    @Override
147
    public String evaluateAsString(Token[] tokens) {
148
        Object value = evaluate(tokens);
1✔
149
        if (value instanceof Object[]) {
1✔
150
            return Arrays.toString((Object[])value);
1✔
151
        } else if (value != null) {
1✔
152
            return value.toString();
1✔
153
        } else {
154
            return null;
×
155
        }
156
    }
157

158
    @Override
159
    public List<Object> evaluateAsList(List<Token[]> tokensList) {
160
        if (tokensList == null || tokensList.isEmpty()) {
×
161
            return null;
×
162
        }
163
        List<Object> valueList = new ArrayList<>(tokensList.size());
×
164
        for (Token[] tokens : tokensList) {
×
165
            Object value = evaluate(tokens);
×
166
            valueList.add(value);
×
167
        }
×
168
        return valueList;
×
169
    }
170

171
    @Override
172
    public Set<Object> evaluateAsSet(Set<Token[]> tokensSet) {
173
        if (tokensSet == null || tokensSet.isEmpty()) {
×
174
            return null;
×
175
        }
176
        Set<Object> valueSet = new HashSet<>();
×
177
        for (Token[] tokens : tokensSet) {
×
178
            Object value = evaluate(tokens);
×
179
            valueSet.add(value);
×
180
        }
×
181
        return valueSet;
×
182
    }
183

184
    @Override
185
    public Map<String, Object> evaluateAsMap(Map<String, Token[]> tokensMap) {
186
        if (tokensMap == null || tokensMap.isEmpty()) {
×
187
            return null;
×
188
        }
189
        Map<String, Object> valueMap = new LinkedHashMap<>();
×
190
        for (Map.Entry<String, Token[]> entry : tokensMap.entrySet()) {
×
191
            Object value = evaluate(entry.getValue());
×
192
            valueMap.put(entry.getKey(), value);
×
193
        }
×
194
        return valueMap;
×
195
    }
196

197
    /**
198
     * Returns an array of {@code String} objects containing all
199
     * of the values the given activity's request parameter has,
200
     * or {@code null} if the parameter does not exist.
201
     * @param name a {@code String} specifying the name of the parameter
202
     * @return an array of {@code String} objects
203
     *      containing the parameter's values
204
     */
205
    protected String[] getParameterValues(String name) {
206
        if (activity.getRequestAdapter() != null) {
1✔
207
            return activity.getRequestAdapter().getParameterValues(name);
1✔
208
        } else {
209
            return null;
×
210
        }
211
    }
212

213
    /**
214
     * Returns the value of the named attribute as an {@code Object}
215
     * of the activity's request attributes or action results.
216
     * @param token the token
217
     * @return an {@code Object} containing the value of the attribute,
218
     *       or {@code null} if the attribute does not exist
219
     */
220
    protected Object getAttribute(Token token) {
221
        Object object = null;
1✔
222
        if (activity.getProcessResult() != null) {
1✔
223
            object = activity.getProcessResult().getResultValue(token.getName());
1✔
224
        }
225
        if (object == null && activity.getRequestAdapter() != null) {
1✔
226
            object = activity.getRequestAdapter().getAttribute(token.getName());
1✔
227
        }
228
        if (object != null && token.getGetterName() != null) {
1✔
229
            object = getBeanProperty(object, token.getGetterName());
×
230
        }
231
        return (object != null ? object : token.getDefaultValue());
1✔
232
    }
233

234
    /**
235
     * Returns the bean instance that matches the given token.
236
     * @param token the token
237
     * @return an instance of the bean
238
     */
239
    protected Object getBean(@NonNull Token token) {
240
        Object value;
241
        if (token.getValueProvider() != null) {
1✔
242
            if (token.getDirectiveType() == TokenDirectiveType.FIELD) {
1✔
NEW
243
                Field field = (Field)token.getValueProvider();
×
244
                if (Modifier.isStatic(field.getModifiers())) {
×
245
                    value = ReflectionUtils.getField(field, null);
×
246
                } else {
247
                    Class<?> beanClass = field.getDeclaringClass();
×
248
                    Object target = activity.getBean(beanClass);
×
249
                    value = ReflectionUtils.getField(field, target);
×
250
                }
251
            } else if (token.getDirectiveType() == TokenDirectiveType.METHOD) {
1✔
NEW
252
                Method method = (Method)token.getValueProvider();
×
253
                if (Modifier.isStatic(method.getModifiers())) {
×
254
                    value = ReflectionUtils.invokeMethod(method, null);
×
255
                } else {
256
                    Class<?> beanClass = method.getDeclaringClass();
×
257
                    Object target = activity.getBean(beanClass);
×
258
                    value = ReflectionUtils.invokeMethod(method, target);
×
259
                }
260
            } else {
×
261
                Class<?> beanClass = (Class<?>)token.getValueProvider();
1✔
262
                String getterName = token.getGetterName();
1✔
263
                if (getterName != null && beanClass.isEnum()) {
1✔
264
                    Object[] enums = beanClass.getEnumConstants();
×
265
                    if (enums != null) {
×
266
                        for (Object en : enums) {
×
267
                            if (getterName.equals(en.toString())) {
×
268
                                return en;
×
269
                            }
270
                        }
271
                    }
272
                }
273
                try {
274
                    value = activity.getBean(beanClass);
×
275
                } catch (NoSuchBeanException | NoUniqueBeanException e) {
1✔
276
                    if (getterName != null) {
1✔
277
                        try {
278
                            value = BeanTypeUtils.getProperty(beanClass, getterName);
1✔
279
                            if (value == null) {
1✔
280
                                value = token.getDefaultValue();
×
281
                            }
282
                            return value;
1✔
283
                        } catch (InvocationTargetException e2) {
×
284
                            // ignore
285
                        }
286
                    }
287
                    throw e;
×
288
                }
×
289
                if (value != null && getterName != null) {
×
290
                    value = getBeanProperty(value, getterName);
×
291
                }
292
            }
×
293
        } else {
294
            value = activity.getBean(token.getName());
1✔
295
            if (value != null && token.getGetterName() != null) {
1✔
296
                value = getBeanProperty(value, token.getGetterName());
1✔
297
            }
298
        }
299
        if (value == null) {
1✔
300
            value = token.getDefaultValue();
×
301
        }
302
        return value;
1✔
303
    }
304

305
    /**
306
     * Return the value of the specified property of the specified bean.
307
     * @param bean the bean object
308
     * @param propertyName the property name
309
     * @return the object
310
     */
311
    protected Object getBeanProperty(Object bean, String propertyName) {
312
        Object value;
313
        try {
314
            value = BeanUtils.getProperty(bean, propertyName);
1✔
315
        } catch (InvocationTargetException e) {
×
316
            value = null;
×
317
        }
1✔
318
        return value;
1✔
319
    }
320

321
    /**
322
     * Returns an Environment variable that matches the given token.
323
     * <p>Example usage:
324
     * <pre>
325
     *   %{classpath:com/aspectran/sample.properties}
326
     *   %{classpath:com/aspectran/sample.properties^propertyName:defaultValue}
327
     *   %{system:test.url}
328
     * </pre></p>
329
     * @param token the token
330
     * @return an environment variable
331
     * @throws Exception if an error has occurred
332
     */
333
    protected Object getProperty(@NonNull Token token) throws Exception {
334
        if (token.getDirectiveType() == TokenDirectiveType.CLASSPATH) {
1✔
335
            try {
336
                Properties props = PropertiesLoaderUtils.loadProperties(token.getValue(), activity.getClassLoader());
1✔
337
                Object value = (token.getGetterName() != null ? props.get(token.getGetterName()) : props);
1✔
338
                return (value != null ? value : token.getDefaultValue());
1✔
339
            } catch (EncryptionInitializationException | EncryptionOperationNotPossibleException e) {
×
340
                // Most of these occur when the password used for encryption is different
341
                logger.error("Failed to decrypt values of encrypted properties while evaluating token " +
×
342
                        token + "; Most of these occur when the password used for encryption is different" , e);
343
                return null;
×
344
            }
345
        } else if (token.getDirectiveType() == TokenDirectiveType.SYSTEM) {
1✔
346
            return SystemUtils.getProperty(token.getValue(), token.getDefaultValue());
×
347
        } else {
348
            Object value = activity.getEnvironment().getProperty(token.getName(), activity);
1✔
349
            if (value != null && token.getGetterName() != null) {
1✔
350
                value = getBeanProperty(value, token.getGetterName());
×
351
            }
352
            if (value == null) {
1✔
353
                value = token.getDefaultValue();
×
354
            }
355
            return value;
1✔
356
        }
357
    }
358

359
    /**
360
     * Executes template, returns the generated output.
361
     * @param token the token
362
     * @return the generated output as {@code String}
363
     */
364
    protected String getTemplate(@NonNull Token token) throws ActivityPerformException {
365
        InstantActivity instantActivity = new InstantActivity(activity, false);
1✔
366
        return instantActivity.perform(() -> {
1✔
367
            activity.getTemplateRenderer().render(token.getName(), instantActivity);
1✔
368
            String result = instantActivity.getResponseAdapter().getWriter().toString();
1✔
369
            return (result != null ? result : token.getDefaultValue());
1✔
370
        });
371
    }
372

373
}
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

© 2025 Coveralls, Inc