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 ch.qos.logback.core.CoreConstants; 017import ch.qos.logback.core.spi.ContextAware; 018 019import java.lang.reflect.Method; 020import java.lang.reflect.Modifier; 021import java.nio.charset.Charset; 022import java.nio.charset.UnsupportedCharsetException; 023 024import static ch.qos.logback.core.CoreConstants.NULL_STR; 025 026/** 027 * Utility class which can convert string into objects. 028 * 029 * @author Ceki Gülcü 030 * 031 */ 032public class StringToObjectConverter { 033 034 private static final Class<?>[] STRING_CLASS_PARAMETER = new Class[] { String.class }; 035 036 static public boolean canBeBuiltFromSimpleString(Class<?> parameterClass) { 037 Package p = parameterClass.getPackage(); 038 if (parameterClass.isPrimitive()) { 039 return true; 040 } else if (p != null && "java.lang".equals(p.getName())) { 041 return true; 042 } else if (followsTheValueOfConvention(parameterClass)) { 043 return true; 044 } else if (parameterClass.isEnum()) { 045 return true; 046 } else if (isOfTypeCharset(parameterClass)) { 047 return true; 048 } 049 return false; 050 } 051 052 /** 053 * Convert <code>val</code> a String parameter to an object of a given type. 054 */ 055 @SuppressWarnings("unchecked") 056 static public Object convertArg(ContextAware ca, String val, Class<?> type) { 057 if (val == null) { 058 return null; 059 } 060 String v = val.trim(); 061 if (String.class.isAssignableFrom(type)) { 062 return v; 063 } else if (Integer.TYPE.isAssignableFrom(type)) { 064 return Integer.valueOf(v); 065 } else if (Long.TYPE.isAssignableFrom(type)) { 066 return Long.valueOf(v); 067 } else if (Float.TYPE.isAssignableFrom(type)) { 068 return Float.valueOf(v); 069 } else if (Double.TYPE.isAssignableFrom(type)) { 070 return Double.valueOf(v); 071 } else if (Boolean.TYPE.isAssignableFrom(type)) { 072 if ("true".equalsIgnoreCase(v)) { 073 return Boolean.TRUE; 074 } else if ("false".equalsIgnoreCase(v)) { 075 return Boolean.FALSE; 076 } 077 } else if (type.isEnum()) { 078 return convertToEnum(ca, v, (Class<? extends Enum<?>>) type); 079 } else if (StringToObjectConverter.followsTheValueOfConvention(type)) { 080 return convertByValueOfMethod(ca, type, v); 081 } else if (isOfTypeCharset(type)) { 082 return convertToCharset(ca, val); 083 } 084 085 return null; 086 } 087 088 static private boolean isOfTypeCharset(Class<?> type) { 089 return Charset.class.isAssignableFrom(type); 090 } 091 092 static private Charset convertToCharset(ContextAware ca, String val) { 093 094 if (NULL_STR.equalsIgnoreCase(val)) { 095 ca.addInfo("Converting the string \"null\" as Charset.defaultCharset()"); 096 return Charset.defaultCharset(); 097 } 098 099 try { 100 return Charset.forName(val); 101 } catch (UnsupportedCharsetException e) { 102 ca.addError("Failed to get charset [" + val + "]", e); 103 return null; 104 } 105 } 106 107 // returned value may be null and in most cases it is null. 108 static public Method getValueOfMethod(Class<?> type) { 109 try { 110 return type.getMethod(CoreConstants.VALUE_OF, STRING_CLASS_PARAMETER); 111 } catch (NoSuchMethodException e) { 112 return null; 113 } catch (SecurityException e) { 114 return null; 115 } 116 } 117 118 static public boolean followsTheValueOfConvention(Class<?> parameterClass) { 119 Method valueOfMethod = getValueOfMethod(parameterClass); 120 if (valueOfMethod == null) 121 return false; 122 123 int mod = valueOfMethod.getModifiers(); 124 return Modifier.isStatic(mod); 125 } 126 127 private static Object convertByValueOfMethod(ContextAware ca, Class<?> type, String val) { 128 try { 129 Method valueOfMethod = type.getMethod(CoreConstants.VALUE_OF, STRING_CLASS_PARAMETER); 130 return valueOfMethod.invoke(null, val); 131 } catch (Exception e) { 132 ca.addError("Failed to invoke " + CoreConstants.VALUE_OF + "{} method in class [" + type.getName() 133 + "] with value [" + val + "]"); 134 return null; 135 } 136 } 137 138 @SuppressWarnings({ "unchecked", "rawtypes" }) 139 private static Object convertToEnum(ContextAware ca, String val, Class<? extends Enum> enumType) { 140 return Enum.valueOf(enumType, val); 141 } 142 143 boolean isBuildableFromSimpleString() { 144 return false; 145 } 146}