com.gitee.l0km.javadocreader.internal.SimpleLog Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javadocreader9 Show documentation
Show all versions of javadocreader9 Show documentation
read comments from java source using javadoc
package com.gitee.l0km.javadocreader.internal;
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;
/**
* 简单日志输出工具类
* @author guyadong
*
*/
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(isAndroid()){
return new AndroidOutput();
}else {
return new StandardOutput();
}
}
public static boolean isAndroid() {
String vmName = System.getProperty("java.vm.name");
if (vmName == null) { // default is false
return false;
}
String lowerVMName = vmName.toLowerCase();
return lowerVMName.contains("dalvik") //
|| lowerVMName.contains("lemur") // aliyun-vm name
;
}
/**
* 返回格式化的日志信息字符串
* 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();
}
public 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));
}
public 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;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy