/** * Copyright (C) 2015 Caratarse Auth Team <lucio.benfante@gmail.com> * * This file is part of Caratarse Auth Model. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.caratarse.auth.model.util; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; import org.springframework.beans.BeansException; import org.springframework.beans.FatalBeanException; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** * Utilities for managing beans. * * Derived from {@link org.springframework.beans.BeanUtils}. * * @author <a href="mailto:lucio.benfante@gmail.com">Lucio Benfante</a> */ public class BeanUtils { /** * Copy the not-null property values of the given source bean into the target bean. * <p> * Note: The source and target classes do not have to match or even be derived from each other, * as long as the properties match. Any bean properties that the source bean exposes but the * target bean does not will silently be ignored. * <p> * This is just a convenience method. For more complex transfer needs, consider using a full * BeanWrapper. * * @param source the source bean * @param target the target bean * @throws BeansException if the copying failed * @see BeanWrapper */ public static void copyNotNullProperties(Object source, Object target) throws BeansException { copyNotNullProperties(source, target, null, (String[]) null); } /** * Copy the not-null property values of the given source bean into the given target bean, only setting * properties defined in the given "editable" class (or interface). * <p> * Note: The source and target classes do not have to match or even be derived from each other, * as long as the properties match. Any bean properties that the source bean exposes but the * target bean does not will silently be ignored. * <p> * This is just a convenience method. For more complex transfer needs, consider using a full * BeanWrapper. * * @param source the source bean * @param target the target bean * @param editable the class (or interface) to restrict property setting to * @throws BeansException if the copying failed * @see BeanWrapper */ public static void copyNotNullProperties(Object source, Object target, Class<?> editable) throws BeansException { copyNotNullProperties(source, target, editable, (String[]) null); } /** * Copy the not-null property values of the given source bean into the given target bean, ignoring the * given "ignoreProperties". * <p> * Note: The source and target classes do not have to match or even be derived from each other, * as long as the properties match. Any bean properties that the source bean exposes but the * target bean does not will silently be ignored. * <p> * This is just a convenience method. For more complex transfer needs, consider using a full * BeanWrapper. * * @param source the source bean * @param target the target bean * @param ignoreProperties array of property names to ignore * @throws BeansException if the copying failed * @see BeanWrapper */ public static void copyNotNullProperties(Object source, Object target, String... ignoreProperties) throws BeansException { copyNotNullProperties(source, target, null, ignoreProperties); } /** * Copy the not-null property values of the given source bean into the given target bean. * <p> * Note: The source and target classes do not have to match or even be derived from each other, * as long as the properties match. Any bean properties that the source bean exposes but the * target bean does not will silently be ignored. * * @param source the source bean * @param target the target bean * @param editable the class (or interface) to restrict property setting to * @param ignoreProperties array of property names to ignore * @throws BeansException if the copying failed * @see BeanWrapper */ private static void copyNotNullProperties(Object source, Object target, Class<?> editable, String... ignoreProperties) throws BeansException { Assert.notNull(source, "Source must not be null"); Assert.notNull(target, "Target must not be null"); Class<?> actualEditable = target.getClass(); if (editable != null) { if (!editable.isInstance(target)) { throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]"); } actualEditable = editable; } PropertyDescriptor[] targetPds = org.springframework.beans.BeanUtils.getPropertyDescriptors( actualEditable); List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null); for (PropertyDescriptor targetPd : targetPds) { Method writeMethod = targetPd.getWriteMethod(); if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd. getName()))) { PropertyDescriptor sourcePd = org.springframework.beans.BeanUtils. getPropertyDescriptor(source.getClass(), targetPd.getName()); if (sourcePd != null) { Method readMethod = sourcePd.getReadMethod(); if (readMethod != null && ClassUtils.isAssignable(writeMethod. getParameterTypes()[0], readMethod.getReturnType())) { try { if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { readMethod.setAccessible(true); } Object value = readMethod.invoke(source); if (value == null) { continue; } if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { writeMethod.setAccessible(true); } writeMethod.invoke(target, value); } catch (Throwable ex) { throw new FatalBeanException( "Could not copy property '" + targetPd.getName() + "' from source to target", ex); } } } } } } }