gu.sql2java.SimpleLog Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sql2java-base Show documentation
Show all versions of sql2java-base Show documentation
sql2java common class package
package gu.sql2java;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import gu.sql2java.utils.Platform;
/**
* 简单日志输出工具类
* @author guyadong
* @since 3.24.0
*
*/
public class SimpleLog {
/** 占位符 */
private static final String DELIM_STR = "(\\{\\}|%s)";
private static final Object[] EMPTY_ARGS = new Object[0];
private final static OutputString outputString = createOutputString();
private static OutputString createOutputString() {
if(Platform.isAndroid()){
return new AndroidOutput();
}else {
return new StandardOutput();
}
}
/**
* 返回格式化的日志信息字符串
* example:
*
* logString("name : {},age:{}","tom",23);
*
* @param format 格式字符串,采用"{}"或"%s"为占位符
* @param args 填充占位符的参数列表,如果数量小于占位符个数则多出的占位符填充"null"
*/
public static String logString(String format, Object ... args){
if(null == format){
return "";
}
if(null == args){
args = EMPTY_ARGS;
}
StringBuilder buffer = new StringBuilder(format.length() + 64);
int beginIndex = 0,count = 0;
Pattern pattern = Pattern.compile(DELIM_STR);
Matcher matcher = pattern.matcher(format);
while(matcher.find()){
buffer.append(format.substring(beginIndex,matcher.start()));
try{
buffer.append(args[count++]);
}catch(IndexOutOfBoundsException e){
// 数组越界时对应占位符填null
buffer.append("null");
}
beginIndex = matcher.end();
}
buffer.append(format.substring(beginIndex,format.length()));
return buffer.toString();
}
private static void log(PrintStream printStream,int level, String format, Object ... args){
if(null == printStream){
return;
}
Thread currentThread = Thread.currentThread();
StackTraceElement stackTrace = currentThread.getStackTrace()[level];
printStream.printf("[%s] (%s:%d) %s\n",
currentThread.getName(),
stackTrace.getFileName(),
stackTrace.getLineNumber(),
logString(format,args));
}
private static void log(OutputString outputString,Level level,String format, Object ... args){
if(null == outputString){
return;
}
Thread currentThread = Thread.currentThread();
StackTraceElement stackTrace = currentThread.getStackTrace()[outputString.stackLeve()];
outputString.log(level, String.format("[%s] (%s:%d) %s %s\n",
currentThread.getName(),
stackTrace.getFileName(),
stackTrace.getLineNumber(),
stackTrace.getMethodName(),
logString(format,args)));
}
/**
* 向{@code printStream}输出日志信息
* example:
*
* log("name : {},age:{}","tom",23);
*
* @param printStream
* @param format 格式字符串,采用"{}"或"%s"为占位符,占位符个数要与{@code args}数组长度匹配
* @param args 填充占位符的参数列表,如果数量小于占位符个数则多出的占位符填充"null"
*/
public static void log(PrintStream printStream,String format, Object ... args){
log(printStream,3,format,args);
}
/**
* @param output 是否输出
* @param printStream
* @param format 格式字符串
* @param args 填充占位符的参数列表
* @see #log(PrintStream, String, Object...)
*/
public static void log(boolean output,PrintStream printStream,String format, Object ... args){
if(output){
log(printStream,3,format,args);
}
}
private static final String formatByCount(int c){
StringBuffer buffer = new StringBuffer();
for(int i=0;i0){
buffer.append(",");
}
buffer.append("{}");
}
return buffer.toString();
}
/**
* 向控制台输出日志信息
* @param arg
* @see #log(OutputString, Level, String, Object...)
*/
public static void logObjects(Object arg){
log(outputString,Level.INFO,formatByCount(1),new Object[]{arg});
}
/**
* 向控制台输出日志信息
* @param arg
* @param args
* @see #log(PrintStream, String, Object...)
*/
public static void logObjects(Object arg,Object ... args){
Object[] array = new Object[args.length+1];
array[0] = arg;
System.arraycopy(args, 0, array, 1, args.length);
log(outputString,Level.INFO,formatByCount(args.length),array);
}
/**
* 向控制台输出日志信息
* @param format 格式字符串,采用"{}"或"%s"为占位符
* @param args
* @see #log(OutputString, Level, String, Object...)
*/
public static void log(String format, Object ... args){
log(outputString,Level.INFO,format,args);
}
/**
* 向控制台输出日志信息
* @param output 是否输出
* @param format 格式字符串,采用"{}"或"%s"为占位符
* @param args
* @see #log(OutputString, Level, String, Object...)
*/
public static void log(boolean output,String format, Object ... args){
if(output){
log(outputString,Level.INFO,format,args);
}
}
public static void log(String msg,Throwable e){
log(outputString,Level.ERROR,"{}\n{}",msg,stackTraceOf(e));
}
public static void log(Throwable e){
log(outputString,Level.ERROR,"{}",stackTraceOf(e));
}
public static final String stackTraceOf(Throwable e){
if(e == null){
e = new NullPointerException("e is null");
}
StringWriter writer = new StringWriter();
PrintWriter pw = new PrintWriter(writer);
e.printStackTrace(pw);
return writer.toString();
}
/**
* @author guyadong
* @see 2.8.0
*/
enum Level{
INFO,ERROR
}
/**
* 消息输出接口
* 应用层通过实现此接口实现日志输出
* @see StandardOutput
* @see AndroidOutput
* @author guyadong
* @see 2.8.0
*/
static interface OutputString{
/**
* 日志信息输出
* @param level 日志输出类型
* @param message 待输出日志信息
*/
void log(Level level, String message);
/**
* 返回输出行号类名所需要的堆栈级数
*/
int stackLeve();
}
/**
* 基于标准控制台输出的{@link OutputString}实现
* @author guyadong
* @see 2.8.0
*/
static class StandardOutput implements OutputString{
final Mapstreams;
public StandardOutput() {
streams = new HashMap<>();
streams.put(Level.INFO, System.out);
streams.put(Level.ERROR, System.err);
}
@Override
public void log(Level level, String message) {
streams.get(level).print(String.valueOf(message));
}
@Override
public int stackLeve() {
return 3;
}
}
/**
* android平台日志(android.util.Log)控制台输出的{@link OutputString}实现
* 非android平台调用会抛出{@link RuntimeException}异常
* @author guyadong
* @see 2.8.0
*/
static class AndroidOutput implements OutputString{
/** 默认日志标签 */
public static final String DEFAULT_TAG = "SIMPLE_LOG";
private final String defaultTag;
private final Mapmethods;
/**
* 构造方法
* @param defaultTag 日志输出标签名,为{@code null}使用默认值{@link #DEFAULT_TAG}
*/
public AndroidOutput(String defaultTag){
methods = new HashMap<>();
this.defaultTag = (null == defaultTag) ? DEFAULT_TAG : defaultTag;
methods.put(Level.INFO, methodOfLog("i"));
methods.put(Level.ERROR, methodOfLog("e"));
}
/**
* 使用默认日志标签的构造方法
*/
public AndroidOutput() {
this(null);
}
/** 反射方式获取 Log的指定方法 方法 */
static Method methodOfLog(String name) {
try {
Class> logClass = Class.forName("android.util.Log");
return logClass.getMethod(name, String.class,String.class);
} catch (ClassNotFoundException e) {
throw new UnsupportedOperationException("UNSUPPORTED PLATFORM,android reqiured");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void log(Level level, String message) {
try {
methods.get(level).invoke(null, defaultTag,String.valueOf(message));
} catch (InvocationTargetException e) {
throw new RuntimeException(e.getTargetException());
}catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public int stackLeve() {
return 4;
}
}
}