ValueHandler.java revision 1870:4aa2e64eff30
1351280Sdim/* 2351280Sdim * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3351280Sdim * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4351280Sdim * 5351280Sdim * This code is free software; you can redistribute it and/or modify it 6351280Sdim * under the terms of the GNU General Public License version 2 only, as 7351280Sdim * published by the Free Software Foundation. 8351280Sdim * 9351280Sdim * This code is distributed in the hope that it will be useful, but WITHOUT 10351280Sdim * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11351280Sdim * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12351280Sdim * version 2 for more details (a copy is included in the LICENSE file that 13351280Sdim * accompanied this code). 14360784Sdim * 15351280Sdim * You should have received a copy of the GNU General Public License version 16351280Sdim * 2 along with this work; if not, write to the Free Software Foundation, 17351280Sdim * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18351280Sdim * 19351280Sdim * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20351280Sdim * or visit www.oracle.com if you need additional information or have any 21351280Sdim * questions. 22351280Sdim */ 23351280Sdim 24351280Sdimpackage jdk.test.failurehandler.value; 25351280Sdim 26351280Sdimimport jdk.test.failurehandler.Utils; 27351280Sdim 28351280Sdimimport java.lang.reflect.Field; 29351280Sdimimport java.lang.reflect.Modifier; 30351280Sdimimport java.util.Objects; 31351280Sdimimport java.util.Properties; 32351280Sdim 33351280Sdimpublic final class ValueHandler { 34351280Sdim public static <T> void apply(T object, Properties properties, 35351280Sdim String prefix) throws InvalidValueException { 36351280Sdim Objects.requireNonNull(object, "object cannot be null"); 37351280Sdim Objects.requireNonNull(properties, "properties cannot be null"); 38351280Sdim Class<?> aClass = object.getClass(); 39351280Sdim while (aClass != null) { 40351280Sdim for (Field field : aClass.getDeclaredFields()) { 41351280Sdim Value p = field.getAnnotation(Value.class); 42351280Sdim if (p != null) { 43351280Sdim applyToField(p, object, field, properties, prefix); 44351280Sdim } else { 45351280Sdim SubValues sub 46351280Sdim = field.getAnnotation(SubValues.class); 47351280Sdim if (sub != null) { 48351280Sdim getAccess(field); 49351280Sdim try { 50351280Sdim apply(field.get(object), properties, 51351280Sdim Utils.prependPrefix(prefix, sub.prefix())); 52351280Sdim } catch (IllegalAccessException e) { 53351280Sdim throw new InvalidValueException(String.format( 54351280Sdim "can't apply sub properties to %s.", 55351280Sdim field.getName())); 56351280Sdim } 57351280Sdim } 58351280Sdim } 59351280Sdim } 60351280Sdim aClass = aClass.getSuperclass(); 61351280Sdim } 62351280Sdim } 63351280Sdim 64351280Sdim private static void applyToField(Value property, Object object, 65351280Sdim Field field, Properties properties, String prefix) 66351280Sdim throws InvalidValueException { 67351280Sdim getAccess(field); 68351280Sdim if (Modifier.isFinal(field.getModifiers())) { 69351280Sdim throw new InvalidValueException( 70351280Sdim String.format("field '%s' is final", field)); 71351280Sdim } 72351280Sdim String name = Utils.prependPrefix(prefix, property.name()); 73351280Sdim String value = getProperty(properties, prefix, property.name()); 74351280Sdim if (value == null) { 75351280Sdim DefaultValue defaultValue 76351280Sdim = field.getAnnotation(DefaultValue.class); 77351280Sdim value = defaultValue == null ? null : defaultValue.value(); 78351280Sdim } 79351280Sdim if (value == null) { 80351280Sdim throw new InvalidValueException(String.format( 81351280Sdim "can't set '%s', because properties don't have '%s'.", 82351280Sdim field.getName(), name)); 83351280Sdim } 84351280Sdim String delimiter = getProperty(properties, 85351280Sdim Utils.prependPrefix(prefix, property.name()), "delimiter"); 86351280Sdim delimiter = delimiter == null ? " " : delimiter; 87351280Sdim Class<? extends ValueParser> parserClass = property.parser(); 88351280Sdim try { 89351280Sdim field.set(object, parserClass.newInstance().parse( 90351280Sdim field.getType(), value, delimiter)); 91351280Sdim } catch (ReflectiveOperationException | IllegalArgumentException e) { 92351280Sdim throw new InvalidValueException( 93351280Sdim String.format("can't set field '%s' : %s", 94351280Sdim field.getName(), e.getMessage()), e); 95351280Sdim } 96351280Sdim } 97351280Sdim 98351280Sdim private static String getProperty(Properties properties, 99351280Sdim String prefix, String name) { 100351280Sdim if (prefix == null || prefix.isEmpty()) { 101351280Sdim return properties.getProperty(name); 102360784Sdim } 103360784Sdim int index = prefix.length(); 104360784Sdim do { 105360784Sdim String value = properties.getProperty( 106360784Sdim Utils.prependPrefix(prefix.substring(0, index), name)); 107351280Sdim if (value != null) { 108351280Sdim return value; 109351280Sdim } 110351280Sdim index = prefix.lastIndexOf('.', index - 1); 111351280Sdim } while (index > 0); 112351280Sdim return properties.getProperty(name); 113351280Sdim } 114351280Sdim 115351280Sdim private static void getAccess(Field field) { 116351280Sdim int modifiers = field.getModifiers(); 117351280Sdim if (!Modifier.isPublic(modifiers)) { 118351280Sdim field.setAccessible(true); 119351280Sdim } 120351280Sdim } 121351280Sdim 122351280Sdim} 123351280Sdim