1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.logging.log4j.core.config.plugins.util;
19
20 import java.io.File;
21 import java.math.BigDecimal;
22 import java.math.BigInteger;
23 import java.net.MalformedURLException;
24 import java.net.URI;
25 import java.net.URISyntaxException;
26 import java.net.URL;
27 import java.nio.charset.Charset;
28 import java.security.Provider;
29 import java.security.Security;
30 import java.util.Map;
31 import java.util.concurrent.ConcurrentHashMap;
32 import java.util.regex.Pattern;
33
34 import javax.xml.bind.DatatypeConverter;
35
36 import org.apache.logging.log4j.Level;
37 import org.apache.logging.log4j.Logger;
38 import org.apache.logging.log4j.core.Filter;
39 import org.apache.logging.log4j.core.layout.HtmlLayout;
40 import org.apache.logging.log4j.core.net.Facility;
41 import org.apache.logging.log4j.core.net.Protocol;
42 import org.apache.logging.log4j.core.util.Assert;
43 import org.apache.logging.log4j.core.util.Loader;
44 import org.apache.logging.log4j.status.StatusLogger;
45 import org.apache.logging.log4j.util.EnglishEnums;
46
47
48
49
50
51 public final class TypeConverters {
52
53
54
55
56
57
58 public static class BigDecimalConverter implements TypeConverter<BigDecimal> {
59 @Override
60 public BigDecimal convert(final String s) {
61 return new BigDecimal(s);
62 }
63 }
64
65
66
67
68 public static class BigIntegerConverter implements TypeConverter<BigInteger> {
69 @Override
70 public BigInteger convert(final String s) {
71 return new BigInteger(s);
72 }
73 }
74
75
76
77
78 public static class BooleanConverter implements TypeConverter<Boolean> {
79 @Override
80 public Boolean convert(final String s) {
81 return Boolean.valueOf(s);
82 }
83 }
84
85
86
87
88
89
90
91
92
93
94
95 public static class ByteArrayConverter implements TypeConverter<byte[]> {
96
97 private static final String PREFIX_0x = "0x";
98 private static final String PREFIX_BASE64 = "Base64:";
99
100 @Override
101 public byte[] convert(final String value) {
102 byte[] bytes;
103 if (value == null || value.isEmpty()) {
104 bytes = new byte[0];
105 } else if (value.startsWith(PREFIX_BASE64)) {
106 final String lexicalXSDBase64Binary = value.substring(PREFIX_BASE64.length());
107 bytes = DatatypeConverter.parseBase64Binary(lexicalXSDBase64Binary);
108 } else if (value.startsWith(PREFIX_0x)) {
109 final String lexicalXSDHexBinary = value.substring(PREFIX_0x.length());
110 bytes = DatatypeConverter.parseHexBinary(lexicalXSDHexBinary);
111 } else {
112 bytes = value.getBytes(Charset.defaultCharset());
113 }
114 return bytes;
115 }
116 }
117
118
119
120
121 public static class ByteConverter implements TypeConverter<Byte> {
122 @Override
123 public Byte convert(final String s) {
124 return Byte.valueOf(s);
125 }
126 }
127
128
129
130
131 public static class CharacterConverter implements TypeConverter<Character> {
132 @Override
133 public Character convert(final String s) {
134 if (s.length() != 1) {
135 throw new IllegalArgumentException("Character string must be of length 1: " + s);
136 }
137 return Character.valueOf(s.toCharArray()[0]);
138 }
139 }
140
141
142
143
144 public static class CharArrayConverter implements TypeConverter<char[]> {
145 @Override
146 public char[] convert(final String s) {
147 return s.toCharArray();
148 }
149 }
150
151
152
153
154 public static class CharsetConverter implements TypeConverter<Charset> {
155 @Override
156 public Charset convert(final String s) {
157 return Charset.forName(s);
158 }
159 }
160
161
162
163
164 public static class ClassConverter implements TypeConverter<Class<?>> {
165 @Override
166 public Class<?> convert(final String s) throws ClassNotFoundException {
167 return Loader.loadClass(s);
168 }
169 }
170
171
172
173
174 public static class DoubleConverter implements TypeConverter<Double> {
175 @Override
176 public Double convert(final String s) {
177 return Double.valueOf(s);
178 }
179 }
180
181
182
183
184
185
186
187 public static class EnumConverter<E extends Enum<E>> implements TypeConverter<E> {
188 private final Class<E> clazz;
189
190 private EnumConverter(final Class<E> clazz) {
191 this.clazz = clazz;
192 }
193
194 @Override
195 public E convert(final String s) {
196 return EnglishEnums.valueOf(clazz, s);
197 }
198 }
199
200
201
202
203 public static class FileConverter implements TypeConverter<File> {
204 @Override
205 public File convert(final String s) {
206 return new File(s);
207 }
208 }
209
210
211
212
213 public static class FloatConverter implements TypeConverter<Float> {
214 @Override
215 public Float convert(final String s) {
216 return Float.valueOf(s);
217 }
218 }
219
220 private static final class Holder {
221 private static final TypeConverters INSTANCE = new TypeConverters();
222 }
223
224
225
226
227 public static class IntegerConverter implements TypeConverter<Integer> {
228 @Override
229 public Integer convert(final String s) {
230 return Integer.valueOf(s);
231 }
232 }
233
234
235
236
237 public static class LevelConverter implements TypeConverter<Level> {
238 @Override
239 public Level convert(final String s) {
240 return Level.valueOf(s);
241 }
242 }
243
244
245
246
247 public static class LongConverter implements TypeConverter<Long> {
248 @Override
249 public Long convert(final String s) {
250 return Long.valueOf(s);
251 }
252 }
253
254
255
256
257 public static class PatternConverter implements TypeConverter<Pattern> {
258 @Override
259 public Pattern convert(final String s) {
260 return Pattern.compile(s);
261 }
262 }
263
264
265
266
267 public static class SecurityProviderConverter implements TypeConverter<Provider> {
268 @Override
269 public Provider convert(final String s) {
270 return Security.getProvider(s);
271 }
272 }
273
274
275
276
277 public static class ShortConverter implements TypeConverter<Short> {
278 @Override
279 public Short convert(final String s) {
280 return Short.valueOf(s);
281 }
282 }
283
284
285
286
287 public static class StringConverter implements TypeConverter<String> {
288 @Override
289 public String convert(final String s) {
290 return s;
291 }
292 }
293
294
295
296
297 public static class UriConverter implements TypeConverter<URI> {
298 @Override
299 public URI convert(final String s) throws URISyntaxException {
300 return new URI(s);
301 }
302 }
303
304
305
306
307 public static class UrlConverter implements TypeConverter<URL> {
308 @Override
309 public URL convert(final String s) throws MalformedURLException {
310 return new URL(s);
311 }
312 }
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331 public static Object convert(final String s, final Class<?> clazz, final Object defaultValue) {
332 final TypeConverter<?> converter = findTypeConverter(Assert.requireNonNull(clazz,
333 "No class specified to convert to."));
334 if (converter == null) {
335 throw new IllegalArgumentException("No type converter found for class: " + clazz.getName());
336 }
337 if (s == null) {
338
339
340 return parseDefaultValue(converter, defaultValue);
341 }
342 try {
343 return converter.convert(s);
344 } catch (final Exception e) {
345 LOGGER.warn("Error while converting string [{}] to type [{}]. Using default value [{}].", s, clazz,
346 defaultValue, e);
347 return parseDefaultValue(converter, defaultValue);
348 }
349 }
350
351
352
353
354
355
356
357
358 public static TypeConverter<?> findTypeConverter(final Class<?> clazz) {
359
360
361
362
363 return Holder.INSTANCE.registry.get(clazz);
364 }
365
366 private static Object parseDefaultValue(final TypeConverter<?> converter, final Object defaultValue) {
367 if (defaultValue == null) {
368 return null;
369 }
370 if (!(defaultValue instanceof String)) {
371 return defaultValue;
372 }
373 try {
374 return converter.convert((String) defaultValue);
375 } catch (final Exception e) {
376 LOGGER.debug("Can't parse default value [{}] for type [{}].", defaultValue, converter.getClass(), e);
377 return null;
378 }
379 }
380
381
382
383
384
385
386
387
388
389
390 public static void registerTypeConverter(final Class<?> clazz, final TypeConverter<?> converter) {
391 Holder.INSTANCE.registry.put(clazz, converter);
392 }
393
394 private static final Logger LOGGER = StatusLogger.getLogger();
395
396 private final Map<Class<?>, TypeConverter<?>> registry = new ConcurrentHashMap<Class<?>, TypeConverter<?>>();
397
398
399
400
401 private TypeConverters() {
402
403 registry.put(Boolean.class, new BooleanConverter());
404 registry.put(Byte.class, new ByteConverter());
405 registry.put(Character.class, new CharacterConverter());
406 registry.put(Double.class, new DoubleConverter());
407 registry.put(Float.class, new FloatConverter());
408 registry.put(Integer.class, new IntegerConverter());
409 registry.put(Long.class, new LongConverter());
410 registry.put(Short.class, new ShortConverter());
411
412 registry.put(boolean.class, registry.get(Boolean.class));
413 registry.put(byte.class, new ByteConverter());
414 registry.put(char[].class, new CharArrayConverter());
415 registry.put(double.class, registry.get(Double.class));
416 registry.put(float.class, registry.get(Float.class));
417 registry.put(int.class, registry.get(Integer.class));
418 registry.put(long.class, registry.get(Long.class));
419 registry.put(short.class, registry.get(Short.class));
420
421 registry.put(byte[].class, new ByteArrayConverter());
422 registry.put(char.class, new CharacterConverter());
423
424 registry.put(BigInteger.class, new BigIntegerConverter());
425 registry.put(BigDecimal.class, new BigDecimalConverter());
426
427 registry.put(String.class, new StringConverter());
428 registry.put(Charset.class, new CharsetConverter());
429 registry.put(File.class, new FileConverter());
430 registry.put(URL.class, new UrlConverter());
431 registry.put(URI.class, new UriConverter());
432 registry.put(Class.class, new ClassConverter());
433 registry.put(Pattern.class, new PatternConverter());
434 registry.put(Provider.class, new SecurityProviderConverter());
435
436 registry.put(Level.class, new LevelConverter());
437 registry.put(Filter.Result.class, new EnumConverter<Filter.Result>(Filter.Result.class));
438 registry.put(Facility.class, new EnumConverter<Facility>(Facility.class));
439 registry.put(Protocol.class, new EnumConverter<Protocol>(Protocol.class));
440 registry.put(HtmlLayout.FontSize.class, new EnumConverter<HtmlLayout.FontSize>(HtmlLayout.FontSize.class));
441 }
442 }