/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * 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 com.alibaba.citrus.util.internal; import static com.alibaba.citrus.util.BasicConstant.*; import static com.alibaba.citrus.util.ClassUtil.*; import static com.alibaba.citrus.util.CollectionUtil.*; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; import com.alibaba.citrus.util.StringUtil; /** * 生成程序中的日志、错误信息的工具类。 * * @author Michael Zhou */ public class MessageFormatter<T> { private final Map<Locale, Reference<ResourceBundle>> bundles; /** 创建一个<code>MessageFormatter</code>实例。 */ public MessageFormatter() { this.bundles = createConcurrentHashMap(); } /** 取得<code>ResourceBundle</code>的名称,默认和类名相同。 */ protected String getBundleName() { return getClass().getName(); } /** 取得指定locale的<code>ResourceBundle</code>。 */ private ResourceBundle getBundle(Locale locale) { if (locale == null) { locale = getDefaultLocale(); } Reference<ResourceBundle> bundleRef = bundles.get(locale); ResourceBundle bundle = null; if (bundleRef != null) { bundle = bundleRef.get(); } if (bundle == null) { bundle = ResourceBundle.getBundle(getBundleName(), locale); bundles.put(locale, new WeakReference<ResourceBundle>(bundle)); } return bundle; } /** 取得指定在enum中所标注的、系统默认locale的消息串,并格式化之。 */ public String format(T key, Object... args) { return format(key, null, args); } /** 取得指定在enum中所标注的、指定locale的消息串,并格式化之。 */ public String format(T key, Locale locale, Object... args) { ResourceBundle bundle = getBundle(locale); String strKey = String.valueOf(key); String message; try { message = format(bundle.getString(strKey), args); } catch (MissingResourceException e) { StringBuilder buffer = new StringBuilder(); buffer.append(strKey).append(": "); if (args != null && args.length > 0) { for (Object arg : args) { buffer.append(arg).append(", "); } } buffer.setLength(buffer.length() - 2); message = buffer.toString(); } return message; } private String format(String format, Object[] args) { format = StringUtil.trimToEmpty(format); if (args.length == 0) { return format; } else { return java.text.MessageFormat.format(format, preprocess(args)); } } /** 预处理参数,使之更好地被显示。 */ protected final Object preprocess(Object o) { if (o == null) { return EMPTY_STRING; } else if (o instanceof Object[]) { return preprocess((Object[]) o); } else if (o instanceof Throwable) { return preprocess((Throwable) o); } else if (o instanceof Class<?>) { return preprocess((Class<?>) o); } else if (o instanceof Double) { double d = (Double) o; if (Double.isNaN(d) || Double.isInfinite(d)) { return o.toString(); } else { return o; } } else if (o instanceof Float) { float f = (Float) o; if (Float.isNaN(f) || Float.isInfinite(f)) { return o.toString(); } else { return o; } } else if (o instanceof Constructor<?>) { return preprocess((Constructor<?>) o); } else if (o instanceof Method) { return preprocess((Method) o); } else { return preprocessObject(o); } } /** 给子类预留接口,以便处理未知类型。 */ protected Object preprocessObject(Object o) { return o; } private Object[] preprocess(Object[] args) { for (int i = 0; i < args.length; i++) { args[i] = preprocess(args[i]); } return args; } private Object preprocess(Throwable t) { String message = t.getMessage(); if (message != null) { return getSimpleClassName(t.getClass()) + " - " + message; } else { return getSimpleClassName(t.getClass()); } } private Object preprocess(Class<?> c) { return getSimpleClassName(c); } private Object preprocess(Constructor<?> method) { try { return preprocessMethodOrConstructor(method.getModifiers(), null, method.getDeclaringClass(), null, method.getParameterTypes(), method.getExceptionTypes()); } catch (Exception e) { return "<" + e + ">"; } } private Object preprocess(Method method) { try { return preprocessMethodOrConstructor(method.getModifiers(), method.getReturnType(), method.getDeclaringClass(), method.getName(), method.getParameterTypes(), method.getExceptionTypes()); } catch (Exception e) { return "<" + e + ">"; } } private Object preprocessMethodOrConstructor(int mod, Class<?> returnType, Class<?> declaringClass, String methodName, Class<?>[] paramTypes, Class<?>[] exceptionTypes) { StringBuilder sb = new StringBuilder(); // return type if (returnType != null) { sb.append(getSimpleClassName(returnType)).append(" "); } // declaring class sb.append(getSimpleClassName(declaringClass)); // method name if (methodName != null) { sb.append(".").append(methodName); } sb.append("("); // params for (int i = 0; i < paramTypes.length; i++) { sb.append(getSimpleClassName(paramTypes[i])); if (i < paramTypes.length - 1) { sb.append(", "); } } sb.append(")"); // exceptions if (exceptionTypes.length > 0) { sb.append(" throws "); for (int i = 0; i < exceptionTypes.length; i++) { sb.append(getSimpleClassName(exceptionTypes[i])); if (i < exceptionTypes.length - 1) { sb.append(","); } } } return sb.toString(); } /** 取得默认的locale。 */ private static Locale getDefaultLocale() { Locale locale = null; if (defaultLocale != null) { locale = defaultLocale.get(); } if (locale == null) { locale = Locale.getDefault(); } return locale; } private static ThreadLocal<Locale> defaultLocale; /** 这个方法是给单元测试预留的,外面的程序不可用。 */ static void setDefaultLocale(Locale locale) { if (defaultLocale == null) { defaultLocale = new ThreadLocal<Locale>(); } defaultLocale.set(locale); } }