The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .buildscript
    └── deploy.sh
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── README_ZH.md
├── build.gradle
├── gradle.properties
├── gradle
    └── wrapper
    │   ├── gradle-wrapper.jar
    │   └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── images
    ├── architecture.png
    ├── logcat-output.png
    └── qq_group.jpg
├── maven-push.gradle
├── settings.gradle
├── xlog-libcat
    ├── README.md
    ├── README_ZH.md
    ├── build.gradle
    ├── gradle.properties
    └── src
    │   └── main
    │       ├── AndroidManifest.xml
    │       └── java
    │           └── com
    │               └── elvishew
    │                   └── xlog
    │                       └── libcat
    │                           ├── LibCat.java
    │                           └── internal
    │                               ├── Cat.java
    │                               └── LogAspect.java
├── xlog-sample
    ├── .gitignore
    ├── build.gradle
    ├── proguard-rules.pro
    └── src
    │   └── main
    │       ├── AndroidManifest.xml
    │       ├── java
    │           └── com
    │           │   └── elvishew
    │           │       └── xlogsample
    │           │           ├── MainActivity.java
    │           │           ├── RecyclerViewPrinter.java
    │           │           └── XLogSampleApplication.java
    │       └── res
    │           ├── drawable-xxxhdpi
    │               └── ic_print_white_24dp.png
    │           ├── layout
    │               ├── activity_main.xml
    │               ├── dialog_change_tag.xml
    │               └── item_log.xml
    │           ├── mipmap-xxxhdpi
    │               └── ic_launcher.png
    │           └── values
    │               ├── arrays.xml
    │               ├── colors.xml
    │               ├── strings.xml
    │               └── styles.xml
└── xlog
    ├── .gitignore
    ├── build.gradle
    ├── gradle.properties
    ├── proguard-rules.pro
    └── src
        ├── main
            ├── AndroidManifest.xml
            └── java
            │   └── com
            │       └── elvishew
            │           └── xlog
            │               ├── LogConfiguration.java
            │               ├── LogItem.java
            │               ├── LogLevel.java
            │               ├── LogUtils.java
            │               ├── Logger.java
            │               ├── XLog.java
            │               ├── flattener
            │                   ├── ClassicFlattener.java
            │                   ├── DefaultFlattener.java
            │                   ├── Flattener.java
            │                   ├── Flattener2.java
            │                   └── PatternFlattener.java
            │               ├── formatter
            │                   ├── FormatException.java
            │                   ├── Formatter.java
            │                   ├── border
            │                   │   ├── BorderFormatter.java
            │                   │   └── DefaultBorderFormatter.java
            │                   ├── message
            │                   │   ├── json
            │                   │   │   ├── DefaultJsonFormatter.java
            │                   │   │   └── JsonFormatter.java
            │                   │   ├── object
            │                   │   │   ├── BundleFormatter.java
            │                   │   │   ├── IntentFormatter.java
            │                   │   │   └── ObjectFormatter.java
            │                   │   ├── throwable
            │                   │   │   ├── DefaultThrowableFormatter.java
            │                   │   │   └── ThrowableFormatter.java
            │                   │   └── xml
            │                   │   │   ├── DefaultXmlFormatter.java
            │                   │   │   └── XmlFormatter.java
            │                   ├── stacktrace
            │                   │   ├── DefaultStackTraceFormatter.java
            │                   │   └── StackTraceFormatter.java
            │                   └── thread
            │                   │   ├── DefaultThreadFormatter.java
            │                   │   └── ThreadFormatter.java
            │               ├── interceptor
            │                   ├── AbstractFilterInterceptor.java
            │                   ├── BlacklistTagsFilterInterceptor.java
            │                   ├── Interceptor.java
            │                   └── WhitelistTagsFilterInterceptor.java
            │               ├── internal
            │                   ├── DefaultsFactory.java
            │                   ├── Platform.java
            │                   ├── SystemCompat.java
            │                   ├── printer
            │                   │   └── file
            │                   │   │   └── backup
            │                   │   │       ├── BackupStrategyWrapper.java
            │                   │   │       └── BackupUtil.java
            │                   └── util
            │                   │   ├── ObjectToStringUtil.java
            │                   │   └── StackTraceUtil.java
            │               └── printer
            │                   ├── AndroidPrinter.java
            │                   ├── ConsolePrinter.java
            │                   ├── Printer.java
            │                   ├── PrinterSet.java
            │                   ├── RemotePrinter.java
            │                   ├── SystemPrinter.java
            │                   ├── file
            │                       ├── FilePrinter.java
            │                       ├── backup
            │                       │   ├── AbstractBackupStrategy.java
            │                       │   ├── BackupStrategy.java
            │                       │   ├── BackupStrategy2.java
            │                       │   ├── FileSizeBackupStrategy.java
            │                       │   ├── FileSizeBackupStrategy2.java
            │                       │   └── NeverBackupStrategy.java
            │                       ├── clean
            │                       │   ├── CleanStrategy.java
            │                       │   ├── FileLastModifiedCleanStrategy.java
            │                       │   └── NeverCleanStrategy.java
            │                       ├── naming
            │                       │   ├── ChangelessFileNameGenerator.java
            │                       │   ├── DateFileNameGenerator.java
            │                       │   ├── FileNameGenerator.java
            │                       │   └── LevelFileNameGenerator.java
            │                       └── writer
            │                       │   ├── SimpleWriter.java
            │                       │   └── Writer.java
            │                   └── flattener
            │                       ├── DefaultLogFlattener.java
            │                       └── LogFlattener.java
        └── test
            └── java
                └── com
                    └── elvishew
                        └── xlog
                            ├── AssertUtil.java
                            ├── ConcurrentTest.java
                            ├── ContainerPrinter.java
                            ├── RandomUtil.java
                            ├── XLogTest.java
                            ├── XLogUtil.java
                            ├── flattener
                                └── PatternFlattenerTest.java
                            ├── interceptor
                                ├── BlacklistTagsFilterInterceptorTest.java
                                └── WhitelistTagsFilterInterceptorTest.java
                            └── printer
                                ├── AndroidPrinterTest.java
                                └── file
                                    └── backup
                                        └── BackupTest.java


/.buildscript/deploy.sh:
--------------------------------------------------------------------------------
 1 | #!/bin/bash
 2 | #
 3 | # Deploy to Sonatype's repo.
 4 | #
 5 | # Adapted from https://github.com/JakeWharton/butterknife/blob/master/.buildscript/deploy_snapshot.sh 
 6 | 
 7 | SLUG="elvishew/xLog"
 8 | JDK="oraclejdk8"
 9 | BRANCH="master"
10 | 
11 | set -e
12 | 
13 | if [ "$TRAVIS_REPO_SLUG" != "$SLUG" ]; then
14 |   echo "Skipping snapshot deployment: wrong repository. Expected '$SLUG' but was '$TRAVIS_REPO_SLUG'."
15 | elif [ "$TRAVIS_JDK_VERSION" != "$JDK" ]; then
16 |   echo "Skipping snapshot deployment: wrong JDK. Expected '$JDK' but was '$TRAVIS_JDK_VERSION'."
17 | elif [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
18 |   echo "Skipping snapshot deployment: was pull request."
19 | elif [ "$TRAVIS_BRANCH" != "$BRANCH" ]; then
20 |   echo "Skipping snapshot deployment: wrong branch. Expected '$BRANCH' but was '$TRAVIS_BRANCH'."
21 | else
22 |   echo "Deploying..."
23 |   ./gradlew uploadArchives
24 |   echo "Deployed!"
25 | fi
26 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .idea
5 | .DS_Store
6 | build
7 | /captures
8 | 


--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
 1 | language: android
 2 | android:
 3 |   components:
 4 |     - tools
 5 |     - platform-tools
 6 |     - build-tools-29.0.3
 7 |     - android-29
 8 |     - extra-android-m2repository
 9 | 
10 | jdk:
11 |   - oraclejdk8
12 | 
13 | after_success:
14 |   - .buildscript/deploy.sh
15 | 
16 | sudo: false
17 | 
18 | cache:
19 |   directories:
20 |     - $HOME/.gradle


--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
 2 | 
 3 | buildscript {
 4 |     repositories {
 5 |         jcenter()
 6 |         google()
 7 |     }
 8 |     dependencies {
 9 |         classpath 'com.android.tools.build:gradle:4.0.1'
10 | 
11 |         // NOTE: Do not place your application dependencies here; they belong
12 |         // in the individual module build.gradle files
13 |     }
14 | }
15 | 
16 | allprojects {
17 |     repositories {
18 |         jcenter()
19 |         google()
20 |     }
21 | }
22 | 
23 | task clean(type: Delete) {
24 |     delete rootProject.buildDir
25 | }
26 | 


--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
 1 | # Project-wide Gradle settings.
 2 | 
 3 | # IDE (e.g. Android Studio) users:
 4 | # Gradle settings configured through the IDE *will override*
 5 | # any settings specified in this file.
 6 | 
 7 | # For more details on how to configure your build environment visit
 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
 9 | 
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 | 
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 | GROUP=com.elvishew
20 | 
21 | POM_URL=https://github.com/elvishew/XLog
22 | POM_SCM_URL=https://github.com/elvishew/XLog
23 | POM_SCM_CONNECTION=scm:git@github.com:elvishew/XLog.git
24 | POM_SCM_DEV_CONNECTION=scm:git@github.com:elvishew/XLog.git
25 | POM_LICENCE_NAME=The Apache Software License, Version 2.0
26 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
27 | POM_LICENCE_DIST=repo
28 | POM_DEVELOPER_ID=elvishew
29 | POM_DEVELOPER_NAME=Elvis Hew
30 | 
31 | android.useAndroidX=true
32 | android.enableJetifier=true


--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elvishew/xLog/3faa6b27a36fe93c71c1b475579f9f57a8698da3/gradle/wrapper/gradle-wrapper.jar


--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Jul 28 14:59:22 CST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
7 | 


--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
  1 | #!/usr/bin/env bash
  2 | 
  3 | ##############################################################################
  4 | ##
  5 | ##  Gradle start up script for UN*X
  6 | ##
  7 | ##############################################################################
  8 | 
  9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
 10 | DEFAULT_JVM_OPTS=""
 11 | 
 12 | APP_NAME="Gradle"
 13 | APP_BASE_NAME=`basename "$0"`
 14 | 
 15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
 16 | MAX_FD="maximum"
 17 | 
 18 | warn ( ) {
 19 |     echo "$*"
 20 | }
 21 | 
 22 | die ( ) {
 23 |     echo
 24 |     echo "$*"
 25 |     echo
 26 |     exit 1
 27 | }
 28 | 
 29 | # OS specific support (must be 'true' or 'false').
 30 | cygwin=false
 31 | msys=false
 32 | darwin=false
 33 | case "`uname`" in
 34 |   CYGWIN* )
 35 |     cygwin=true
 36 |     ;;
 37 |   Darwin* )
 38 |     darwin=true
 39 |     ;;
 40 |   MINGW* )
 41 |     msys=true
 42 |     ;;
 43 | esac
 44 | 
 45 | # Attempt to set APP_HOME
 46 | # Resolve links: $0 may be a link
 47 | PRG="$0"
 48 | # Need this for relative symlinks.
 49 | while [ -h "$PRG" ] ; do
 50 |     ls=`ls -ld "$PRG"`
 51 |     link=`expr "$ls" : '.*-> \(.*\)
#39;`
 52 |     if expr "$link" : '/.*' > /dev/null; then
 53 |         PRG="$link"
 54 |     else
 55 |         PRG=`dirname "$PRG"`"/$link"
 56 |     fi
 57 | done
 58 | SAVED="`pwd`"
 59 | cd "`dirname \"$PRG\"`/" >/dev/null
 60 | APP_HOME="`pwd -P`"
 61 | cd "$SAVED" >/dev/null
 62 | 
 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
 64 | 
 65 | # Determine the Java command to use to start the JVM.
 66 | if [ -n "$JAVA_HOME" ] ; then
 67 |     if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
 68 |         # IBM's JDK on AIX uses strange locations for the executables
 69 |         JAVACMD="$JAVA_HOME/jre/sh/java"
 70 |     else
 71 |         JAVACMD="$JAVA_HOME/bin/java"
 72 |     fi
 73 |     if [ ! -x "$JAVACMD" ] ; then
 74 |         die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
 75 | 
 76 | Please set the JAVA_HOME variable in your environment to match the
 77 | location of your Java installation."
 78 |     fi
 79 | else
 80 |     JAVACMD="java"
 81 |     which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
 82 | 
 83 | Please set the JAVA_HOME variable in your environment to match the
 84 | location of your Java installation."
 85 | fi
 86 | 
 87 | # Increase the maximum file descriptors if we can.
 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
 89 |     MAX_FD_LIMIT=`ulimit -H -n`
 90 |     if [ $? -eq 0 ] ; then
 91 |         if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
 92 |             MAX_FD="$MAX_FD_LIMIT"
 93 |         fi
 94 |         ulimit -n $MAX_FD
 95 |         if [ $? -ne 0 ] ; then
 96 |             warn "Could not set maximum file descriptor limit: $MAX_FD"
 97 |         fi
 98 |     else
 99 |         warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 |     fi
101 | fi
102 | 
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 |     GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 | 
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 |     APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 |     CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 |     JAVACMD=`cygpath --unix "$JAVACMD"`
113 | 
114 |     # We build the pattern for arguments to be converted via cygpath
115 |     ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 |     SEP=""
117 |     for dir in $ROOTDIRSRAW ; do
118 |         ROOTDIRS="$ROOTDIRS$SEP$dir"
119 |         SEP="|"
120 |     done
121 |     OURCYGPATTERN="(^($ROOTDIRS))"
122 |     # Add a user-defined pattern to the cygpath arguments
123 |     if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 |         OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 |     fi
126 |     # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 |     i=0
128 |     for arg in "$@" ; do
129 |         CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 |         CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
131 | 
132 |         if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
133 |             eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 |         else
135 |             eval `echo args$i`="\"$arg\""
136 |         fi
137 |         i=$((i+1))
138 |     done
139 |     case $i in
140 |         (0) set -- ;;
141 |         (1) set -- "$args0" ;;
142 |         (2) set -- "$args0" "$args1" ;;
143 |         (3) set -- "$args0" "$args1" "$args2" ;;
144 |         (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 |         (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 |         (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 |         (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 |         (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 |         (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 |     esac
151 | fi
152 | 
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 |     JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 | 
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 | 


--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
 1 | @if "%DEBUG%" == "" @echo off
 2 | @rem ##########################################################################
 3 | @rem
 4 | @rem  Gradle startup script for Windows
 5 | @rem
 6 | @rem ##########################################################################
 7 | 
 8 | @rem Set local scope for the variables with windows NT shell
 9 | if "%OS%"=="Windows_NT" setlocal
10 | 
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 | 
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 | 
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 | 
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 | 
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 | 
32 | goto fail
33 | 
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 | 
38 | if exist "%JAVA_EXE%" goto init
39 | 
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 | 
46 | goto fail
47 | 
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 | 
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 | 
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 | 
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 | 
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 | 
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 | 
69 | :execute
70 | @rem Setup the command line
71 | 
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 | 
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 | 
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 | 
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 | 
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 | 
90 | :omega
91 | 


--------------------------------------------------------------------------------
/images/architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elvishew/xLog/3faa6b27a36fe93c71c1b475579f9f57a8698da3/images/architecture.png


--------------------------------------------------------------------------------
/images/logcat-output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elvishew/xLog/3faa6b27a36fe93c71c1b475579f9f57a8698da3/images/logcat-output.png


--------------------------------------------------------------------------------
/images/qq_group.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elvishew/xLog/3faa6b27a36fe93c71c1b475579f9f57a8698da3/images/qq_group.jpg


--------------------------------------------------------------------------------
/maven-push.gradle:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2013 Chris Banes
  3 |  * Copyright 2021 Elvis Hew
  4 |  *
  5 |  * Licensed under the Apache License, Version 2.0 (the "License");
  6 |  * you may not use this file except in compliance with the License.
  7 |  * You may obtain a copy of the License at
  8 |  *
  9 |  *     http://www.apache.org/licenses/LICENSE-2.0
 10 |  *
 11 |  * Unless required by applicable law or agreed to in writing, software
 12 |  * distributed under the License is distributed on an "AS IS" BASIS,
 13 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14 |  * See the License for the specific language governing permissions and
 15 |  * limitations under the License.
 16 |  */
 17 | 
 18 | apply plugin: 'maven'
 19 | apply plugin: 'signing'
 20 | 
 21 | def isReleaseBuild() {
 22 |     return VERSION_NAME.contains("SNAPSHOT") == false
 23 | }
 24 | 
 25 | def getReleaseRepositoryUrl() {
 26 |     return hasProperty('RELEASE_REPOSITORY_URL') ? RELEASE_REPOSITORY_URL
 27 |             : "https://oss.sonatype.org/service/local/staging/deploy/maven2/"
 28 | }
 29 | 
 30 | def getSnapshotRepositoryUrl() {
 31 |     return hasProperty('SNAPSHOT_REPOSITORY_URL') ? SNAPSHOT_REPOSITORY_URL
 32 |             : "https://oss.sonatype.org/content/repositories/snapshots/"
 33 | }
 34 | 
 35 | def getRepositoryUsername() {
 36 |     return hasProperty('NEXUS_USERNAME') ? NEXUS_USERNAME : ""
 37 | }
 38 | 
 39 | def getRepositoryPassword() {
 40 |     return hasProperty('NEXUS_PASSWORD') ? NEXUS_PASSWORD : ""
 41 | }
 42 | 
 43 | afterEvaluate { project ->
 44 |     uploadArchives {
 45 |         repositories {
 46 |             mavenDeployer {
 47 |                 beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
 48 | 
 49 |                 pom.groupId = GROUP
 50 |                 pom.artifactId = POM_ARTIFACT_ID
 51 |                 pom.version = VERSION_NAME
 52 | 
 53 |                 repository(url: getReleaseRepositoryUrl()) {
 54 |                     authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
 55 |                 }
 56 |                 snapshotRepository(url: getSnapshotRepositoryUrl()) {
 57 |                     authentication(userName: getRepositoryUsername(), password: getRepositoryPassword())
 58 |                 }
 59 | 
 60 |                 pom.project {
 61 |                     name POM_NAME
 62 |                     packaging POM_PACKAGING
 63 |                     description POM_DESCRIPTION
 64 |                     url POM_URL
 65 | 
 66 |                     scm {
 67 |                         url POM_SCM_URL
 68 |                         connection POM_SCM_CONNECTION
 69 |                         developerConnection POM_SCM_DEV_CONNECTION
 70 |                     }
 71 | 
 72 |                     licenses {
 73 |                         license {
 74 |                             name POM_LICENCE_NAME
 75 |                             url POM_LICENCE_URL
 76 |                             distribution POM_LICENCE_DIST
 77 |                         }
 78 |                     }
 79 | 
 80 |                     developers {
 81 |                         developer {
 82 |                             id POM_DEVELOPER_ID
 83 |                             name POM_DEVELOPER_NAME
 84 |                         }
 85 |                     }
 86 |                 }
 87 |             }
 88 |         }
 89 |     }
 90 | 
 91 |     signing {
 92 |         required { isReleaseBuild() && gradle.taskGraph.hasTask("uploadArchives") }
 93 |         sign configurations.archives
 94 |     }
 95 | 
 96 |     task androidJavadocs(type: Javadoc) {
 97 |         source = android.sourceSets.main.java.srcDirs
 98 |         android.libraryVariants.all { variant ->
 99 |             if (variant.name == 'release') {
100 |                 owner.classpath += variant.javaCompiler.classpath
101 |                 if (JavaVersion.current().isJava8Compatible()) {
102 |                     options.addStringOption('Xdoclint:none', '-quiet')
103 |                 }
104 |             }
105 |         }
106 |         classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
107 |     }
108 | 
109 |     task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
110 |         classifier = 'javadoc'
111 |         from androidJavadocs.destinationDir
112 |     }
113 | 
114 |     task androidSourcesJar(type: Jar) {
115 |         classifier = 'sources'
116 |         from android.sourceSets.main.java.sourceFiles
117 |     }
118 | 
119 |     artifacts {
120 |         archives androidSourcesJar
121 |         archives androidJavadocsJar
122 |     }
123 | }


--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':xlog', ':xlog-libcat', ':xlog-sample'
2 | 


--------------------------------------------------------------------------------
/xlog-libcat/README.md:
--------------------------------------------------------------------------------
  1 | # LibCat
  2 | 
  3 | [简体中文](https://github.com/elvishew/XLog/blob/master/xlog-libcat/README_ZH.md)
  4 | 
  5 | Intercept the logs directly logged by `android.util.Log` within whole app's code, and redirect the logs to specified `Printer`.
  6 | 
  7 | Mostly, `LibCat` is used to intercept the logs from third party modules/libraries, and save the logs to the log file, by specifying a `FilePrinter`.
  8 | 
  9 | About `Printer`s, see more in [XLog].
 10 | 
 11 | ## Quick Start
 12 | 
 13 | Add in build.gradle
 14 | 
 15 | ```groovy
 16 | apply plugin: 'android-aspectjx'
 17 | 
 18 | android {
 19 |     compileOptions {
 20 |         sourceCompatibility JavaVersion.VERSION_1_8
 21 |         targetCompatibility JavaVersion.VERSION_1_8
 22 |     }
 23 | }
 24 | 
 25 | buildscript {
 26 |     repositories {
 27 |         jcenter()
 28 |         google()
 29 |     }
 30 |     dependencies {
 31 |         classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.10'
 32 |     }
 33 | }
 34 | 
 35 | aspectjx {
 36 |     // if you use kotlin in your project make sure to exclude `kotlin`,
 37 |     // otherwise a build error `zip file is empty` will be thrown
 38 |     exclude 'kotlin'
 39 | 
 40 |     // add 'exclude' packages/classes that you don't want to intercept the logs from
 41 |     exclude 'androidx.appcompat'
 42 |     exclude 'android.support'
 43 | 
 44 |     // or add 'include' packages/classes that you want to intercept the logs from
 45 | }
 46 | 
 47 | dependencies {
 48 |     implementation 'com.elvishew:xlog-libcat:1.0.0'
 49 | }
 50 | ```
 51 | 
 52 | Config when initializing app
 53 | 
 54 | ```java
 55 | LibCat.config(true, printer);
 56 | ```
 57 | 
 58 | Then, all future logs logged by `android.util.Log` will be redirected to `printer`.
 59 | 
 60 | ## Examples
 61 | 
 62 | * Logs in `logcat` and `printer`
 63 | 
 64 | ```java
 65 | LibCat.config(true, printer);
 66 | ```
 67 | 
 68 | * Logs in `logcat` only (exactly like the situation before using `LibCat`)
 69 | 
 70 | ```java
 71 | LibCat.config(true, null);
 72 | ```
 73 | 
 74 | * Logs in `printer` only
 75 | 
 76 | ```java
 77 | LibCat.config(false, printer);
 78 | ```
 79 | 
 80 | * Logs disappear totally
 81 | 
 82 | ```java
 83 | LibCat.config(false, null);
 84 | ```
 85 | 
 86 | ## References
 87 | 
 88 | [AspectJ]
 89 | 
 90 | [AspectJX]
 91 | 
 92 | ## Attention
 93 | During compiling app, [AspectJ] will remove all callings of `android.util.Log` and replace with `LibCat` logic. No source code will be changed, but only bytecode.
 94 | 
 95 | ## License
 96 | 
 97 | <pre>
 98 | Copyright 2021 Elvis Hew
 99 | 
100 | Licensed under the Apache License, Version 2.0 (the "License");
101 | you may not use this file except in compliance with the License.
102 | You may obtain a copy of the License at
103 | 
104 |    http://www.apache.org/licenses/LICENSE-2.0
105 | 
106 | Unless required by applicable law or agreed to in writing, software
107 | distributed under the License is distributed on an "AS IS" BASIS,
108 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
109 | See the License for the specific language governing permissions and
110 | limitations under the License.
111 | </pre>
112 | 
113 | [AspectJ]: https://www.eclipse.org/aspectj/
114 | [AspectJX]: https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx
115 | [Printer]: https://github.com/elvishew/XLog/blob/master/xlog/src/main/java/com/elvishew/xlog/printer/Printer.java
116 | [XLog]: https://github.com/elvishew/xLog/blob/master/README.md
117 | 


--------------------------------------------------------------------------------
/xlog-libcat/README_ZH.md:
--------------------------------------------------------------------------------
  1 | # LibCat
  2 | 
  3 | [English](https://github.com/elvishew/XLog/blob/master/xlog-libcat/README.md)
  4 | 
  5 | 拦截所有在 APP 代码里通过 `android.util.Log` 直接打印的日志,并把这些日志重定向到指定的 `Printer`。
  6 | 
  7 | 大多数情况下,`LibCat` 被用来拦截第三方模块/库的日志,并通过指定 `FilePrinter`,把这些日志保存到文件中。
  8 | 
  9 | 关于 `Printer`,请到 [XLog] 了解更多信息。
 10 | 
 11 | ## 快速开始
 12 | 
 13 | 在 build.gradle 添加
 14 | 
 15 | ```groovy
 16 | apply plugin: 'android-aspectjx'
 17 | 
 18 | android {
 19 |     compileOptions {
 20 |         sourceCompatibility JavaVersion.VERSION_1_8
 21 |         targetCompatibility JavaVersion.VERSION_1_8
 22 |     }
 23 | }
 24 | 
 25 | buildscript {
 26 |     repositories {
 27 |         jcenter()
 28 |         google()
 29 |     }
 30 |     dependencies {
 31 |         classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.10'
 32 |     }
 33 | }
 34 | 
 35 | aspectjx {
 36 |     // 如果你的项目中使用了 kotlin,确保 exclude `kotlin`,不然编译会报 zip file is empty
 37 |     exclude 'kotlin'
 38 | 
 39 |     // 添加 'exclude' 你不想拦截日志的包/类
 40 |     exclude 'androidx.appcompat'
 41 |     exclude 'android.support'
 42 | 
 43 |     // 或者:添加 'include' 你要拦截日志的包/类
 44 | }
 45 | 
 46 | dependencies {
 47 |     implementation 'com.elvishew:xlog-libcat:1.0.0'
 48 | }
 49 | ```
 50 | 
 51 | 在初始化 APP 时进行配置
 52 | 
 53 | ```java
 54 | LibCat.config(true, printer);
 55 | ```
 56 | 
 57 | 这样, 此后通过 `android.util.Log` 打印的所有日志将被重定向到 `printer`。
 58 | 
 59 | ## 示例
 60 | 
 61 | * 在 `logcat` 和 `printer` 中都有日志
 62 | 
 63 | ```java
 64 | LibCat.config(true, printer);
 65 | ```
 66 | 
 67 | * 只在 `logcat` 有日志 (和没有使用 `LibCat` 时一样的现象)
 68 | 
 69 | ```java
 70 | LibCat.config(true, null);
 71 | ```
 72 | 
 73 | * 只在 `printer` 有日志
 74 | 
 75 | ```java
 76 | LibCat.config(false, printer);
 77 | ```
 78 | 
 79 | * 日志彻底消失
 80 | 
 81 | ```java
 82 | LibCat.config(false, null);
 83 | ```
 84 | 
 85 | ## 参考
 86 | 
 87 | [AspectJ]
 88 | 
 89 | [AspectJX]
 90 | 
 91 | ## 注意
 92 | 在编译阶段,[AspectJ] 会移除所有对 `android.util.Log` 的调用,并替换成 `LibCat` 的相关逻辑。除了编译出的字节码外,所有源码不会被改变。
 93 | 
 94 | ## License
 95 | 
 96 | <pre>
 97 | Copyright 2021 Elvis Hew
 98 | 
 99 | Licensed under the Apache License, Version 2.0 (the "License");
100 | you may not use this file except in compliance with the License.
101 | You may obtain a copy of the License at
102 | 
103 |    http://www.apache.org/licenses/LICENSE-2.0
104 | 
105 | Unless required by applicable law or agreed to in writing, software
106 | distributed under the License is distributed on an "AS IS" BASIS,
107 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108 | See the License for the specific language governing permissions and
109 | limitations under the License.
110 | </pre>
111 | 
112 | [AspectJ]: https://www.eclipse.org/aspectj/
113 | [AspectJX]: https://github.com/HujiangTechnology/gradle_plugin_android_aspectjx
114 | [Printer]: https://github.com/elvishew/XLog/blob/master/xlog/src/main/java/com/elvishew/xlog/printer/Printer.java
115 | [XLog]: https://github.com/elvishew/xLog/blob/master/README_ZH.md
116 | 


--------------------------------------------------------------------------------
/xlog-libcat/build.gradle:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2021 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | apply plugin: 'com.android.library'
18 | apply from: '../maven-push.gradle'
19 | 
20 | android {
21 |     compileSdkVersion 29
22 |     buildToolsVersion "29.0.3"
23 | 
24 |     compileOptions {
25 |         sourceCompatibility JavaVersion.VERSION_1_8
26 |         targetCompatibility JavaVersion.VERSION_1_8
27 |     }
28 | 
29 |     defaultConfig {
30 |         minSdkVersion 14
31 |         targetSdkVersion 29
32 |     }
33 | 
34 |     buildTypes {
35 |         release {
36 |             minifyEnabled false
37 |             proguardFiles getDefaultProguardFile('proguard-android-optimize.txt')
38 |         }
39 |     }
40 | }
41 | 
42 | dependencies {
43 |     api 'com.elvishew:xlog:1.11.1'
44 |     api 'org.aspectj:aspectjrt:1.9.5'
45 | }


--------------------------------------------------------------------------------
/xlog-libcat/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=XLog: LibCat
2 | POM_ARTIFACT_ID=xlog-libcat
3 | POM_PACKAGING=jar
4 | POM_DESCRIPTION=Intercept the origin log and pass it to specific printer
5 | 
6 | VERSION_NAME=1.0.0
7 | VERSION_CODE=3
8 | 


--------------------------------------------------------------------------------
/xlog-libcat/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
 1 | <!--
 2 |   ~ Copyright 2021 Elvis Hew
 3 |   ~
 4 |   ~ Licensed under the Apache License, Version 2.0 (the "License");
 5 |   ~ you may not use this file except in compliance with the License.
 6 |   ~ You may obtain a copy of the License at
 7 |   ~
 8 |   ~     http://www.apache.org/licenses/LICENSE-2.0
 9 |   ~
10 |   ~ Unless required by applicable law or agreed to in writing, software
11 |   ~ distributed under the License is distributed on an "AS IS" BASIS,
12 |   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |   ~ See the License for the specific language governing permissions and
14 |   ~ limitations under the License.
15 |   -->
16 | 
17 | <manifest package="com.elvishew.xlog.libcat" />


--------------------------------------------------------------------------------
/xlog-libcat/src/main/java/com/elvishew/xlog/libcat/LibCat.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2021 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.libcat;
18 | 
19 | import com.elvishew.xlog.libcat.internal.Cat;
20 | import com.elvishew.xlog.printer.Printer;
21 | 
22 | /**
23 |  * Intercept the origin log logged by {@link android.util.Log}, and pass it to specific {@link Printer}.
24 |  * <p>
25 |  * Call {@link #config(boolean, Printer)} to config LibCat when initializing app.
26 |  * <p>
27 |  * Please note that LibCat only work after you apply the 'android-aspectjx' plugin in your app's 'build.gradle'.
28 |  */
29 | public class LibCat {
30 | 
31 |   /**
32 |    * Config LibCat.
33 |    *
34 |    * @param keepOriginLog whether the origin log logged by {@link android.util.Log} should be kept,
35 |    *                      which means you can still see them in 'logcat', default to be true
36 |    * @param output        specify a {@link Printer} to print the intercepted logs, can be null if
37 |    *                      there is no need to print the logs to other place
38 |    */
39 |   public static void config(boolean keepOriginLog, Printer output) {
40 |     Cat.keepOriginLog = keepOriginLog;
41 |     Cat.output = output;
42 |   }
43 | }
44 | 


--------------------------------------------------------------------------------
/xlog-libcat/src/main/java/com/elvishew/xlog/libcat/internal/Cat.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2021 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.libcat.internal;
18 | 
19 | import com.elvishew.xlog.printer.Printer;
20 | 
21 | /**
22 |  * Intercept the origin log logged by {@link android.util.Log}, and pass it to specific {@link Printer}.
23 |  */
24 | public class Cat {
25 | 
26 |   public static boolean keepOriginLog = true;
27 | 
28 |   public static Printer output;
29 | 
30 |   private Cat() {
31 |   }
32 | 
33 |   public static int v(String tag, String msg) {
34 |     return println(android.util.Log.VERBOSE, tag, msg);
35 |   }
36 | 
37 |   public static int v(String tag, String msg, Throwable tr) {
38 |     return println(android.util.Log.VERBOSE, tag, msg + '\n' + android.util.Log.getStackTraceString(tr));
39 |   }
40 | 
41 |   public static int d(String tag, String msg) {
42 |     return println(android.util.Log.DEBUG, tag, msg);
43 |   }
44 | 
45 |   public static int d(String tag, String msg, Throwable tr) {
46 |     return println(android.util.Log.DEBUG, tag, msg + '\n' + android.util.Log.getStackTraceString(tr));
47 |   }
48 | 
49 |   public static int i(String tag, String msg) {
50 |     return println(android.util.Log.INFO, tag, msg);
51 |   }
52 | 
53 |   public static int i(String tag, String msg, Throwable tr) {
54 |     return println(android.util.Log.INFO, tag, msg + '\n' + android.util.Log.getStackTraceString(tr));
55 |   }
56 | 
57 |   public static int w(String tag, String msg) {
58 |     return println(android.util.Log.WARN, tag, msg);
59 |   }
60 | 
61 |   public static int w(String tag, String msg, Throwable tr) {
62 |     return println(android.util.Log.WARN, tag, msg + '\n' + android.util.Log.getStackTraceString(tr));
63 |   }
64 | 
65 |   public static int w(String tag, Throwable tr) {
66 |     return println(android.util.Log.WARN, tag, android.util.Log.getStackTraceString(tr));
67 |   }
68 | 
69 |   public static int e(String tag, String msg) {
70 |     return println(android.util.Log.ERROR, tag, msg);
71 |   }
72 | 
73 |   public static int e(String tag, String msg, Throwable tr) {
74 |     return println(android.util.Log.ERROR, tag, msg + '\n' + android.util.Log.getStackTraceString(tr));
75 |   }
76 | 
77 |   public static int println(int priority, String tag, String msg) {
78 |     int ret = 0;
79 |     if (keepOriginLog) {
80 |       ret = android.util.Log.println(priority, tag, msg);
81 |     }
82 |     if (output != null) {
83 |       output.println(priority, tag, msg);
84 |     }
85 |     return ret;
86 |   }
87 | }
88 | 


--------------------------------------------------------------------------------
/xlog-libcat/src/main/java/com/elvishew/xlog/libcat/internal/LogAspect.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2021 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlog.libcat.internal;
 18 | 
 19 | import org.aspectj.lang.JoinPoint;
 20 | import org.aspectj.lang.annotation.Around;
 21 | import org.aspectj.lang.annotation.Aspect;
 22 | import org.aspectj.lang.annotation.Pointcut;
 23 | 
 24 | /**
 25 |  * Aspect all logging via {@link android.util.Log}.
 26 |  */
 27 | @Aspect
 28 | public class LogAspect {
 29 | 
 30 |   @Pointcut("within(com.elvishew.xlog..*)")
 31 |   public void withinXlog() {
 32 |   }
 33 | 
 34 |   @Pointcut("call(* android.util.Log.v(String, String))")
 35 |   public void call_Log_V_SS() {
 36 |   }
 37 | 
 38 |   @Pointcut("call(* android.util.Log.v(String, String, Throwable))")
 39 |   public void call_Log_V_SST() {
 40 |   }
 41 | 
 42 |   @Pointcut("call(* android.util.Log.d(String, String))")
 43 |   public void call_Log_D_SS() {
 44 |   }
 45 | 
 46 |   @Pointcut("call(* android.util.Log.d(String, String, Throwable))")
 47 |   public void call_Log_D_SST() {
 48 |   }
 49 | 
 50 |   @Pointcut("call(* android.util.Log.i(String, String))")
 51 |   public void call_Log_I_SS() {
 52 |   }
 53 | 
 54 |   @Pointcut("call(* android.util.Log.i(String, String, Throwable))")
 55 |   public void call_Log_I_SST() {
 56 |   }
 57 | 
 58 |   @Pointcut("call(* android.util.Log.w(String, String))")
 59 |   public void call_Log_W_SS() {
 60 |   }
 61 | 
 62 |   @Pointcut("call(* android.util.Log.w(String, String, Throwable))")
 63 |   public void call_Log_W_SST() {
 64 |   }
 65 | 
 66 |   @Pointcut("call(* android.util.Log.w(String, Throwable))")
 67 |   public void call_Log_W_ST() {
 68 |   }
 69 | 
 70 |   @Pointcut("call(* android.util.Log.e(String, String))")
 71 |   public void call_Log_E_SS() {
 72 |   }
 73 | 
 74 |   @Pointcut("call(* android.util.Log.e(String, String, Throwable))")
 75 |   public void call_Log_E_SST() {
 76 |   }
 77 | 
 78 |   @Pointcut("call(* android.util.Log.println(int, String, String))")
 79 |   public void call_Log_Println_ISS() {
 80 |   }
 81 | 
 82 |   @Around("call_Log_V_SS() && !withinXlog()")
 83 |   public int cat_Log_V_SS(JoinPoint joinPoint) {
 84 |     Object[] args = joinPoint.getArgs();
 85 |     return Cat.v((String) args[0], (String) args[1]);
 86 |   }
 87 | 
 88 |   @Around("call_Log_V_SST() && !withinXlog()")
 89 |   public int cat_Log_V_SST(JoinPoint joinPoint) {
 90 |     Object[] args = joinPoint.getArgs();
 91 |     return Cat.v((String) args[0], (String) args[1], (Throwable) args[2]);
 92 |   }
 93 | 
 94 |   @Around("call_Log_D_SS() && !withinXlog()")
 95 |   public int cat_Log_D_SS(JoinPoint joinPoint) {
 96 |     Object[] args = joinPoint.getArgs();
 97 |     return Cat.d((String) args[0], (String) args[1]);
 98 |   }
 99 | 
100 |   @Around("call_Log_D_SST() && !withinXlog()")
101 |   public int cat_Log_D_SST(JoinPoint joinPoint) {
102 |     Object[] args = joinPoint.getArgs();
103 |     return Cat.d((String) args[0], (String) args[1], (Throwable) args[2]);
104 |   }
105 | 
106 |   @Around("call_Log_I_SS() && !withinXlog()")
107 |   public int cat_Log_I_SS(JoinPoint joinPoint) {
108 |     Object[] args = joinPoint.getArgs();
109 |     return Cat.i((String) args[0], (String) args[1]);
110 |   }
111 | 
112 |   @Around("call_Log_I_SST() && !withinXlog()")
113 |   public int cat_Log_I_SST(JoinPoint joinPoint) {
114 |     Object[] args = joinPoint.getArgs();
115 |     return Cat.i((String) args[0], (String) args[1], (Throwable) args[2]);
116 |   }
117 | 
118 |   @Around("call_Log_W_SS() && !withinXlog()")
119 |   public int cat_Log_W_SS(JoinPoint joinPoint) {
120 |     Object[] args = joinPoint.getArgs();
121 |     return Cat.w((String) args[0], (String) args[1]);
122 |   }
123 | 
124 |   @Around("call_Log_W_SST() && !withinXlog()")
125 |   public int cat_Log_W_SST(JoinPoint joinPoint) {
126 |     Object[] args = joinPoint.getArgs();
127 |     return Cat.w((String) args[0], (String) args[1], (Throwable) args[2]);
128 |   }
129 | 
130 |   @Around("call_Log_W_ST() && !withinXlog()")
131 |   public int cat_Log_W_ST(JoinPoint joinPoint) {
132 |     Object[] args = joinPoint.getArgs();
133 |     return Cat.w((String) args[0], (Throwable) args[1]);
134 |   }
135 | 
136 |   @Around("call_Log_E_SS() && !withinXlog()")
137 |   public int cat_Log_E_SS(JoinPoint joinPoint) {
138 |     Object[] args = joinPoint.getArgs();
139 |     return Cat.e((String) args[0], (String) args[1]);
140 |   }
141 | 
142 |   @Around("call_Log_E_SST() && !withinXlog()")
143 |   public int cat_Log_E_SST(JoinPoint joinPoint) {
144 |     Object[] args = joinPoint.getArgs();
145 |     return Cat.e((String) args[0], (String) args[1], (Throwable) args[2]);
146 |   }
147 | 
148 |   @Around("call_Log_Println_ISS() && !withinXlog()")
149 |   public int cat_Log_Println_ISS(JoinPoint joinPoint) {
150 |     Object[] args = joinPoint.getArgs();
151 |     return Cat.println((Integer) args[0], (String) args[1], (String) args[2]);
152 |   }
153 | }
154 | 


--------------------------------------------------------------------------------
/xlog-sample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | 


--------------------------------------------------------------------------------
/xlog-sample/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'com.android.application'
 2 | apply plugin: 'android-aspectjx'
 3 | 
 4 | android {
 5 |     compileSdkVersion 29
 6 |     buildToolsVersion "29.0.3"
 7 | 
 8 |     compileOptions {
 9 |         sourceCompatibility JavaVersion.VERSION_1_8
10 |         targetCompatibility JavaVersion.VERSION_1_8
11 |     }
12 | 
13 |     defaultConfig {
14 |         applicationId "com.elvishew.xlogsample"
15 |         minSdkVersion 14
16 |         targetSdkVersion 29
17 |         versionCode 1
18 |         versionName "1.0"
19 |     }
20 |     buildTypes {
21 |         release {
22 |             minifyEnabled false
23 |             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
24 |         }
25 |     }
26 | }
27 | 
28 | buildscript {
29 |     repositories {
30 |         jcenter()
31 |         google()
32 |     }
33 |     dependencies {
34 |         classpath 'com.hujiang.aspectjx:gradle-android-plugin-aspectjx:2.0.10'
35 |     }
36 | }
37 | 
38 | aspectjx {
39 |     exclude 'androidx.appcompat'
40 |     exclude 'android.support'
41 | }
42 | 
43 | dependencies {
44 |     implementation 'com.elvishew:xlog:1.11.1'
45 |     implementation 'com.elvishew:xlog-libcat:1.0.0'
46 |     implementation fileTree(dir: 'libs', include: ['*.jar'])
47 |     implementation 'com.google.android.material:material:1.3.0-alpha02'
48 |     implementation 'androidx.appcompat:appcompat:1.3.0-alpha02'
49 |     implementation 'androidx.legacy:legacy-support-v4:1.0.0'
50 |     testImplementation 'junit:junit:4.12'
51 | }
52 | 


--------------------------------------------------------------------------------
/xlog-sample/proguard-rules.pro:
--------------------------------------------------------------------------------
 1 | # Add project specific ProGuard rules here.
 2 | # By default, the flags in this file are appended to flags specified
 3 | # in /Users/elvishew/Library/Android/sdk/tools/proguard/proguard-android.txt
 4 | # You can edit the include path and order by changing the proguardFiles
 5 | # directive in build.gradle.
 6 | #
 7 | # For more details, see
 8 | #   http://developer.android.com/guide/developing/tools/proguard.html
 9 | 
10 | # Add any project specific keep options here:
11 | 
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | #   public *;
17 | #}
18 | 


--------------------------------------------------------------------------------
/xlog-sample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?><!--
 2 |   ~ Copyright 2016 Elvis Hew
 3 |   ~
 4 |   ~ Licensed under the Apache License, Version 2.0 (the "License");
 5 |   ~ you may not use this file except in compliance with the License.
 6 |   ~ You may obtain a copy of the License at
 7 |   ~
 8 |   ~     http://www.apache.org/licenses/LICENSE-2.0
 9 |   ~
10 |   ~ Unless required by applicable law or agreed to in writing, software
11 |   ~ distributed under the License is distributed on an "AS IS" BASIS,
12 |   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |   ~ See the License for the specific language governing permissions and
14 |   ~ limitations under the License.
15 |   -->
16 | 
17 | <manifest package="com.elvishew.xlogsample"
18 |     xmlns:android="http://schemas.android.com/apk/res/android">
19 | 
20 |     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
21 | 
22 |     <application
23 |         android:name=".XLogSampleApplication"
24 |         android:allowBackup="true"
25 |         android:icon="@mipmap/ic_launcher"
26 |         android:label="@string/app_name"
27 |         android:supportsRtl="true"
28 |         android:theme="@style/AppTheme">
29 |         <activity
30 |             android:name=".MainActivity"
31 |             android:screenOrientation="portrait"
32 |             android:theme="@style/AppTheme.NoActionBar">
33 |             <intent-filter>
34 |                 <action android:name="android.intent.action.MAIN" />
35 | 
36 |                 <category android:name="android.intent.category.LAUNCHER" />
37 |             </intent-filter>
38 |         </activity>
39 |     </application>
40 | 
41 | </manifest>


--------------------------------------------------------------------------------
/xlog-sample/src/main/java/com/elvishew/xlogsample/RecyclerViewPrinter.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2016 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlogsample;
 18 | 
 19 | import android.view.LayoutInflater;
 20 | import android.view.View;
 21 | import android.view.ViewGroup;
 22 | import android.widget.TextView;
 23 | 
 24 | import androidx.recyclerview.widget.LinearLayoutManager;
 25 | import androidx.recyclerview.widget.RecyclerView;
 26 | 
 27 | import com.elvishew.xlog.LogLevel;
 28 | import com.elvishew.xlog.flattener.Flattener2;
 29 | import com.elvishew.xlog.flattener.PatternFlattener;
 30 | import com.elvishew.xlog.printer.Printer;
 31 | 
 32 | import java.util.ArrayList;
 33 | import java.util.List;
 34 | 
 35 | /**
 36 |  * Display logs in a {@link androidx.recyclerview.widget.RecyclerView}.
 37 |  */
 38 | public class RecyclerViewPrinter implements Printer {
 39 | 
 40 |   private RecyclerView recyclerView;
 41 | 
 42 |   private LogAdapter adapter;
 43 | 
 44 |   public RecyclerViewPrinter(RecyclerView recyclerView) {
 45 |     // Setup the recycler view.
 46 |     adapter = new LogAdapter(LayoutInflater.from(recyclerView.getContext()));
 47 |     LinearLayoutManager layoutManager = new LinearLayoutManager(recyclerView.getContext());
 48 |     recyclerView.setLayoutManager(layoutManager);
 49 |     recyclerView.setAdapter(adapter);
 50 | 
 51 |     this.recyclerView = recyclerView;
 52 |   }
 53 | 
 54 |   @Override
 55 |   public void println(int logLevel, String tag, String msg) {
 56 |     // Append the log the the recycler view.
 57 |     adapter.addLog(new LogItem(System.currentTimeMillis(), logLevel, tag, msg));
 58 | 
 59 |     // Scroll to the bottom so we can see the newly-printed log.
 60 |     recyclerView.scrollToPosition(adapter.getItemCount() - 1);
 61 |   }
 62 | 
 63 |   private static class LogItem {
 64 | 
 65 |     static Flattener2 flattener = new PatternFlattener("{d HH:mm:ss.SSS} {l}/{t}: ");
 66 | 
 67 |     long timeMillis;
 68 |     int logLevel;
 69 |     String tag;
 70 |     String msg;
 71 | 
 72 |     private String label;
 73 | 
 74 |     LogItem(long timeMillis, int logLevel, String tag, String msg) {
 75 |       this.timeMillis = timeMillis;
 76 |       this.logLevel = logLevel;
 77 |       this.tag = tag;
 78 |       this.msg = msg;
 79 |     }
 80 | 
 81 |     /**
 82 |      * Get the label, with formatted time, log level and tag.
 83 |      */
 84 |     String getLabel() {
 85 |       // Lazily concat the label.
 86 |       if (label == null) {
 87 |         label = flattener.flatten(timeMillis, logLevel, tag, msg).toString();
 88 |       }
 89 |       return label;
 90 |     }
 91 |   }
 92 | 
 93 |   private static class LogAdapter extends RecyclerView.Adapter<LogViewHolder> {
 94 | 
 95 |     private LayoutInflater inflater;
 96 | 
 97 |     private List<LogItem> logs = new ArrayList<>();
 98 | 
 99 |     LogAdapter(LayoutInflater inflater) {
100 |       this.inflater = inflater;
101 |     }
102 | 
103 |     void addLog(LogItem logItem) {
104 |       logs.add(logItem);
105 |       notifyItemInserted(logs.size() - 1);
106 |     }
107 | 
108 |     @Override
109 |     public LogViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
110 |       View itemView = inflater.inflate(R.layout.item_log, parent, false);
111 |       return new LogViewHolder(itemView);
112 |     }
113 | 
114 |     @Override
115 |     public void onBindViewHolder(LogViewHolder holder, int position) {
116 |       LogItem logItem = logs.get(position);
117 | 
118 |       // Set color according to different log level.
119 |       int color = getHighlightColor(logItem.logLevel);
120 |       holder.labelView.setTextColor(color);
121 |       holder.messageView.setTextColor(color);
122 | 
123 |       // Display label and message.
124 |       holder.labelView.setText(logItem.getLabel());
125 |       holder.messageView.setText(logItem.msg);
126 |     }
127 | 
128 |     /**
129 |      * Get the highlight color for specific log level.
130 |      *
131 |      * @param logLevel the specific log level
132 |      * @return the highlight color
133 |      */
134 |     private int getHighlightColor(int logLevel) {
135 |       int hightlightColor;
136 |       switch (logLevel) {
137 |         case LogLevel.VERBOSE:
138 |           hightlightColor = 0xffbbbbbb;
139 |           break;
140 |         case LogLevel.DEBUG:
141 |           hightlightColor = 0xffffffff;
142 |           break;
143 |         case LogLevel.INFO:
144 |           hightlightColor = 0xff6a8759;
145 |           break;
146 |         case LogLevel.WARN:
147 |           hightlightColor = 0xffbbb529;
148 |           break;
149 |         case LogLevel.ERROR:
150 |           hightlightColor = 0xffff6b68;
151 |           break;
152 |         default:
153 |           hightlightColor = 0xffffff00;
154 |           break;
155 |       }
156 |       return hightlightColor;
157 |     }
158 | 
159 |     @Override
160 |     public int getItemCount() {
161 |       return logs.size();
162 |     }
163 |   }
164 | 
165 |   private static class LogViewHolder extends RecyclerView.ViewHolder {
166 | 
167 |     TextView labelView;
168 |     TextView messageView;
169 | 
170 |     LogViewHolder(View itemView) {
171 |       super(itemView);
172 |       labelView = (TextView) itemView.findViewById(R.id.label);
173 |       messageView = (TextView) itemView.findViewById(R.id.message);
174 |     }
175 |   }
176 | }
177 | 


--------------------------------------------------------------------------------
/xlog-sample/src/main/java/com/elvishew/xlogsample/XLogSampleApplication.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2016 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlogsample;
 18 | 
 19 | import android.app.Application;
 20 | import android.os.Build;
 21 | 
 22 | import com.elvishew.xlog.LogConfiguration;
 23 | import com.elvishew.xlog.LogLevel;
 24 | import com.elvishew.xlog.XLog;
 25 | import com.elvishew.xlog.flattener.ClassicFlattener;
 26 | import com.elvishew.xlog.interceptor.BlacklistTagsFilterInterceptor;
 27 | import com.elvishew.xlog.libcat.LibCat;
 28 | import com.elvishew.xlog.printer.AndroidPrinter;
 29 | import com.elvishew.xlog.printer.Printer;
 30 | import com.elvishew.xlog.printer.file.FilePrinter;
 31 | import com.elvishew.xlog.printer.file.naming.DateFileNameGenerator;
 32 | import com.elvishew.xlog.printer.file.writer.SimpleWriter;
 33 | 
 34 | import java.io.File;
 35 | 
 36 | public class XLogSampleApplication extends Application {
 37 | 
 38 |   public static Printer globalFilePrinter;
 39 | 
 40 |   private static final long MAX_TIME = 1000 * 60 * 60 * 24 * 2; // two days
 41 | 
 42 |   @Override
 43 |   public void onCreate() {
 44 |     super.onCreate();
 45 | 
 46 |     initXlog();
 47 |   }
 48 | 
 49 |   /**
 50 |    * Initialize XLog.
 51 |    */
 52 |   private void initXlog() {
 53 |     LogConfiguration config = new LogConfiguration.Builder()
 54 |         .logLevel(BuildConfig.DEBUG ? LogLevel.ALL             // Specify log level, logs below this level won't be printed, default: LogLevel.ALL
 55 |             : LogLevel.NONE)
 56 |         .tag(getString(R.string.global_tag))                   // Specify TAG, default: "X-LOG"
 57 |         // .enableThreadInfo()                                 // Enable thread info, disabled by default
 58 |         // .enableStackTrace(2)                                // Enable stack trace info with depth 2, disabled by default
 59 |         // .enableBorder()                                     // Enable border, disabled by default
 60 |         // .jsonFormatter(new MyJsonFormatter())               // Default: DefaultJsonFormatter
 61 |         // .xmlFormatter(new MyXmlFormatter())                 // Default: DefaultXmlFormatter
 62 |         // .throwableFormatter(new MyThrowableFormatter())     // Default: DefaultThrowableFormatter
 63 |         // .threadFormatter(new MyThreadFormatter())           // Default: DefaultThreadFormatter
 64 |         // .stackTraceFormatter(new MyStackTraceFormatter())   // Default: DefaultStackTraceFormatter
 65 |         // .borderFormatter(new MyBoardFormatter())            // Default: DefaultBorderFormatter
 66 |         // .addObjectFormatter(AnyClass.class,                 // Add formatter for specific class of object
 67 |         //     new AnyClassObjectFormatter())                  // Use Object.toString() by default
 68 |         .addInterceptor(new BlacklistTagsFilterInterceptor(    // Add blacklist tags filter
 69 |             "blacklist1", "blacklist2", "blacklist3"))
 70 |         // .addInterceptor(new WhitelistTagsFilterInterceptor( // Add whitelist tags filter
 71 |         //     "whitelist1", "whitelist2", "whitelist3"))
 72 |         // .addInterceptor(new MyInterceptor())                // Add a log interceptor
 73 |         .build();
 74 | 
 75 |     Printer androidPrinter = new AndroidPrinter();             // Printer that print the log using android.util.Log
 76 |     Printer filePrinter = new FilePrinter                      // Printer that print the log to the file system
 77 |         .Builder(new File(getExternalCacheDir().getAbsolutePath(), "log").getPath())       // Specify the path to save log file
 78 |         .fileNameGenerator(new DateFileNameGenerator())        // Default: ChangelessFileNameGenerator("log")
 79 |         // .backupStrategy(new MyBackupStrategy())             // Default: FileSizeBackupStrategy(1024 * 1024)
 80 |         // .cleanStrategy(new FileLastModifiedCleanStrategy(MAX_TIME))     // Default: NeverCleanStrategy()
 81 |         .flattener(new ClassicFlattener())                     // Default: DefaultFlattener
 82 |         .writer(new SimpleWriter() {                           // Default: SimpleWriter
 83 |           @Override
 84 |           public void onNewFileCreated(File file) {
 85 |             super.onNewFileCreated(file);
 86 |             final String header = "\n>>>>>>>>>>>>>>>> File Header >>>>>>>>>>>>>>>>" +
 87 |                     "\nDevice Manufacturer: " + Build.MANUFACTURER +
 88 |                     "\nDevice Model       : " + Build.MODEL +
 89 |                     "\nAndroid Version    : " + Build.VERSION.RELEASE +
 90 |                     "\nAndroid SDK        : " + Build.VERSION.SDK_INT +
 91 |                     "\nApp VersionName    : " + BuildConfig.VERSION_NAME +
 92 |                     "\nApp VersionCode    : " + BuildConfig.VERSION_CODE +
 93 |                     "\n<<<<<<<<<<<<<<<< File Header <<<<<<<<<<<<<<<<\n\n";
 94 |             appendLog(header);
 95 |           }
 96 |         })
 97 |         .build();
 98 | 
 99 |     XLog.init(                                                 // Initialize XLog
100 |         config,                                                // Specify the log configuration, if not specified, will use new LogConfiguration.Builder().build()
101 |         androidPrinter,                                        // Specify printers, if no printer is specified, AndroidPrinter(for Android)/ConsolePrinter(for java) will be used.
102 |         filePrinter);
103 | 
104 |     // For future usage: partial usage in MainActivity.
105 |     globalFilePrinter = filePrinter;
106 | 
107 |     // Intercept all logs(including logs logged by third party modules/libraries) and print them to file.
108 |     LibCat.config(true, filePrinter);
109 |   }
110 | }
111 | 


--------------------------------------------------------------------------------
/xlog-sample/src/main/res/drawable-xxxhdpi/ic_print_white_24dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elvishew/xLog/3faa6b27a36fe93c71c1b475579f9f57a8698da3/xlog-sample/src/main/res/drawable-xxxhdpi/ic_print_white_24dp.png


--------------------------------------------------------------------------------
/xlog-sample/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
  1 | <?xml version="1.0" encoding="utf-8"?><!--
  2 |   ~ Copyright 2016 Elvis Hew
  3 |   ~
  4 |   ~ Licensed under the Apache License, Version 2.0 (the "License");
  5 |   ~ you may not use this file except in compliance with the License.
  6 |   ~ You may obtain a copy of the License at
  7 |   ~
  8 |   ~     http://www.apache.org/licenses/LICENSE-2.0
  9 |   ~
 10 |   ~ Unless required by applicable law or agreed to in writing, software
 11 |   ~ distributed under the License is distributed on an "AS IS" BASIS,
 12 |   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |   ~ See the License for the specific language governing permissions and
 14 |   ~ limitations under the License.
 15 |   -->
 16 | <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
 17 |     xmlns:app="http://schemas.android.com/apk/res-auto"
 18 |     xmlns:tools="http://schemas.android.com/tools"
 19 |     android:layout_width="match_parent"
 20 |     android:layout_height="match_parent"
 21 |     tools:context=".MainActivity">
 22 | 
 23 |     <com.google.android.material.appbar.AppBarLayout
 24 |         android:layout_width="match_parent"
 25 |         android:layout_height="wrap_content"
 26 |         android:theme="@style/AppTheme.AppBarOverlay">
 27 | 
 28 |         <androidx.appcompat.widget.Toolbar
 29 |             android:id="@+id/toolbar"
 30 |             android:layout_width="match_parent"
 31 |             android:layout_height="?attr/actionBarSize"
 32 |             android:background="?attr/colorPrimary"
 33 |             app:popupTheme="@style/AppTheme.PopupOverlay" />
 34 |     </com.google.android.material.appbar.AppBarLayout>
 35 | 
 36 |     <LinearLayout
 37 |         android:layout_width="match_parent"
 38 |         android:layout_height="match_parent"
 39 |         android:layout_marginTop="?attr/actionBarSize"
 40 |         android:orientation="vertical"
 41 |         android:padding="16dp">
 42 | 
 43 |         <LinearLayout
 44 |             android:layout_width="match_parent"
 45 |             android:layout_height="wrap_content">
 46 | 
 47 |             <TextView
 48 |                 android:layout_width="wrap_content"
 49 |                 android:layout_height="wrap_content"
 50 |                 android:layout_gravity="center_vertical"
 51 |                 android:layout_marginEnd="16dp"
 52 |                 android:layout_marginRight="16dp"
 53 |                 android:text="@string/label_tag"
 54 |                 android:textColor="?android:attr/textColorPrimary" />
 55 | 
 56 |             <TextView
 57 |                 android:id="@+id/tag"
 58 |                 android:layout_width="match_parent"
 59 |                 android:layout_height="wrap_content"
 60 |                 android:layout_gravity="center_vertical"
 61 |                 android:gravity="end|right"
 62 |                 android:singleLine="true"
 63 |                 android:text="@string/global_tag"
 64 |                 android:textColor="?android:attr/textColorPrimary"
 65 |                 android:textSize="16dp" />
 66 |         </LinearLayout>
 67 | 
 68 |         <RelativeLayout
 69 |             android:layout_width="match_parent"
 70 |             android:layout_height="wrap_content">
 71 | 
 72 |             <TextView
 73 |                 android:layout_width="wrap_content"
 74 |                 android:layout_height="wrap_content"
 75 |                 android:layout_gravity="center_vertical"
 76 |                 android:text="@string/label_level"
 77 |                 android:textColor="?android:attr/textColorPrimary" />
 78 | 
 79 |             <Spinner
 80 |                 android:id="@+id/level"
 81 |                 android:layout_width="wrap_content"
 82 |                 android:layout_height="wrap_content"
 83 |                 android:layout_alignParentEnd="true"
 84 |                 android:layout_alignParentRight="true"
 85 |                 android:layout_gravity="center_vertical"
 86 |                 android:entries="@array/level_entries" />
 87 |         </RelativeLayout>
 88 | 
 89 |         <CheckedTextView
 90 |             android:id="@+id/thread_info"
 91 |             android:layout_width="match_parent"
 92 |             android:layout_height="wrap_content"
 93 |             android:checkMark="?android:attr/listChoiceIndicatorMultiple"
 94 |             android:gravity="center_vertical"
 95 |             android:text="@string/label_thread_info"
 96 |             android:textColor="?android:attr/textColorPrimary" />
 97 | 
 98 |         <CheckedTextView
 99 |             android:id="@+id/stack_trace_info"
100 |             android:layout_width="match_parent"
101 |             android:layout_height="wrap_content"
102 |             android:checkMark="?android:attr/listChoiceIndicatorMultiple"
103 |             android:gravity="center_vertical"
104 |             android:text="@string/label_stack_trace_info"
105 |             android:textColor="?android:attr/textColorPrimary" />
106 | 
107 |         <RelativeLayout
108 |             android:id="@+id/stack_trace_depth_container"
109 |             android:layout_width="match_parent"
110 |             android:layout_height="wrap_content">
111 | 
112 |             <TextView
113 |                 android:layout_width="wrap_content"
114 |                 android:layout_height="wrap_content"
115 |                 android:layout_gravity="center_vertical"
116 |                 android:text="@string/label_stack_trace_depth"
117 |                 android:textColor="?android:attr/textColorPrimary" />
118 | 
119 |             <Spinner
120 |                 android:id="@+id/stack_trace_depth"
121 |                 android:layout_width="wrap_content"
122 |                 android:layout_height="wrap_content"
123 |                 android:layout_alignParentEnd="true"
124 |                 android:layout_alignParentRight="true"
125 |                 android:layout_gravity="center_vertical"
126 |                 android:entries="@array/stack_trace_depth_entries" />
127 |         </RelativeLayout>
128 | 
129 |         <CheckedTextView
130 |             android:id="@+id/border"
131 |             android:layout_width="match_parent"
132 |             android:layout_height="wrap_content"
133 |             android:checkMark="?android:attr/listChoiceIndicatorMultiple"
134 |             android:gravity="center_vertical"
135 |             android:text="@string/label_border"
136 |             android:textColor="?android:attr/textColorPrimary" />
137 | 
138 |         <HorizontalScrollView
139 |             android:layout_width="match_parent"
140 |             android:layout_height="match_parent"
141 |             android:background="#ff000000">
142 | 
143 |             <androidx.recyclerview.widget.RecyclerView
144 |                 android:id="@+id/log_container"
145 |                 android:layout_width="wrap_content"
146 |                 android:layout_height="match_parent"
147 |                 android:clipToPadding="false"
148 |                 android:padding="5dp" />
149 |         </HorizontalScrollView>
150 |     </LinearLayout>
151 | 
152 |     <com.google.android.material.floatingactionbutton.FloatingActionButton
153 |         android:id="@+id/print"
154 |         android:layout_width="wrap_content"
155 |         android:layout_height="wrap_content"
156 |         android:layout_gravity="right|end|bottom"
157 |         android:layout_margin="16dp"
158 |         app:srcCompat="@drawable/ic_print_white_24dp" />
159 | 
160 | </FrameLayout>
161 | 


--------------------------------------------------------------------------------
/xlog-sample/src/main/res/layout/dialog_change_tag.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?><!--
 2 |   ~ Copyright 2016 Elvis Hew
 3 |   ~
 4 |   ~ Licensed under the Apache License, Version 2.0 (the "License");
 5 |   ~ you may not use this file except in compliance with the License.
 6 |   ~ You may obtain a copy of the License at
 7 |   ~
 8 |   ~     http://www.apache.org/licenses/LICENSE-2.0
 9 |   ~
10 |   ~ Unless required by applicable law or agreed to in writing, software
11 |   ~ distributed under the License is distributed on an "AS IS" BASIS,
12 |   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |   ~ See the License for the specific language governing permissions and
14 |   ~ limitations under the License.
15 |   -->
16 | 
17 | <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
18 |     android:layout_width="match_parent"
19 |     android:layout_height="wrap_content"
20 |     android:padding="16dp">
21 | 
22 |     <EditText
23 |         android:id="@+id/tag"
24 |         android:layout_width="match_parent"
25 |         android:layout_height="wrap_content"
26 |         android:inputType="text" />
27 | </FrameLayout>


--------------------------------------------------------------------------------
/xlog-sample/src/main/res/layout/item_log.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?><!--
 2 |   ~ Copyright 2016 Elvis Hew
 3 |   ~
 4 |   ~ Licensed under the Apache License, Version 2.0 (the "License");
 5 |   ~ you may not use this file except in compliance with the License.
 6 |   ~ You may obtain a copy of the License at
 7 |   ~
 8 |   ~     http://www.apache.org/licenses/LICENSE-2.0
 9 |   ~
10 |   ~ Unless required by applicable law or agreed to in writing, software
11 |   ~ distributed under the License is distributed on an "AS IS" BASIS,
12 |   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |   ~ See the License for the specific language governing permissions and
14 |   ~ limitations under the License.
15 |   -->
16 | 
17 | <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
18 |     android:layout_width="wrap_content"
19 |     android:layout_height="wrap_content">
20 | 
21 |     <TextView
22 |         android:id="@+id/label"
23 |         android:layout_width="wrap_content"
24 |         android:layout_height="wrap_content" />
25 | 
26 |     <TextView
27 |         android:id="@+id/message"
28 |         android:layout_width="wrap_content"
29 |         android:layout_height="wrap_content" />
30 | </LinearLayout>


--------------------------------------------------------------------------------
/xlog-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/elvishew/xLog/3faa6b27a36fe93c71c1b475579f9f57a8698da3/xlog-sample/src/main/res/mipmap-xxxhdpi/ic_launcher.png


--------------------------------------------------------------------------------
/xlog-sample/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?><!--
 2 |   ~ Copyright 2016 Elvis Hew
 3 |   ~
 4 |   ~ Licensed under the Apache License, Version 2.0 (the "License");
 5 |   ~ you may not use this file except in compliance with the License.
 6 |   ~ You may obtain a copy of the License at
 7 |   ~
 8 |   ~     http://www.apache.org/licenses/LICENSE-2.0
 9 |   ~
10 |   ~ Unless required by applicable law or agreed to in writing, software
11 |   ~ distributed under the License is distributed on an "AS IS" BASIS,
12 |   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |   ~ See the License for the specific language governing permissions and
14 |   ~ limitations under the License.
15 |   -->
16 | 
17 | <resources>
18 |     <string-array name="level_entries">
19 |         <item>VERBOSE</item>
20 |         <item>DEBUG</item>
21 |         <item>INFO</item>
22 |         <item>WARN</item>
23 |         <item>ERROR</item>
24 |     </string-array>
25 | 
26 |     <string-array name="stack_trace_depth_entries">
27 |         <item>No Limitation</item>
28 |         <item>1</item>
29 |         <item>2</item>
30 |         <item>3</item>
31 |         <item>4</item>
32 |         <item>5</item>
33 |     </string-array>
34 | </resources>


--------------------------------------------------------------------------------
/xlog-sample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?><!--
 2 |   ~ Copyright 2016 Elvis Hew
 3 |   ~
 4 |   ~ Licensed under the Apache License, Version 2.0 (the "License");
 5 |   ~ you may not use this file except in compliance with the License.
 6 |   ~ You may obtain a copy of the License at
 7 |   ~
 8 |   ~     http://www.apache.org/licenses/LICENSE-2.0
 9 |   ~
10 |   ~ Unless required by applicable law or agreed to in writing, software
11 |   ~ distributed under the License is distributed on an "AS IS" BASIS,
12 |   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |   ~ See the License for the specific language governing permissions and
14 |   ~ limitations under the License.
15 |   -->
16 | 
17 | <resources>
18 |     <color name="colorPrimary">#3F51B5</color>
19 |     <color name="colorPrimaryDark">#303F9F</color>
20 |     <color name="colorAccent">#FF4081</color>
21 | </resources>
22 | 


--------------------------------------------------------------------------------
/xlog-sample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?><!--
 2 |   ~ Copyright 2016 Elvis Hew
 3 |   ~
 4 |   ~ Licensed under the Apache License, Version 2.0 (the "License");
 5 |   ~ you may not use this file except in compliance with the License.
 6 |   ~ You may obtain a copy of the License at
 7 |   ~
 8 |   ~     http://www.apache.org/licenses/LICENSE-2.0
 9 |   ~
10 |   ~ Unless required by applicable law or agreed to in writing, software
11 |   ~ distributed under the License is distributed on an "AS IS" BASIS,
12 |   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |   ~ See the License for the specific language governing permissions and
14 |   ~ limitations under the License.
15 |   -->
16 | 
17 | <resources>
18 |     <string name="app_name">XLog Sample</string>
19 | 
20 |     <string name="global_tag" translatable="false">XLog</string>
21 | 
22 |     <string name="label_tag">Tag</string>
23 |     <string name="label_level">Level</string>
24 |     <string name="label_thread_info">Thread info</string>
25 |     <string name="label_stack_trace_info">Stack trace info</string>
26 |     <string name="label_stack_trace_depth">Stack trace depth</string>
27 |     <string name="label_border">Border</string>
28 | 
29 |     <string name="permission_request">Permission request</string>
30 |     <string name="permission_explanation">Logging to file need the write-external-storage permission.</string>
31 |     <string name="allow">Allow</string>
32 |     <string name="go_to_settings">Go to settings</string>
33 | 
34 |     <string name="change_tag">Change tag</string>
35 | </resources>
36 | 


--------------------------------------------------------------------------------
/xlog-sample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
 1 | <?xml version="1.0" encoding="utf-8"?><!--
 2 |   ~ Copyright 2016 Elvis Hew
 3 |   ~
 4 |   ~ Licensed under the Apache License, Version 2.0 (the "License");
 5 |   ~ you may not use this file except in compliance with the License.
 6 |   ~ You may obtain a copy of the License at
 7 |   ~
 8 |   ~     http://www.apache.org/licenses/LICENSE-2.0
 9 |   ~
10 |   ~ Unless required by applicable law or agreed to in writing, software
11 |   ~ distributed under the License is distributed on an "AS IS" BASIS,
12 |   ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |   ~ See the License for the specific language governing permissions and
14 |   ~ limitations under the License.
15 |   -->
16 | 
17 | <resources>
18 | 
19 |     <!-- Base application theme. -->
20 |     <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
21 |         <!-- Customize your theme here. -->
22 |         <item name="colorPrimary">@color/colorPrimary</item>
23 |         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
24 |         <item name="colorAccent">@color/colorAccent</item>
25 |     </style>
26 | 
27 |     <style name="AppTheme.NoActionBar">
28 |         <item name="windowActionBar">false</item>
29 |         <item name="windowNoTitle">true</item>
30 |     </style>
31 | 
32 |     <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
33 | 
34 |     <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
35 | 
36 | </resources>
37 | 


--------------------------------------------------------------------------------
/xlog/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 | 


--------------------------------------------------------------------------------
/xlog/build.gradle:
--------------------------------------------------------------------------------
 1 | apply plugin: 'com.android.library'
 2 | apply from: '../maven-push.gradle'
 3 | 
 4 | android {
 5 |     compileSdkVersion 29
 6 |     buildToolsVersion "29.0.3"
 7 | 
 8 |     defaultConfig {
 9 |         minSdkVersion 14
10 |         targetSdkVersion 29
11 |     }
12 |     buildTypes {
13 |         release {
14 |             minifyEnabled false
15 |             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
16 |         }
17 |     }
18 | }
19 | 
20 | dependencies {
21 |     implementation fileTree(dir: 'libs', include: ['*.jar'])
22 |     testImplementation 'junit:junit:4.12'
23 | }
24 | 


--------------------------------------------------------------------------------
/xlog/gradle.properties:
--------------------------------------------------------------------------------
1 | POM_NAME=XLog
2 | POM_ARTIFACT_ID=xlog
3 | POM_PACKAGING=jar
4 | POM_DESCRIPTION=Android logger, pretty, powerful and flexible, logging to file and everywhere
5 | 
6 | VERSION_NAME=1.11.1
7 | VERSION_CODE=20
8 | 


--------------------------------------------------------------------------------
/xlog/proguard-rules.pro:
--------------------------------------------------------------------------------
 1 | # Add project specific ProGuard rules here.
 2 | # By default, the flags in this file are appended to flags specified
 3 | # in /Users/elvishew/Library/Android/sdk/tools/proguard/proguard-android.txt
 4 | # You can edit the include path and order by changing the proguardFiles
 5 | # directive in build.gradle.
 6 | #
 7 | # For more details, see
 8 | #   http://developer.android.com/guide/developing/tools/proguard.html
 9 | 
10 | # Add any project specific keep options here:
11 | 
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | #   public *;
17 | #}
18 | 


--------------------------------------------------------------------------------
/xlog/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 | <manifest package="com.elvishew.xlog"/>
2 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/LogItem.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog;
18 | 
19 | /**
20 |  * Represent a single log going to be printed.
21 |  *
22 |  * @since 1.3.0
23 |  */
24 | public class LogItem {
25 | 
26 |   /**
27 |    * Level of the log.
28 |    *
29 |    * @see LogLevel
30 |    */
31 |   public int level;
32 | 
33 |   /**
34 |    * The tag, should not be null.
35 |    */
36 |   public String tag;
37 | 
38 |   /**
39 |    * The formatted message, should not be null.
40 |    */
41 |   public String msg;
42 | 
43 |   /**
44 |    * The formatted thread info, null if thread info is disabled.
45 |    *
46 |    * @see LogConfiguration.Builder#t()
47 |    * @see LogConfiguration.Builder#nt()
48 |    */
49 |   public String threadInfo;
50 | 
51 |   /**
52 |    * The formatted stack trace info, null if stack trace info is disabled.
53 |    *
54 |    * @see LogConfiguration.Builder#st(int)
55 |    * @see LogConfiguration.Builder#nst()
56 |    */
57 |   public String stackTraceInfo;
58 | 
59 |   public LogItem(int level, String tag, String msg) {
60 |     this.level = level;
61 |     this.tag = tag;
62 |     this.msg = msg;
63 |   }
64 | 
65 |   public LogItem(int level, String tag, String threadInfo, String stackTraceInfo, String msg) {
66 |     this.level = level;
67 |     this.tag = tag;
68 |     this.threadInfo = threadInfo;
69 |     this.stackTraceInfo = stackTraceInfo;
70 |     this.msg = msg;
71 |   }
72 | }
73 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/LogLevel.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2015 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlog;
 18 | 
 19 | /**
 20 |  * Log level indicate how important the log is.
 21 |  * <p>
 22 |  * Usually when we log a message, we also specify the log level explicitly or implicitly,
 23 |  * so if we setup a log level using <code>XLog.init(...)</code>, all the logs which is with
 24 |  * a log level smaller than the setup one would not be printed.
 25 |  * <p>
 26 |  * The priority of log levels is: {@link #VERBOSE} &lt; {@link #DEBUG} &lt; {@link #INFO} &lt;
 27 |  * {@link #WARN} &lt; {@link #ERROR}.
 28 |  * <br>And there are two special log levels which are usually used for Log#init:
 29 |  * {@link #NONE} and {@link #ALL}, {@link #NONE} for not printing any log and {@link #ALL} for
 30 |  * printing all logs.
 31 |  *
 32 |  * @see #VERBOSE
 33 |  * @see #DEBUG
 34 |  * @see #INFO
 35 |  * @see #WARN
 36 |  * @see #ERROR
 37 |  * @see #NONE
 38 |  * @see #ALL
 39 |  */
 40 | public class LogLevel {
 41 | 
 42 |   /**
 43 |    * Log level for XLog.v.
 44 |    */
 45 |   public static final int VERBOSE = 2;
 46 | 
 47 |   /**
 48 |    * Log level for XLog.d.
 49 |    */
 50 |   public static final int DEBUG = 3;
 51 | 
 52 |   /**
 53 |    * Log level for XLog.i.
 54 |    */
 55 |   public static final int INFO = 4;
 56 | 
 57 |   /**
 58 |    * Log level for XLog.w.
 59 |    */
 60 |   public static final int WARN = 5;
 61 | 
 62 |   /**
 63 |    * Log level for XLog.e.
 64 |    */
 65 |   public static final int ERROR = 6;
 66 | 
 67 |   /**
 68 |    * Log level for XLog#init, printing all logs.
 69 |    */
 70 |   public static final int ALL = Integer.MIN_VALUE;
 71 | 
 72 |   /**
 73 |    * Log level for XLog#init, printing no log.
 74 |    */
 75 |   public static final int NONE = Integer.MAX_VALUE;
 76 | 
 77 |   /**
 78 |    * Get a name representing the specified log level.
 79 |    * <p>
 80 |    * The returned name may be<br>
 81 |    * Level less than {@link LogLevel#VERBOSE}: "VERBOSE-N", N means levels below
 82 |    * {@link LogLevel#VERBOSE}<br>
 83 |    * {@link LogLevel#VERBOSE}: "VERBOSE"<br>
 84 |    * {@link LogLevel#DEBUG}: "DEBUG"<br>
 85 |    * {@link LogLevel#INFO}: "INFO"<br>
 86 |    * {@link LogLevel#WARN}: "WARN"<br>
 87 |    * {@link LogLevel#ERROR}: "ERROR"<br>
 88 |    * Level greater than {@link LogLevel#ERROR}: "ERROR+N", N means levels above
 89 |    * {@link LogLevel#ERROR}
 90 |    *
 91 |    * @param logLevel the log level to get name for
 92 |    * @return the name
 93 |    */
 94 |   public static String getLevelName(int logLevel) {
 95 |     String levelName;
 96 |     switch (logLevel) {
 97 |       case VERBOSE:
 98 |         levelName = "VERBOSE";
 99 |         break;
100 |       case DEBUG:
101 |         levelName = "DEBUG";
102 |         break;
103 |       case INFO:
104 |         levelName = "INFO";
105 |         break;
106 |       case WARN:
107 |         levelName = "WARN";
108 |         break;
109 |       case ERROR:
110 |         levelName = "ERROR";
111 |         break;
112 |       default:
113 |         if (logLevel < VERBOSE) {
114 |           levelName = "VERBOSE-" + (VERBOSE - logLevel);
115 |         } else {
116 |           levelName = "ERROR+" + (logLevel - ERROR);
117 |         }
118 |         break;
119 |     }
120 |     return levelName;
121 |   }
122 | 
123 |   /**
124 |    * Get a short name representing the specified log level.
125 |    * <p>
126 |    * The returned name may be<br>
127 |    * Level less than {@link LogLevel#VERBOSE}: "V-N", N means levels below
128 |    * {@link LogLevel#VERBOSE}<br>
129 |    * {@link LogLevel#VERBOSE}: "V"<br>
130 |    * {@link LogLevel#DEBUG}: "D"<br>
131 |    * {@link LogLevel#INFO}: "I"<br>
132 |    * {@link LogLevel#WARN}: "W"<br>
133 |    * {@link LogLevel#ERROR}: "E"<br>
134 |    * Level greater than {@link LogLevel#ERROR}: "E+N", N means levels above
135 |    * {@link LogLevel#ERROR}
136 |    *
137 |    * @param logLevel the log level to get short name for
138 |    * @return the short name
139 |    */
140 |   public static String getShortLevelName(int logLevel) {
141 |     String levelName;
142 |     switch (logLevel) {
143 |       case VERBOSE:
144 |         levelName = "V";
145 |         break;
146 |       case DEBUG:
147 |         levelName = "D";
148 |         break;
149 |       case INFO:
150 |         levelName = "I";
151 |         break;
152 |       case WARN:
153 |         levelName = "W";
154 |         break;
155 |       case ERROR:
156 |         levelName = "E";
157 |         break;
158 |       default:
159 |         if (logLevel < VERBOSE) {
160 |           levelName = "V-" + (VERBOSE - logLevel);
161 |         } else {
162 |           levelName = "E+" + (logLevel - ERROR);
163 |         }
164 |         break;
165 |     }
166 |     return levelName;
167 |   }
168 | }
169 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/LogUtils.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2016 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlog;
 18 | 
 19 | import java.io.BufferedInputStream;
 20 | import java.io.BufferedOutputStream;
 21 | import java.io.File;
 22 | import java.io.FileInputStream;
 23 | import java.io.FileOutputStream;
 24 | import java.io.IOException;
 25 | import java.util.zip.ZipEntry;
 26 | import java.util.zip.ZipOutputStream;
 27 | 
 28 | import static com.elvishew.xlog.XLog.assertInitialization;
 29 | 
 30 | /**
 31 |  * Utilities for convenience.
 32 |  *
 33 |  * @since 1.2.0
 34 |  */
 35 | public class LogUtils {
 36 | 
 37 |   /**
 38 |    * Format a JSON string using default JSON formatter.
 39 |    *
 40 |    * @param json the JSON string to format
 41 |    * @return the formatted string
 42 |    */
 43 |   public static String formatJson(String json) {
 44 |     assertInitialization();
 45 |     return XLog.sLogConfiguration.jsonFormatter.format(json);
 46 |   }
 47 | 
 48 |   /**
 49 |    * Format an XML string using default XML formatter.
 50 |    *
 51 |    * @param xml the XML string to format
 52 |    * @return the formatted string
 53 |    */
 54 |   public static String formatXml(String xml) {
 55 |     assertInitialization();
 56 |     return XLog.sLogConfiguration.xmlFormatter.format(xml);
 57 |   }
 58 | 
 59 |   /**
 60 |    * Format a throwable using default throwable formatter.
 61 |    *
 62 |    * @param throwable the throwable to format
 63 |    * @return the formatted string
 64 |    */
 65 |   public static String formatThrowable(Throwable throwable) {
 66 |     assertInitialization();
 67 |     return XLog.sLogConfiguration.throwableFormatter.format(throwable);
 68 |   }
 69 | 
 70 |   /**
 71 |    * Format a thread using default thread formatter.
 72 |    *
 73 |    * @param thread the thread to format
 74 |    * @return the formatted string
 75 |    */
 76 |   public static String formatThread(Thread thread) {
 77 |     assertInitialization();
 78 |     return XLog.sLogConfiguration.threadFormatter.format(thread);
 79 |   }
 80 | 
 81 |   /**
 82 |    * Format a stack trace using default stack trace formatter.
 83 |    *
 84 |    * @param stackTrace the stack trace to format
 85 |    * @return the formatted string
 86 |    */
 87 |   public static String formatStackTrace(StackTraceElement[] stackTrace) {
 88 |     assertInitialization();
 89 |     return XLog.sLogConfiguration.stackTraceFormatter.format(stackTrace);
 90 |   }
 91 | 
 92 |   /**
 93 |    * Add border to string segments using default border formatter.
 94 |    *
 95 |    * @param segments the string segments to add border to
 96 |    * @return the bordered string segments
 97 |    */
 98 |   public static String addBorder(String[] segments) {
 99 |     assertInitialization();
100 |     return XLog.sLogConfiguration.borderFormatter.format(segments);
101 |   }
102 | 
103 |   /**
104 |    * Compress all files under the specific folder to a single zip file.
105 |    * <p>
106 |    * Should be call in background thread.
107 |    *
108 |    * @param folderPath  the specific folder path
109 |    * @param zipFilePath the zip file path
110 |    * @throws IOException if any error occurs
111 |    * @since 1.4.0
112 |    */
113 |   public static void compress(String folderPath, String zipFilePath) throws IOException {
114 |     File folder = new File(folderPath);
115 |     if (!folder.exists() || !folder.isDirectory()) {
116 |       throw new IOException("Folder " + folderPath + " does't exist or isn't a directory");
117 |     }
118 | 
119 |     File zipFile = new File(zipFilePath);
120 |     if (!zipFile.exists()) {
121 |       File zipFolder = zipFile.getParentFile();
122 |       if (!zipFolder.exists()) {
123 |         if (!zipFolder.mkdirs()) {
124 |           throw new IOException("Zip folder " + zipFolder.getAbsolutePath() + " not created");
125 |         }
126 |       }
127 |       if (!zipFile.createNewFile()) {
128 |         throw new IOException("Zip file " + zipFilePath + " not created");
129 |       }
130 |     }
131 | 
132 |     BufferedInputStream bis;
133 |     ZipOutputStream zos = new ZipOutputStream(
134 |         new BufferedOutputStream(new FileOutputStream(zipFile)));
135 |     try {
136 |       final int BUFFER_SIZE = 8 * 1024; // 8K
137 |       byte buffer[] = new byte[BUFFER_SIZE];
138 |       for (String fileName : folder.list()) {
139 |         if (fileName.equals(".") || fileName.equals("..")) {
140 |           continue;
141 |         }
142 | 
143 |         File file = new File(folder, fileName);
144 |         if (!file.isFile()) {
145 |           continue;
146 |         }
147 | 
148 |         FileInputStream fis = new FileInputStream(file);
149 |         bis = new BufferedInputStream(fis, BUFFER_SIZE);
150 |         try {
151 |           ZipEntry entry = new ZipEntry(fileName);
152 |           zos.putNextEntry(entry);
153 |           int count;
154 |           while ((count = bis.read(buffer, 0, BUFFER_SIZE)) != -1) {
155 |             zos.write(buffer, 0, count);
156 |           }
157 |         } finally {
158 |           try {
159 |             bis.close();
160 |           } catch (IOException e) {
161 |             // Ignore
162 |           }
163 |         }
164 |       }
165 |     } finally {
166 |       try {
167 |         zos.close();
168 |       } catch (IOException e) {
169 |         // Ignore
170 |       }
171 |     }
172 |   }
173 | }
174 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/flattener/ClassicFlattener.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.flattener;
18 | 
19 | import com.elvishew.xlog.LogLevel;
20 | 
21 | /**
22 |  * The classic flattener, flatten the log with pattern "{@value #DEFAULT_PATTERN}".
23 |  * <p>
24 |  * Imagine there is a log, with {@link LogLevel#DEBUG} level, "my_tag" tag and "Simple message"
25 |  * message, the flattened log would be: "2016-11-30 13:00:00.000 D/my_tag: Simple message"
26 |  *
27 |  * @since 1.3.0
28 |  */
29 | public class ClassicFlattener extends PatternFlattener {
30 | 
31 |   private static final String DEFAULT_PATTERN = "{d} {l}/{t}: {m}";
32 | 
33 |   public ClassicFlattener() {
34 |     super(DEFAULT_PATTERN);
35 |   }
36 | }
37 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/flattener/DefaultFlattener.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.flattener;
18 | 
19 | import com.elvishew.xlog.LogLevel;
20 | 
21 | /**
22 |  * Simply join the timestamp, log level, tag and message together.
23 |  *
24 |  * @since 1.3.0
25 |  */
26 | public class DefaultFlattener implements Flattener, Flattener2 {
27 | 
28 |   @Override
29 |   public CharSequence flatten(int logLevel, String tag, String message) {
30 |     return flatten(System.currentTimeMillis(), logLevel, tag, message);
31 |   }
32 | 
33 |   @Override
34 |   public CharSequence flatten(long timeMillis, int logLevel, String tag, String message) {
35 |     return Long.toString(timeMillis)
36 |         + '|' + LogLevel.getShortLevelName(logLevel)
37 |         + '|' + tag
38 |         + '|' + message;
39 |   }
40 | }
41 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/flattener/Flattener.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.flattener;
18 | 
19 | /**
20 |  * The flattener used to flatten log elements(log level, tag and message) to a single CharSequence.
21 |  *
22 |  * @since 1.3.0
23 |  * @deprecated use {@link Flattener2} instead, since 1.6.0
24 |  */
25 | @Deprecated
26 | public interface Flattener {
27 | 
28 |   /**
29 |    * Flatten the log.
30 |    *
31 |    * @param logLevel the level of log
32 |    * @param tag      the tag of log
33 |    * @param message  the message of log
34 |    * @return the formatted final log Charsequence
35 |    */
36 |   CharSequence flatten(int logLevel, String tag, String message);
37 | }
38 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/flattener/Flattener2.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2018 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.flattener;
18 | 
19 | /**
20 |  * The flattener used to flatten log elements(log time milliseconds, level, tag and message) to
21 |  * a single CharSequence.
22 |  *
23 |  * @since 1.6.0
24 |  */
25 | public interface Flattener2 {
26 | 
27 |   /**
28 |    * Flatten the log.
29 |    *
30 |    * @param timeMillis the time milliseconds of log
31 |    * @param logLevel  the level of log
32 |    * @param tag       the tag of log
33 |    * @param message   the message of log
34 |    * @return the formatted final log Charsequence
35 |    */
36 |   CharSequence flatten(long timeMillis, int logLevel, String tag, String message);
37 | }
38 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/FormatException.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter;
18 | 
19 | /**
20 |  * Thrown to indicate that the format of the data is something wrong.
21 |  */
22 | public class FormatException extends RuntimeException {
23 |   /**
24 |    * Constructs a <code>FormatException</code> with no
25 |    * detail message.
26 |    */
27 |   public FormatException() {
28 |     super();
29 |   }
30 | 
31 |   /**
32 |    * Constructs a <code>FormatException</code> with the
33 |    * specified detail message.
34 |    *
35 |    * @param s the detail message.
36 |    */
37 |   public FormatException(String s) {
38 |     super(s);
39 |   }
40 | 
41 |   /**
42 |    * Constructs a new exception with the specified detail message and
43 |    * cause.
44 |    * <p>
45 |    * <p>Note that the detail message associated with <code>cause</code> is
46 |    * <i>not</i> automatically incorporated in this exception's detail
47 |    * message.
48 |    *
49 |    * @param message the detail message (which is saved for later retrieval
50 |    *                by the {@link Throwable#getMessage()} method).
51 |    * @param cause   the cause (which is saved for later retrieval by the
52 |    *                {@link Throwable#getCause()} method).  (A <tt>null</tt> value
53 |    *                is permitted, and indicates that the cause is nonexistent or
54 |    *                unknown.)
55 |    */
56 |   public FormatException(String message, Throwable cause) {
57 |     super(message, cause);
58 |   }
59 | 
60 |   /**
61 |    * Constructs a new exception with the specified cause and a detail
62 |    * message of <tt>(cause==null ? null : cause.toString())</tt> (which
63 |    * typically contains the class and detail message of <tt>cause</tt>).
64 |    * This constructor is useful for exceptions that are little more than
65 |    * wrappers for other throwables (for example, {@link
66 |    * java.security.PrivilegedActionException}).
67 |    *
68 |    * @param cause the cause (which is saved for later retrieval by the
69 |    *              {@link Throwable#getCause()} method).  (A <tt>null</tt> value is
70 |    *              permitted, and indicates that the cause is nonexistent or
71 |    *              unknown.)
72 |    */
73 |   public FormatException(Throwable cause) {
74 |     super(cause);
75 |   }
76 | 
77 |   private static final long serialVersionUID = -5365630128856068164L;
78 | }
79 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/Formatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter;
18 | 
19 | /**
20 |  * A formatter is used for format the data that is not a string, or that is a string but not well
21 |  * formatted, we should format the data to a well formatted string so printers can print them.
22 |  *
23 |  * @param <T> the type of the data
24 |  */
25 | public interface Formatter<T> {
26 | 
27 |   /**
28 |    * Format the data to a readable and loggable string.
29 |    *
30 |    * @param data the data to format
31 |    * @return the formatted string data
32 |    */
33 |   String format(T data);
34 | }
35 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/border/BorderFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.border;
18 | 
19 | import com.elvishew.xlog.formatter.Formatter;
20 | 
21 | /**
22 |  * The border formatter used to wrap string segments with borders when logging.
23 |  * <p>
24 |  * e.g:
25 |  * <br>
26 |  * <br>╔════════════════════════════════════════════════════════════════════════════
27 |  * <br>║Thread: main
28 |  * <br>╟────────────────────────────────────────────────────────────────────────────
29 |  * <br>║	├ com.elvishew.xlog.SampleClassB.sampleMethodB(SampleClassB.java:100)
30 |  * <br>║	└ com.elvishew.xlog.SampleClassA.sampleMethodA(SampleClassA.java:50)
31 |  * <br>╟────────────────────────────────────────────────────────────────────────────
32 |  * <br>║Here is a simple message
33 |  * <br>╚════════════════════════════════════════════════════════════════════════════
34 |  */
35 | public interface BorderFormatter extends Formatter<String[]> {
36 | }
37 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/border/DefaultBorderFormatter.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2016 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlog.formatter.border;
 18 | 
 19 | import com.elvishew.xlog.internal.SystemCompat;
 20 | 
 21 | /**
 22 |  * String segments wrapped with borders look like:
 23 |  * <br>╔════════════════════════════════════════════════════════════════════════════
 24 |  * <br>║String segment 1
 25 |  * <br>╟────────────────────────────────────────────────────────────────────────────
 26 |  * <br>║String segment 2
 27 |  * <br>╟────────────────────────────────────────────────────────────────────────────
 28 |  * <br>║String segment 3
 29 |  * <br>╚════════════════════════════════════════════════════════════════════════════
 30 |  */
 31 | public class DefaultBorderFormatter implements BorderFormatter {
 32 | 
 33 |   private static final char VERTICAL_BORDER_CHAR = '║';
 34 | 
 35 |   // Length: 100.
 36 |   private static final String TOP_HORIZONTAL_BORDER =
 37 |       "╔═════════════════════════════════════════════════" +
 38 |           "══════════════════════════════════════════════════";
 39 | 
 40 |   // Length: 99.
 41 |   private static final String DIVIDER_HORIZONTAL_BORDER =
 42 |       "╟─────────────────────────────────────────────────" +
 43 |           "──────────────────────────────────────────────────";
 44 | 
 45 |   // Length: 100.
 46 |   private static final String BOTTOM_HORIZONTAL_BORDER =
 47 |       "╚═════════════════════════════════════════════════" +
 48 |           "══════════════════════════════════════════════════";
 49 | 
 50 |   @Override
 51 |   public String format(String[] segments) {
 52 |     if (segments == null || segments.length == 0) {
 53 |       return "";
 54 |     }
 55 | 
 56 |     String[] nonNullSegments = new String[segments.length];
 57 |     int nonNullCount = 0;
 58 |     for (String segment : segments) {
 59 |       if (segment != null) {
 60 |         nonNullSegments[nonNullCount++] = segment;
 61 |       }
 62 |     }
 63 |     if (nonNullCount == 0) {
 64 |       return "";
 65 |     }
 66 | 
 67 |     StringBuilder msgBuilder = new StringBuilder();
 68 |     msgBuilder.append(TOP_HORIZONTAL_BORDER).append(SystemCompat.lineSeparator);
 69 |     for (int i = 0; i < nonNullCount; i++) {
 70 |       msgBuilder.append(appendVerticalBorder(nonNullSegments[i]));
 71 |       if (i != nonNullCount - 1) {
 72 |         msgBuilder.append(SystemCompat.lineSeparator).append(DIVIDER_HORIZONTAL_BORDER)
 73 |             .append(SystemCompat.lineSeparator);
 74 |       } else {
 75 |         msgBuilder.append(SystemCompat.lineSeparator).append(BOTTOM_HORIZONTAL_BORDER);
 76 |       }
 77 |     }
 78 |     return msgBuilder.toString();
 79 |   }
 80 | 
 81 |   /**
 82 |    * Add {@value #VERTICAL_BORDER_CHAR} to each line of msg.
 83 |    *
 84 |    * @param msg the message to add border
 85 |    * @return the message with {@value #VERTICAL_BORDER_CHAR} in the start of each line
 86 |    */
 87 |   private static String appendVerticalBorder(String msg) {
 88 |     StringBuilder borderedMsgBuilder = new StringBuilder(msg.length() + 10);
 89 |     String[] lines = msg.split(SystemCompat.lineSeparator);
 90 |     for (int i = 0, N = lines.length; i < N; i++) {
 91 |       if (i != 0) {
 92 |         borderedMsgBuilder.append(SystemCompat.lineSeparator);
 93 |       }
 94 |       String line = lines[i];
 95 |       borderedMsgBuilder.append(VERTICAL_BORDER_CHAR).append(line);
 96 |     }
 97 |     return borderedMsgBuilder.toString();
 98 |   }
 99 | }
100 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/message/json/DefaultJsonFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.message.json;
18 | 
19 | import com.elvishew.xlog.formatter.FormatException;
20 | import com.elvishew.xlog.internal.Platform;
21 | 
22 | import org.json.JSONArray;
23 | import org.json.JSONObject;
24 | 
25 | /**
26 |  * Simply format the JSON using {@link JSONObject} and {@link JSONArray}.
27 |  */
28 | public class DefaultJsonFormatter implements JsonFormatter {
29 | 
30 |   private static final int JSON_INDENT = 4;
31 | 
32 |   @Override
33 |   public String format(String json) {
34 |     String formattedString = null;
35 |     if (json == null || json.trim().length() == 0) {
36 |       Platform.get().warn("JSON empty.");
37 |       return "";
38 |     }
39 |     try {
40 |       if (json.startsWith("{")) {
41 |         JSONObject jsonObject = new JSONObject(json);
42 |         formattedString = jsonObject.toString(JSON_INDENT);
43 |       } else if (json.startsWith("[")) {
44 |         JSONArray jsonArray = new JSONArray(json);
45 |         formattedString = jsonArray.toString(JSON_INDENT);
46 |       } else {
47 |         Platform.get().warn("JSON should start with { or [");
48 |         return json;
49 |       }
50 |     } catch (Exception e) {
51 |       Platform.get().warn(e.getMessage());
52 |       return json;
53 |     }
54 |     return formattedString;
55 |   }
56 | }
57 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/message/json/JsonFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.message.json;
18 | 
19 | import com.elvishew.xlog.formatter.Formatter;
20 | 
21 | /**
22 |  * The JSON formatter used to format the JSON string when log a JSON string.
23 |  */
24 | public interface JsonFormatter extends Formatter<String> {
25 | }
26 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/message/object/BundleFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.message.object;
18 | 
19 | import android.os.Bundle;
20 | 
21 | import com.elvishew.xlog.internal.util.ObjectToStringUtil;
22 | 
23 | /**
24 |  * Format an Bundle object to a string.
25 |  *
26 |  * @since 1.4.0
27 |  */
28 | public class BundleFormatter implements ObjectFormatter<Bundle> {
29 | 
30 |   /**
31 |    * Format an Bundle object to a string.
32 |    *
33 |    * @param data the Bundle object to format
34 |    * @return the formatted string
35 |    */
36 |   @Override
37 |   public String format(Bundle data) {
38 |     return ObjectToStringUtil.bundleToString(data);
39 |   }
40 | }
41 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/message/object/IntentFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.message.object;
18 | 
19 | import android.content.Intent;
20 | 
21 | import com.elvishew.xlog.internal.util.ObjectToStringUtil;
22 | 
23 | /**
24 |  * Format an Intent object to a string.
25 |  *
26 |  * @since 1.4.0
27 |  */
28 | public class IntentFormatter implements ObjectFormatter<Intent> {
29 | 
30 |   /**
31 |    * Format an Intent object to a string.
32 |    *
33 |    * @param data the Intent object to format
34 |    * @return the formatted string
35 |    */
36 |   @Override
37 |   public String format(Intent data) {
38 |     return ObjectToStringUtil.intentToString(data);
39 |   }
40 | }
41 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/message/object/ObjectFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.message.object;
18 | 
19 | import com.elvishew.xlog.formatter.Formatter;
20 | 
21 | /**
22 |  * The Object formatter used to format an object to a string.
23 |  *
24 |  * @param <T> the type of object
25 |  * @since 1.1.0
26 |  */
27 | public interface ObjectFormatter<T> extends Formatter<T> {
28 | }
29 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/message/throwable/DefaultThrowableFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.message.throwable;
18 | 
19 | import com.elvishew.xlog.internal.util.StackTraceUtil;
20 | 
21 | /**
22 |  * Simply put each stack trace(method name, source file and line number) of the throwable
23 |  * in a single line.
24 |  */
25 | public class DefaultThrowableFormatter implements ThrowableFormatter {
26 | 
27 |   @Override
28 |   public String format(Throwable tr) {
29 |     return StackTraceUtil.getStackTraceString(tr);
30 |   }
31 | }
32 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/message/throwable/ThrowableFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.message.throwable;
18 | 
19 | import com.elvishew.xlog.formatter.Formatter;
20 | 
21 | /**
22 |  * The throwable formatter used to format the throwable when log a message with throwable.
23 |  */
24 | public interface ThrowableFormatter extends Formatter<Throwable> {
25 | }
26 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/message/xml/DefaultXmlFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.message.xml;
18 | 
19 | import com.elvishew.xlog.internal.Platform;
20 | import com.elvishew.xlog.internal.SystemCompat;
21 | import com.elvishew.xlog.formatter.FormatException;
22 | 
23 | import java.io.StringReader;
24 | import java.io.StringWriter;
25 | 
26 | import javax.xml.transform.OutputKeys;
27 | import javax.xml.transform.Source;
28 | import javax.xml.transform.Transformer;
29 | import javax.xml.transform.TransformerFactory;
30 | import javax.xml.transform.stream.StreamResult;
31 | import javax.xml.transform.stream.StreamSource;
32 | 
33 | /**
34 |  * Simply format the XML with a indent of {@value XML_INDENT}.
35 |  * <br>TODO: Make indent size and enable/disable state configurable.
36 |  */
37 | public class DefaultXmlFormatter implements XmlFormatter {
38 | 
39 |   private static final int XML_INDENT = 4;
40 | 
41 |   @Override
42 |   public String format(String xml) {
43 |     String formattedString;
44 |     if (xml == null || xml.trim().length() == 0) {
45 |       Platform.get().warn("XML empty.");
46 |       return "";
47 |     }
48 |     try {
49 |       Source xmlInput = new StreamSource(new StringReader(xml));
50 |       StreamResult xmlOutput = new StreamResult(new StringWriter());
51 |       Transformer transformer = TransformerFactory.newInstance().newTransformer();
52 |       transformer.setOutputProperty(OutputKeys.INDENT, "yes");
53 |       transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount",
54 |           String.valueOf(XML_INDENT));
55 |       transformer.transform(xmlInput, xmlOutput);
56 |       formattedString = xmlOutput.getWriter().toString().replaceFirst(">", ">"
57 |           + SystemCompat.lineSeparator);
58 |     } catch (Exception e) {
59 |       Platform.get().warn(e.getMessage());
60 |       return xml;
61 |     }
62 |     return formattedString;
63 |   }
64 | }
65 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/message/xml/XmlFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.message.xml;
18 | 
19 | import com.elvishew.xlog.formatter.Formatter;
20 | 
21 | /**
22 |  * The XML formatter used to format the XML string when log a XML string.
23 |  */
24 | public interface XmlFormatter extends Formatter<String> {
25 | }
26 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/stacktrace/DefaultStackTraceFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.stacktrace;
18 | 
19 | import com.elvishew.xlog.internal.SystemCompat;
20 | 
21 | /**
22 |  * Formatted stack trace looks like:
23 |  * <br>	├ com.elvishew.xlog.SampleClassC.sampleMethodC(SampleClassC.java:200)
24 |  * <br>	├ com.elvishew.xlog.SampleClassB.sampleMethodB(SampleClassB.java:100)
25 |  * <br>	└ com.elvishew.xlog.SampleClassA.sampleMethodA(SampleClassA.java:50)
26 |  */
27 | public class DefaultStackTraceFormatter implements StackTraceFormatter {
28 | 
29 |   @Override
30 |   public String format(StackTraceElement[] stackTrace) {
31 |     StringBuilder sb = new StringBuilder(256);
32 |     if (stackTrace == null || stackTrace.length == 0) {
33 |       return null;
34 |     } else if (stackTrace.length == 1) {
35 |       return "\t─ " + stackTrace[0].toString();
36 |     } else {
37 |       for (int i = 0, N = stackTrace.length; i < N; i++) {
38 |         if (i != N - 1) {
39 |           sb.append("\t├ ");
40 |           sb.append(stackTrace[i].toString());
41 |           sb.append(SystemCompat.lineSeparator);
42 |         } else {
43 |           sb.append("\t└ ");
44 |           sb.append(stackTrace[i].toString());
45 |         }
46 |       }
47 |       return sb.toString();
48 |     }
49 |   }
50 | }
51 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/stacktrace/StackTraceFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.stacktrace;
18 | 
19 | import com.elvishew.xlog.formatter.Formatter;
20 | 
21 | /**
22 |  * The stack trace formatter used to format the stack trace when logging.
23 |  */
24 | public interface StackTraceFormatter extends Formatter<StackTraceElement[]> {
25 | }
26 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/thread/DefaultThreadFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.thread;
18 | 
19 | /**
20 |  * Formatted stack trace looks like:
21 |  * <br>Thread: thread-name
22 |  */
23 | public class DefaultThreadFormatter implements ThreadFormatter {
24 | 
25 |   @Override
26 |   public String format(Thread data) {
27 |     return "Thread: " + data.getName();
28 |   }
29 | }
30 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/formatter/thread/ThreadFormatter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.formatter.thread;
18 | 
19 | import com.elvishew.xlog.formatter.Formatter;
20 | 
21 | /**
22 |  * The thread formatter used to format the thread info when logging.
23 |  */
24 | public interface ThreadFormatter extends Formatter<Thread> {
25 | }
26 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/interceptor/AbstractFilterInterceptor.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.interceptor;
18 | 
19 | import com.elvishew.xlog.LogItem;
20 | 
21 | /**
22 |  * An filter interceptor is used to filter some specific logs out, this filtered logs won't be
23 |  * printed by any printer.
24 |  *
25 |  * @since 1.3.0
26 |  */
27 | public abstract class AbstractFilterInterceptor implements Interceptor {
28 | 
29 |   /**
30 |    * {@inheritDoc}
31 |    *
32 |    * @param log the original log
33 |    * @return the original log if it is acceptable, or null if it should be filtered out
34 |    */
35 |   @Override
36 |   public LogItem intercept(LogItem log) {
37 |     if (reject(log)) {
38 |       // Filter this log out.
39 |       return null;
40 |     }
41 |     return log;
42 |   }
43 | 
44 |   /**
45 |    * Whether specific log should be filtered out.
46 |    *
47 |    * @param log the specific log
48 |    * @return true if the log should be filtered out, false otherwise
49 |    */
50 |   protected abstract boolean reject(LogItem log);
51 | }
52 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/interceptor/BlacklistTagsFilterInterceptor.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.interceptor;
18 | 
19 | import com.elvishew.xlog.LogItem;
20 | 
21 | import java.util.Arrays;
22 | 
23 | /**
24 |  * Filter out the logs with a tag that is in the blacklist.
25 |  *
26 |  * @since 1.3.0
27 |  */
28 | public class BlacklistTagsFilterInterceptor extends AbstractFilterInterceptor {
29 | 
30 |   private Iterable<String> blacklistTags;
31 | 
32 |   /**
33 |    * Constructor
34 |    *
35 |    * @param blacklistTags the blacklist tags, the logs with a tag that is in the blacklist will be
36 |    *                      filtered out
37 |    */
38 |   public BlacklistTagsFilterInterceptor(String... blacklistTags) {
39 |     this(Arrays.asList(blacklistTags));
40 |   }
41 | 
42 |   /**
43 |    * Constructor
44 |    *
45 |    * @param blacklistTags the blacklist tags, the logs with a tag that is in the blacklist will be
46 |    *                      filtered out
47 |    */
48 |   public BlacklistTagsFilterInterceptor(Iterable<String> blacklistTags) {
49 |     if (blacklistTags == null) {
50 |       throw new NullPointerException();
51 |     }
52 |     this.blacklistTags = blacklistTags;
53 |   }
54 | 
55 |   /**
56 |    * {@inheritDoc}
57 |    *
58 |    * @return true if the tag of the log is in the blacklist, false otherwise
59 |    */
60 |   @Override
61 |   protected boolean reject(LogItem log) {
62 |     if (blacklistTags != null) {
63 |       for (String disabledTag : blacklistTags) {
64 |         if (log.tag.equals(disabledTag)) {
65 |           return true;
66 |         }
67 |       }
68 |     }
69 |     return false;
70 |   }
71 | }
72 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/interceptor/Interceptor.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.interceptor;
18 | 
19 | import com.elvishew.xlog.LogConfiguration;
20 | import com.elvishew.xlog.LogItem;
21 | 
22 | /**
23 |  * Interceptors are used to intercept every log after formatting message, thread info and
24 |  * stack trace info, and before printing, normally we can modify or drop the log.
25 |  * <p>
26 |  * Remember interceptors are ordered, which means earlier added interceptor will get the log
27 |  * first.
28 |  * <p>
29 |  * If any interceptor remove the log(by returning null when {@link #intercept(LogItem)}),
30 |  * then the interceptors behind that one won't receive the log, and the log won't be printed at all.
31 |  *
32 |  * @see LogConfiguration.Builder#addInterceptor(Interceptor)
33 |  * @see com.elvishew.xlog.XLog#addInterceptor(Interceptor)
34 |  * @since 1.3.0
35 |  */
36 | public interface Interceptor {
37 | 
38 |   /**
39 |    * Intercept the log.
40 |    *
41 |    * @param log the original log
42 |    * @return the modified log, or null if the log should not be printed
43 |    */
44 |   LogItem intercept(LogItem log);
45 | }
46 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/interceptor/WhitelistTagsFilterInterceptor.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.interceptor;
18 | 
19 | import com.elvishew.xlog.LogItem;
20 | 
21 | import java.util.Arrays;
22 | 
23 | /**
24 |  * Filter out the logs with a tag that is NOT in the whitelist.
25 |  *
26 |  * @since 1.3.0
27 |  */
28 | public class WhitelistTagsFilterInterceptor extends AbstractFilterInterceptor {
29 | 
30 |   private Iterable<String> whitelistTags;
31 | 
32 |   /**
33 |    * Constructor
34 |    *
35 |    * @param whitelistTags the whitelist tags, the logs with a tag that is NOT in the whitelist
36 |    *                      will be filtered out
37 |    */
38 |   public WhitelistTagsFilterInterceptor(String... whitelistTags) {
39 |     this(Arrays.asList(whitelistTags));
40 |   }
41 | 
42 |   /**
43 |    * Constructor
44 |    *
45 |    * @param whitelistTags the whitelist tags, the logs with a tag that is NOT in the whitelist
46 |    *                      will be filtered out
47 |    */
48 |   public WhitelistTagsFilterInterceptor(Iterable<String> whitelistTags) {
49 |     if (whitelistTags == null) {
50 |       throw new NullPointerException();
51 |     }
52 |     this.whitelistTags = whitelistTags;
53 |   }
54 | 
55 |   /**
56 |    * {@inheritDoc}
57 |    *
58 |    * @return true if the tag of the log is NOT in the whitelist, false otherwise
59 |    */
60 |   @Override
61 |   protected boolean reject(LogItem log) {
62 |     if (whitelistTags != null) {
63 |       for (String enabledTag : whitelistTags) {
64 |         if (log.tag.equals(enabledTag)) {
65 |           return false;
66 |         }
67 |       }
68 |     }
69 |     return true;
70 |   }
71 | }
72 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/internal/DefaultsFactory.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2016 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlog.internal;
 18 | 
 19 | import com.elvishew.xlog.flattener.DefaultFlattener;
 20 | import com.elvishew.xlog.flattener.Flattener;
 21 | import com.elvishew.xlog.flattener.Flattener2;
 22 | import com.elvishew.xlog.formatter.border.BorderFormatter;
 23 | import com.elvishew.xlog.formatter.border.DefaultBorderFormatter;
 24 | import com.elvishew.xlog.formatter.message.json.DefaultJsonFormatter;
 25 | import com.elvishew.xlog.formatter.message.json.JsonFormatter;
 26 | import com.elvishew.xlog.formatter.message.object.ObjectFormatter;
 27 | import com.elvishew.xlog.formatter.message.throwable.DefaultThrowableFormatter;
 28 | import com.elvishew.xlog.formatter.message.throwable.ThrowableFormatter;
 29 | import com.elvishew.xlog.formatter.message.xml.DefaultXmlFormatter;
 30 | import com.elvishew.xlog.formatter.message.xml.XmlFormatter;
 31 | import com.elvishew.xlog.formatter.stacktrace.DefaultStackTraceFormatter;
 32 | import com.elvishew.xlog.formatter.stacktrace.StackTraceFormatter;
 33 | import com.elvishew.xlog.formatter.thread.DefaultThreadFormatter;
 34 | import com.elvishew.xlog.formatter.thread.ThreadFormatter;
 35 | import com.elvishew.xlog.printer.Printer;
 36 | import com.elvishew.xlog.printer.file.FilePrinter;
 37 | import com.elvishew.xlog.printer.file.backup.BackupStrategy2;
 38 | import com.elvishew.xlog.internal.printer.file.backup.BackupStrategyWrapper;
 39 | import com.elvishew.xlog.printer.file.backup.FileSizeBackupStrategy;
 40 | import com.elvishew.xlog.printer.file.clean.CleanStrategy;
 41 | import com.elvishew.xlog.printer.file.clean.NeverCleanStrategy;
 42 | import com.elvishew.xlog.printer.file.naming.ChangelessFileNameGenerator;
 43 | import com.elvishew.xlog.printer.file.naming.FileNameGenerator;
 44 | import com.elvishew.xlog.printer.file.writer.SimpleWriter;
 45 | import com.elvishew.xlog.printer.file.writer.Writer;
 46 | 
 47 | import java.util.Map;
 48 | 
 49 | /**
 50 |  * Factory for providing default implementation.
 51 |  */
 52 | public class DefaultsFactory {
 53 | 
 54 |   private static final String DEFAULT_LOG_FILE_NAME = "log";
 55 | 
 56 |   private static final long DEFAULT_LOG_FILE_MAX_SIZE = 1024 * 1024; // 1M bytes;
 57 | 
 58 |   /**
 59 |    * Create the default JSON formatter.
 60 |    */
 61 |   public static JsonFormatter createJsonFormatter() {
 62 |     return new DefaultJsonFormatter();
 63 |   }
 64 | 
 65 |   /**
 66 |    * Create the default XML formatter.
 67 |    */
 68 |   public static XmlFormatter createXmlFormatter() {
 69 |     return new DefaultXmlFormatter();
 70 |   }
 71 | 
 72 |   /**
 73 |    * Create the default throwable formatter.
 74 |    */
 75 |   public static ThrowableFormatter createThrowableFormatter() {
 76 |     return new DefaultThrowableFormatter();
 77 |   }
 78 | 
 79 |   /**
 80 |    * Create the default thread formatter.
 81 |    */
 82 |   public static ThreadFormatter createThreadFormatter() {
 83 |     return new DefaultThreadFormatter();
 84 |   }
 85 | 
 86 |   /**
 87 |    * Create the default stack trace formatter.
 88 |    */
 89 |   public static StackTraceFormatter createStackTraceFormatter() {
 90 |     return new DefaultStackTraceFormatter();
 91 |   }
 92 | 
 93 |   /**
 94 |    * Create the default border formatter.
 95 |    */
 96 |   public static BorderFormatter createBorderFormatter() {
 97 |     return new DefaultBorderFormatter();
 98 |   }
 99 | 
100 |   /**
101 |    * Create the default {@link Flattener}.
102 |    */
103 |   public static Flattener createFlattener() {
104 |     return new DefaultFlattener();
105 |   }
106 | 
107 |   /**
108 |    * Create the default {@link Flattener2}.
109 |    */
110 |   public static Flattener2 createFlattener2() {
111 |     return new DefaultFlattener();
112 |   }
113 | 
114 |   /**
115 |    * Create the default printer.
116 |    */
117 |   public static Printer createPrinter() {
118 |     return Platform.get().defaultPrinter();
119 |   }
120 | 
121 |   /**
122 |    * Create the default file name generator for {@link FilePrinter}.
123 |    */
124 |   public static FileNameGenerator createFileNameGenerator() {
125 |     return new ChangelessFileNameGenerator(DEFAULT_LOG_FILE_NAME);
126 |   }
127 | 
128 |   /**
129 |    * Create the default backup strategy for {@link FilePrinter}.
130 |    */
131 |   public static BackupStrategy2 createBackupStrategy() {
132 |     return new BackupStrategyWrapper(new FileSizeBackupStrategy(DEFAULT_LOG_FILE_MAX_SIZE));
133 |   }
134 | 
135 |   /**
136 |    * Create the default clean strategy for {@link FilePrinter}.
137 |    */
138 |   public static CleanStrategy createCleanStrategy() {
139 |     return new NeverCleanStrategy();
140 |   }
141 | 
142 |   /**
143 |    * Create the default writer for {@link FilePrinter}.
144 |    */
145 |   public static Writer createWriter() {
146 |     return new SimpleWriter();
147 |   }
148 | 
149 |   /**
150 |    * Get the builtin object formatters.
151 |    *
152 |    * @return the builtin object formatters
153 |    */
154 |   public static Map<Class<?>, ObjectFormatter<?>> builtinObjectFormatters() {
155 |     return Platform.get().builtinObjectFormatters();
156 |   }
157 | }
158 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/internal/Platform.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2016 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlog.internal;
 18 | 
 19 | import android.annotation.SuppressLint;
 20 | import android.content.Intent;
 21 | import android.os.Build;
 22 | import android.os.Bundle;
 23 | 
 24 | import com.elvishew.xlog.formatter.message.object.BundleFormatter;
 25 | import com.elvishew.xlog.formatter.message.object.IntentFormatter;
 26 | import com.elvishew.xlog.formatter.message.object.ObjectFormatter;
 27 | import com.elvishew.xlog.printer.AndroidPrinter;
 28 | import com.elvishew.xlog.printer.ConsolePrinter;
 29 | import com.elvishew.xlog.printer.Printer;
 30 | 
 31 | import java.util.Collections;
 32 | import java.util.HashMap;
 33 | import java.util.Map;
 34 | 
 35 | public class Platform {
 36 | 
 37 |   private static final Platform PLATFORM = findPlatform();
 38 | 
 39 |   public static Platform get() {
 40 |     return PLATFORM;
 41 |   }
 42 | 
 43 |   @SuppressLint("NewApi")
 44 |   String lineSeparator() {
 45 |     return System.lineSeparator();
 46 |   }
 47 | 
 48 |   Printer defaultPrinter() {
 49 |     return new ConsolePrinter();
 50 |   }
 51 | 
 52 |   Map<Class<?>, ObjectFormatter<?>> builtinObjectFormatters() {
 53 |     return Collections.emptyMap();
 54 |   }
 55 | 
 56 |   public void warn(String msg) {
 57 |     System.out.println(msg);
 58 |   }
 59 | 
 60 |   public void error(String msg) {
 61 |     System.out.println(msg);
 62 |   }
 63 | 
 64 |   private static Platform findPlatform() {
 65 |     try {
 66 |       Class.forName("android.os.Build");
 67 |       if (Build.VERSION.SDK_INT != 0) {
 68 |         return new Android();
 69 |       }
 70 |     } catch (ClassNotFoundException ignored) {
 71 |     }
 72 |     return new Platform();
 73 |   }
 74 | 
 75 |   static class Android extends Platform {
 76 | 
 77 |     private static final Map<Class<?>, ObjectFormatter<?>> BUILTIN_OBJECT_FORMATTERS;
 78 | 
 79 |     static {
 80 |       Map<Class<?>, ObjectFormatter<?>> objectFormatters = new HashMap<>();
 81 |       objectFormatters.put(Bundle.class, new BundleFormatter());
 82 |       objectFormatters.put(Intent.class, new IntentFormatter());
 83 |       BUILTIN_OBJECT_FORMATTERS = Collections.unmodifiableMap(objectFormatters);
 84 |     }
 85 | 
 86 |     @Override
 87 |     String lineSeparator() {
 88 |       if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
 89 |         return "\n";
 90 |       }
 91 |       return System.lineSeparator();
 92 |     }
 93 | 
 94 |     @Override
 95 |     Printer defaultPrinter() {
 96 |       return new AndroidPrinter();
 97 |     }
 98 | 
 99 |     @Override
100 |     Map<Class<?>, ObjectFormatter<?>> builtinObjectFormatters() {
101 |       return BUILTIN_OBJECT_FORMATTERS;
102 |     }
103 | 
104 |     @Override
105 |     public void warn(String msg) {
106 |       android.util.Log.w("XLog", msg);
107 |     }
108 | 
109 |     @Override
110 |     public void error(String msg) {
111 |       android.util.Log.e("XLog", msg);
112 |     }
113 |   }
114 | }
115 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/internal/SystemCompat.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.internal;
18 | 
19 | /**
20 |  * System environment.
21 |  */
22 | public class SystemCompat {
23 | 
24 |   /**
25 |    * The line separator of system.
26 |    */
27 |   public static String lineSeparator = Platform.get().lineSeparator();
28 | }
29 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/internal/printer/file/backup/BackupStrategyWrapper.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2021 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.internal.printer.file.backup;
18 | 
19 | import com.elvishew.xlog.printer.file.backup.BackupStrategy;
20 | import com.elvishew.xlog.printer.file.backup.BackupStrategy2;
21 | 
22 | import java.io.File;
23 | 
24 | /**
25 |  * Wrap a {@link BackupStrategy} to fit the {@link BackupStrategy2} interface, and perform like
26 |  * a {@link BackupStrategy} with the old logic before v1.9.0.
27 |  */
28 | public class BackupStrategyWrapper implements BackupStrategy2 {
29 | 
30 |   private BackupStrategy backupStrategy;
31 | 
32 |   public BackupStrategyWrapper(BackupStrategy backupStrategy) {
33 |     this.backupStrategy = backupStrategy;
34 |   }
35 | 
36 |   @Override
37 |   public int getMaxBackupIndex() {
38 |     return 1;
39 |   }
40 | 
41 |   @Override
42 |   public String getBackupFileName(String fileName, int backupIndex) {
43 |     return fileName + ".bak";
44 |   }
45 | 
46 |   @Override
47 |   public boolean shouldBackup(File file) {
48 |     return backupStrategy.shouldBackup(file);
49 |   }
50 | }
51 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/internal/printer/file/backup/BackupUtil.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2021 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.internal.printer.file.backup;
18 | 
19 | import com.elvishew.xlog.printer.file.backup.BackupStrategy2;
20 | 
21 | import java.io.File;
22 | 
23 | public class BackupUtil {
24 | 
25 |   /**
26 |    * Shift existed backups if needed, and backup the logging file.
27 |    *
28 |    * @param loggingFile    the logging file
29 |    * @param backupStrategy the strategy should be use when backing up
30 |    */
31 |   public static void backup(File loggingFile, BackupStrategy2 backupStrategy) {
32 |     String loggingFileName = loggingFile.getName();
33 |     String path = loggingFile.getParent();
34 |     File backupFile;
35 |     File nextBackupFile;
36 |     int maxBackupIndex = backupStrategy.getMaxBackupIndex();
37 |     if (maxBackupIndex > 0) {
38 |       backupFile = new File(path, backupStrategy.getBackupFileName(loggingFileName, maxBackupIndex));
39 |       if (backupFile.exists()) {
40 |         backupFile.delete();
41 |       }
42 |       for (int i = maxBackupIndex - 1; i > 0; i--) {
43 |         backupFile = new File(path, backupStrategy.getBackupFileName(loggingFileName, i));
44 |         if (backupFile.exists()) {
45 |           nextBackupFile = new File(path, backupStrategy.getBackupFileName(loggingFileName, i + 1));
46 |           backupFile.renameTo(nextBackupFile);
47 |         }
48 |       }
49 |       nextBackupFile = new File(path, backupStrategy.getBackupFileName(loggingFileName, 1));
50 |       loggingFile.renameTo(nextBackupFile);
51 |     } else if (maxBackupIndex == BackupStrategy2.NO_LIMIT) {
52 |       for (int i = 1; i < Integer.MAX_VALUE; i++) {
53 |         nextBackupFile = new File(path, backupStrategy.getBackupFileName(loggingFileName, i));
54 |         if (!nextBackupFile.exists()) {
55 |           loggingFile.renameTo(nextBackupFile);
56 |           break;
57 |         }
58 |       }
59 |     } else {
60 |       // Illegal maxBackIndex, could not come here.
61 |     }
62 |   }
63 | 
64 |   /**
65 |    * Check if a {@link BackupStrategy2} is valid, will throw a exception if invalid.
66 |    *
67 |    * @param backupStrategy the backup strategy to be verify
68 |    */
69 |   public static void verifyBackupStrategy(BackupStrategy2 backupStrategy) {
70 |     int maxBackupIndex = backupStrategy.getMaxBackupIndex();
71 |     if (maxBackupIndex < 0) {
72 |       throw new IllegalArgumentException("Max backup index should not be less than 0");
73 |     } else if (maxBackupIndex == Integer.MAX_VALUE) {
74 |       throw new IllegalArgumentException("Max backup index too big: " + maxBackupIndex);
75 |     }
76 |   }
77 | }
78 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/internal/util/ObjectToStringUtil.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2016 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlog.internal.util;
 18 | 
 19 | import android.content.ClipData;
 20 | import android.content.ComponentName;
 21 | import android.content.Intent;
 22 | import android.graphics.Rect;
 23 | import android.net.Uri;
 24 | import android.os.Build;
 25 | import android.os.Bundle;
 26 | import android.os.Parcelable;
 27 | 
 28 | import java.lang.reflect.InvocationTargetException;
 29 | import java.lang.reflect.Method;
 30 | import java.util.Arrays;
 31 | import java.util.Set;
 32 | 
 33 | /**
 34 |  * Utility for formatting object to string.
 35 |  */
 36 | public class ObjectToStringUtil {
 37 | 
 38 |   /**
 39 |    * Bundle object to string, the string would be in the format of "Bundle[{...}]".
 40 |    */
 41 |   public static String bundleToString(Bundle bundle) {
 42 |     if (bundle == null) {
 43 |       return "null";
 44 |     }
 45 | 
 46 |     StringBuilder b = new StringBuilder(128);
 47 |     b.append("Bundle[{");
 48 |     bundleToShortString(bundle, b);
 49 |     b.append("}]");
 50 |     return b.toString();
 51 |   }
 52 | 
 53 |   /**
 54 |    * Intent object to string, the string would be in the format of "Intent { ... }".
 55 |    */
 56 |   public static String intentToString(Intent intent) {
 57 |     if (intent == null) {
 58 |       return "null";
 59 |     }
 60 | 
 61 |     StringBuilder b = new StringBuilder(128);
 62 |     b.append("Intent { ");
 63 |     intentToShortString(intent, b);
 64 |     b.append(" }");
 65 |     return b.toString();
 66 |   }
 67 | 
 68 |   private static void bundleToShortString(Bundle bundle, StringBuilder b) {
 69 |     boolean first = true;
 70 |     for (String key : bundle.keySet()) {
 71 |       if (!first) {
 72 |         b.append(", ");
 73 |       }
 74 |       b.append(key).append('=');
 75 |       Object value = bundle.get(key);
 76 |       if (value instanceof int[]) {
 77 |         b.append(Arrays.toString((int[]) value));
 78 |       } else if (value instanceof byte[]) {
 79 |         b.append(Arrays.toString((byte[]) value));
 80 |       } else if (value instanceof boolean[]) {
 81 |         b.append(Arrays.toString((boolean[]) value));
 82 |       } else if (value instanceof short[]) {
 83 |         b.append(Arrays.toString((short[]) value));
 84 |       } else if (value instanceof long[]) {
 85 |         b.append(Arrays.toString((long[]) value));
 86 |       } else if (value instanceof float[]) {
 87 |         b.append(Arrays.toString((float[]) value));
 88 |       } else if (value instanceof double[]) {
 89 |         b.append(Arrays.toString((double[]) value));
 90 |       } else if (value instanceof String[]) {
 91 |         b.append(Arrays.toString((String[]) value));
 92 |       } else if (value instanceof CharSequence[]) {
 93 |         b.append(Arrays.toString((CharSequence[]) value));
 94 |       } else if (value instanceof Parcelable[]) {
 95 |         b.append(Arrays.toString((Parcelable[]) value));
 96 |       } else if (value instanceof Bundle) {
 97 |         b.append(bundleToString((Bundle) value));
 98 |       } else {
 99 |         b.append(value);
100 |       }
101 |       first = false;
102 |     }
103 |   }
104 | 
105 |   private static void intentToShortString(Intent intent, StringBuilder b) {
106 |     boolean first = true;
107 |     String mAction = intent.getAction();
108 |     if (mAction != null) {
109 |       b.append("act=").append(mAction);
110 |       first = false;
111 |     }
112 |     Set<String> mCategories = intent.getCategories();
113 |     if (mCategories != null) {
114 |       if (!first) {
115 |         b.append(' ');
116 |       }
117 |       first = false;
118 |       b.append("cat=[");
119 |       boolean firstCategory = true;
120 |       for (String c : mCategories) {
121 |         if (!firstCategory) {
122 |           b.append(',');
123 |         }
124 |         b.append(c);
125 |         firstCategory = false;
126 |       }
127 |       b.append("]");
128 |     }
129 |     Uri mData = intent.getData();
130 |     if (mData != null) {
131 |       if (!first) {
132 |         b.append(' ');
133 |       }
134 |       first = false;
135 |       b.append("dat=");
136 |       if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
137 |         b.append(uriToSafeString(mData));
138 |       } else {
139 |         String scheme = mData.getScheme();
140 |         if (scheme != null) {
141 |           if (scheme.equalsIgnoreCase("tel")) {
142 |             b.append("tel:xxx-xxx-xxxx");
143 |           } else if (scheme.equalsIgnoreCase("smsto")) {
144 |             b.append("smsto:xxx-xxx-xxxx");
145 |           } else {
146 |             b.append(mData);
147 |           }
148 |         } else {
149 |           b.append(mData);
150 |         }
151 |       }
152 |     }
153 |     String mType = intent.getType();
154 |     if (mType != null) {
155 |       if (!first) {
156 |         b.append(' ');
157 |       }
158 |       first = false;
159 |       b.append("typ=").append(mType);
160 |     }
161 |     int mFlags = intent.getFlags();
162 |     if (mFlags != 0) {
163 |       if (!first) {
164 |         b.append(' ');
165 |       }
166 |       first = false;
167 |       b.append("flg=0x").append(Integer.toHexString(mFlags));
168 |     }
169 |     String mPackage = intent.getPackage();
170 |     if (mPackage != null) {
171 |       if (!first) {
172 |         b.append(' ');
173 |       }
174 |       first = false;
175 |       b.append("pkg=").append(mPackage);
176 |     }
177 |     ComponentName mComponent = intent.getComponent();
178 |     if (mComponent != null) {
179 |       if (!first) {
180 |         b.append(' ');
181 |       }
182 |       first = false;
183 |       b.append("cmp=").append(mComponent.flattenToShortString());
184 |     }
185 |     Rect mSourceBounds = intent.getSourceBounds();
186 |     if (mSourceBounds != null) {
187 |       if (!first) {
188 |         b.append(' ');
189 |       }
190 |       first = false;
191 |       b.append("bnds=").append(mSourceBounds.toShortString());
192 |     }
193 |     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
194 |       ClipData mClipData = intent.getClipData();
195 |       if (mClipData != null) {
196 |         if (!first) {
197 |           b.append(' ');
198 |         }
199 |         first = false;
200 |         b.append("(has clip)");
201 |       }
202 |     }
203 |     Bundle mExtras = intent.getExtras();
204 |     if (mExtras != null) {
205 |       if (!first) {
206 |         b.append(' ');
207 |       }
208 |       b.append("extras={");
209 |       bundleToShortString(mExtras, b);
210 |       b.append('}');
211 |     }
212 |     if (Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
213 |       Intent mSelector = intent.getSelector();
214 |       if (mSelector != null) {
215 |         b.append(" sel=");
216 |         intentToShortString(mSelector, b);
217 |         b.append("}");
218 |       }
219 |     }
220 |   }
221 | 
222 |   private static String uriToSafeString(Uri uri) {
223 |     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
224 |       try {
225 |         Method toSafeString = Uri.class.getDeclaredMethod("toSafeString");
226 |         toSafeString.setAccessible(true);
227 |         return (String) toSafeString.invoke(uri);
228 |       } catch (NoSuchMethodException e) {
229 |         e.printStackTrace();
230 |       } catch (InvocationTargetException e) {
231 |         e.printStackTrace();
232 |       } catch (IllegalAccessException e) {
233 |         e.printStackTrace();
234 |       }
235 |     }
236 |     return uri.toString();
237 |   }
238 | }
239 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/internal/util/StackTraceUtil.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2015 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlog.internal.util;
 18 | 
 19 | import com.elvishew.xlog.XLog;
 20 | 
 21 | import java.io.PrintWriter;
 22 | import java.io.StringWriter;
 23 | import java.net.UnknownHostException;
 24 | 
 25 | /**
 26 |  * Utility related with stack trace.
 27 |  */
 28 | public class StackTraceUtil {
 29 | 
 30 |   private static final String XLOG_STACK_TRACE_ORIGIN;
 31 | 
 32 |   static {
 33 |     // Let's start from xlog library.
 34 |     String xlogClassName = XLog.class.getName();
 35 |     XLOG_STACK_TRACE_ORIGIN = xlogClassName.substring(0, xlogClassName.lastIndexOf('.') + 1);
 36 |   }
 37 | 
 38 |   /**
 39 |    * Get a loggable stack trace from a Throwable
 40 |    *
 41 |    * @param tr An exception to log
 42 |    */
 43 |   public static String getStackTraceString(Throwable tr) {
 44 |     if (tr == null) {
 45 |       return "";
 46 |     }
 47 | 
 48 |     // This is to reduce the amount of log spew that apps do in the non-error
 49 |     // condition of the network being unavailable.
 50 |     Throwable t = tr;
 51 |     while (t != null) {
 52 |       if (t instanceof UnknownHostException) {
 53 |         return "";
 54 |       }
 55 |       t = t.getCause();
 56 |     }
 57 | 
 58 |     StringWriter sw = new StringWriter();
 59 |     PrintWriter pw = new PrintWriter(sw);
 60 |     tr.printStackTrace(pw);
 61 |     pw.flush();
 62 |     return sw.toString();
 63 |   }
 64 | 
 65 |   /**
 66 |    * Get the real stack trace and then crop it with a max depth.
 67 |    *
 68 |    * @param stackTrace the full stack trace
 69 |    * @param maxDepth   the max depth of real stack trace that will be cropped, 0 means no limitation
 70 |    * @return the cropped real stack trace
 71 |    */
 72 |   public static StackTraceElement[] getCroppedRealStackTrack(StackTraceElement[] stackTrace,
 73 |                                                              String stackTraceOrigin,
 74 |                                                              int maxDepth) {
 75 |     return cropStackTrace(getRealStackTrack(stackTrace, stackTraceOrigin), maxDepth);
 76 |   }
 77 | 
 78 |   /**
 79 |    * Get the real stack trace, all elements that come from XLog library would be dropped.
 80 |    *
 81 |    * @param stackTrace the full stack trace
 82 |    * @return the real stack trace, all elements come from system and library user
 83 |    */
 84 |   private static StackTraceElement[] getRealStackTrack(StackTraceElement[] stackTrace,
 85 |                                                        String stackTraceOrigin) {
 86 |     int ignoreDepth = 0;
 87 |     int allDepth = stackTrace.length;
 88 |     String className;
 89 |     for (int i = allDepth - 1; i >= 0; i--) {
 90 |       className = stackTrace[i].getClassName();
 91 |       if (className.startsWith(XLOG_STACK_TRACE_ORIGIN)
 92 |           || (stackTraceOrigin != null && className.startsWith(stackTraceOrigin))) {
 93 |         ignoreDepth = i + 1;
 94 |         break;
 95 |       }
 96 |     }
 97 |     int realDepth = allDepth - ignoreDepth;
 98 |     StackTraceElement[] realStack = new StackTraceElement[realDepth];
 99 |     System.arraycopy(stackTrace, ignoreDepth, realStack, 0, realDepth);
100 |     return realStack;
101 |   }
102 | 
103 |   /**
104 |    * Crop the stack trace with a max depth.
105 |    *
106 |    * @param callStack the original stack trace
107 |    * @param maxDepth  the max depth of real stack trace that will be cropped,
108 |    *                  0 means no limitation
109 |    * @return the cropped stack trace
110 |    */
111 |   private static StackTraceElement[] cropStackTrace(StackTraceElement[] callStack,
112 |                                                     int maxDepth) {
113 |     int realDepth = callStack.length;
114 |     if (maxDepth > 0) {
115 |       realDepth = Math.min(maxDepth, realDepth);
116 |     }
117 |     StackTraceElement[] realStack = new StackTraceElement[realDepth];
118 |     System.arraycopy(callStack, 0, realStack, 0, realDepth);
119 |     return realStack;
120 |   }
121 | }
122 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/AndroidPrinter.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2015 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlog.printer;
 18 | 
 19 | /**
 20 |  * Log {@link Printer} using {@link android.util.Log}.
 21 |  */
 22 | public class AndroidPrinter implements Printer {
 23 | 
 24 |   /**
 25 |    * Generally, android has a default length limit of 4096 for single log, but
 26 |    * some device(like HUAWEI) has its own shorter limit, so we just use 4000
 27 |    * and wish it could run well in all devices.
 28 |    */
 29 |   static final int DEFAULT_MAX_CHUNK_SIZE = 4000;
 30 | 
 31 |   /**
 32 |    * Whether the log should be separated by line separator automatically.
 33 |    */
 34 |   private boolean autoSeparate;
 35 | 
 36 |   private int maxChunkSize;
 37 | 
 38 |   /**
 39 |    * Constructor.
 40 |    * <p>
 41 |    * If single message is too long, it will be separated to several chunks automatically, the max
 42 |    * size of each chunk default to be {@value #DEFAULT_MAX_CHUNK_SIZE}, you can specify the
 43 |    * maxChunkSize using {@link #AndroidPrinter(int)}.
 44 |    */
 45 |   public AndroidPrinter() {
 46 |     this(false, DEFAULT_MAX_CHUNK_SIZE);
 47 |   }
 48 | 
 49 |   /**
 50 |    * Constructor.
 51 |    *
 52 |    * @param autoSeparate whether the message should be separated by line separator automatically.
 53 |    *                     Imaging there is a message "line1\nline2\nline3", and each line has chars
 54 |    *                     less than max-chunk-size, then the message would be separated to 3 lines
 55 |    *                     automatically
 56 |    * @since 1.7.1
 57 |    */
 58 |   public AndroidPrinter(boolean autoSeparate) {
 59 |     this(autoSeparate, DEFAULT_MAX_CHUNK_SIZE);
 60 |   }
 61 | 
 62 |   /**
 63 |    * Constructor.
 64 |    *
 65 |    * @param maxChunkSize the max size of each chunk. If the message is too long, it will be
 66 |    *                     separated to several chunks automatically
 67 |    * @since 1.4.1
 68 |    */
 69 |   public AndroidPrinter(int maxChunkSize) {
 70 |     this(false, maxChunkSize);
 71 |   }
 72 | 
 73 |   /**
 74 |    * Constructor.
 75 |    *
 76 |    * @param autoSeparate whether the message should be separated by line separator automatically.
 77 |    *                     Imaging there is a message "line1\nline2\nline3", and each line has chars
 78 |    *                     less than max-chunk-size, then the message would be separated to 3 lines
 79 |    *                     automatically
 80 |    * @param maxChunkSize the max size of each chunk. If the message is too long, it will be
 81 |    *                     separated to several chunks automatically
 82 |    * @since 1.7.1
 83 |    */
 84 |   public AndroidPrinter(boolean autoSeparate, int maxChunkSize) {
 85 |     this.autoSeparate = autoSeparate;
 86 |     this.maxChunkSize = maxChunkSize;
 87 |   }
 88 | 
 89 |   @Override
 90 |   public void println(int logLevel, String tag, String msg) {
 91 |     int msgLength = msg.length();
 92 |     int start = 0;
 93 |     int end;
 94 |     while (start < msgLength) {
 95 |       if (msg.charAt(start) == '\n') {
 96 |         start++;
 97 |         continue;
 98 |       }
 99 |       end = Math.min(start + maxChunkSize, msgLength);
100 |       if (autoSeparate) {
101 |         int newLine = msg.indexOf('\n', start);
102 |         end = newLine != -1 ? Math.min(end,newLine) : end;
103 |       } else {
104 |         end = adjustEnd(msg, start, end);
105 |       }
106 |       printChunk(logLevel, tag, msg.substring(start, end));
107 | 
108 |       start = end;
109 |     }
110 |   }
111 | 
112 |   /**
113 |    * Move the end to the nearest line separator('\n') (if exist).
114 |    */
115 |   static int adjustEnd(String msg, int start, int originEnd) {
116 |     if (originEnd == msg.length()) {
117 |       // Already end of message.
118 |       return originEnd;
119 |     }
120 |     if (msg.charAt(originEnd) == '\n') {
121 |       // Already prior to '\n'.
122 |       return originEnd;
123 |     }
124 |     // Search back for '\n'.
125 |     int last = originEnd - 1;
126 |     while (start < last) {
127 |       if (msg.charAt(last) == '\n') {
128 |         return last;
129 |       }
130 |       last--;
131 |     }
132 |     return originEnd;
133 |   }
134 | 
135 |   /**
136 |    * Print single chunk of log in new line.
137 |    *
138 |    * @param logLevel the level of log
139 |    * @param tag      the tag of log
140 |    * @param msg      the msg of log
141 |    */
142 |   void printChunk(int logLevel, String tag, String msg) {
143 |     android.util.Log.println(logLevel, tag, msg);
144 |   }
145 | }
146 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/ConsolePrinter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer;
18 | 
19 | import com.elvishew.xlog.internal.DefaultsFactory;
20 | import com.elvishew.xlog.flattener.Flattener;
21 | 
22 | /**
23 |  * Log {@link Printer} using {@code System.out.println(String)}.
24 |  *
25 |  * @since 1.3.0
26 |  */
27 | public class ConsolePrinter implements Printer {
28 | 
29 |   /**
30 |    * The log flattener when print a log.
31 |    */
32 |   private Flattener flattener;
33 | 
34 |   /**
35 |    * Constructor.
36 |    */
37 |   public ConsolePrinter() {
38 |     this.flattener = DefaultsFactory.createFlattener();
39 |   }
40 | 
41 |   /**
42 |    * Constructor.
43 |    *
44 |    * @param flattener the log flattener when print a log
45 |    */
46 |   public ConsolePrinter(Flattener flattener) {
47 |     this.flattener = flattener;
48 |   }
49 | 
50 |   @Override
51 |   public void println(int logLevel, String tag, String msg) {
52 |     String flattenedLog = flattener.flatten(logLevel, tag, msg).toString();
53 |     System.out.println(flattenedLog);
54 |   }
55 | }
56 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/Printer.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer;
18 | 
19 | import com.elvishew.xlog.printer.file.FilePrinter;
20 | 
21 | /**
22 |  * A printer is used for printing the log to somewhere, like android shell, terminal
23 |  * or file system.
24 |  * <p>
25 |  * There are 4 main implementation of Printer.
26 |  * <br>{@link AndroidPrinter}, print log to android shell terminal.
27 |  * <br>{@link ConsolePrinter}, print log to console via System.out.
28 |  * <br>{@link FilePrinter}, print log to file system.
29 |  * <br>{@link RemotePrinter}, print log to remote server, this is empty implementation yet.
30 |  */
31 | public interface Printer {
32 | 
33 |   /**
34 |    * Print log in new line.
35 |    *
36 |    * @param logLevel the level of log
37 |    * @param tag      the tag of log
38 |    * @param msg      the msg of log
39 |    */
40 |   void println(int logLevel, String tag, String msg);
41 | }
42 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/PrinterSet.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer;
18 | 
19 | /**
20 |  * Represents a group of Printers that should used to print logs in the same time, each printer
21 |  * may probably print the log to different place.
22 |  */
23 | public class PrinterSet implements Printer {
24 | 
25 |   private Printer[] printers;
26 | 
27 |   /**
28 |    * Constructor, pass printers in and will use all these printers to print the same logs.
29 |    *
30 |    * @param printers the printers used to print the same logs
31 |    */
32 |   public PrinterSet(Printer... printers) {
33 |     this.printers = printers;
34 |   }
35 | 
36 |   @Override
37 |   public void println(int logLevel, String tag, String msg) {
38 |     for (Printer printer : printers) {
39 |       printer.println(logLevel, tag, msg);
40 |     }
41 |   }
42 | }
43 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/RemotePrinter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer;
18 | 
19 | /**
20 |  * Log {@link Printer} which should print the log to remote server.
21 |  * <p>
22 |  * This is just a empty implementation telling you that you can do
23 |  * such thing, you can override {@link #println(int, String, String)} )} and sending the log by your
24 |  * implementation.
25 |  */
26 | public class RemotePrinter implements Printer {
27 | 
28 |   @Override
29 |   public void println(int logLevel, String tag, String msg) {
30 |     // TODO: Send the log to your server.
31 |   }
32 | }
33 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/SystemPrinter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer;
18 | 
19 | /**
20 |  * @deprecated use {@link ConsolePrinter} instead, since 1.3.0
21 |  */
22 | @Deprecated
23 | public class SystemPrinter extends ConsolePrinter {
24 | }
25 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/backup/AbstractBackupStrategy.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2021 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.file.backup;
18 | 
19 | /**
20 |  * An abstract {@link BackupStrategy2}, simply append '.bak.n' to the end of normal file name when
21 |  * naming a backup with index n.
22 |  * <p>
23 |  * Developers can simply extend this class when defining their own {@link BackupStrategy2}.
24 |  *
25 |  * @since 1.9.0
26 |  */
27 | public abstract class AbstractBackupStrategy implements BackupStrategy2 {
28 | 
29 |   @Override
30 |   public String getBackupFileName(String fileName, int backupIndex) {
31 |     return fileName + ".bak." + backupIndex;
32 |   }
33 | }
34 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/backup/BackupStrategy.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.file.backup;
18 | 
19 | import java.io.File;
20 | 
21 | /**
22 |  * Decide whether the log file should be backup and use a new file for next logging.
23 |  */
24 | public interface BackupStrategy {
25 | 
26 |   /**
27 |    * Whether we should backup a specified log file.
28 |    *
29 |    * @param file the log file
30 |    * @return true is we should backup the log file
31 |    */
32 |   boolean shouldBackup(File file);
33 | }
34 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/backup/BackupStrategy2.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2021 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.file.backup;
18 | 
19 | /**
20 |  * Decide whether and how the log file should be backed up and use a new file for next logging.
21 |  *
22 |  * @since 1.9.0
23 |  */
24 | public interface BackupStrategy2 extends BackupStrategy {
25 | 
26 |   /**
27 |    * Don't limit the backup index, which means there is no limit to the number of backup files.
28 |    */
29 |   int NO_LIMIT = 0;
30 | 
31 |   /**
32 |    * Get the max index of backup.
33 |    * <p>
34 |    * Generally, the max index should be greater than 1, and recommended to be less than 10.
35 |    * <p>
36 |    * Imagine the normal log file name is 'log', and max backup index is 'n', as the log grows,
37 |    * a log record would go from 'log' to 'log.bak.1', then to 'log.bak.2', 'log.bak.3', and finally
38 |    * to 'log.bak.n', the greater index, the older log.
39 |    * <br>After that, the log record will no longer exist in the file system.
40 |    * <p>
41 |    * If you don't want to limit the max index, then return {@link #NO_LIMIT}.
42 |    * <br>With returning {@link #NO_LIMIT}, When you backing up, the oldest log would be saved to
43 |    * 'log.bak.1', and then 'log.bak.2'...'log.bak.n', the greater index, the newer log.
44 |    * <p>
45 |    * Don't return {@link Integer#MAX_VALUE} or any value less than 0, otherwise an exception will
46 |    * be thrown.
47 |    *
48 |    * @return the max index of backup
49 |    */
50 |   int getMaxBackupIndex();
51 | 
52 |   /**
53 |    * Get the backup file name for specific index.
54 |    * <p>
55 |    * Generally, a backup file with normal file name 'log' and index 'n' could simply be 'log.bak.n',
56 |    * you can specify your own naming rules, by overriding this method.
57 |    * <p>
58 |    * Make sure to return different backup file name with different backup index, and same backup
59 |    * file name with same index. Otherwise, it will lead to unexpected behavior.
60 |    *
61 |    * @param fileName    the normal file name, generated by
62 |    *                    {@link com.elvishew.xlog.printer.file.naming.FileNameGenerator#generateFileName(int, long)}
63 |    * @param backupIndex the backup index, which will increase from 1 to {@link #getMaxBackupIndex()}
64 |    * @return the backup file name
65 |    */
66 |   String getBackupFileName(String fileName, int backupIndex);
67 | }
68 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/backup/FileSizeBackupStrategy.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.file.backup;
18 | 
19 | import java.io.File;
20 | 
21 | /**
22 |  * Limit the file size of a max length.
23 |  *
24 |  * @deprecated use {@link FileSizeBackupStrategy2} instead, since 1.9.0.
25 |  * A {@link FileSizeBackupStrategy2} allows you to define the max number of backup files
26 |  */
27 | @Deprecated
28 | public class FileSizeBackupStrategy implements BackupStrategy {
29 | 
30 |   private long maxSize;
31 | 
32 |   /**
33 |    * Constructor.
34 |    *
35 |    * @param maxSize the max size the file can reach
36 |    */
37 |   public FileSizeBackupStrategy(long maxSize) {
38 |     this.maxSize = maxSize;
39 |   }
40 | 
41 |   @Override
42 |   public boolean shouldBackup(File file) {
43 |     return file.length() > maxSize;
44 |   }
45 | }
46 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/backup/FileSizeBackupStrategy2.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2021 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.file.backup;
18 | 
19 | import java.io.File;
20 | 
21 | /**
22 |  * Limit the file size of a max length.
23 |  *
24 |  * @since 1.9.0
25 |  */
26 | public class FileSizeBackupStrategy2 extends AbstractBackupStrategy {
27 | 
28 |   private long maxSize;
29 | 
30 |   private int maxBackupIndex;
31 | 
32 |   /**
33 |    * Constructor.
34 |    *
35 |    * @param maxSize        the max size the file can reach
36 |    * @param maxBackupIndex the max backup index, or {@link #NO_LIMIT}, see {@link #getMaxBackupIndex()}
37 |    */
38 |   public FileSizeBackupStrategy2(long maxSize, int maxBackupIndex) {
39 |     this.maxSize = maxSize;
40 |     this.maxBackupIndex = maxBackupIndex;
41 |   }
42 | 
43 |   @Override
44 |   public boolean shouldBackup(File file) {
45 |     return file.length() > maxSize;
46 |   }
47 | 
48 |   @Override
49 |   public int getMaxBackupIndex() {
50 |     return maxBackupIndex;
51 |   }
52 | }
53 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/backup/NeverBackupStrategy.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.file.backup;
18 | 
19 | import java.io.File;
20 | 
21 | /**
22 |  * Never backup the log file.
23 |  *
24 |  * @since 1.3.0
25 |  */
26 | public class NeverBackupStrategy implements BackupStrategy {
27 | 
28 |   @Override
29 |   public boolean shouldBackup(File file) {
30 |     return false;
31 |   }
32 | }
33 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/clean/CleanStrategy.java:
--------------------------------------------------------------------------------
 1 | package com.elvishew.xlog.printer.file.clean;
 2 | 
 3 | import java.io.File;
 4 | 
 5 | /**
 6 |  * Decide whether the log file should be clean.
 7 |  *
 8 |  * @since 1.5.0
 9 |  */
10 | public interface CleanStrategy {
11 | 
12 |   /**
13 |    * Whether we should clean a specified log file.
14 |    *
15 |    * @param file the log file
16 |    * @return true is we should clean the log file
17 |    */
18 |   boolean shouldClean(File file);
19 | }
20 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/clean/FileLastModifiedCleanStrategy.java:
--------------------------------------------------------------------------------
 1 | package com.elvishew.xlog.printer.file.clean;
 2 | 
 3 | import java.io.File;
 4 | 
 5 | /**
 6 |  * Limit the file life of a max time.
 7 |  *
 8 |  * @since 1.5.0
 9 |  */
10 | public class FileLastModifiedCleanStrategy implements CleanStrategy {
11 | 
12 |   private long maxTimeMillis;
13 | 
14 |   /**
15 |    * Constructor.
16 |    *
17 |    * @param maxTimeMillis the max time the file can keep
18 |    */
19 |   public FileLastModifiedCleanStrategy(long maxTimeMillis) {
20 |     this.maxTimeMillis = maxTimeMillis;
21 |   }
22 | 
23 |   @Override
24 |   public boolean shouldClean(File file) {
25 |     long currentTimeMillis = System.currentTimeMillis();
26 |     long lastModified = file.lastModified();
27 |     return (currentTimeMillis - lastModified > maxTimeMillis);
28 |   }
29 | }
30 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/clean/NeverCleanStrategy.java:
--------------------------------------------------------------------------------
 1 | package com.elvishew.xlog.printer.file.clean;
 2 | 
 3 | import java.io.File;
 4 | 
 5 | /**
 6 |  * Never Limit the file life.
 7 |  *
 8 |  * @since 1.5.0
 9 |  */
10 | public class NeverCleanStrategy implements CleanStrategy {
11 | 
12 |   @Override
13 |   public boolean shouldClean(File file) {
14 |     return false;
15 |   }
16 | }
17 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/naming/ChangelessFileNameGenerator.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.file.naming;
18 | 
19 | /**
20 |  * Generate a file name that is changeless.
21 |  */
22 | public class ChangelessFileNameGenerator implements FileNameGenerator {
23 | 
24 |   private final String fileName;
25 | 
26 |   /**
27 |    * Constructor.
28 |    *
29 |    * @param fileName the changeless file name
30 |    */
31 |   public ChangelessFileNameGenerator(String fileName) {
32 |     this.fileName = fileName;
33 |   }
34 | 
35 |   @Override
36 |   public boolean isFileNameChangeable() {
37 |     return false;
38 |   }
39 | 
40 |   @Override
41 |   public String generateFileName(int logLevel, long timestamp) {
42 |     return fileName;
43 |   }
44 | }
45 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/naming/DateFileNameGenerator.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.file.naming;
18 | 
19 | import java.text.SimpleDateFormat;
20 | import java.util.Date;
21 | import java.util.Locale;
22 | import java.util.TimeZone;
23 | 
24 | /**
25 |  * Generate file name according to the timestamp, different dates will lead to different file names.
26 |  */
27 | public class DateFileNameGenerator implements FileNameGenerator {
28 | 
29 |   ThreadLocal<SimpleDateFormat> mLocalDateFormat = new ThreadLocal<SimpleDateFormat>() {
30 | 
31 |     @Override
32 |     protected SimpleDateFormat initialValue() {
33 |       return new SimpleDateFormat("yyyy-MM-dd", Locale.US);
34 |     }
35 |   };
36 | 
37 |   @Override
38 |   public boolean isFileNameChangeable() {
39 |     return true;
40 |   }
41 | 
42 |   /**
43 |    * Generate a file name which represent a specific date.
44 |    */
45 |   @Override
46 |   public String generateFileName(int logLevel, long timestamp) {
47 |     SimpleDateFormat sdf = mLocalDateFormat.get();
48 |     sdf.setTimeZone(TimeZone.getDefault());
49 |     return sdf.format(new Date(timestamp));
50 |   }
51 | }
52 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/naming/FileNameGenerator.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.file.naming;
18 | 
19 | /**
20 |  * Generates names for log files.
21 |  */
22 | public interface FileNameGenerator {
23 | 
24 |   /**
25 |    * Whether the generated file name will change or not.
26 |    *
27 |    * @return true if the file name is changeable
28 |    */
29 |   boolean isFileNameChangeable();
30 | 
31 |   /**
32 |    * Generate file name for specified log level and timestamp.
33 |    *
34 |    * @param logLevel  the level of the log
35 |    * @param timestamp the timestamp when the logging happen
36 |    * @return the generated file name
37 |    */
38 |   String generateFileName(int logLevel, long timestamp);
39 | }
40 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/naming/LevelFileNameGenerator.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.file.naming;
18 | 
19 | import com.elvishew.xlog.LogLevel;
20 | 
21 | /**
22 |  * Generate file name according to the log level, different levels lead to different file names.
23 |  */
24 | public class LevelFileNameGenerator implements FileNameGenerator {
25 | 
26 |   @Override
27 |   public boolean isFileNameChangeable() {
28 |     return true;
29 |   }
30 | 
31 |   /**
32 |    * Generate a file name which represent a specific log level.
33 |    */
34 |   @Override
35 |   public String generateFileName(int logLevel, long timestamp) {
36 |     return LogLevel.getLevelName(logLevel);
37 |   }
38 | }
39 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/writer/SimpleWriter.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2021 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlog.printer.file.writer;
 18 | 
 19 | import com.elvishew.xlog.internal.Platform;
 20 | 
 21 | import java.io.BufferedWriter;
 22 | import java.io.File;
 23 | import java.io.FileWriter;
 24 | 
 25 | /**
 26 |  * A simple implementation of {@link Writer}.
 27 |  * <p>
 28 |  * Subclass can override {@link #onNewFileCreated(File)} and do some initialization work to the new
 29 |  * file, such as calling {@link #appendLog(String)} to add a file header.
 30 |  *
 31 |  * @since 1.11.0
 32 |  */
 33 | public class SimpleWriter extends Writer {
 34 | 
 35 |   /**
 36 |    * The name of opened log file.
 37 |    */
 38 |   private String logFileName;
 39 | 
 40 |   /**
 41 |    * The opened log file.
 42 |    */
 43 |   private File logFile;
 44 | 
 45 |   private BufferedWriter bufferedWriter;
 46 | 
 47 |   @Override
 48 |   public boolean open(File file) {
 49 |     logFileName = file.getName();
 50 |     logFile = file;
 51 | 
 52 |     boolean isNewFile = false;
 53 | 
 54 |     // Create log file if not exists.
 55 |     if (!logFile.exists()) {
 56 |       try {
 57 |         File parent = logFile.getParentFile();
 58 |         if (!parent.exists()) {
 59 |           parent.mkdirs();
 60 |         }
 61 |         logFile.createNewFile();
 62 |         isNewFile = true;
 63 |       } catch (Exception e) {
 64 |         e.printStackTrace();
 65 |         close();
 66 |         return false;
 67 |       }
 68 |     }
 69 | 
 70 |     // Create buffered writer.
 71 |     try {
 72 |       bufferedWriter = new BufferedWriter(new FileWriter(logFile, true));
 73 |       if (isNewFile) {
 74 |         onNewFileCreated(logFile);
 75 |       }
 76 |     } catch (Exception e) {
 77 |       e.printStackTrace();
 78 |       close();
 79 |       return false;
 80 |     }
 81 |     return true;
 82 |   }
 83 | 
 84 |   @Override
 85 |   public boolean isOpened() {
 86 |     return bufferedWriter != null && logFile.exists();
 87 |   }
 88 | 
 89 |   @Override
 90 |   public File getOpenedFile() {
 91 |     return logFile;
 92 |   }
 93 | 
 94 |   @Override
 95 |   public String getOpenedFileName() {
 96 |     return logFileName;
 97 |   }
 98 | 
 99 |   /**
100 |    * Called after a log file is newly created.
101 |    * <p>
102 |    * You can do some initialization work to the new file, such as calling {@link #appendLog(String)}
103 |    * to add a file header.
104 |    * <p>
105 |    * Called in worker thread.
106 |    *
107 |    * @param file the newly created log file
108 |    */
109 |   public void onNewFileCreated(File file) {
110 |   }
111 | 
112 |   @Override
113 |   public void appendLog(String log) {
114 |     try {
115 |       bufferedWriter.write(log);
116 |       bufferedWriter.newLine();
117 |       bufferedWriter.flush();
118 |     } catch (Exception e) {
119 |       Platform.get().warn("append log failed: " + e.getMessage());
120 |     }
121 |   }
122 | 
123 |   @Override
124 |   public boolean close() {
125 |     if (bufferedWriter != null) {
126 |       try {
127 |         bufferedWriter.close();
128 |       } catch (Exception e) {
129 |         e.printStackTrace();
130 |       }
131 |     }
132 |     bufferedWriter = null;
133 |     logFileName = null;
134 |     logFile = null;
135 |     return true;
136 |   }
137 | }
138 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/file/writer/Writer.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2021 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.file.writer;
18 | 
19 | import java.io.File;
20 | 
21 | /**
22 |  * A writer is used to write log into log file.
23 |  * <p>
24 |  * Used in worker thread.
25 |  *
26 |  * @since 1.11.0
27 |  */
28 | public abstract class Writer {
29 | 
30 |   /**
31 |    * Open a specific log file for future writing, if it doesn't exist yet, just create it.
32 |    *
33 |    * @param file the specific log file, may not exist
34 |    * @return true if the log file is successfully opened, false otherwise
35 |    */
36 |   public abstract boolean open(File file);
37 | 
38 |   /**
39 |    * Whether a log file is successfully opened in previous {@link #open(File)}.
40 |    *
41 |    * @return true if log file is opened, false otherwise
42 |    */
43 |   public abstract boolean isOpened();
44 | 
45 |   /**
46 |    * Get the opened log file.
47 |    *
48 |    * @return the opened log file, or null if log file not opened
49 |    */
50 |   public abstract File getOpenedFile();
51 | 
52 |   /**
53 |    * Get the name of opened log file.
54 |    *
55 |    * @return the name of opened log file, or null if log file not opened
56 |    */
57 |   public abstract String getOpenedFileName();
58 | 
59 |   /**
60 |    * Append the log to the end of the opened log file, normally an extra line separator is needed.
61 |    *
62 |    * @param log the log to append
63 |    */
64 |   public abstract void appendLog(String log);
65 | 
66 |   /**
67 |    * Make sure the opened log file is closed, normally called before switching the log file.
68 |    *
69 |    * @return true if the log file is successfully closed, false otherwise
70 |    */
71 |   public abstract boolean close();
72 | }
73 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/flattener/DefaultLogFlattener.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.flattener;
18 | 
19 | import com.elvishew.xlog.flattener.DefaultFlattener;
20 | 
21 | /**
22 |  * @deprecated use {@link DefaultFlattener} instead, since 1.3.0
23 |  */
24 | @Deprecated
25 | public class DefaultLogFlattener extends DefaultFlattener {
26 | }
27 | 


--------------------------------------------------------------------------------
/xlog/src/main/java/com/elvishew/xlog/printer/flattener/LogFlattener.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer.flattener;
18 | 
19 | import com.elvishew.xlog.flattener.Flattener;
20 | 
21 | /**
22 |  * @deprecated use {@link Flattener} instead, since 1.3.0
23 |  */
24 | @Deprecated
25 | public interface LogFlattener extends Flattener {
26 | }
27 | 


--------------------------------------------------------------------------------
/xlog/src/test/java/com/elvishew/xlog/AssertUtil.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog;
18 | 
19 | import java.util.List;
20 | 
21 | import static org.junit.Assert.assertTrue;
22 | 
23 | public class AssertUtil {
24 | 
25 |   public static void assertHasLog(List<LogItem> logsContainer, LogItem target) {
26 |     boolean result = false;
27 |     for (LogItem log : logsContainer) {
28 |       if ((log.level == target.level)
29 |           && log.tag.equals(target.tag)
30 |           && log.msg.equals(target.msg)) {
31 |         result = true;
32 |       }
33 |     }
34 |     assertTrue("Missing log: " + target, result);
35 |   }
36 | 
37 |   public static void assertHasLog(List<LogItem> logsContainer, String msg) {
38 |     boolean result = false;
39 |     for (LogItem log : logsContainer) {
40 |       if (log.msg.equals(msg)) {
41 |         result = true;
42 |       }
43 |     }
44 |     assertTrue("Missing log: " + msg, result);
45 |   }
46 | 
47 |   public static void assertHasLog(List<LogItem> logsContainer, int position, String msg) {
48 |     boolean result = false;
49 |     if (logsContainer.size() > position
50 |         && logsContainer.get(position) != null
51 |         && logsContainer.get(position).msg.equals(msg)) {
52 |       result = true;
53 |     }
54 |     assertTrue("Missing log: " + msg, result);
55 |   }
56 | 
57 |   public static void assertNoLog(List<LogItem> logsContainer) {
58 |     boolean result = logsContainer.size() == 0;
59 |     assertTrue("Unexpected log found", result);
60 |   }
61 | }
62 | 


--------------------------------------------------------------------------------
/xlog/src/test/java/com/elvishew/xlog/ConcurrentTest.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2016 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlog;
 18 | 
 19 | import com.elvishew.xlog.printer.Printer;
 20 | 
 21 | import org.junit.Test;
 22 | 
 23 | import java.util.ArrayList;
 24 | import java.util.List;
 25 | import java.util.concurrent.atomic.AtomicBoolean;
 26 | 
 27 | import static com.elvishew.xlog.LogLevel.VERBOSE;
 28 | import static org.junit.Assert.assertEquals;
 29 | import static org.junit.Assert.assertTrue;
 30 | 
 31 | public class ConcurrentTest {
 32 | 
 33 |   @Test
 34 |   public void printLogsConcurrently() {
 35 | 
 36 |     // 5 printers and 5 containers.
 37 | 
 38 |     List<SequencedLog> logsContainer1 = new ArrayList<>();
 39 |     List<SequencedLog> logsContainer2 = new ArrayList<>();
 40 |     List<SequencedLog> logsContainer3 = new ArrayList<>();
 41 |     List<SequencedLog> logsContainer4 = new ArrayList<>();
 42 |     List<SequencedLog> logsContainer5 = new ArrayList<>();
 43 | 
 44 |     ThreadSafePrinter printer1 = new ThreadSafePrinter(logsContainer1);
 45 |     ThreadSafePrinter printer2 = new ThreadSafePrinter(logsContainer2);
 46 |     ThreadSafePrinter printer3 = new ThreadSafePrinter(logsContainer3);
 47 |     ThreadSafePrinter printer4 = new ThreadSafePrinter(logsContainer4);
 48 |     ThreadSafePrinter printer5 = new ThreadSafePrinter(logsContainer5);
 49 | 
 50 |     XLog.init(VERBOSE, printer1, printer2, printer3, printer4, printer5);
 51 | 
 52 |     // 4 threads print logs concurrently.
 53 | 
 54 |     final AtomicBoolean t1Done = new AtomicBoolean(false);
 55 |     final AtomicBoolean t2Done = new AtomicBoolean(false);
 56 |     final AtomicBoolean t3Done = new AtomicBoolean(false);
 57 |     final AtomicBoolean t4Done = new AtomicBoolean(false);
 58 | 
 59 |     final int logsCount = 2000;
 60 |     new Thread(new Runnable() {
 61 |       @Override
 62 |       public void run() {
 63 |         for (int i = 0; i < logsCount; i++) {
 64 |           XLog.i("t1 " + i);
 65 |           XLog.i("t1 " + i);
 66 |           XLog.i("t1 " + i);
 67 |         }
 68 |         t1Done.set(true);
 69 |       }
 70 |     }).start();
 71 | 
 72 |     new Thread(new Runnable() {
 73 |       @Override
 74 |       public void run() {
 75 |         for (int j = 0; j < logsCount; j++) {
 76 |           XLog.d("t2 " + j);
 77 |         }
 78 |         t2Done.set(true);
 79 |       }
 80 |     }).start();
 81 | 
 82 |     new Thread(new Runnable() {
 83 |       @Override
 84 |       public void run() {
 85 |         for (int k = 0; k < logsCount; k++) {
 86 |           XLog.d("t3 " + k);
 87 |           XLog.d("t3 " + k);
 88 |         }
 89 |         t3Done.set(true);
 90 |       }
 91 |     }).start();
 92 | 
 93 |     new Thread(new Runnable() {
 94 |       @Override
 95 |       public void run() {
 96 |         for (int k = 0; k < logsCount; k++) {
 97 |           XLog.d("t4 " + k);
 98 |           XLog.d("t4 " + k);
 99 |           XLog.d("t4 " + k);
100 |         }
101 |         t4Done.set(true);
102 |       }
103 |     }).start();
104 | 
105 |     // Wait until done.
106 |     while (!t1Done.get() || !t2Done.get() || !t3Done.get() || !t4Done.get()) ;
107 | 
108 |     // Assert logs number in all containers.
109 |     assertEquals(logsContainer1.size(), logsContainer2.size());
110 |     assertEquals(logsContainer1.size(), logsContainer3.size());
111 |     assertEquals(logsContainer1.size(), logsContainer4.size());
112 |     assertEquals(logsContainer1.size(), logsContainer5.size());
113 | 
114 |     // Assert logs content in all containers.
115 |     int size = logsContainer1.size();
116 |     for (int i = 0; i < size; i++) {
117 |       assertLog(logsContainer1.get(i), logsContainer2.get(i));
118 |       assertLog(logsContainer1.get(i), logsContainer3.get(i));
119 |       assertLog(logsContainer1.get(i), logsContainer4.get(i));
120 |       assertLog(logsContainer1.get(i), logsContainer5.get(i));
121 |     }
122 |   }
123 | 
124 |   private void assertLog(SequencedLog expected, SequencedLog log) {
125 |     assertTrue("Expect " + expected + " but found " + log, expected.seq == log.seq);
126 |   }
127 | 
128 |   private static class ThreadSafePrinter implements Printer {
129 | 
130 |     int seq;
131 | 
132 |     private List<SequencedLog> logsContainers;
133 | 
134 |     public ThreadSafePrinter(List<SequencedLog> logsContainer) {
135 |       this.logsContainers = logsContainer;
136 |     }
137 | 
138 |     @Override
139 |     public void println(int logLevel, String tag, String msg) {
140 |       synchronized (this) {
141 |         logsContainers.add(new SequencedLog(seq++, msg));
142 |       }
143 |     }
144 |   }
145 | 
146 |   private static class SequencedLog {
147 |     int seq;
148 |     String msg;
149 | 
150 |     SequencedLog(int seq, String msg) {
151 |       this.seq = seq;
152 |       this.msg = msg;
153 |     }
154 | 
155 |     @Override
156 |     public String toString() {
157 |       return "seq: " + seq + ", msg: " + msg;
158 |     }
159 |   }
160 | }


--------------------------------------------------------------------------------
/xlog/src/test/java/com/elvishew/xlog/ContainerPrinter.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2015 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog;
18 | 
19 | import com.elvishew.xlog.printer.Printer;
20 | 
21 | import java.util.ArrayList;
22 | import java.util.List;
23 | 
24 | public class ContainerPrinter implements Printer {
25 | 
26 |   private List<LogItem> logsContainers = new ArrayList<>();
27 | 
28 |   public ContainerPrinter(List<LogItem> logsContainer) {
29 |     this.logsContainers = logsContainer;
30 |   }
31 | 
32 |   @Override
33 |   public void println(int logLevel, String tag, String msg) {
34 |     LogItem log = onPrint(new LogItem(logLevel, tag, msg));
35 |     afterPrint(log);
36 |   }
37 | 
38 |   protected LogItem onPrint(LogItem logItem) {
39 |     return logItem;
40 |   }
41 | 
42 |   private void afterPrint(LogItem log) {
43 |     logsContainers.add(log);
44 |   }
45 | }
46 | 


--------------------------------------------------------------------------------
/xlog/src/test/java/com/elvishew/xlog/RandomUtil.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog;
18 | 
19 | import java.util.Random;
20 | 
21 | public class RandomUtil {
22 | 
23 |   private static Random sAsciiCharRandom = new Random();
24 | 
25 |   public static char randomAsciiChar() {
26 |     return (char) (sAsciiCharRandom.nextInt(100) + 28/* Just don't random to a line separator*/);
27 |   }
28 | }
29 | 


--------------------------------------------------------------------------------
/xlog/src/test/java/com/elvishew/xlog/XLogUtil.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog;
18 | 
19 | public class XLogUtil {
20 | 
21 |   public static void beforeTest() {
22 |     XLog.sIsInitialized = false;
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/xlog/src/test/java/com/elvishew/xlog/flattener/PatternFlattenerTest.java:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Copyright 2016 Elvis Hew
  3 |  *
  4 |  * Licensed under the Apache License, Version 2.0 (the "License");
  5 |  * you may not use this file except in compliance with the License.
  6 |  * You may obtain a copy of the License at
  7 |  *
  8 |  *     http://www.apache.org/licenses/LICENSE-2.0
  9 |  *
 10 |  * Unless required by applicable law or agreed to in writing, software
 11 |  * distributed under the License is distributed on an "AS IS" BASIS,
 12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13 |  * See the License for the specific language governing permissions and
 14 |  * limitations under the License.
 15 |  */
 16 | 
 17 | package com.elvishew.xlog.flattener;
 18 | 
 19 | import org.junit.Test;
 20 | 
 21 | import java.util.List;
 22 | 
 23 | import static org.junit.Assert.assertEquals;
 24 | import static org.junit.Assert.assertFalse;
 25 | import static org.junit.Assert.assertNotNull;
 26 | import static org.junit.Assert.assertNull;
 27 | import static org.junit.Assert.assertTrue;
 28 | 
 29 | public class PatternFlattenerTest {
 30 | 
 31 |   @Test
 32 |   public void testParsePattern() {
 33 |     List<String> parameters = PatternFlattener.parsePattern(
 34 |         "{d yyyy-MM-dd hh:mm:ss.SSS} {l}/{t}: {m}");
 35 |     assertNotNull(parameters);
 36 |     assertEquals(4, parameters.size());
 37 |     assertEquals("d yyyy-MM-dd hh:mm:ss.SSS", parameters.get(0));
 38 |     assertEquals("l", parameters.get(1));
 39 |     assertEquals("t", parameters.get(2));
 40 |     assertEquals("m", parameters.get(3));
 41 | 
 42 |     parameters = PatternFlattener.parsePattern(
 43 |         "Abc { d yyyy  } {l }/{ t}: { m } def");
 44 |     assertNotNull(parameters);
 45 |     assertEquals(4, parameters.size());
 46 |     assertEquals(" d yyyy  ", parameters.get(0));
 47 |     assertEquals("l ", parameters.get(1));
 48 |     assertEquals(" t", parameters.get(2));
 49 |     assertEquals(" m ", parameters.get(3));
 50 | 
 51 |     parameters = PatternFlattener.parsePattern(
 52 |         "No valid parameter {f }");
 53 |     assertNotNull(parameters);
 54 |     assertEquals(1, parameters.size());
 55 |     assertEquals("f ", parameters.get(0));
 56 | 
 57 |     parameters = PatternFlattener.parsePattern(
 58 |         "No parameter");
 59 |     assertNotNull(parameters);
 60 |     assertEquals(0, parameters.size());
 61 |   }
 62 | 
 63 |   @Test
 64 |   public void testParseDateParameter() {
 65 |     // Test date format.
 66 |     PatternFlattener.ParameterFiller parameterFiller = PatternFlattener.parseDateParameter(
 67 |         "{d yyyy}", "d yyyy");
 68 |     assertNoNullAndClass(parameterFiller, PatternFlattener.DateFiller.class);
 69 |     assertEquals("yyyy", ((PatternFlattener.DateFiller) parameterFiller).dateFormat);
 70 | 
 71 |     // Test default date format.
 72 |     parameterFiller = PatternFlattener.parseDateParameter("{d}", "d");
 73 |     assertNoNullAndClass(parameterFiller, PatternFlattener.DateFiller.class);
 74 |     assertEquals(PatternFlattener.DEFAULT_DATE_FORMAT,
 75 |         ((PatternFlattener.DateFiller) parameterFiller).dateFormat);
 76 | 
 77 |     // Test invalid format.
 78 |     parameterFiller = PatternFlattener.parseDateParameter("{D}", "D");
 79 |     assertNull(parameterFiller);
 80 |   }
 81 | 
 82 |   @Test
 83 |   public void testParseLevelParameter() {
 84 |     // Test short level format.
 85 |     PatternFlattener.ParameterFiller parameterFiller = PatternFlattener.parseLevelParameter("{l}", "l");
 86 |     assertNoNullAndClass(parameterFiller, PatternFlattener.LevelFiller.class);
 87 |     assertFalse(((PatternFlattener.LevelFiller) parameterFiller).useLongName);
 88 | 
 89 |     // Test long level format.
 90 |     parameterFiller = PatternFlattener.parseLevelParameter("{L}", "L");
 91 |     assertNoNullAndClass(parameterFiller, PatternFlattener.LevelFiller.class);
 92 |     assertTrue(((PatternFlattener.LevelFiller) parameterFiller).useLongName);
 93 | 
 94 |     // Test invalid format.
 95 |     parameterFiller = PatternFlattener.parseDateParameter("{ll}", "ll");
 96 |     assertNull(parameterFiller);
 97 |   }
 98 | 
 99 |   @Test
100 |   public void testParseTagParameter() {
101 |     PatternFlattener.ParameterFiller parameterFiller = PatternFlattener.parseTagParameter(
102 |         "{t}", "t");
103 |     assertNoNullAndClass(parameterFiller, PatternFlattener.TagFiller.class);
104 | 
105 |     // Test invalid format.
106 |     parameterFiller = PatternFlattener.parseDateParameter("{T}", "T");
107 |     assertNull(parameterFiller);
108 |   }
109 | 
110 |   @Test
111 |   public void testParseMessageParameter() {
112 |     PatternFlattener.ParameterFiller parameterFiller = PatternFlattener.parseMessageParameter(
113 |         "{m}", "m");
114 |     assertNoNullAndClass(parameterFiller, PatternFlattener.MessageFiller.class);
115 | 
116 |     // Test invalid format.
117 |     parameterFiller = PatternFlattener.parseDateParameter("{M}", "M");
118 |     assertNull(parameterFiller);
119 |   }
120 | 
121 |   private void assertNoNullAndClass(PatternFlattener.ParameterFiller parameterFiller, Class<?> clazz) {
122 |     assertNotNull("Parameter filler not created", parameterFiller);
123 |     assertTrue("Parameter filler class not expected: " + parameterFiller.getClass(),
124 |         parameterFiller.getClass() == clazz);
125 |   }
126 | }


--------------------------------------------------------------------------------
/xlog/src/test/java/com/elvishew/xlog/interceptor/BlacklistTagsFilterInterceptorTest.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.interceptor;
18 | 
19 | import com.elvishew.xlog.LogItem;
20 | import com.elvishew.xlog.LogLevel;
21 | 
22 | import org.junit.Before;
23 | import org.junit.Test;
24 | 
25 | import static org.junit.Assert.assertNotNull;
26 | import static org.junit.Assert.assertNull;
27 | 
28 | public class BlacklistTagsFilterInterceptorTest {
29 | 
30 |   private BlacklistTagsFilterInterceptor interceptor;
31 | 
32 |   @Before
33 |   public void setup() {
34 |     interceptor = new BlacklistTagsFilterInterceptor("abc", "def");
35 |   }
36 | 
37 |   @Test
38 |   public void testBlacklist() throws Exception {
39 |     assertTagRejected("abc");
40 |     assertTagRejected("def");
41 | 
42 |     assertTagAccepted("");
43 |     assertTagAccepted("ab");
44 |     assertTagAccepted("abcd");
45 |     assertTagAccepted("bcd");
46 |     assertTagAccepted("abcdef");
47 |     assertTagAccepted("defg");
48 |     assertTagAccepted("ef");
49 |   }
50 | 
51 |   private void assertTagAccepted(String tag) {
52 |     LogItem log = new LogItem(LogLevel.DEBUG, tag, "Message");
53 |     assertNotNull("Tag " + log.tag + " should be accepted", interceptor.intercept(log));
54 |   }
55 | 
56 |   private void assertTagRejected(String tag) {
57 |     LogItem log = new LogItem(LogLevel.DEBUG, tag, "Message");
58 |     assertNull("Tag " + log.tag + " should be rejected", interceptor.intercept(log));
59 |   }
60 | }


--------------------------------------------------------------------------------
/xlog/src/test/java/com/elvishew/xlog/interceptor/WhitelistTagsFilterInterceptorTest.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.interceptor;
18 | 
19 | import com.elvishew.xlog.LogItem;
20 | import com.elvishew.xlog.LogLevel;
21 | 
22 | import org.junit.Before;
23 | import org.junit.Test;
24 | 
25 | import static org.junit.Assert.assertNotNull;
26 | import static org.junit.Assert.assertNull;
27 | 
28 | public class WhitelistTagsFilterInterceptorTest {
29 | 
30 |   private WhitelistTagsFilterInterceptor interceptor;
31 | 
32 |   @Before
33 |   public void setup() {
34 |     interceptor = new WhitelistTagsFilterInterceptor("abc", "def");
35 |   }
36 | 
37 |   @Test
38 |   public void testWhitelist() throws Exception {
39 |     assertTagAccepted("abc");
40 |     assertTagAccepted("def");
41 | 
42 |     assertTagRejected("");
43 |     assertTagRejected("ab");
44 |     assertTagRejected("abcd");
45 |     assertTagRejected("bcd");
46 |     assertTagRejected("abcdef");
47 |     assertTagRejected("defg");
48 |     assertTagRejected("ef");
49 |   }
50 | 
51 |   private void assertTagAccepted(String tag) {
52 |     LogItem log = new LogItem(LogLevel.DEBUG, tag, "Message");
53 |     assertNotNull("Tag " + log.tag + " should be accepted", interceptor.intercept(log));
54 |   }
55 | 
56 |   private void assertTagRejected(String tag) {
57 |     LogItem log = new LogItem(LogLevel.DEBUG, tag, "Message");
58 |     assertNull("Tag " + log.tag + " should be rejected", interceptor.intercept(log));
59 |   }
60 | }


--------------------------------------------------------------------------------
/xlog/src/test/java/com/elvishew/xlog/printer/AndroidPrinterTest.java:
--------------------------------------------------------------------------------
 1 | /*
 2 |  * Copyright 2016 Elvis Hew
 3 |  *
 4 |  * Licensed under the Apache License, Version 2.0 (the "License");
 5 |  * you may not use this file except in compliance with the License.
 6 |  * You may obtain a copy of the License at
 7 |  *
 8 |  *     http://www.apache.org/licenses/LICENSE-2.0
 9 |  *
10 |  * Unless required by applicable law or agreed to in writing, software
11 |  * distributed under the License is distributed on an "AS IS" BASIS,
12 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 |  * See the License for the specific language governing permissions and
14 |  * limitations under the License.
15 |  */
16 | 
17 | package com.elvishew.xlog.printer;
18 | 
19 | import com.elvishew.xlog.AssertUtil;
20 | import com.elvishew.xlog.LogItem;
21 | import com.elvishew.xlog.LogLevel;
22 | import com.elvishew.xlog.RandomUtil;
23 | import com.elvishew.xlog.XLog;
24 | import com.elvishew.xlog.XLogUtil;
25 | 
26 | import org.junit.Before;
27 | import org.junit.Test;
28 | 
29 | import java.util.ArrayList;
30 | import java.util.List;
31 | 
32 | import static org.junit.Assert.assertEquals;
33 | 
34 | public class AndroidPrinterTest {
35 | 
36 |   List<LogItem> logContainer = new ArrayList<>();
37 | 
38 |   @Before
39 |   public void setup() {
40 |     XLogUtil.beforeTest();
41 |     XLog.init(LogLevel.ALL, new AndroidPrinter() {
42 |       @Override
43 |       void printChunk(int logLevel, String tag, String msg) {
44 |         logContainer.add(new LogItem(logLevel, tag, msg));
45 |       }
46 |     });
47 |   }
48 | 
49 |   @Test
50 |   public void testPrintShortMessage() throws Exception {
51 |     String msg = "This is a short message";
52 |     XLog.d(msg);
53 |     assertEquals(1, logContainer.size());
54 |     AssertUtil.assertHasLog(logContainer, msg);
55 |   }
56 | 
57 |   @Test
58 |   public void testPrint4kMessage() throws Exception {
59 |     int length = AndroidPrinter.DEFAULT_MAX_CHUNK_SIZE;
60 |     StringBuilder sb = new StringBuilder(length);
61 |     for (int i = 0; i < length; i++) {
62 |       sb.append(RandomUtil.randomAsciiChar());
63 |     }
64 |     String msg = sb.toString();
65 |     XLog.d(msg);
66 |     assertEquals(1, logContainer.size());
67 |     AssertUtil.assertHasLog(logContainer, msg);
68 |   }
69 | 
70 |   @Test
71 |   public void testPrintLongMessage() throws Exception {
72 |     int messageChunkLength = AndroidPrinter.DEFAULT_MAX_CHUNK_SIZE;
73 |     int length = (int) (3.6 * messageChunkLength);
74 |     StringBuilder sb = new StringBuilder(length);
75 |     for (int i = 0; i < length; i++) {
76 |       sb.append(RandomUtil.randomAsciiChar());
77 |     }
78 |     String msg = sb.toString();
79 |     XLog.d(msg);
80 |     assertEquals(4, logContainer.size());
81 | 
82 |     int start = 0;
83 |     int end = 0;
84 |     for (int i = 0; end < length; i++) {
85 |       end = AndroidPrinter.adjustEnd(msg, start, Math.min(start + messageChunkLength, length));
86 |       String chunk = msg.substring(start, end);
87 |       AssertUtil.assertHasLog(logContainer, i, chunk);
88 | 
89 |       start = end;
90 |     }
91 |   }
92 | }


--------------------------------------------------------------------------------