001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.jms.pool;
018
019import java.lang.reflect.Method;
020import java.util.Iterator;
021import java.util.Map;
022import java.util.Map.Entry;
023import javax.net.ssl.SSLServerSocket;
024import org.slf4j.Logger;
025import org.slf4j.LoggerFactory;
026
027public final class IntrospectionSupport {
028
029    private static final Logger LOG = LoggerFactory.getLogger(IntrospectionSupport.class);
030
031    private IntrospectionSupport() {
032    }
033
034    public static boolean setProperties(Object target, Map props) {
035        boolean rc = false;
036
037        if (target == null) {
038            throw new IllegalArgumentException("target was null.");
039        }
040        if (props == null) {
041            throw new IllegalArgumentException("props was null.");
042        }
043
044        for (Iterator<?> iter = props.entrySet().iterator(); iter.hasNext();) {
045            Entry<?,?> entry = (Entry<?,?>)iter.next();
046            if (setProperty(target, (String)entry.getKey(), entry.getValue())) {
047                iter.remove();
048                rc = true;
049            }
050        }
051
052        return rc;
053    }
054
055    public static boolean setProperty(Object target, String name, Object value) {
056        try {
057            Class<?> clazz = target.getClass();
058            if (target instanceof SSLServerSocket) {
059                // overcome illegal access issues with internal implementation class
060                clazz = SSLServerSocket.class;
061            }
062            Method setter = findSetterMethod(clazz, name);
063            if (setter == null) {
064                return false;
065            }
066
067            // If the type is null or it matches the needed type, just use the
068            // value directly
069            if (value == null || value.getClass() == setter.getParameterTypes()[0]) {
070                setter.invoke(target, value);
071            } else {
072                // We need to convert it
073                setter.invoke(target, convert(value, setter.getParameterTypes()[0]));
074            }
075            return true;
076        } catch (Exception e) {
077            LOG.error(String.format("Could not set property %s on %s", name, target), e);
078            return false;
079        }
080    }
081
082    private static Object convert(Object value, Class to) {
083        if (value == null) {
084            // lets avoid NullPointerException when converting to boolean for null values
085            if (boolean.class.isAssignableFrom(to)) {
086                return Boolean.FALSE;
087            }
088            return null;
089        }
090
091        // eager same instance type test to avoid the overhead of invoking the type converter
092        // if already same type
093        if (to.isAssignableFrom(value.getClass())) {
094            return to.cast(value);
095        }
096
097        if (boolean.class.isAssignableFrom(to) && value instanceof String) {
098            return Boolean.valueOf((String)value);
099        }
100
101        throw new IllegalArgumentException("Cannot convert from " + value.getClass()
102                    + " to " + to + " with value " + value);
103    }
104
105    private static Method findSetterMethod(Class clazz, String name) {
106        // Build the method name.
107        name = "set" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
108        Method[] methods = clazz.getMethods();
109        for (Method method : methods) {
110            Class<?> params[] = method.getParameterTypes();
111            if (method.getName().equals(name) && params.length == 1 ) {
112                return method;
113            }
114        }
115        return null;
116    }
117
118}