001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.joran.util; 015 016import java.lang.reflect.Method; 017import java.lang.reflect.Modifier; 018import java.nio.charset.Charset; 019import java.nio.charset.UnsupportedCharsetException; 020 021import ch.qos.logback.core.CoreConstants; 022import ch.qos.logback.core.spi.ContextAware; 023 024/** 025 * Utility class which can convert string into objects. 026 * 027 * @author Ceki Gülcü 028 * 029 */ 030public class StringToObjectConverter { 031 032 private static final Class<?>[] STRING_CLASS_PARAMETER = new Class[] { String.class }; 033 034 static public boolean canBeBuiltFromSimpleString(Class<?> parameterClass) { 035 Package p = parameterClass.getPackage(); 036 if (parameterClass.isPrimitive()) { 037 return true; 038 } else if (p != null && "java.lang".equals(p.getName())) { 039 return true; 040 } else if (followsTheValueOfConvention(parameterClass)) { 041 return true; 042 } else if (parameterClass.isEnum()) { 043 return true; 044 } else if (isOfTypeCharset(parameterClass)) { 045 return true; 046 } 047 return false; 048 } 049 050 /** 051 * Convert <code>val</code> a String parameter to an object of a given type. 052 */ 053 @SuppressWarnings("unchecked") 054 public static Object convertArg(ContextAware ca, String val, Class<?> type) { 055 if (val == null) { 056 return null; 057 } 058 String v = val.trim(); 059 if (String.class.isAssignableFrom(type)) { 060 return v; 061 } else if (Integer.TYPE.isAssignableFrom(type)) { 062 return Integer.valueOf(v); 063 } else if (Long.TYPE.isAssignableFrom(type)) { 064 return Long.valueOf(v); 065 } else if (Float.TYPE.isAssignableFrom(type)) { 066 return Float.valueOf(v); 067 } else if (Double.TYPE.isAssignableFrom(type)) { 068 return Double.valueOf(v); 069 } else if (Boolean.TYPE.isAssignableFrom(type)) { 070 if ("true".equalsIgnoreCase(v)) { 071 return Boolean.TRUE; 072 } else if ("false".equalsIgnoreCase(v)) { 073 return Boolean.FALSE; 074 } 075 } else if (type.isEnum()) { 076 return convertToEnum(ca, v, (Class<? extends Enum<?>>) type); 077 } else if (StringToObjectConverter.followsTheValueOfConvention(type)) { 078 return convertByValueOfMethod(ca, type, v); 079 } else if (isOfTypeCharset(type)) { 080 return convertToCharset(ca, val); 081 } 082 083 return null; 084 } 085 086 static private boolean isOfTypeCharset(Class<?> type) { 087 return Charset.class.isAssignableFrom(type); 088 } 089 090 static private Charset convertToCharset(ContextAware ca, String val) { 091 try { 092 return Charset.forName(val); 093 } catch (UnsupportedCharsetException e) { 094 ca.addError("Failed to get charset [" + val + "]", e); 095 return null; 096 } 097 } 098 099 // returned value may be null and in most cases it is null. 100 public static Method getValueOfMethod(Class<?> type) { 101 try { 102 return type.getMethod(CoreConstants.VALUE_OF, STRING_CLASS_PARAMETER); 103 } catch (NoSuchMethodException e) { 104 return null; 105 } catch (SecurityException e) { 106 return null; 107 } 108 } 109 110 static private boolean followsTheValueOfConvention(Class<?> parameterClass) { 111 Method valueOfMethod = getValueOfMethod(parameterClass); 112 if (valueOfMethod == null) 113 return false; 114 115 int mod = valueOfMethod.getModifiers(); 116 return Modifier.isStatic(mod); 117 } 118 119 private static Object convertByValueOfMethod(ContextAware ca, Class<?> type, String val) { 120 try { 121 Method valueOfMethod = type.getMethod(CoreConstants.VALUE_OF, STRING_CLASS_PARAMETER); 122 return valueOfMethod.invoke(null, val); 123 } catch (Exception e) { 124 ca.addError("Failed to invoke " + CoreConstants.VALUE_OF + "{} method in class [" + type.getName() 125 + "] with value [" + val + "]"); 126 return null; 127 } 128 } 129 130 @SuppressWarnings({ "unchecked", "rawtypes" }) 131 private static Object convertToEnum(ContextAware ca, String val, Class<? extends Enum> enumType) { 132 return Enum.valueOf(enumType, val); 133 } 134 135 boolean isBuildableFromSimpleString() { 136 return false; 137 } 138}