pax_global_header00006660000000000000000000000064137601213600014511gustar00rootroot0000000000000052 comment=8920c5da40f90c4e8b060e1c39357d04d007f152 jcabi-log-0.19.0/000077500000000000000000000000001376012136000134275ustar00rootroot00000000000000jcabi-log-0.19.0/.0pdd.yml000066400000000000000000000001351376012136000150560ustar00rootroot00000000000000errors: - yegor256@gmail.com # alerts: # github: # - yegor256 tags: - pdd - bug jcabi-log-0.19.0/.gitattributes000066400000000000000000000003461376012136000163250ustar00rootroot00000000000000# Check out all text files in UNIX format, with LF as end of line # Don't change this file. If you have any ideas about it, please # submit a separate issue about it and we'll discuss. * text=auto eol=lf *.java ident *.xml ident jcabi-log-0.19.0/.github/000077500000000000000000000000001376012136000147675ustar00rootroot00000000000000jcabi-log-0.19.0/.github/ISSUE_TEMPLATE.md000066400000000000000000000013621376012136000174760ustar00rootroot00000000000000Make sure the title of the issue explains the problem you are having. Also, the description of the issue must clearly explain what is broken, not what you want us to implement. Go through this checklist and make sure you answer "YES" to all points: - You have all pre-requisites listed in README.md installed - You are sure that you are not reporting a duplicate (search all issues) - You say "is broken" or "doesn't work" in the title - You tell us what you are trying to do - You explain the results you are getting - You suggest an alternative result you would like to see This article will help you understand what we are looking for: http://www.yegor256.com/2014/11/24/principles-of-bug-tracking.html Thank you for your contribution! jcabi-log-0.19.0/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000012271376012136000205720ustar00rootroot00000000000000Many thanks for your contribution, we truly appreciate it. We will appreciate it even more, if you make sure that you can say "YES" to each point in this short checklist: - You made a small amount of changes (less than 100 lines, less than 10 files) - You made changes related to only one bug (create separate PRs for separate problems) - You are ready to defend your changes (there will be a code review) - You don't touch what you don't understand - You ran the build locally and it passed This article will help you understand what we are looking for: http://www.yegor256.com/2015/02/09/serious-code-reviewer.html Thank you for your contribution! jcabi-log-0.19.0/.gitignore000066400000000000000000000000741376012136000154200ustar00rootroot00000000000000target/ .idea jcabi-log.iml /.project .settings /.classpath jcabi-log-0.19.0/.pdd000066400000000000000000000002251376012136000141760ustar00rootroot00000000000000--source=. --verbose --exclude target/**/* --exclude src/main/resources/images/**/* --rule min-words:20 --rule min-estimate:0 --rule max-estimate:90 jcabi-log-0.19.0/.rultor.yml000066400000000000000000000014131376012136000155560ustar00rootroot00000000000000env: MAVEN_OPTS: -XX:MaxPermSize=256m -Xmx1g assets: secring.gpg: yegor256/home#assets/secring.gpg settings.xml: yegor256/home#assets/jcabi/settings.xml pubring.gpg: yegor256/home#assets/pubring.gpg install: | sudo update-java-alternatives -s java-1.8.0-openjdk-amd64 sudo gem install pdd sudo gem install xcop pdd --file=/dev/null merge: script: |- mvn clean install -Pqulice --errors --settings ../settings.xml deploy: script: |- mvn clean deploy -Pqulice --errors --settings ../settings.xml release: script: |- mvn versions:set "-DnewVersion=${tag}" git commit -am "${tag}" mvn clean deploy -Pqulice -Psonatype -Pjcabi --errors --settings ../settings.xml # mvn clean site-deploy -Pjcabi -Psite --errors --settings ../settings.xml jcabi-log-0.19.0/.travis.yml000066400000000000000000000007231376012136000155420ustar00rootroot00000000000000language: java sudo: false cache: directories: - $HOME/.m2 script: - set -e - mvn clean install -Pqulice --errors --batch-mode - mvn clean - pdd --source=$(pwd) --file=/dev/null - est --dir=est --file=/dev/null before_install: - rvm install 2.6.0 - rvm use 2.6.0 install: - gem install pdd -v 0.20.5 - gem install est -v 0.3.4 - gem install xcop -v 0.6 env: global: - MAVEN_OPTS="-Xmx256m" - JAVA_OPTS="-Xmx256m" jdk: - openjdk8 jcabi-log-0.19.0/LICENSE.txt000066400000000000000000000027031376012136000152540ustar00rootroot00000000000000Copyright (c) 2012-2020, jcabi.com All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1) Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3) Neither the name of the jcabi.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. jcabi-log-0.19.0/README.md000066400000000000000000000045141376012136000147120ustar00rootroot00000000000000 [![EO principles respected here](https://www.elegantobjects.org/badge.svg)](https://www.elegantobjects.org) [![Managed by Zerocracy](https://www.0crat.com/badge/C3RUBL5H9.svg)](https://www.0crat.com/p/C3RUBL5H9) [![DevOps By Rultor.com](http://www.rultor.com/b/jcabi/jcabi-log)](http://www.rultor.com/p/jcabi/jcabi-log) [![We recommend IntelliJ IDEA](https://www.elegantobjects.org/intellij-idea.svg)](https://www.jetbrains.com/idea/) [![Build Status](https://travis-ci.org/jcabi/jcabi-log.svg?branch=master)](https://travis-ci.org/jcabi/jcabi-log) [![PDD status](http://www.0pdd.com/svg?name=jcabi/jcabi-log)](http://www.0pdd.com/p?name=jcabi/jcabi-log) [![Build status](https://ci.appveyor.com/api/projects/status/tk5nksux8peh2n8o/branch/master?svg=true)](https://ci.appveyor.com/project/yegor256/jcabi-log/branch/master) [![Coverage Status](https://coveralls.io/repos/jcabi/jcabi-log/badge.svg?branch=master&service=github)](https://coveralls.io/github/jcabi/jcabi-log?branch=master) [![jpeek report](https://i.jpeek.org/com.jcabi/jcabi-log/badge.svg)](https://i.jpeek.org/com.jcabi/jcabi-log/) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.jcabi/jcabi-log/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.jcabi/jcabi-log) [![Javadoc](https://javadoc.io/badge/com.jcabi/jcabi-log.svg)](http://www.javadoc.io/doc/com.jcabi/jcabi-log) [![Hits-of-Code](https://hitsofcode.com/github/jcabi/jcabi-log)](https://hitsofcode.com/view/github/jcabi/jcabi-log) More details are here: [log.jcabi.com](https://log.jcabi.com/index.html) Read this blog post: [_Get Rid of Java Static Loggers_](https://www.yegor256.com/2014/05/23/avoid-java-static-logger.html) `Logger` is a convenient static wrapper of [slf4j](http://www.slf4j.org/) (don't forget to include one of [SLF4J Bindings](http://www.slf4j.org/manual.html#binding) into the project): ```java import com.jcabi.log.Logger; class Foo { void bar(int value) { Logger.debug(this, "method #bar(%d) was called", value); } } ``` ## How to contribute? Fork the repository, make changes, submit a pull request. We promise to review your changes same day and apply to the `master` branch, if they look correct. Please run Maven build before submitting a pull request: ``` $ mvn clean install -Pqulice ``` jcabi-log-0.19.0/appveyor.yml000066400000000000000000000020211376012136000160120ustar00rootroot00000000000000version: '{build}' skip_tags: true clone_depth: 10 environment: matrix: - JAVA_HOME: C:\Program Files\Java\jdk1.7.0 #- JAVA_HOME: C:\Program Files\Java\jdk1.8.0 branches: only: - master except: - gh-pages os: Windows Server 2012 install: - ps: | Add-Type -AssemblyName System.IO.Compression.FileSystem if (!(Test-Path -Path "C:\maven" )) { (new-object System.Net.WebClient).DownloadFile('http://www.us.apache.org/dist/maven/maven-3/3.2.5/binaries/apache-maven-3.2.5-bin.zip', 'C:\maven-bin.zip') [System.IO.Compression.ZipFile]::ExtractToDirectory("C:\maven-bin.zip", "C:\maven") } - cmd: SET PATH=C:\maven\apache-maven-3.2.5\bin;%JAVA_HOME%\bin;%PATH:C:\Ruby193\bin;=% - cmd: SET MAVEN_OPTS=-XX:MaxPermSize=2g -Xmx4g - cmd: SET JAVA_OPTS=-XX:MaxPermSize=2g -Xmx4g - cmd: mvn --version - cmd: java -version build_script: - mvn clean package -B -Dmaven.test.skip=true test_script: - mvn clean install --batch-mode -Pqulice cache: - C:\maven\ - C:\Users\appveyor\.m2 jcabi-log-0.19.0/pom.xml000066400000000000000000000110661376012136000147500ustar00rootroot00000000000000 4.0.0 com.jcabi jcabi 1.26.0 jcabi-log 0.19.0 jcabi-log bundle Wrapper of SLF4J and a few supplementary logging classes github https://github.com/jcabi/jcabi-log/issues travis https://travis-ci.org/jcabi/jcabi-log scm:git:github.com:jcabi/jcabi-log.git scm:git:github.com:jcabi/jcabi-log.git https://github.com/jcabi/jcabi-log github-pages https://log.jcabi.com/ org.projectlombok lombok log4j log4j compile true org.slf4j slf4j-api 1.8.0-beta1 org.junit.jupiter junit-jupiter-params 5.6.2 test org.apache.commons commons-lang3 test org.apache.commons commons-text test maven-surefire-plugin Cp1251 qulice com.qulice qulice-maven-plugin findbugs:.* duplicatefinder:.* jcabi-log-0.19.0/src/000077500000000000000000000000001376012136000142165ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/000077500000000000000000000000001376012136000146325ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/000077500000000000000000000000001376012136000173715ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/invoker.properties000066400000000000000000000000331376012136000231600ustar00rootroot00000000000000invoker.goals = clean test jcabi-log-0.19.0/src/it/it-decoloring/pom.xml000066400000000000000000000046461376012136000207200ustar00rootroot00000000000000 4.0.0 com.jcabi jcabi 1.26.0 com.jcabi jcabi-log-test 1.0-SNAPSHOT @project.groupId@ @project.artifactId@ @project.version@ org.apache.commons commons-text test log4j log4j test jcabi-log-0.19.0/src/it/it-decoloring/src/000077500000000000000000000000001376012136000201605ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/src/main/000077500000000000000000000000001376012136000211045ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/src/main/java/000077500000000000000000000000001376012136000220255ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/src/main/java/com/000077500000000000000000000000001376012136000226035ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/src/main/java/com/jcabi/000077500000000000000000000000001376012136000236535ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/src/main/java/com/jcabi/log/000077500000000000000000000000001376012136000244345ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/src/main/java/com/jcabi/log/MulticolorLayoutIntegration.java000066400000000000000000000035511376012136000330360ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; /** * Integration tests for MulticolorLayout. These have to * be run with maven-invoker-plugin because they set the system property * com.jcabi.log.coloring, which interferes with other tests (tests are run * by multiple threads at once) * @since 0.1 */ public final class MulticolorLayoutIntegration { } jcabi-log-0.19.0/src/it/it-decoloring/src/main/java/com/jcabi/log/package-info.java000066400000000000000000000031171376012136000276250ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * Integration tests. */ package com.jcabi.log; jcabi-log-0.19.0/src/it/it-decoloring/src/test/000077500000000000000000000000001376012136000211375ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/src/test/java/000077500000000000000000000000001376012136000220605ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/src/test/java/com/000077500000000000000000000000001376012136000226365ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/src/test/java/com/jcabi/000077500000000000000000000000001376012136000237065ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/src/test/java/com/jcabi/log/000077500000000000000000000000001376012136000244675ustar00rootroot00000000000000MulticolorLayoutIntegrationTest.java000066400000000000000000000176101376012136000336530ustar00rootroot00000000000000jcabi-log-0.19.0/src/it/it-decoloring/src/test/java/com/jcabi/log/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import org.apache.commons.text.StringEscapeUtils; import org.apache.log4j.Level; import org.apache.log4j.spi.LoggingEvent; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.mockito.Mockito; /** * Integration tests for MulticolorLayout. These have to * be run with maven-invoker-plugin because they set the system property * com.jcabi.log.coloring, which interferes with other tests (tests are run * by multiple threads at once) * @since 0.1 */ public final class MulticolorLayoutIntegrationTest { /** * Conversation pattern for test case. */ private static final String CONV_PATTERN = "[%color{%p}] %color{%m}"; /** * Property that dictates wheter the text should be coloured or not. */ private static final String COLORING_PROPERTY = "com.jcabi.log.coloring"; /** * MulticolorLayout disables default color * when -Dcom.jcabi.log.coloring=false. * @throws Exception - if something goes wrong. */ @Test public void disablesDefaultColor() throws Exception { final MulticolorLayout layout = new MulticolorLayout(); layout.setConversionPattern( MulticolorLayoutIntegrationTest.CONV_PATTERN ); final LoggingEvent event = Mockito.mock(LoggingEvent.class); Mockito.doReturn(Level.DEBUG).when(event).getLevel(); Mockito.doReturn("no color").when(event).getRenderedMessage(); MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo( "[\\u001B[2;37mDEBUG\\u001B[m] \\u001B[2;37mno color\\u001B[m" ) ); System.getProperties().setProperty( MulticolorLayoutIntegrationTest.COLORING_PROPERTY, Boolean.FALSE.toString() ); try { MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo( "[DEBUG] no color" ) ); } finally { System.getProperties().setProperty( MulticolorLayoutIntegrationTest.COLORING_PROPERTY, Boolean.TRUE.toString() ); } } /** * MulticolorLayout disables the color that overwrites the default one. * @throws Exception - if something goes wrong. */ @Test public void disablesOverridenDefaultColor() throws Exception { final MulticolorLayout layout = new MulticolorLayout(); layout.setConversionPattern("[%color{%p}] %m"); layout.setLevels("DEBUG:2;10"); final LoggingEvent event = Mockito.mock(LoggingEvent.class); Mockito.doReturn(Level.DEBUG).when(event).getLevel(); Mockito.doReturn("no colour text").when(event).getRenderedMessage(); MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo( "[\\u001B[2;10mDEBUG\\u001B[m] no colour text" ) ); System.getProperties().setProperty( MulticolorLayoutIntegrationTest.COLORING_PROPERTY, Boolean.FALSE.toString() ); try { MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo( "[DEBUG] no colour text" ) ); } finally { System.getProperties().setProperty( MulticolorLayoutIntegrationTest.COLORING_PROPERTY, Boolean.TRUE.toString() ); } } /** * MulticolorLayout disables constant color * when -Dcom.jcabi.log.coloring=false. * @throws Exception - if something goes wrong. */ @Test public void disablesConstantColor() throws Exception { final MulticolorLayout layout = new MulticolorLayout(); layout.setConversionPattern("[%color-blue{%p}] %color-blue{%m}"); final LoggingEvent event = Mockito.mock(LoggingEvent.class); Mockito.doReturn(Level.DEBUG).when(event).getLevel(); Mockito.doReturn("no color text").when(event).getRenderedMessage(); MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo( "[\\u001B[34mDEBUG\\u001B[m] \\u001B[34mno color text\\u001B[m" ) ); System.getProperties().setProperty( MulticolorLayoutIntegrationTest.COLORING_PROPERTY, Boolean.FALSE.toString() ); try { MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo( "[DEBUG] no color text" ) ); } finally { System.getProperties().setProperty( MulticolorLayoutIntegrationTest.COLORING_PROPERTY, Boolean.TRUE.toString() ); } } /** * MulticolorLayout disables the color that overwrites the constant one. * @throws Exception - if something goes wrong. */ @Test public void disablesOverridenConstantColor() throws Exception { final MulticolorLayout layout = new MulticolorLayout(); layout.setConversionPattern("[%color-red{%p}] %color-red{%m}"); layout.setColors("red:12"); final LoggingEvent event = Mockito.mock(LoggingEvent.class); Mockito.doReturn(Level.DEBUG).when(event).getLevel(); Mockito.doReturn("test").when(event).getRenderedMessage(); MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo( "[\\u001B[12mDEBUG\\u001B[m] \\u001B[12mtest\\u001B[m" ) ); System.getProperties().setProperty( MulticolorLayoutIntegrationTest.COLORING_PROPERTY, Boolean.FALSE.toString() ); try { MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo( "[DEBUG] test" ) ); } finally { System.getProperties().setProperty( MulticolorLayoutIntegrationTest.COLORING_PROPERTY, Boolean.TRUE.toString() ); } } } jcabi-log-0.19.0/src/it/it-decoloring/src/test/java/com/jcabi/log/package-info.java000066400000000000000000000031171376012136000276600ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * Integration tests. */ package com.jcabi.log; jcabi-log-0.19.0/src/it/settings.xml000066400000000000000000000044711376012136000172220ustar00rootroot00000000000000 it-repo true local.central @localRepositoryUrl@ true true local.central @localRepositoryUrl@ true true jcabi-log-0.19.0/src/main/000077500000000000000000000000001376012136000151425ustar00rootroot00000000000000jcabi-log-0.19.0/src/main/java/000077500000000000000000000000001376012136000160635ustar00rootroot00000000000000jcabi-log-0.19.0/src/main/java/com/000077500000000000000000000000001376012136000166415ustar00rootroot00000000000000jcabi-log-0.19.0/src/main/java/com/jcabi/000077500000000000000000000000001376012136000177115ustar00rootroot00000000000000jcabi-log-0.19.0/src/main/java/com/jcabi/log/000077500000000000000000000000001376012136000204725ustar00rootroot00000000000000jcabi-log-0.19.0/src/main/java/com/jcabi/log/ColorfullyFormatted.java000066400000000000000000000047171376012136000253460ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; /** * Formats a log event using ANSI color codes. * @since 0.18 */ class ColorfullyFormatted implements Formatted { /** * The basic information to be formatted with colors. */ private final transient String basic; /** * Color used as the replacement. */ private final transient String color; /** * Constructor. * @param bas Basic string to be formatted * @param col Color to be used to paint the output */ ColorfullyFormatted(final String bas, final String col) { this.basic = bas; this.color = col; } @Override public String format() { return this.basic.replaceAll( new ControlSequenceIndicatorFormatted("%s\\?m").format(), String.format( "%s%sm", new ControlSequenceIndicatorFormatted("%s").format(), this.color ) ); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/Colors.java000066400000000000000000000063031376012136000226000ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * Store human readable color data. * @since 0.18 */ public class Colors { /** * Colors with names. */ private final transient ConcurrentMap map; /** * Public ctor. */ public Colors() { this.map = Colors.colorMap(); } /** * Add color to color map. * @param key Key to add * @param value Value to add */ public final void addColor(final String key, final String value) { this.map.put(key, value); } /** * Convert our text to ANSI color. * @param meta Meta text * @return ANSI color */ public final String ansi(final String meta) { final String ansi; if (meta == null) { ansi = "?"; } else if (meta.matches("[a-z]+")) { ansi = this.map.get(meta); if (ansi == null) { throw new IllegalArgumentException( String.format("unknown color '%s'", meta) ); } } else { ansi = meta; } return ansi; } /** * Color map. * @return Map of colors */ private static ConcurrentMap colorMap() { final ConcurrentMap map = new ConcurrentHashMap<>(); map.put("black", "30"); map.put("blue", "34"); map.put("cyan", "36"); map.put("green", "32"); map.put("magenta", "35"); map.put("red", "31"); map.put("yellow", "33"); map.put("white", "37"); return map; } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/ControlSequenceIndicatorFormatted.java000066400000000000000000000041711376012136000301540ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; /** * Replaces string format with a Control Sequence Indicator. * @since 0.18 */ public class ControlSequenceIndicatorFormatted implements Formatted { /** * Pattern to be used to find replacement points. */ private final transient String pattern; /** * Construtor. * @param pat Pattern to be used to find replacement points */ public ControlSequenceIndicatorFormatted(final String pat) { this.pattern = pat; } @Override public final String format() { return String.format(this.pattern, "\u001b\\["); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/ConversionPattern.java000066400000000000000000000106111376012136000250170ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Generates the conversion pattern. * @since 0.18 */ class ConversionPattern { /** * Regular expression for all matches. */ private static final Pattern METAS = Pattern.compile( "%color(?:-([a-z]+|[0-9]{1,3};[0-9]{1,3};[0-9]{1,3}))?\\{" ); /** * Pattern to be validated. */ private final transient String pattern; /** * Colors to be used. */ private final transient Colors colors; /** * Constructor. * @param pat Pattern to be used * @param col Colors to be used */ ConversionPattern(final String pat, final Colors col) { this.pattern = pat; this.colors = col; } /** * Generates the conversion pattern. * @return Conversion pattern */ public String generate() { String remaining = this.pattern; final Matcher matcher = ConversionPattern.METAS.matcher( remaining ); final StringBuffer buf = new StringBuffer(0); while (matcher.find()) { final int argstart = matcher.end(); final int argend = findArgumentEnd(remaining, argstart); if (argend < 0) { break; } matcher.appendReplacement(buf, ""); buf.append(ConversionPattern.csi()) .append(this.colors.ansi(matcher.group(1))) .append('m') .append(remaining, argstart, argend) .append(ConversionPattern.csi()) .append('m'); remaining = remaining.substring(argend + 1); matcher.reset(remaining); } matcher.appendTail(buf); return buf.toString(); } /** * Find the matching closing curly brace while keeping any nested curly * brace pairs balanced. * @param pattern Pattern to find the match in. * @param start Index of first character after the opening curly brace * @return Index of the closing curly brace, or -1 if not found */ private static int findArgumentEnd(final String pattern, final int start) { int count = 1; int index = start; while (index < pattern.length()) { final char character = pattern.charAt(index); if (character == '}') { --count; if (count == 0) { break; } } else if (character == '{') { ++count; } ++index; } if (index == pattern.length()) { index = -1; } return index; } /** * Formats a string with a Control Sequence Information. * @return Formatted string */ private static String csi() { return new ControlSequenceIndicatorFormatted("%s").format(); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/DecorException.java000066400000000000000000000046061376012136000242560ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Exception if some problem with decor. * * @since 0.1 */ @ToString @EqualsAndHashCode(callSuper = false) final class DecorException extends Exception { /** * Serialization marker. */ private static final long serialVersionUID = 0x7526FA78EEDAC465L; /** * Public ctor. * @param cause Cause of it * @param format The message * @param args Optional arguments */ DecorException(final Throwable cause, final String format, final Object... args) { super(String.format(format, args), cause); } /** * Public ctor. * @param format The message * @param args Optional arguments */ DecorException(final String format, final Object... args) { super(String.format(format, args)); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/DecorsManager.java000066400000000000000000000135001376012136000240460ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Formattable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Manager of all decors. * * @since 0.1 */ @ToString @EqualsAndHashCode final class DecorsManager { /** * Storage of all found decors. * @checkstyle LineLength (2 lines) */ private static final ConcurrentMap> DECORS = new ConcurrentHashMap<>(0); static { DecorsManager.DECORS.put("dom", DomDecor.class); DecorsManager.DECORS.put("exception", ExceptionDecor.class); DecorsManager.DECORS.put("list", ListDecor.class); DecorsManager.DECORS.put("ms", MsDecor.class); DecorsManager.DECORS.put("nano", NanoDecor.class); DecorsManager.DECORS.put("object", ObjectDecor.class); DecorsManager.DECORS.put("size", SizeDecor.class); DecorsManager.DECORS.put("secret", SecretDecor.class); DecorsManager.DECORS.put("text", TextDecor.class); DecorsManager.DECORS.put("type", TypeDecor.class); } /** * Private ctor. */ private DecorsManager() { // empty } /** * Get decor by key. * @param key Key for the formatter to be used to fmt the arguments * @param arg The arbument to supply * @return The decor * @throws DecorException If some problem */ @SuppressWarnings("PMD.ProhibitPublicStaticMethods") public static Formattable decor(final String key, final Object arg) throws DecorException { final Class type = DecorsManager.find(key); final Formattable decor; try { decor = (Formattable) DecorsManager.ctor(type).newInstance(arg); } catch (final InstantiationException ex) { throw new DecorException( ex, "Can't instantiate %s(%s)", type.getName(), arg.getClass().getName() ); } catch (final IllegalAccessException ex) { throw new DecorException( ex, "Can't access %s(%s)", type.getName(), arg.getClass().getName() ); } catch (final InvocationTargetException ex) { throw new DecorException( ex, "Can't invoke %s(%s)", type.getName(), arg.getClass().getName() ); } return decor; } /** * Find decor. * @param key Key for the formatter to be used to fmt the arguments * @return The type of decor found * @throws DecorException If some problem */ @SuppressWarnings("unchecked") private static Class find(final String key) throws DecorException { final Class type; if (DecorsManager.DECORS.containsKey(key)) { type = DecorsManager.DECORS.get(key); } else { try { type = (Class) Class.forName(key); } catch (final ClassNotFoundException ex) { throw new DecorException( ex, "Decor '%s' not found and class can't be instantiated", key ); } } return type; } /** * Get ctor of the type. * @param type The type * @return The ctor * @throws DecorException If some problem */ private static Constructor ctor(final Class type) throws DecorException { final Constructor[] ctors = type.getDeclaredConstructors(); if (ctors.length != 1) { throw new DecorException( "%s should have just one one-arg ctor, but there are %d", type.getName(), ctors.length ); } final Constructor ctor = ctors[0]; if (ctor.getParameterTypes().length != 1) { throw new DecorException( "%s public ctor should have just once parameter", type.getName() ); } return ctor; } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/DomDecor.java000066400000000000000000000077041376012136000230410ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.io.StringWriter; import java.util.Formattable; import java.util.Formatter; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import lombok.EqualsAndHashCode; import lombok.ToString; import org.w3c.dom.Node; /** * Decorates XML Document. * * @since 0.1 */ @ToString @EqualsAndHashCode(of = "node") final class DomDecor implements Formattable { /** * DOM transformer factory, DOM. */ private static final TransformerFactory FACTORY = TransformerFactory.newInstance(); /** * The document. */ private final transient Node node; /** * Public ctor. * @param doc The document * @throws DecorException If some problem with it */ @SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors") DomDecor(final Object doc) throws DecorException { if (doc != null && !(doc instanceof Node)) { throw new DecorException( String.format( "Instance of org.w3c.dom.Node required, while %s provided", doc.getClass().getName() ) ); } this.node = (Node) doc; } // @checkstyle ParameterNumber (4 lines) @Override public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { final StringWriter writer = new StringWriter(); if (this.node == null) { writer.write("NULL"); } else { try { final Transformer trans = DomDecor.FACTORY.newTransformer(); trans.setOutputProperty(OutputKeys.INDENT, "yes"); trans.setOutputProperty(OutputKeys.STANDALONE, "no"); trans.transform( new DOMSource(this.node), new StreamResult(writer) ); } catch (final TransformerConfigurationException ex) { throw new IllegalStateException(ex); } catch (final TransformerException ex) { throw new IllegalStateException(ex); } } formatter.format("%s", writer.toString()); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/DullyFormatted.java000066400000000000000000000041351376012136000242770ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; /** * Formats a log event without using ANSI color codes. * @since 0.18 */ class DullyFormatted implements Formatted { /** * String to be formatted. */ private final transient String basic; /** * Contructor. * @param bas String to be formatted */ DullyFormatted(final String bas) { this.basic = bas; } @Override public String format() { return this.basic.replaceAll( new ControlSequenceIndicatorFormatted("%s([0-9]*|\\?)m").format(), "" ); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/ExceptionDecor.java000066400000000000000000000057051376012136000242570ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Formattable; import java.util.FormattableFlags; import java.util.Formatter; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Decorates an exception. * *

For example: * *

 * try {
 *   // ...
 * } catch (final IOException ex) {
 *   Logger.error("failed to open file: %[exception]s", ex);
 *   throw new IllegalArgumentException(ex);
 * }
 * 
* * @since 0.1 */ @ToString @EqualsAndHashCode(of = "throwable") final class ExceptionDecor implements Formattable { /** * The exception. */ private final transient Throwable throwable; /** * Public ctor. * @param thr The exception */ ExceptionDecor(final Throwable thr) { this.throwable = thr; } // @checkstyle ParameterNumber (4 lines) @Override public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { final String text; if (this.throwable == null) { text = "NULL"; } else if ((flags & FormattableFlags.ALTERNATE) == 0) { final StringWriter writer = new StringWriter(); this.throwable.printStackTrace(new PrintWriter(writer)); text = writer.toString(); } else { text = this.throwable.getMessage(); } formatter.format("%s", text); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/Formatted.java000066400000000000000000000034231376012136000232640ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; /** * Contract for a class that know how to format something. * @since 0.18 */ interface Formatted { /** * Return something formatted. * @return Formatted version of something */ String format(); } jcabi-log-0.19.0/src/main/java/com/jcabi/log/ListDecor.java000066400000000000000000000065371376012136000232400ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Arrays; import java.util.Collection; import java.util.Formattable; import java.util.Formatter; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Format list. * @since 0.1 */ @ToString @EqualsAndHashCode(of = "list") final class ListDecor implements Formattable { /** * The list. */ private final transient Collection list; /** * Public ctor. * @param obj The object to format * @throws DecorException If some problem with it */ @SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors") ListDecor(final Object obj) throws DecorException { if (obj == null || obj instanceof Collection) { this.list = Collection.class.cast(obj); } else if (obj instanceof Object[]) { this.list = Arrays.asList((Object[]) obj); } else { throw new DecorException( String.format( "Collection or array required, while %s provided", obj.getClass().getName() ) ); } } // @checkstyle ParameterNumber (4 lines) @Override public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { final StringBuilder builder = new StringBuilder(0); builder.append('['); if (this.list == null) { builder.append("NULL"); } else { boolean first = true; for (final Object item : this.list) { if (!first) { builder.append(", "); } builder.append(String.format("\"%s\"", item)); first = false; } } builder.append(']'); formatter.format("%s", builder.toString()); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/Logger.java000066400000000000000000000426661376012136000225720ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.logging.Level; import lombok.EqualsAndHashCode; import lombok.ToString; import org.slf4j.LoggerFactory; /** * Universal logger, and adapter between your app and SLF4J API. * *

Instead of relying * on some logging engine you can use this class, which transforms all * messages to SLF4J. This approach gives you a perfect decoupling of business * logic and logging mechanism. All methods in the class are called * statically, without the necessity to instantiate the class. * *

Use it like this in any class, and in any package: * *

 package com.example.XXX;
 * import com.jcabi.log.Logger;
 * public class MyClass {
 *   public void foo(Integer num) {
 *     Logger.info(this, "foo(%d) just called", num);
 *   }
 * }
* *

Or statically (pay attention to {@code MyClass.class}): * *

 public class MyClass {
 *   public static void foo(Integer num) {
 *     Logger.info(MyClass.class, "foo(%d) just called", num);
 *   }
 * }
* *

Exact binding between SLF4J and logging facility has to be * specified in {@code pom.xml} of your project (or in classpath directly). * *

For performance reasons in most cases before sending a * {@code TRACE} or {@code DEBUG} log message you may check whether this * logging level is enabled in the project, e.g.: * *

 //...
 * if (Logger.isTraceEnabled(this)) {
 *   Logger.trace(this, "#foo() called");
 * }
 * //...
* *

There is only one reason to do so - if you want to save time spent on * preparing of the arguments. By default, such a call is made inside every * method of {@link Logger} class. * * @since 0.1 */ @ToString @EqualsAndHashCode @SuppressWarnings( { "PMD.TooManyMethods", "PMD.GodClass", "PMD.ProhibitPublicStaticMethods" } ) public final class Logger { /** * Empty array of objects. */ private static final Object[] EMPTY = {}; /** * UTF-8. */ private static final String UTF_8 = "UTF-8"; /** * This is utility class. */ private Logger() { // intentionally empty } /** * Format one string. * @param fmt The format * @param args List of arbitrary arguments * @return Formatted string */ public static String format(final String fmt, final Object... args) { final String result; if (args.length == 0) { result = fmt; } else { final PreFormatter pre = new PreFormatter(fmt, args); result = String.format(pre.getFormat(), pre.getArguments()); } return result; } /** * Protocol one message, with {@code TRACE} priority level. * @param source The source of the logging operation * @param msg The text message to be logged * @since 0.7.11 */ public static void trace(final Object source, final String msg) { Logger.trace(source, msg, Logger.EMPTY); } /** * Protocol one message, with {@code TRACE} priority level. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of arguments */ public static void trace( final Object source, final String msg, final Object... args ) { if (Logger.isTraceEnabled(source)) { Logger.traceForced(source, msg, args); } } /** * Protocol one message, with {@code TRACE} priority level * without internal checking whether {@code TRACE} level is enabled. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of arguments */ public static void traceForced( final Object source, final String msg, final Object... args ) { Logger.logger(source).trace(Logger.format(msg, args)); } /** * Protocol one message, with {@code DEBUG} priority level. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @since 0.7.11 */ public static void debug(final Object source, final String msg) { Logger.debug(source, msg, Logger.EMPTY); } /** * Protocol one message, with {@code DEBUG} priority level. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of arguments */ public static void debug( final Object source, final String msg, final Object... args ) { if (Logger.isDebugEnabled(source)) { Logger.debugForced(source, msg, args); } } /** * Protocol one message, with {@code DEBUG} priority level * without internal checking whether {@code DEBUG} level is enabled. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of arguments */ public static void debugForced( final Object source, final String msg, final Object... args ) { Logger.logger(source).debug(Logger.format(msg, args)); } /** * Protocol one message, with {@code INFO} priority level. * @param source The source of the logging operation * @param msg The text message to be logged * @since 0.7.11 */ public static void info(final Object source, final String msg) { Logger.info(source, msg, Logger.EMPTY); } /** * Protocol one message, with {@code INFO} priority level. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of arguments */ public static void info( final Object source, final String msg, final Object... args ) { if (Logger.isInfoEnabled(source)) { Logger.infoForced(source, msg, args); } } /** * Protocol one message, with {@code INFO} priority level * without internal checking whether {@code INFO} level is enabled. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of arguments */ public static void infoForced( final Object source, final String msg, final Object... args ) { Logger.logger(source).info(Logger.format(msg, args)); } /** * Protocol one message, with {@code WARN} priority level. * @param source The source of the logging operation * @param msg The text message to be logged * @since 0.7.11 */ public static void warn(final Object source, final String msg) { Logger.warn(source, msg, Logger.EMPTY); } /** * Protocol one message, with {@code WARN} priority level. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of arguments */ public static void warn( final Object source, final String msg, final Object... args ) { if (Logger.isWarnEnabled(source)) { Logger.warnForced(source, msg, args); } } /** * Protocol one message, with {@code WARN} priority level * without internal checking whether {@code WARN} level is enabled. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of arguments */ public static void warnForced( final Object source, final String msg, final Object... args ) { Logger.logger(source).warn(Logger.format(msg, args)); } /** * Protocol one message, with {@code ERROR} priority level. * @param source The source of the logging operation * @param msg The text message to be logged * @since 0.7.11 */ public static void error(final Object source, final String msg) { Logger.error(source, msg, Logger.EMPTY); } /** * Protocol one message, with {@code ERROR} priority level. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of arguments */ public static void error(final Object source, final String msg, final Object... args) { Logger.logger(source).error(Logger.format(msg, args)); } /** * Validates whether {@code TRACE} priority level is enabled for * this particular logger. * @param source The source of the logging operation * @return Is it enabled? */ public static boolean isTraceEnabled(final Object source) { return Logger.logger(source).isTraceEnabled(); } /** * Validates whether {@code DEBUG} priority level is enabled for * this particular logger. * @param source The source of the logging operation * @return Is it enabled? */ public static boolean isDebugEnabled(final Object source) { return Logger.logger(source).isDebugEnabled(); } /** * Validates whether {@code INFO} priority level is enabled for * this particular logger. * @param source The source of the logging operation * @return Is it enabled? * @since 0.5 */ public static boolean isInfoEnabled(final Object source) { return Logger.logger(source).isInfoEnabled(); } /** * Validates whether {@code INFO} priority level is enabled for * this particular logger. * @param source The source of the logging operation * @return Is it enabled? * @since 0.5 */ public static boolean isWarnEnabled(final Object source) { return Logger.logger(source).isWarnEnabled(); } /** * Is the given logging level enabled? * @param level The level of logging * @param source The source of the logging operation * @return Is it enabled? * @since 0.13 */ public static boolean isEnabled(final Level level, final Object source) { boolean enabled = false; if (level.equals(Level.SEVERE)) { enabled = Logger.logger(source).isErrorEnabled(); } else if (level.equals(Level.WARNING)) { enabled = Logger.logger(source).isWarnEnabled(); } else if (level.equals(Level.INFO) || level.equals(Level.CONFIG)) { enabled = Logger.logger(source).isInfoEnabled(); } else if (level.equals(Level.FINE) || level.equals(Level.ALL)) { enabled = Logger.logger(source).isDebugEnabled(); } else if (level.equals(Level.FINER) || level.equals(Level.FINEST)) { enabled = Logger.logger(source).isTraceEnabled(); } return enabled; } /** * Log one line using the logging level specified. * @param level The level of logging * @param source The source of the logging operation * @param msg The text message to be logged * @param args Optional arguments for string formatting * @since 0.8 * @checkstyle ParameterNumber (4 lines) */ public static void log(final Level level, final Object source, final String msg, final Object... args) { if (level.equals(Level.SEVERE)) { Logger.error(source, msg, args); } else if (level.equals(Level.WARNING)) { Logger.warn(source, msg, args); } else if (level.equals(Level.INFO) || level.equals(Level.CONFIG)) { Logger.info(source, msg, args); } else if (level.equals(Level.FINE) || level.equals(Level.ALL)) { Logger.debug(source, msg, args); } else if (level.equals(Level.FINER) || level.equals(Level.FINEST)) { Logger.trace(source, msg, args); } } /** * Returns an {@link OutputStream}, which converts all incoming data * into logging lines (separated by {@code \x0A} in UTF-8). * @param level The level of logging * @param source The source of the logging operation * @return Output stream directly pointed to the logging facility * @see some discussion * @since 0.8 * @checkstyle MagicNumberCheck (20 lines) */ public static OutputStream stream(final Level level, final Object source) { // @checkstyle AnonInnerLengthCheck (50 lines) return new OutputStream() { private final transient ByteArrayOutputStream buffer = new ByteArrayOutputStream(); @Override public void write(final int data) throws IOException { if (data == '\n') { Logger.log( level, source, this.buffer.toString(Logger.UTF_8) ); this.buffer.reset(); } else if (data >= 0x20 && data <= 0x7f) { this.buffer.write(data); } else { this.buffer.write( String.format( "\\x%02x", data & 0xff ).getBytes(Logger.UTF_8) ); } } }; } /** * Log messages constructed from Suppliers. * It is more efficient to use method referencing because the method * won't be called unless the specified logging level is enabled. * * This saves you the effort of having to check if the level is enabled * before calling the logging method. * E.g. *

     *     if (Logger.isDebugEnabled(this)) {
     *         Logger.debug(this, "Some %s", calculate());
     *     }
     * 

* turns into
*
     *     Logger.withSupplier().debug(this, "Some %s", this::calculate());
     * 

* and the calculate() method won't be called unless the debug level is * active. * * @return Object containing methods for logging with Supplier-constructed * messages */ public static SupplierLogger withSupplier() { return new SupplierLogger(); } /** * Set final static field in order to fix the %L log4j parameter. * @param field Field * @param value New value * @throws NoSuchFieldException If some problem * @throws IllegalAccessException If some problem * @checkstyle ThrowsCountCheck (4 lines) */ private static void setFinalStatic(final Field field, final Object value) throws NoSuchFieldException, IllegalAccessException { field.setAccessible(true); final Field modifiers = Field.class.getDeclaredField("modifiers"); modifiers.setAccessible(true); modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL); field.set(null, value); } /** * Get the instance of the logger for this particular caller. * @param source Source of the logging operation * @return The instance of {@code Logger} class */ private static org.slf4j.Logger logger(final Object source) { final org.slf4j.Logger logger; if (source instanceof Class) { logger = LoggerFactory.getLogger((Class) source); } else if (source instanceof String) { logger = LoggerFactory.getLogger(String.class.cast(source)); } else { logger = LoggerFactory.getLogger(source.getClass()); } if ("org.slf4j.impl.Log4jLoggerAdapter" .equals(logger.getClass().getName())) { try { final Field fqcn = logger.getClass() .getDeclaredField("FQCN"); setFinalStatic(fqcn, Logger.class.getName()); } catch (final NoSuchFieldException ex) { throw new IllegalStateException(ex); } catch (final IllegalAccessException ex) { throw new IllegalStateException(ex); } } return logger; } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/MsDecor.java000066400000000000000000000113621376012136000226740ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Formattable; import java.util.FormattableFlags; import java.util.Formatter; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Decorate time interval in milliseconds. * *

For example: * *

 * final long start = System.currentTimeMillis();
 * // some operations
 * Logger.debug("completed in %[ms]s", System.currentTimeMillis() - start);
 * 
* * @since 0.1 */ @ToString @EqualsAndHashCode(of = "millis") final class MsDecor implements Formattable { /** * The period to work with, in milliseconds. */ private final transient Double millis; /** * Public ctor. * @param msec The interval in milliseconds */ @SuppressWarnings( { "PMD.NullAssignment", "PMD.ConstructorOnlyInitializesOrCallOtherConstructors" } ) MsDecor(final Long msec) { if (msec == null) { this.millis = null; } else { this.millis = Double.valueOf(msec); } } // @checkstyle ParameterNumber (4 lines) @Override public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { if (this.millis == null) { formatter.format("NULL"); } else { final StringBuilder format = new StringBuilder(0); format.append('%'); if ((flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags .LEFT_JUSTIFY) { format.append('-'); } if (width > 0) { format.append(Integer.toString(width)); } if ((flags & FormattableFlags.UPPERCASE) == FormattableFlags .UPPERCASE) { format.append('S'); } else { format.append('s'); } formatter.format(format.toString(), this.toText(precision)); } } /** * Create text. * @param precision The precision * @return The text * @checkstyle MagicNumber (50 lines) */ private String toText(final int precision) { final double number; final String title; if (this.millis < 1000.0) { number = this.millis; title = "ms"; } else if (this.millis < (double) (1000L * 60L)) { number = this.millis / 1000.0; title = "s"; } else if (this.millis < (double) (1000L * 60L * 60L)) { number = this.millis / (double) (1000L * 60L); title = "min"; } else if (this.millis < (double) (1000L * 60L * 60L * 24L)) { number = this.millis / (double) (1000L * 60L * 60L); title = "hr"; } else if (this.millis < (double) (1000L * 60L * 60L * 24L * 30L)) { number = this.millis / (double) (1000L * 60L * 60L * 24L); title = "days"; } else { number = this.millis / (double) (1000L * 60L * 60L * 24L * 30L); title = "mon"; } final String format; if (precision >= 0) { format = String.format("%%.%df%%s", precision); } else { format = "%.0f%s"; } return String.format(format, number, title); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/MulticolorLayout.java000066400000000000000000000171571376012136000246770ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import lombok.EqualsAndHashCode; import lombok.ToString; import org.apache.log4j.EnhancedPatternLayout; import org.apache.log4j.Level; import org.apache.log4j.spi.LoggingEvent; /** * Multi-color layout for LOG4J. * *

Use it in your LOG4J configuration: * *

 log4j.rootLogger=INFO, CONSOLE
 * log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
 * log4j.appender.CONSOLE.layout=com.jcabi.log.MulticolorLayout
 * log4j.appender.CONSOLE.layout.ConversionPattern=[%color{%-5p}] %c: %m%n
* *

The part of the message wrapped with {@code %color{...}} * will change its color according to the logging level of the event. Without * this highlighting the behavior of the layout is identical to * {@link EnhancedPatternLayout}. You can use {@code %color-red{...}} if you * want to use specifically red color for the wrapped piece of text. Supported * colors are: {@code red}, {@code blue}, {@code yellow}, {@code cyan}, * {@code black}, and {@code white}. * *

Besides that you can specify any ANSI color you like with * {@code %color-;;{...}}, where * {@code } is a binary mask of attributes, * {@code } is a background color, and * {@code } is a foreground color. Read more about * ANSI escape code. * *

This class or its parents are not serializable. * *

Maven dependency for this class is * (see How * to use with Maven instructions): * *

<dependency>
 *  <groupId>com.jcabi</groupId>
 *  <artifactId>jcabi-log</artifactId>
 * </dependency>
* @since 0.1.10 * @see ANSI escape code * @see PatternLayout from LOG4J * @see How to use with Maven */ @ToString @EqualsAndHashCode(callSuper = false) @SuppressWarnings("PMD.NonStaticInitializer") public final class MulticolorLayout extends EnhancedPatternLayout { /** * Name of the property that is used to disable log coloring. */ private static final String COLORING_PROPERY = "com.jcabi.log.coloring"; /** * Colors of levels. */ private final transient ConcurrentMap levels = MulticolorLayout.levelMap(); /** * Store original conversation pattern to be able * to recalculate it, if new colors are provided. */ private transient String base; /** * Color human readable data. */ private final transient Colors colors = new Colors(); @Override public void setConversionPattern(final String pattern) { this.base = pattern; super.setConversionPattern( new ConversionPattern(this.base, this.colors).generate() ); } /** * Allow to overwrite or specify new ANSI color names * in a javascript map like format. * * @param cols JavaScript like map of color names * @since 0.9 */ @SuppressWarnings("PMD.UseConcurrentHashMap") public void setColors(final String cols) { final Map parsed = new ParseableInformation( cols ).information(); for (final Entry entry : parsed.entrySet()) { this.colors.addColor(entry.getKey(), entry.getValue()); } if (this.base != null) { this.setConversionPattern(this.base); } } /** * Allow to overwrite the ANSI color values for the log levels * in a javascript map like format. * @param lev JavaScript like map of levels * @since 0.9 */ @SuppressWarnings("PMD.UseConcurrentHashMap") public void setLevels(final String lev) { final Map parsed = new ParseableLevelInformation( lev ).information(); for (final Entry entry : parsed.entrySet()) { this.levels.put(entry.getKey(), entry.getValue()); } } @Override public String format(final LoggingEvent event) { final Formatted formatted; if (MulticolorLayout.isColoringEnabled()) { formatted = this.colorfulFormatting(event); } else { formatted = this.dullFormatting(event); } return formatted.format(); } /** * Generate a dull {@code Formatted}. * @param event Event to be formatted * @return A {@link Formatted} to format the event * @checkstyle NonStaticMethodCheck (10 lines) */ private Formatted dullFormatting(final LoggingEvent event) { return new DullyFormatted(super.format(event)); } /** * Generate a colorful {@code Formatted}. * @param event Event to be formatted * @return Text of a log event, probably colored with ANSI color codes */ private Formatted colorfulFormatting(final LoggingEvent event) { return new ColorfullyFormatted( super.format(event), this.levels.get(event.getLevel().toString()) ); } /** * Level map. * @return Map of levels */ private static ConcurrentMap levelMap() { final ConcurrentMap map = new ConcurrentHashMap<>(0); map.put(Level.TRACE.toString(), "2;33"); map.put(Level.DEBUG.toString(), "2;37"); map.put(Level.INFO.toString(), "0;37"); map.put(Level.WARN.toString(), "0;33"); map.put(Level.ERROR.toString(), "0;31"); map.put(Level.FATAL.toString(), "0;35"); return map; } /** * Should the logged text be colored or not. * @return True if the coloring is enabled, or false otherwise. */ private static boolean isColoringEnabled() { return !"false".equals( System.getProperty(MulticolorLayout.COLORING_PROPERY) ); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/NanoDecor.java000066400000000000000000000107331376012136000232110ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Formattable; import java.util.FormattableFlags; import java.util.Formatter; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Decorate time interval in nanoseconds. * *

For example: * *

 * final long start = System.nanoTime();
 * // some operations
 * Logger.debug("completed in %[nano]s", System.nanoTime() - start);
 * 
* * @since 0.1 */ @ToString @EqualsAndHashCode(of = "nano") final class NanoDecor implements Formattable { /** * The period to work with, in nanoseconds. */ private final transient Double nano; /** * Public ctor. * @param nan The interval in nanoseconds */ @SuppressWarnings( { "PMD.NullAssignment", "PMD.ConstructorOnlyInitializesOrCallOtherConstructors" } ) NanoDecor(final Long nan) { if (nan == null) { this.nano = null; } else { this.nano = Double.valueOf(nan); } } // @checkstyle ParameterNumber (4 lines) @Override public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { if (this.nano == null) { formatter.format("NULL"); } else { final StringBuilder format = new StringBuilder(0); format.append('%'); if ((flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags .LEFT_JUSTIFY) { format.append('-'); } if (width > 0) { format.append(Integer.toString(width)); } if ((flags & FormattableFlags.UPPERCASE) == FormattableFlags .UPPERCASE) { format.append('S'); } else { format.append('s'); } formatter.format(format.toString(), this.toText(precision)); } } /** * Create text. * @param precision The precision * @return The text */ private String toText(final int precision) { final double number; final String title; // @checkstyle MagicNumber (15 lines) if (this.nano < 1000L) { number = this.nano; title = "ns"; } else if (this.nano < 1000L * 1000) { number = this.nano / 1000L; title = "µs"; } else if (this.nano < 1000L * 1000 * 1000) { number = this.nano / (1000L * 1000); title = "ms"; } else if (this.nano < 1000L * 1000 * 1000 * 60) { number = this.nano / (1000L * 1000 * 1000); title = "s"; } else { number = this.nano / (1000L * 1000 * 1000 * 60); title = "min"; } final String format; if (precision >= 0) { format = String.format("%%.%df%%s", precision); } else { format = "%.0f%s"; } return String.format(format, number, title); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/ObjectDecor.java000066400000000000000000000125651376012136000235310ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.lang.reflect.Field; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Arrays; import java.util.Formattable; import java.util.Formatter; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Format internal structure of an object. * @since 0.1 */ @ToString @EqualsAndHashCode(of = "object") final class ObjectDecor implements Formattable { /** * The object to work with. */ private final transient Object object; /** * Public ctor. * @param obj The object to format */ ObjectDecor(final Object obj) { this.object = obj; } // @checkstyle ParameterNumber (4 lines) @Override public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { if (this.object == null) { formatter.format("NULL"); } else if (this.object.getClass().isArray()) { formatter.format( AccessController.doPrivileged( new ArrayFormatAction((Object[]) this.object) ) ); } else { final String output = AccessController.doPrivileged( new ObjectDecor.ObjectContentsFormatAction(this.object) ); formatter.format(output); } } /** * {@link PrivilegedAction} for obtaining array contents. * * @since 0.1 */ private static final class ArrayFormatAction implements PrivilegedAction { /** * Array to format. */ private final transient Object[] array; /** * Constructor. * @param arr Array to format */ ArrayFormatAction(final Object... arr) { this.array = Arrays.copyOf(arr, arr.length); } @Override @SuppressWarnings("PMD.AvoidInstantiatingObjectsInLoops") public String run() { final StringBuilder builder = new StringBuilder("["); final Formatter formatter = new Formatter(builder); for (final Object obj : this.array) { new ObjectDecor(obj).formatTo(formatter, 0, 0, 0); // @checkstyle MultipleStringLiteralsCheck (1 line) builder.append(", "); } builder.replace(builder.length() - 2, builder.length(), "]"); return builder.toString(); } } /** * {@link PrivilegedAction} for obtaining object contents. * * @since 0.1 */ private static final class ObjectContentsFormatAction implements PrivilegedAction { /** * Object to format. */ private final transient Object object; /** * Constructor. * @param obj Object to format */ ObjectContentsFormatAction(final Object obj) { this.object = obj; } @Override public String run() { final StringBuilder builder = new StringBuilder("{"); for (final Field field : this.object.getClass().getDeclaredFields()) { field.setAccessible(true); try { builder.append( String.format( "%s: \"%s\"", field.getName(), field.get(this.object) ) ); } catch (final IllegalAccessException ex) { throw new IllegalStateException(ex); } // @checkstyle MultipleStringLiteralsCheck (1 line) builder.append(", "); } builder.replace(builder.length() - 2, builder.length(), "}"); return builder.toString(); } } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/ParseableInformation.java000066400000000000000000000062131376012136000254430ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.HashMap; import java.util.Map; /** * Converts items inside a string like K1:V1,K2:V2 - where K is for key and V * is for value - to a {@code Map} of string key and string value. * @since 0.18 */ class ParseableInformation { /** * Information content to be parsed. */ private final transient String content; /** * Construtor. * @param cont Content to be parsed */ ParseableInformation(final String cont) { super(); this.content = cont; } /** * Parse the information. * @return A {@link Map} with a key,value pair os strings */ @SuppressWarnings("PMD.UseConcurrentHashMap") public final Map information() { final Map parsed = new HashMap<>(0); try { for (final String item : this.items()) { final String[] values = item.split(":"); parsed.put(values[0], values[1]); } } catch (final ArrayIndexOutOfBoundsException ex) { throw new IllegalStateException( String.format(new StringBuilder() .append("Information is not using the pattern ") .append("KEY1:VALUE,KEY2:VALUE %s") .toString(), this.content ), ex ); } return parsed; } /** * Split the information using {@link ParseableInformation#SPLIT_ITEMS} * pattern. * @return An array of items */ private String[] items() { return this.content.split(","); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/ParseableLevelInformation.java000066400000000000000000000057101376012136000264340ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import org.apache.log4j.Level; /** * Parse information like {@code ParseInformation} does, but increments with * some extra checks for {@code Level}s. * @since 0.18 */ class ParseableLevelInformation { /** * Information content to be parsed. */ private final transient String content; /** * Construtor. * @param cont Content to be parsed */ ParseableLevelInformation(final String cont) { this.content = cont; } /** * Parse the level information. * @return A {@link Map} with key,value pair of strings */ @SuppressWarnings("PMD.UseConcurrentHashMap") public final Map information() { final Map parsed = new ParseableInformation( this.content ).information(); final Map converted = new HashMap<>(0); for (final Entry entry : parsed.entrySet()) { final String level = entry.getKey().toUpperCase(Locale.ENGLISH); if (Level.toLevel(level, null) == null) { throw new IllegalStateException( String.format(Locale.ENGLISH, "Unknown level '%s'", level) ); } converted.put(level, entry.getValue()); } return converted; } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/PreFormatter.java000066400000000000000000000131431376012136000237510ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Arrays; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Processor of formatting string and arguments, before sending it to * {@link String#format(String,Object[])}. * * @since 0.1 */ @ToString @EqualsAndHashCode(of = { "format", "arguments" }) final class PreFormatter { /** * Pattern used for matching format string arguments. */ private static final Pattern PATTERN = Pattern.compile( // @checkstyle LineLength (1 line) "%(\\d+\\$)?(\\[([A-Za-z\\-\\.0-9]+)\\])?[\\+\\-]?(?:\\d*(?:\\.\\d+)?)?[a-zA-Z%]" ); /** * List of no argument specifier. */ private static final List NO_ARG_SPECIFIERS = Arrays.asList("%n", "%%"); /** * The formatting string. */ private transient String format; /** * List of arguments. */ private transient List arguments; /** * Public ctor. * @param fmt The formatting string * @param args The list of arguments */ @SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors") PreFormatter(final String fmt, final Object... args) { this.process(fmt, args); } /** * Get new formatting string. * @return The formatting text */ public String getFormat() { return this.format; } /** * Get new list of arguments. * @return The list of arguments */ public Object[] getArguments() { return this.arguments.toArray(new Object[this.arguments.size()]); } /** * Process the data provided. * @param fmt The formatting string * @param args The list of arguments * @checkstyle ExecutableStatementCountCheck (100 lines) */ @SuppressWarnings("PMD.ConfusingTernary") private void process(final CharSequence fmt, final Object... args) { this.arguments = new CopyOnWriteArrayList(); final StringBuffer buf = new StringBuffer(fmt.length()); final Matcher matcher = PreFormatter.PATTERN.matcher(fmt); int pos = 0; while (matcher.find()) { final String group = matcher.group(); if (PreFormatter.NO_ARG_SPECIFIERS.contains(group)) { matcher.appendReplacement( buf, Matcher.quoteReplacement(group) ); } else { final String decor = matcher.group(3); if (matcher.group(1) != null) { matcher.appendReplacement( buf, Matcher.quoteReplacement(group) ); --pos; } else if (decor == null) { matcher.appendReplacement( buf, Matcher.quoteReplacement(group) ); this.arguments.add(args[pos]); } else { matcher.appendReplacement( buf, Matcher.quoteReplacement( group.replace(matcher.group(2), "") ) ); try { this.arguments.add( DecorsManager.decor(decor, args[pos]) ); } catch (final DecorException ex) { this.arguments.add( String.format("[%s]", ex.getMessage()) ); } } ++pos; } } if (pos < args.length) { throw new IllegalArgumentException( String.format( // @checkstyle LineLength (1 line) "There are %d parameter(s) but only %d format argument(s) were provided.", args.length, pos ) ); } matcher.appendTail(buf); this.format = buf.toString(); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/SecretDecor.java000066400000000000000000000073141376012136000235440ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Formattable; import java.util.FormattableFlags; import java.util.Formatter; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Decorator of a secret text. * @since 0.1 */ @ToString @EqualsAndHashCode(of = "secret") final class SecretDecor implements Formattable { /** * The secret to work with. */ private final transient String secret; /** * Public ctor. * @param scrt The secret */ @SuppressWarnings( { "PMD.NullAssignment", "PMD.ConstructorOnlyInitializesOrCallOtherConstructors" } ) SecretDecor(final Object scrt) { if (scrt == null) { this.secret = null; } else { this.secret = scrt.toString(); } } // @checkstyle ParameterNumber (4 lines) @Override public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { if (this.secret == null) { formatter.format("NULL"); } else { final StringBuilder fmt = new StringBuilder(10); fmt.append('%'); if ((flags & FormattableFlags.LEFT_JUSTIFY) != 0) { fmt.append('-'); } if (width != 0) { fmt.append(width); } if ((flags & FormattableFlags.UPPERCASE) == 0) { fmt.append('s'); } else { fmt.append('S'); } formatter.format( fmt.toString(), SecretDecor.scramble(this.secret) ); } } /** * Scramble it and make unreadable. * @param text The text to scramble * @return The result */ private static String scramble(final String text) { final StringBuilder out = new StringBuilder(10); if (text.isEmpty()) { out.append('?'); } else { out.append(text.charAt(0)); } out.append("***"); if (text.isEmpty()) { out.append('?'); } else { out.append(text.charAt(text.length() - 1)); } return out.toString(); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/SizeDecor.java000066400000000000000000000105701376012136000232270ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Formattable; import java.util.FormattableFlags; import java.util.Formatter; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Size decorator. * @since 0.1 */ @ToString @EqualsAndHashCode(of = "size") final class SizeDecor implements Formattable { /** * Highest power supported by this SizeDecor. */ private static final int MAX_POWER = 6; /** * Map of prefixes for powers of 1024. */ private static final ConcurrentMap SUFFIXES = new ConcurrentHashMap<>(0); /** * The size to work with. */ private final transient Long size; static { // @checkstyle MagicNumber (9 lines) SizeDecor.SUFFIXES.put(0, "b"); SizeDecor.SUFFIXES.put(1, "Kb"); SizeDecor.SUFFIXES.put(2, "Mb"); SizeDecor.SUFFIXES.put(3, "Gb"); SizeDecor.SUFFIXES.put(4, "Tb"); SizeDecor.SUFFIXES.put(5, "Pb"); SizeDecor.SUFFIXES.put(6, "Eb"); } /** * Public ctor. * @param sze The size */ SizeDecor(final Long sze) { this.size = sze; } // @checkstyle ParameterNumber (4 lines) @Override public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { if (this.size == null) { formatter.format("NULL"); } else { final StringBuilder format = new StringBuilder().append('%'); if ((flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags .LEFT_JUSTIFY) { format.append('-'); } if (width > 0) { format.append(Integer.toString(width)); } if ((flags & FormattableFlags.UPPERCASE) == FormattableFlags .UPPERCASE) { format.append('S'); } else { format.append('s'); } formatter.format( format.toString(), this.formatSizeWithSuffix(precision) ); } } /** * Format the size, with suffix. * @param precision The precision to use * @return The formatted size */ private String formatSizeWithSuffix(final int precision) { int power = 0; double number = this.size; // @checkstyle MagicNumber (2 lines) while (number / 1024 >= 1 && power < SizeDecor.MAX_POWER) { number = number / 1024; power += 1; } final String suffix = SizeDecor.SUFFIXES.get(power); final String format; if (precision >= 0) { format = String.format("%%.%df%%s", precision); } else { format = "%.0f%s"; } return String.format(format, number, suffix); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/Supplier.java000066400000000000000000000037471376012136000231530ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; /** * Functional interface used as assignment target for Java8 lambda expressions * or method references. Can be used for method referencing when the method * signature respects the following: returns something and takes no arguments. * * @param The type of results supplied by this supplier * @since 0.18 */ public interface Supplier { /** * Gets a result. * @return A result */ T get(); } jcabi-log-0.19.0/src/main/java/com/jcabi/log/SupplierLogger.java000066400000000000000000000107761376012136000243130ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; /** * Logging methods which take {@link Supplier} arguments. * Used with Java 8 method referencing. * @since 0.18 * @checkstyle HideUtilityClassConstructorCheck (500 lines) */ @SuppressWarnings({ "PMD.ProhibitPublicStaticMethods", "PMD.UseUtilityClass" }) final class SupplierLogger { /** * Log one message, with {@code TRACE} priority level. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of {@link Supplier} arguments. Objects are going * to be extracted from them and used for log message interpolation */ public static void trace( final Object source, final String msg, final Supplier... args) { if (Logger.isTraceEnabled(source)) { Logger.traceForced(source, msg, SupplierLogger.supplied(args)); } } /** * Log one message, with {@code DEBUG} priority level. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of {@link Supplier} arguments. Objects are going * to be extracted from them and used for log message interpolation */ public static void debug( final Object source, final String msg, final Supplier... args) { if (Logger.isDebugEnabled(source)) { Logger.debugForced(source, msg, SupplierLogger.supplied(args)); } } /** * Log one message, with {@code INFO} priority level. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of {@link Supplier} arguments. Objects are going * to be extracted from them and used for log message interpolation */ public static void info( final Object source, final String msg, final Supplier... args) { if (Logger.isInfoEnabled(source)) { Logger.infoForced(source, msg, SupplierLogger.supplied(args)); } } /** * Log one message, with {@code WARN} priority level. * @param source The source of the logging operation * @param msg The text message to be logged, with meta-tags * @param args List of {@link Supplier} arguments. Objects are going * to be extracted from them and used for log message interpolation */ public static void warn( final Object source, final String msg, final Supplier... args) { if (Logger.isWarnEnabled(source)) { Logger.warnForced(source, msg, SupplierLogger.supplied(args)); } } /** * Return the results of the given suppliers. * @param args Suppliers * @return Object array */ private static Object[] supplied(final Supplier... args) { final Object[] supplied = new Object[args.length]; for (int idx = 0; idx < supplied.length; ++idx) { supplied[idx] = args[idx].get(); } return supplied; } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/TextDecor.java000066400000000000000000000067401376012136000232450ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Formattable; import java.util.Formatter; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Decorator of a text. * *

For example: * *

public void func(Object input) {
 *   Logger.debug("Long input '%[text]s' provided", input);
 * }
* * @since 0.1.5 */ @ToString @EqualsAndHashCode(of = "object") final class TextDecor implements Formattable { /** * Maximum length to show. */ public static final int MAX = 100; /** * The object. */ private final transient Object object; /** * Public ctor. * @param obj The object */ TextDecor(final Object obj) { this.object = obj; } // @checkstyle ParameterNumber (4 lines) @Override public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { if (this.object == null) { formatter.format("NULL"); } else { formatter.format("%s", TextDecor.pretty(this.object.toString())); } } /** * Make it look pretty. * @param text The text to prettify * @return The result */ @SuppressWarnings("PMD.ConsecutiveAppendsShouldReuse") private static String pretty(final String text) { final String result; if (text.length() < TextDecor.MAX) { result = text; } else { final int skip = text.length() - TextDecor.MAX; final StringBuilder output = new StringBuilder(text.length()); output.append(text.substring(0, (text.length() - skip) / 2)); // @checkstyle MultipleStringLiterals (1 line) output.append("..").append(Integer.toString(skip)).append(".."); output.append( text.substring(text.length() - TextDecor.MAX + output.length()) ); result = output.toString(); } return result.replace("\n", "\\n"); } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/TypeDecor.java000066400000000000000000000047731376012136000232460ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Formattable; import java.util.Formatter; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Decorator of a type. * *

For example: * *

 * public void func(Object input) {
 *   Logger.debug("Input of type %[type]s provided", input);
 * }
 * 
* * @since 0.1 */ @ToString @EqualsAndHashCode(of = "object") final class TypeDecor implements Formattable { /** * The object. */ private final transient Object object; /** * Public ctor. * @param obj The object */ TypeDecor(final Object obj) { this.object = obj; } // @checkstyle ParameterNumber (4 lines) @Override public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { if (this.object == null) { formatter.format("NULL"); } else { formatter.format("%s", this.object.getClass().getName()); } } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/VerboseCallable.java000066400000000000000000000200521376012136000243610ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Wrapper of {@link Callable}, that logs all uncaught runtime exceptions. * *

You can use it with scheduled executor, for example: * *

 Executors.newFixedThreadPool(1).submit(
 *   new VerboseCallable(callable, true)
 * );
* *

Now, every runtime exception that is not caught inside your * {@link Callable} will be reported to log (using {@link Logger}). * Two-arguments constructor can be used when you need to instruct the class * about what to do with the exception: either swallow it or escalate. * Sometimes it's very important to swallow exceptions. Otherwise an entire * thread may get stuck (like in the example above). * *

This class is thread-safe. * * @since 0.16 * @param Type of result * @see VerboseThreads * @link Java theory and practice: Dealing with InterruptedException */ @ToString @EqualsAndHashCode(of = { "origin", "rethrow", "verbose" }) @SuppressWarnings("PMD.DoNotUseThreads") public final class VerboseCallable implements Callable { /** * Original runnable. */ private final transient Callable origin; /** * Rethrow exceptions (TRUE) or swallow them? */ private final transient boolean rethrow; /** * Shall we report a full stacktrace? */ private final transient boolean verbose; /** * Default constructor, doesn't swallow exceptions. * @param callable Callable to wrap */ public VerboseCallable(final Callable callable) { this(callable, false); } /** * Default constructor, doesn't swallow exceptions. * @param callable Callable to wrap * @param swallow Shall we swallow exceptions * ({@code TRUE}) or re-throw * ({@code FALSE})? Exception swallowing means that {@link #call()} * will never throw any exceptions (in any case all exceptions are logged * using {@link Logger}. */ public VerboseCallable(final Callable callable, final boolean swallow) { this(callable, swallow, true); } /** * Default constructor. * @param runnable Runnable to wrap * @param swallow Shall we swallow exceptions * ({@code TRUE}) or re-throw * ({@code FALSE})? Exception swallowing means that {@link #call()} * will never throw any exceptions (in any case all exceptions are logged * using {@link Logger}. * @param vrbs Shall we report the entire * stacktrace of the exception * ({@code TRUE}) or just its message in one line ({@code FALSE}) */ @SuppressWarnings("PMD.AvoidCatchingGenericException") public VerboseCallable(final Runnable runnable, final boolean swallow, final boolean vrbs) { this( new Callable() { @Override public T call() throws Exception { runnable.run(); return null; } @Override public String toString() { return runnable.toString(); } }, swallow, vrbs ); } /** * Default constructor, with configurable behavior for exceptions. * @param runnable Runnable to wrap * @param swallow Shall we swallow exceptions * ({@code TRUE}) or re-throw * ({@code FALSE})? Exception swallowing means that {@link #call()} * will never throw any exceptions (in any case all exceptions are logged * using {@link Logger}. */ public VerboseCallable(final Runnable runnable, final boolean swallow) { this(runnable, swallow, true); } /** * Default constructor, with fully configurable behavior. * @param callable Runnable to wrap * @param swallow Shall we swallow exceptions * ({@code TRUE}) or re-throw * ({@code FALSE})? Exception swallowing means that {@link #call()} * will never throw any exceptions (in any case all exceptions are logged * using {@link Logger}. * @param vrbs Shall we report the entire * stacktrace of the exception * ({@code TRUE}) or just its message in one line ({@code FALSE}) */ @SuppressWarnings("PMD.BooleanInversion") public VerboseCallable(final Callable callable, final boolean swallow, final boolean vrbs) { this.origin = callable; this.rethrow = !swallow; this.verbose = vrbs; } @Override @SuppressWarnings("PMD.AvoidCatchingGenericException") public T call() throws Exception { T result = null; try { result = this.origin.call(); // @checkstyle IllegalCatch (1 line) } catch (final RuntimeException ex) { if (this.rethrow) { Logger.warn( this, "escalated runtime exception: %s", this.tail(ex) ); throw ex; } Logger.warn(this, "swallowed runtime exception: %s", this.tail(ex)); // @checkstyle IllegalCatch (1 line) } catch (final Exception ex) { if (this.rethrow) { Logger.warn(this, "escalated exception: %s", this.tail(ex)); throw ex; } Logger.warn(this, "swallowed exception: %s", this.tail(ex)); // @checkstyle IllegalCatch (1 line) } catch (final Error error) { if (this.rethrow) { Logger.error(this, "escalated error: %s", this.tail(error)); throw error; } Logger.error(this, "swallowed error: %s", this.tail(error)); } try { TimeUnit.MICROSECONDS.sleep(1L); } catch (final InterruptedException ex) { Thread.currentThread().interrupt(); throw new IllegalStateException(ex); } return result; } /** * Make a tail of the error/warning message, using the exception thrown. * @param throwable The exception/error caught * @return The message to show in logs */ private String tail(final Throwable throwable) { final String tail; if (this.verbose) { tail = Logger.format("%[exception]s", throwable); } else { tail = Logger.format( "%[type]s('%s')", throwable, throwable.getMessage() ); } return tail; } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/VerboseProcess.java000066400000000000000000000434311376012136000243060ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.nio.channels.Channels; import java.nio.channels.ClosedByInterruptException; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Utility class for getting {@code stdout} from a running process * and logging it through SLF4J. * *

For example: * *

 String name = new VerboseProcess(
 *   new ProcessBuilder("who", "am", "i")
 * ).stdout();
* *

The class throws an exception if the process returns a non-zero exit * code. * *

The class is thread-safe. * * @since 0.5 */ @ToString @EqualsAndHashCode(of = "process") @SuppressWarnings({ "PMD.DoNotUseThreads", "PMD.TooManyMethods" }) public final class VerboseProcess implements Closeable { /** * Charset. */ private static final String UTF_8 = "UTF-8"; /** * Number of stream monitors. */ private static final int N_MONITORS = 2; /** * The process we're working with. */ private final transient Process process; /** * Log level for stdout. */ private final transient Level olevel; /** * Log level for stderr. */ private final transient Level elevel; /** * Stream monitors. */ private final transient Thread[] monitors; /** * Flag to indicate the closure of this process. */ private transient boolean closed; /** * Public ctor. * @param prc The process to work with */ public VerboseProcess(final Process prc) { this(prc, Level.INFO, Level.WARNING); } /** * Public ctor (builder will be configured to redirect error input to * the {@code stdout} and will receive an empty {@code stdin}). * @param builder Process builder to work with */ public VerboseProcess(final ProcessBuilder builder) { this(VerboseProcess.start(builder)); } /** * Public ctor, with a given process and logging levels for {@code stdout} * and {@code stderr}. Neither {@code stdout} nor {@code stderr} cannot be * set to {@link Level#ALL} because it is intended to be used only for * internal configuration. * @param prc Process to execute and monitor * @param stdout Log level for stdout * @param stderr Log level for stderr * @since 0.11 */ @SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors") public VerboseProcess(final Process prc, final Level stdout, final Level stderr) { if (prc == null) { throw new IllegalArgumentException("process can't be NULL"); } if (stdout == null) { throw new IllegalArgumentException("stdout LEVEL can't be NULL"); } if (stderr == null) { throw new IllegalArgumentException("stderr LEVEL can't be NULL"); } if (Level.ALL.equals(stdout)) { throw new IllegalArgumentException( // @checkstyle LineLength (1 line) "stdout LEVEL can't be set to ALL because it is intended only for internal configuration" ); } if (Level.ALL.equals(stderr)) { throw new IllegalArgumentException( // @checkstyle LineLength (1 line) "stderr LEVEL can't be set to ALL because it is intended only for internal configuration" ); } this.process = prc; this.olevel = stdout; this.elevel = stderr; this.monitors = new Thread[VerboseProcess.N_MONITORS]; } /** * Public ctor, with a given process and logging levels for {@code stdout} * and {@code stderr}. * @param bdr Process builder to execute and monitor * @param stdout Log level for stdout * @param stderr Log level for stderr * @since 0.12 */ public VerboseProcess(final ProcessBuilder bdr, final Level stdout, final Level stderr) { this(VerboseProcess.start(bdr), stdout, stderr); } /** * Get {@code stdout} from the process, after its finish (the method will * wait for the process and log its output). * *

The method will check process exit code, and if it won't be equal * to zero a runtime exception will be thrown. A non-zero exit code * usually is an indicator of problem. If you want to ignore this code, * use {@link #stdoutQuietly()} instead. * * @return Full {@code stdout} of the process */ public String stdout() { return this.stdout(true); } /** * Get {@code stdout} from the process, after its finish (the method will * wait for the process and log its output). * *

This method ignores exit code of the process. Even if it is * not equal to zero (which usually is an indicator of an error), the * method will quietly return its output. The method is useful when * you're running a background process. You will kill it with * {@link Process#destroy()}, which usually will lead to a non-zero * exit code, which you want to ignore. * * @return Full {@code stdout} of the process * @since 0.10 */ public String stdoutQuietly() { return this.stdout(false); } /** * Wait for the process to stop, logging its output in parallel. * @return Stdout produced by the process * @throws InterruptedException If interrupted in between */ public VerboseProcess.Result waitFor() throws InterruptedException { final CountDownLatch done = new CountDownLatch( VerboseProcess.N_MONITORS ); final ByteArrayOutputStream stdout = new ByteArrayOutputStream(); final ByteArrayOutputStream stderr = new ByteArrayOutputStream(); this.launchMonitors(done, stdout, stderr); int code = 0; try { code = this.process.waitFor(); } finally { Logger.debug( this, "#waitFor(): process finished: %s", this.process ); if (!done.await(2L, TimeUnit.SECONDS)) { Logger.error(this, "#wait() failed"); } } try { return new VerboseProcess.Result( code, stdout.toString(VerboseProcess.UTF_8), stderr.toString(VerboseProcess.UTF_8) ); } catch (final UnsupportedEncodingException ex) { throw new IllegalStateException(ex); } } @Override public void close() { synchronized (this.monitors) { this.closed = true; } for (final Thread monitor : this.monitors) { if (monitor != null) { monitor.interrupt(); Logger.debug(this, "monitor interrupted"); } } this.process.destroy(); Logger.debug(this, "underlying process destroyed"); } /** * Start a process from the given builder. * @param builder Process builder to work with * @return Process started */ private static Process start(final ProcessBuilder builder) { if (builder == null) { throw new IllegalArgumentException("builder can't be NULL"); } try { final Process process = builder.start(); process.getOutputStream().close(); return process; } catch (final IOException ex) { throw new IllegalStateException(ex); } } /** * Get standard output and check for non-zero exit code (if required). * @param check TRUE if we should check for non-zero exit code * @return Full {@code stdout} of the process */ @SuppressWarnings("PMD.PrematureDeclaration") private String stdout(final boolean check) { final long start = System.currentTimeMillis(); final VerboseProcess.Result result; try { result = this.waitFor(); } catch (final InterruptedException ex) { Thread.currentThread().interrupt(); throw new IllegalStateException(ex); } Logger.debug( this, "#stdout(): process %s completed (code=%d, size=%d) in %[ms]s", this.process, result.code(), result.stdout().length(), System.currentTimeMillis() - start ); if (check && result.code() != 0) { throw new IllegalArgumentException( Logger.format( "Non-zero exit code %d: %[text]s", result.code(), result.stdout() ) ); } return result.stdout(); } /** * Launch monitors for the underlying process. * @param done Latch that signals termination of all monitors * @param stdout Stream to write the underlying process's output * @param stderr Stream to wrint the underlying process's error output */ private void launchMonitors( final CountDownLatch done, final ByteArrayOutputStream stdout, final ByteArrayOutputStream stderr) { synchronized (this.monitors) { if (this.closed) { done.countDown(); done.countDown(); } else { this.monitors[0] = this.monitor( this.process.getInputStream(), done, stdout, this.olevel, "out" ); Logger.debug( this, "#waitFor(): waiting for stdout of %s in %s...", this.process, this.monitors[0] ); this.monitors[1] = this.monitor( this.process.getErrorStream(), done, stderr, this.elevel, "err" ); Logger.debug( this, "#waitFor(): waiting for stderr of %s in %s...", this.process, this.monitors[1] ); } } } /** * Monitor this input input. * @param input Stream to monitor * @param done Count down latch to signal when done * @param output Buffer to write to * @param level Logging level * @param name Name of this monitor. Used in logging as part of threadname * @return Thread which is monitoring * @checkstyle ParameterNumber (6 lines) */ private Thread monitor(final InputStream input, final CountDownLatch done, final OutputStream output, final Level level, final String name) { final Thread thread = new Thread( new VerboseRunnable( new VerboseProcess.Monitor(input, done, output, level), false ) ); thread.setName( String.format( "VrbPrc.Monitor-%d-%s", this.hashCode(), name ) ); thread.setDaemon(true); thread.start(); return thread; } /** * Close quietly. * @param res Resource to close */ private static void close(final Closeable res) { try { res.close(); } catch (final IOException ex) { Logger.error( VerboseProcess.class, "failed to close resource: %[exception]s", ex ); } } /** * Stream monitor. * * @since 0.1 */ private static final class Monitor implements Callable { /** * Stream to read. */ private final transient InputStream input; /** * Latch to count down when done. */ private final transient CountDownLatch done; /** * Buffer to save output. */ private final transient OutputStream output; /** * Log level. */ private final transient Level level; /** * Ctor. * @param inp Stream to monitor * @param latch Count down latch to signal when done * @param out Buffer to write to * @param lvl Logging level * @checkstyle ParameterNumber (5 lines) */ Monitor(final InputStream inp, final CountDownLatch latch, final OutputStream out, final Level lvl) { this.input = inp; this.done = latch; this.output = out; this.level = lvl; } @Override public Void call() throws Exception { final BufferedReader reader = new BufferedReader( Channels.newReader( Channels.newChannel(this.input), VerboseProcess.UTF_8 ) ); try { final BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(this.output, VerboseProcess.UTF_8) ); try { while (true) { if (Thread.interrupted()) { Logger.debug( VerboseProcess.class, "explicitly interrupting read from buffer" ); break; } final String line = reader.readLine(); if (line == null) { break; } Logger.log( this.level, VerboseProcess.class, ">> %s", line ); writer.write(line); writer.newLine(); } } catch (final ClosedByInterruptException ex) { Thread.interrupted(); Logger.debug( VerboseProcess.class, "Monitor is interrupted in the expected way" ); } catch (final IOException ex) { Logger.error( VerboseProcess.class, "Error reading from process stream: %[exception]s", ex ); } finally { VerboseProcess.close(writer); this.done.countDown(); } } finally { VerboseProcess.close(reader); } return null; } } /** * Class representing the result of a process. * * @since 0.1 */ public static final class Result { /** * Returned code from the process. */ private final transient int exit; /** * {@code stdout} from the process. */ private final transient String out; /** * {@code stderr} from the process. */ private final transient String err; /** * Result class constructor. * @param code The exit code. * @param stdout The {@code stdout} from the process. * @param stderr The {@code stderr} from the process. */ Result(final int code, final String stdout, final String stderr) { this.exit = code; this.out = stdout; this.err = stderr; } /** * Get {@code code} from the process. * @return Full {@code code} of the process */ public int code() { return this.exit; } /** * Get {@code stdout} from the process. * @return Full {@code stdout} of the process */ public String stdout() { return this.out; } /** * Get {@code stderr} from the process. * @return Full {@code stderr} of the process */ public String stderr() { return this.err; } } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/VerboseRunnable.java000066400000000000000000000203611376012136000244330ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.concurrent.Callable; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Wrapper of {@link Runnable}, that logs all uncaught runtime exceptions. * *

You can use it with scheduled executor, for example: * *

 Executors.newScheduledThreadPool(2).scheduleAtFixedRate(
 *   new VerboseRunnable(runnable, true), 1L, 1L, TimeUnit.SECONDS
 * );
* *

Now, every runtime exception that is not caught inside your * {@link Runnable} will be reported to log (using {@link Logger}). * Two-arguments constructor can be used when you need to instruct the class * about what to do with the exception: either swallow it or escalate. * Sometimes it's very important to swallow exceptions. Otherwise an entire * thread may get stuck (like in the example above). * *

This class is thread-safe. * * @since 0.1.3 * @see VerboseThreads * @link Java theory and practice: Dealing with InterruptedException */ @ToString @EqualsAndHashCode(of = { "origin", "rethrow", "verbose" }) @SuppressWarnings("PMD.DoNotUseThreads") public final class VerboseRunnable implements Runnable { /** * Original runnable. */ private final transient Runnable origin; /** * Rethrow exceptions (TRUE) or swallow them? */ private final transient boolean rethrow; /** * Shall we report a full stacktrace? */ private final transient boolean verbose; /** * Default constructor, doesn't swallow exceptions. * @param runnable Runnable to wrap */ public VerboseRunnable(final Runnable runnable) { this(runnable, false); } /** * Default constructor, doesn't swallow exceptions. * @param callable Callable to wrap * @since 0.7.17 */ public VerboseRunnable(final Callable callable) { this(callable, false); } /** * Default constructor, doesn't swallow exceptions. * @param callable Callable to wrap * @param swallow Shall we swallow exceptions * ({@code TRUE}) or re-throw * ({@code FALSE})? Exception swallowing means that {@link #run()} * will never throw any exceptions (in any case all exceptions are logged * using {@link Logger}. * @since 0.1.10 */ public VerboseRunnable(final Callable callable, final boolean swallow) { this(callable, swallow, true); } /** * Default constructor. * @param callable Callable to wrap * @param swallow Shall we swallow exceptions * ({@code TRUE}) or re-throw * ({@code FALSE})? Exception swallowing means that {@link #run()} * will never throw any exceptions (in any case all exceptions are logged * using {@link Logger}. * @param vrbs Shall we report the entire * stacktrace of the exception * ({@code TRUE}) or just its message in one line ({@code FALSE}) * @since 0.7.17 */ @SuppressWarnings("PMD.AvoidCatchingGenericException") public VerboseRunnable(final Callable callable, final boolean swallow, final boolean vrbs) { this( new Runnable() { @Override public void run() { try { callable.call(); } catch (final InterruptedException ex) { Thread.currentThread().interrupt(); throw new IllegalStateException(ex); // @checkstyle IllegalCatch (1 line) } catch (final Exception ex) { throw new IllegalStateException(ex); } } @Override public String toString() { return callable.toString(); } }, swallow, vrbs ); } /** * Default constructor, with configurable behavior for exceptions. * @param runnable Runnable to wrap * @param swallow Shall we swallow exceptions * ({@code TRUE}) or re-throw * ({@code FALSE})? Exception swallowing means that {@link #run()} * will never throw any exceptions (in any case all exceptions are logged * using {@link Logger}. * @since 0.1.4 */ public VerboseRunnable(final Runnable runnable, final boolean swallow) { this(runnable, swallow, true); } /** * Default constructor, with fully configurable behavior. * @param runnable Runnable to wrap * @param swallow Shall we swallow exceptions * ({@code TRUE}) or re-throw * ({@code FALSE})? Exception swallowing means that {@link #run()} * will never throw any exceptions (in any case all exceptions are logged * using {@link Logger}. * @param vrbs Shall we report the entire * stacktrace of the exception * ({@code TRUE}) or just its message in one line ({@code FALSE}) * @since 0.7.17 */ @SuppressWarnings("PMD.BooleanInversion") public VerboseRunnable(final Runnable runnable, final boolean swallow, final boolean vrbs) { this.origin = runnable; this.rethrow = !swallow; this.verbose = vrbs; } @Override @SuppressWarnings("PMD.AvoidCatchingGenericException") public void run() { try { this.origin.run(); // @checkstyle IllegalCatch (1 line) } catch (final RuntimeException ex) { if (this.rethrow) { Logger.warn(this, "escalated exception: %s", this.tail(ex)); throw ex; } Logger.warn(this, "swallowed exception: %s", this.tail(ex)); // @checkstyle IllegalCatch (1 line) } catch (final Error error) { if (this.rethrow) { Logger.error(this, "escalated error: %s", this.tail(error)); throw error; } Logger.error(this, "swallowed error: %s", this.tail(error)); } if (Thread.currentThread().isInterrupted()) { Thread.currentThread().interrupt(); throw new IllegalStateException( "the thread has been interrupted" ); } } /** * Make a tail of the error/warning message, using the exception thrown. * @param throwable The exception/error caught * @return The message to show in logs */ private String tail(final Throwable throwable) { final String tail; if (this.verbose) { tail = Logger.format("%[exception]s", throwable); } else { tail = Logger.format( "%[type]s('%s')", throwable, throwable.getMessage() ); } return tail; } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/VerboseThreads.java000066400000000000000000000170251376012136000242620ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; import lombok.EqualsAndHashCode; import lombok.ToString; /** * Convenient {@link ThreadFactory}, that logs all uncaught exceptions. * *

The factory should be used together * with executor services from {@code java.util.concurrent} package. Without * these "verbose" threads your runnable tasks will not report anything to * console once they die because of a runtime exception, for example: * *

 Executors.newScheduledThreadPool(2).scheduleAtFixedRate(
 *   new Runnable() {
 *     @Override
 *     public void run() {
 *       // some sensitive operation that may throw
 *       // a runtime exception
 *     },
 *     1L, 1L, TimeUnit.SECONDS
 *   }
 * );
* *

The exception in this example will never be caught by nobody. It will * just terminate current execution of the {@link Runnable} task. Moreover, * it won't reach any {@link Thread.UncaughtExceptionHandler}, * because this * is how {@link java.util.concurrent.ScheduledExecutorService} * is behaving. This is how we solve * the problem with {@link VerboseThreads}: * *

 ThreadFactory factory = new VerboseThreads();
 * Executors.newScheduledThreadPool(2, factory).scheduleAtFixedRate(
 *   new Runnable() {
 *     @Override
 *     public void run() {
 *       // the same sensitive operation that may throw
 *       // a runtime exception
 *     },
 *     1L, 1L, TimeUnit.SECONDS
 *   }
 * );
* *

Now, every runtime exception that is not caught inside your * {@link Runnable} will be reported to log (using {@link Logger}). * *

This class is thread-safe. * * @since 0.1.2 * @see VerboseRunnable */ @ToString @EqualsAndHashCode(of = { "group", "prefix", "number", "daemon", "priority" }) @SuppressWarnings("PMD.DoNotUseThreads") public final class VerboseThreads implements ThreadFactory { /** * Thread group. */ private final transient ThreadGroup group; /** * Prefix to use. */ private final transient String prefix; /** * Number of the next thread to create. */ private final transient AtomicInteger number; /** * Create threads as daemons? */ private final transient boolean daemon; /** * Default thread priority. */ private final transient int priority; /** * Default constructor ({@code "verbose"} as a prefix, threads are daemons, * default thread priority is {@code 1}). */ public VerboseThreads() { this("verbose", true, 1); } /** * Detailed constructor, with a prefix of thread names (threads are daemons, * default thread priority is {@code 1}). * @param pfx Prefix for thread names */ public VerboseThreads(final String pfx) { this(pfx, true, 1); } /** * Detailed constructor, with a prefix of thread names (threads are daemons, * default thread priority is {@code 1}). * @param type Prefix will be build from this type name */ public VerboseThreads(final Object type) { this(type.getClass().getSimpleName(), true, 1); } /** * Detailed constructor, with a prefix of thread names (threads are daemons, * default thread priority is {@code 1}). * @param type Prefix will be build from this type name */ public VerboseThreads(final Class type) { this(type.getSimpleName(), true, 1); } /** * Detailed constructor. * @param pfx Prefix for thread names * @param dmn Threads should be daemons? * @param prt Default priority for all threads */ public VerboseThreads(final String pfx, final boolean dmn, final int prt) { this.prefix = pfx; this.daemon = dmn; this.priority = prt; this.group = new VerboseThreads.Group(pfx); this.number = new AtomicInteger(1); } @Override public Thread newThread(final Runnable runnable) { final Thread thread = new Thread( this.group, new VerboseThreads.Wrap(runnable) ); thread.setName( String.format( "%s-%d", this.prefix, this.number.getAndIncrement() ) ); thread.setDaemon(this.daemon); thread.setPriority(this.priority); return thread; } /** * Group to use. * * @since 0.1 */ private static final class Group extends ThreadGroup { /** * Ctor. * @param name Name of it */ Group(final String name) { super(name); } @Override public void uncaughtException(final Thread thread, final Throwable throwable) { Logger.warn(this, "%[exception]s", throwable); } } /** * Runnable decorator. * * @since 0.1 */ private static final class Wrap implements Runnable { /** * Origin runnable. */ private final transient Runnable origin; /** * Ctor. * @param runnable Origin runnable */ Wrap(final Runnable runnable) { this.origin = runnable; } @Override @SuppressWarnings("PMD.AvoidCatchingGenericException") public void run() { try { this.origin.run(); // @checkstyle IllegalCatch (1 line) } catch (final RuntimeException ex) { Logger.warn( this, "%s: %[exception]s", Thread.currentThread().getName(), ex ); throw ex; // @checkstyle IllegalCatch (1 line) } catch (final Error error) { Logger.error( this, "%s (error): %[exception]s", Thread.currentThread().getName(), error ); throw error; } } } } jcabi-log-0.19.0/src/main/java/com/jcabi/log/package-info.java000066400000000000000000000037001376012136000236610ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * Convenient logging utils. * *

The only dependency you need is (check our latest version available * at www.jcabi.com): * *

<depedency>
 *   <groupId>com.jcabi</groupId>
 *   <artifactId>jcabi-log</artifactId>
 * </dependency>
* * @see project website */ package com.jcabi.log; jcabi-log-0.19.0/src/site/000077500000000000000000000000001376012136000151625ustar00rootroot00000000000000jcabi-log-0.19.0/src/site/apt/000077500000000000000000000000001376012136000157465ustar00rootroot00000000000000jcabi-log-0.19.0/src/site/apt/decors.apt.vm000066400000000000000000000065401376012136000203610ustar00rootroot00000000000000 ------ Logging decors ------ Yegor Bugayenko ------ 2012-04-29 ------ ~~ ~~ Copyright (c) 2012-2020, jcabi.com ~~ All rights reserved. ~~ ~~ Redistribution and use in source and binary forms, with or without ~~ modification, are permitted provided that the following conditions ~~ are met: 1) Redistributions of source code must retain the above ~~ copyright notice, this list of conditions and the following ~~ disclaimer. 2) Redistributions in binary form must reproduce the above ~~ copyright notice, this list of conditions and the following ~~ disclaimer in the documentation and/or other materials provided ~~ with the distribution. 3) Neither the name of the jcabi.com nor ~~ the names of its contributors may be used to endorse or promote ~~ products derived from this software without specific prior written ~~ permission. ~~ ~~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ~~ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT ~~ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ~~ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ~~ THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, ~~ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ~~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ~~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ~~ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ~~ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ~~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ~~ OF THE POSSIBILITY OF SUCH DAMAGE. ~~ Decors Log an event like this: +-- import com.jcabi.log.Logger; class Foo { void bar(int value) { final long start = System.nanoTime(); // some operations Logger.debug( this, "bar(%d): done in %[nano]d", value, System.nanoTime() - start ); } } +-- You will see something like this in log: --- [DEBUG] Foo: #bar(1234): done in 3.45ms --- Nano-seconds will be formatted as time through a built-in "decor". There are a few other pre-defined decors: * <<>> -- converts <<>> to text. * <<>> -- exception message and full stacktrace; * <<>> -- array or list of elements into text; * <<>> -- milliseconds into their text presentation; * <<>> -- nanoseconds into their text presentation; * <<>> -- makes text readable; * <<>> -- type name of the object. In order to use your own decor just implement {{{http://docs.oracle.com/javase/7/docs/api/java/util/Formattable.html}<<>>}}: +-- import com.jcabi.log.Decor; import java.util.Formattable; import java.util.Formatter; public final class DataDecor implements Formattable { private final transient Data data; public DataDecor(final Data dat) { this.data = dat; } @Override public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { formatter.format("%s", this.data.getSomeValueOutOfIt()); } } +-- Then, provide its class name in log formatting string, for example: +-- import com.jcabi.log.Logger; public class Main { public static void main(String[] args) { Logger.debug( this, "bar(%d): show some data: %[com.example.DataDecor]s", value, data ); } } +-- jcabi-log-0.19.0/src/site/apt/index.apt.vm000066400000000000000000000075301376012136000202110ustar00rootroot00000000000000 ------ Static Wrapper of SLF4J ------ Yegor Bugayenko ------ 2012-04-29 ------ ~~ ~~ Copyright (c) 2012-2020, jcabi.com ~~ All rights reserved. ~~ ~~ Redistribution and use in source and binary forms, with or without ~~ modification, are permitted provided that the following conditions ~~ are met: 1) Redistributions of source code must retain the above ~~ copyright notice, this list of conditions and the following ~~ disclaimer. 2) Redistributions in binary form must reproduce the above ~~ copyright notice, this list of conditions and the following ~~ disclaimer in the documentation and/or other materials provided ~~ with the distribution. 3) Neither the name of the jcabi.com nor ~~ the names of its contributors may be used to endorse or promote ~~ products derived from this software without specific prior written ~~ permission. ~~ ~~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ~~ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT ~~ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ~~ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ~~ THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, ~~ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ~~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ~~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ~~ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ~~ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ~~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ~~ OF THE POSSIBILITY OF SUCH DAMAGE. ~~ Static Wrapper of SLF4J {{{./apidocs-${project.version}/com/jcabi/log/Logger.html}<<>>}} is a convenient static wrapper of {{{http://www.slf4j.org/}slf4j}} (don't forget to include one of {{{http://www.slf4j.org/manual.html#binding}SLF4J Bindings}} into the project): +-- import com.jcabi.log.Logger; class Foo { void bar(int value) { Logger.debug(this, "method #bar(%d) was called", value); } } +-- Read also about log {{{./decors.html}decors}} and a convenient AOP annotation {{{http://aspects.jcabi.com/annotation-loggable.html}<<<@Loggable>>>}} from {{{http://aspects.jcabi.com/index.html}jcabi-aspects}}. There are a few other convenient classes in this package: * {{{./apidocs-${project.version}/com/jcabi/log/VerboseRunnable.html}<<>>}}: wrapper around <<>> that swallows all runtime exceptions and logs them to SLF4J. * {{{./apidocs-${project.version}/com/jcabi/log/VerboseProcess.html}<<>>}}: wrapper around <<>> that monitors process executions, collects its output into a <<>> and logs everything through SLF4J. * {{{./apidocs-${project.version}/com/jcabi/log/VerboseThreads.html}<<>>}}: an implementation of <<>> that instantiates threads that log all runtime exceptions through SLF4J. The only dependency you need is (you can also download {{{http://repo1.maven.org/maven2/com/jcabi/jcabi-log/${project.version}/jcabi-log-${project.version}.jar}<<>>}} and add it to the classpath): +-- com.jcabi jcabi-log ${project.version} +-- * Cutting Edge Version If you want to use current version of the product, you can do it with this configuration in your <<>>: +-- oss.sonatype.org https://oss.sonatype.org/content/repositories/snapshots/ com.jcabi jcabi-log 1.0-SNAPSHOT +-- jcabi-log-0.19.0/src/site/apt/multicolor.apt.vm000066400000000000000000000060421376012136000212700ustar00rootroot00000000000000 ------ Multicolor Layout for LOG4J ------ Yegor Bugayenko ------ 2012-08-30 ------ ~~ ~~ Copyright (c) 2012-2020, jcabi.com ~~ All rights reserved. ~~ ~~ Redistribution and use in source and binary forms, with or without ~~ modification, are permitted provided that the following conditions ~~ are met: 1) Redistributions of source code must retain the above ~~ copyright notice, this list of conditions and the following ~~ disclaimer. 2) Redistributions in binary form must reproduce the above ~~ copyright notice, this list of conditions and the following ~~ disclaimer in the documentation and/or other materials provided ~~ with the distribution. 3) Neither the name of the jcabi.com nor ~~ the names of its contributors may be used to endorse or promote ~~ products derived from this software without specific prior written ~~ permission. ~~ ~~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ~~ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT ~~ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ~~ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ~~ THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, ~~ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ~~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ~~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ~~ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ~~ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ~~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ~~ OF THE POSSIBILITY OF SUCH DAMAGE. ~~ Multicolor Layout for LOG4J Configure it in your <<>>: +-- log4j.rootLogger=INFO, CONSOLE log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=com.jcabi.log.MulticolorLayout log4j.appender.CONSOLE.layout.ConversionPattern=[%color{%-5p}] %c: %m%n +-- Or in XML config: +-- +-- In version 0.9 there is an ability to re-defined standard colors for logging levels. Besides that, it's possible to re-define numeric values of standard colors, for example: +-- log4j.appender.CONSOLE.layout.Levels=INFO:2;10,WARN:2;32 log4j.appender.CONSOLE.layout.Colors=white:10 +-- Or: +-- +-- Read JavaDoc of {{{./apidocs-${project.version}/com/jcabi/log/MulticolorLayout.html}<<>>}}. The only dependency you need is (you can also download {{{http://repo1.maven.org/maven2/com/jcabi/jcabi-log/${project.version}/jcabi-log-${project.version}.jar}<<>>}} and add it to the classpath): +-- com.jcabi jcabi-log ${project.version} +-- jcabi-log-0.19.0/src/site/apt/threads-VerboseProcess.apt.vm000066400000000000000000000052361376012136000234770ustar00rootroot00000000000000 ------ Process That Logs And Consumes Output ------ Yegor Bugayenko ------ 2012-12-16 ------ ~~ ~~ Copyright (c) 2012-2020, jcabi.com ~~ All rights reserved. ~~ ~~ Redistribution and use in source and binary forms, with or without ~~ modification, are permitted provided that the following conditions ~~ are met: 1) Redistributions of source code must retain the above ~~ copyright notice, this list of conditions and the following ~~ disclaimer. 2) Redistributions in binary form must reproduce the above ~~ copyright notice, this list of conditions and the following ~~ disclaimer in the documentation and/or other materials provided ~~ with the distribution. 3) Neither the name of the jcabi.com nor ~~ the names of its contributors may be used to endorse or promote ~~ products derived from this software without specific prior written ~~ permission. ~~ ~~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ~~ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT ~~ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ~~ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ~~ THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, ~~ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ~~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ~~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ~~ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ~~ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ~~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ~~ OF THE POSSIBILITY OF SUCH DAMAGE. ~~ Process That Logs And Consumes Output {{{./apidocs-${project.version}/com/jcabi/log/VerboseProcess.html}<<>>}} logs output of a java {{{http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html}<<>>}} and consumes its output at the same time, for example: +-- public class Main { public static void main(String[] args) { String name = new VerboseProcess( new ProcessBuilder("who", "am", "i") ).stdout(); System.out.println("I am: " + name); } } +-- {{{./apidocs-${project.version}/com/jcabi/log/VerboseProcess.html}<<>>}} throws an exception if the process returns a non-zero exit code. The only dependency you need is (you can also download {{{http://repo1.maven.org/maven2/com/jcabi/jcabi-log/${project.version}/jcabi-log-${project.version}.jar}<<>>}} and add it to the classpath): +-- com.jcabi jcabi-log ${project.version} +-- jcabi-log-0.19.0/src/site/apt/threads-VerboseRunnable.apt.vm000066400000000000000000000061741376012136000236310ustar00rootroot00000000000000 ------ Runnable That Logs Runtime Exceptions ------ Yegor Bugayenko ------ 2012-12-16 ------ ~~ ~~ Copyright (c) 2012-2020, jcabi.com ~~ All rights reserved. ~~ ~~ Redistribution and use in source and binary forms, with or without ~~ modification, are permitted provided that the following conditions ~~ are met: 1) Redistributions of source code must retain the above ~~ copyright notice, this list of conditions and the following ~~ disclaimer. 2) Redistributions in binary form must reproduce the above ~~ copyright notice, this list of conditions and the following ~~ disclaimer in the documentation and/or other materials provided ~~ with the distribution. 3) Neither the name of the jcabi.com nor ~~ the names of its contributors may be used to endorse or promote ~~ products derived from this software without specific prior written ~~ permission. ~~ ~~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ~~ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT ~~ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ~~ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ~~ THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, ~~ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ~~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ~~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ~~ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ~~ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ~~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ~~ OF THE POSSIBILITY OF SUCH DAMAGE. ~~ Runnable That Logs Runtime Exceptions You can use {{{./apidocs-${project.version}/com/jcabi/log/VerboseRunnable.html}<<>>}}: with scheduled executor, for example: +-- public class Main { public static void main(String[] args) { Executors.newScheduledThreadPool(2).scheduleAtFixedRate( new VerboseRunnable( new Runnable() { @Override public void run() { // some operation that may lead to a runtime // exception, which we want to log through SLF4J } } ), 1L, 1L, TimeUnit.SECONDS ); } } +-- Now, every runtime exception that is not caught inside your {{{http://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html}<<>>}} will be reported to log (using {{{./apidocs-${project.version}/com/jcabi/log/Logger.html}<<>>}}). Two-arguments constructor can be used when you need to instruct the class about what to do with the exception: either swallow it or escalate. Sometimes it's very important to swallow exceptions. Otherwise an entire thread may get stuck (like in the example above). The only dependency you need is (you can also download {{{http://repo1.maven.org/maven2/com/jcabi/jcabi-log/${project.version}/jcabi-log-${project.version}.jar}<<>>}} and add it to the classpath): +-- com.jcabi jcabi-log ${project.version} +-- jcabi-log-0.19.0/src/site/apt/threads-VerboseThreads.apt.vm000066400000000000000000000104051376012136000234450ustar00rootroot00000000000000 ------ Thread Factory that Logs Exceptions ------ Yegor Bugayenko ------ 2012-12-16 ------ ~~ ~~ Copyright (c) 2012-2020, jcabi.com ~~ All rights reserved. ~~ ~~ Redistribution and use in source and binary forms, with or without ~~ modification, are permitted provided that the following conditions ~~ are met: 1) Redistributions of source code must retain the above ~~ copyright notice, this list of conditions and the following ~~ disclaimer. 2) Redistributions in binary form must reproduce the above ~~ copyright notice, this list of conditions and the following ~~ disclaimer in the documentation and/or other materials provided ~~ with the distribution. 3) Neither the name of the jcabi.com nor ~~ the names of its contributors may be used to endorse or promote ~~ products derived from this software without specific prior written ~~ permission. ~~ ~~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ~~ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT ~~ NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND ~~ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ~~ THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, ~~ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ~~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ~~ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ~~ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, ~~ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ~~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED ~~ OF THE POSSIBILITY OF SUCH DAMAGE. ~~ Thread Factory that Logs Exceptions {{{./apidocs-${project.version}/com/jcabi/log/VerboseThreads.html}<<>>}} is an implementation of {{{http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadFactory.html}<<>>}} that instantiates threads that log all runtime exceptions through SLF4J. {{{./apidocs-${project.version}/com/jcabi/log/VerboseThreads.html}<<>>}} factory should be used together with executor services from <<>> package. Without this "verbose" thread factory your runnable tasks will not report anything to console once they die because of a runtime exception, for example: +-- public class Main { public static void main(String[] args) { Executors.newScheduledThreadPool(2).scheduleAtFixedRate( new Runnable() { @Override public void run() { // some sensitive operation that may throw // a runtime exception } }, 1L, 1L, TimeUnit.SECONDS ); } } +-- The exception in this example will never be caught by nobody. It will just terminate current execution of the <<>> task. Moreover, it won't reach any {{{http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.UncaughtExceptionHandler.html}<<>>}}, because this is how {{{http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ScheduledExecutorService.html}<<>>}} is behaving by default. This is how we solve the problem with {{{./apidocs-${project.version}/com/jcabi/log/VerboseThreads.html}<<>>}}: +-- public class Main { public static void main(String[] args) { ThreadFactory factory = new VerboseThreads(); Executors.newScheduledThreadPool(2, factory).scheduleAtFixedRate( new Runnable() { @Override public void run() { // the same sensitive operation that may throw // a runtime exception } }, 1L, 1L, TimeUnit.SECONDS ); } } +-- Now, every runtime exception that is not caught inside your {{{http://docs.oracle.com/javase/7/docs/api/java/lang/Runnable.html}<<>>}} will be reported to log (using {{{./apidocs-${project.version}/com/jcabi/log/Logger.html}<<>>}}). The only dependency you need is (you can also download {{{http://repo1.maven.org/maven2/com/jcabi/jcabi-log/${project.version}/jcabi-log-${project.version}.jar}<<>>}} and add it to the classpath): +-- com.jcabi jcabi-log ${project.version} +-- jcabi-log-0.19.0/src/site/resources/000077500000000000000000000000001376012136000171745ustar00rootroot00000000000000jcabi-log-0.19.0/src/site/resources/CNAME000066400000000000000000000000161376012136000177370ustar00rootroot00000000000000log.jcabi.com jcabi-log-0.19.0/src/site/site.xml000066400000000000000000000061131376012136000166510ustar00rootroot00000000000000 com.jcabi jcabi-maven-skin 1.5.1 jcabi http://img.jcabi.com/logo-square.svg http://www.jcabi.com/ 64 64 UA-1963507-23 jcabi-log-0.19.0/src/test/000077500000000000000000000000001376012136000151755ustar00rootroot00000000000000jcabi-log-0.19.0/src/test/java/000077500000000000000000000000001376012136000161165ustar00rootroot00000000000000jcabi-log-0.19.0/src/test/java/com/000077500000000000000000000000001376012136000166745ustar00rootroot00000000000000jcabi-log-0.19.0/src/test/java/com/jcabi/000077500000000000000000000000001376012136000177445ustar00rootroot00000000000000jcabi-log-0.19.0/src/test/java/com/jcabi/log/000077500000000000000000000000001376012136000205255ustar00rootroot00000000000000jcabi-log-0.19.0/src/test/java/com/jcabi/log/ConversionPatternTest.java000066400000000000000000000121011376012136000257060ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; /** * Test case for {@link ConversionPattern}. * @since 0.19 */ @SuppressWarnings("PMD.AvoidDuplicateLiterals") public final class ConversionPatternTest { /** * Control Sequence Indicator. */ private static final String CSI = "\u001b\\["; /** * Default color map for testing. */ private static final Colors COLORS = new Colors(); @Test public void testGenerateNoReplacement() { MatcherAssert.assertThat( convert(""), Matchers.equalTo("") ); MatcherAssert.assertThat( convert("foo"), Matchers.equalTo("foo") ); MatcherAssert.assertThat( convert("%color"), Matchers.equalTo("%color") ); MatcherAssert.assertThat( convert("%color-"), Matchers.equalTo("%color-") ); MatcherAssert.assertThat( convert("%color{%c{1}foo"), Matchers.equalTo("%color{%c{1}foo") ); } @Test public void testGenerateEmpty() { MatcherAssert.assertThat( convert("%color{}"), Matchers.equalTo(colorWrap("")) ); } @Test public void testGenerateSimple() { MatcherAssert.assertThat( convert("%color{Hello World}"), Matchers.equalTo(colorWrap("Hello World")) ); MatcherAssert.assertThat( convert("%color{Hello World}foo"), Matchers.equalTo(String.format("%sfoo", colorWrap("Hello World"))) ); MatcherAssert.assertThat( convert("%color{Hello}%color{World}"), Matchers.equalTo( String.format("%s%s", colorWrap("Hello"), colorWrap("World")) ) ); } @Test public void testGenerateCurlyBraces() { MatcherAssert.assertThat( ConversionPatternTest.convert("%color{%c{1}}"), Matchers.equalTo(ConversionPatternTest.colorWrap("%c{1}")) ); MatcherAssert.assertThat( ConversionPatternTest.convert("%color{%c{1}}foo"), Matchers.equalTo( String.format("%sfoo", ConversionPatternTest.colorWrap("%c{1}")) ) ); MatcherAssert.assertThat( ConversionPatternTest.convert("%color{%c1}}foo"), Matchers.equalTo( String.format("%s}foo", ConversionPatternTest.colorWrap("%c1")) ) ); MatcherAssert.assertThat( ConversionPatternTest.convert("%color{%c{{{1}{2}}}}foo"), Matchers.equalTo( String.format( "%sfoo", ConversionPatternTest.colorWrap("%c{{{1}{2}}}") ) ) ); } /** * Convenience method to generate conversion pattern for the tests. * @param pat Pattern to be used * @return Conversion pattern */ private static String convert(final String pat) { return new ConversionPattern( pat, ConversionPatternTest.COLORS ).generate(); } /** * Wraps the given string in the expected ANSI color sequence. * @param str Input string to wrap. * @return Wrapped string. */ private static String colorWrap(final String str) { return String.format( "%s?m%s%sm", ConversionPatternTest.CSI, str, ConversionPatternTest.CSI ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/DecorMocker.java000066400000000000000000000045361376012136000235750ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Formattable; import java.util.Formatter; /** * Primitive decor, for testing only. * @since 0.1 */ public final class DecorMocker implements Formattable { /** * The text. */ private final transient String text; /** * Public ctor. * @param txt The text to output */ public DecorMocker(final Object txt) { this.text = txt.toString(); } // @checkstyle ParameterNumber (4 lines) @Override public void formatTo(final Formatter formatter, final int flags, final int width, final int precision) { formatter.format( String.format( "%s [f=%d, w=%d, p=%d]", this.text, flags, width, precision ) ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/DecorsManagerTest.java000066400000000000000000000043201376012136000247410ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * Test case for {@link DecorsManager}. * @since 0.1 */ public final class DecorsManagerTest { @Test public void hasBuiltInDecors() throws Exception { MatcherAssert.assertThat( DecorsManager.decor("nano", 1L), Matchers.instanceOf(NanoDecor.class) ); } @Test public void throwsExceptionForAbsentDecor() { Assertions.assertThrows( DecorException.class, () -> DecorsManager.decor("non-existing-formatter", null) ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/DomDecorTest.java000066400000000000000000000054441376012136000237330ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Formattable; import java.util.Formatter; import javax.xml.parsers.DocumentBuilderFactory; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.mockito.hamcrest.MockitoHamcrest; import org.w3c.dom.Document; /** * Test case for {@link DomDecor}. * * @since 0.1 */ public final class DomDecorTest { @Test public void convertsDocumentToText() throws Exception { final Document doc = DocumentBuilderFactory.newInstance() .newDocumentBuilder().newDocument(); doc.appendChild(doc.createElement("root")); final Formattable decor = new DomDecor(doc); final Appendable dest = Mockito.mock(Appendable.class); final Formatter fmt = new Formatter(dest); decor.formatTo(fmt, 0, 0, 0); Mockito.verify(dest).append( MockitoHamcrest.argThat(Matchers.containsString("")) ); } @Test public void convertsNullToText() throws Exception { final Formattable decor = new DomDecor(null); final Appendable dest = Mockito.mock(Appendable.class); final Formatter fmt = new Formatter(dest); decor.formatTo(fmt, 0, 0, 0); Mockito.verify(dest).append("NULL"); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/ExceptionDecorTest.java000066400000000000000000000056161376012136000251530ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.io.IOException; import java.util.Formattable; import java.util.Formatter; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.mockito.hamcrest.MockitoHamcrest; /** * Test case for {@link ExceptionDecor}. * @since 0.1 */ public final class ExceptionDecorTest { @Test public void convertsExceptionToText() throws Exception { final Formattable decor = new ExceptionDecor(new IOException("ouch!")); final Appendable dest = Mockito.mock(Appendable.class); final Formatter fmt = new Formatter(dest); decor.formatTo(fmt, 0, 0, 0); Mockito.verify(dest).append( MockitoHamcrest.argThat( Matchers.allOf( Matchers.containsString( "java.io.IOException: ouch!" ), Matchers.containsString( "at com.jcabi.log.ExceptionDecorTest." ) ) ) ); } @Test public void convertsNullToText() throws Exception { final Formattable decor = new ExceptionDecor(null); final Appendable dest = Mockito.mock(Appendable.class); final Formatter fmt = new Formatter(dest); decor.formatTo(fmt, 0, 0, 0); Mockito.verify(dest).append("NULL"); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/LineNumberTest.java000066400000000000000000000061261376012136000242750ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.io.StringWriter; import java.util.concurrent.TimeUnit; import org.apache.log4j.Appender; import org.apache.log4j.Level; import org.apache.log4j.LogManager; import org.apache.log4j.PatternLayout; import org.apache.log4j.WriterAppender; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; /** * Test case for %L pattern. * If you change this class, you have to care about line number * in "com.jcabi.log.LineNumberTest:72" * @since 1.18 */ public final class LineNumberTest { /** * Conversation pattern for test case. */ private static final String CONV_PATTERN = "%c:%L"; @Test public void testLineNumber() throws Exception { final PatternLayout layout = new PatternLayout(); layout.setConversionPattern(LineNumberTest.CONV_PATTERN); final org.apache.log4j.Logger root = LogManager.getRootLogger(); final Level level = root.getLevel(); root.setLevel(Level.INFO); final StringWriter writer = new StringWriter(); final Appender appender = new WriterAppender(layout, writer); root.addAppender(appender); try { Logger.info(this, "Test"); TimeUnit.MILLISECONDS.sleep(1L); MatcherAssert.assertThat( writer.toString(), Matchers.containsString( "com.jcabi.log.LineNumberTest:245" ) ); } finally { root.removeAppender(appender); root.setLevel(level); } } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/ListDecorTest.java000066400000000000000000000072571376012136000241330ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Locale; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Test case for {@link ListDecor}. * * @since 0.1 * @checkstyle ParameterNumberCheck (500 lines) */ public final class ListDecorTest { @ParameterizedTest @MethodSource("params") public void testPrintsRight(final Object list, final String text, final int flags, final int width, final int precision) throws DecorException { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Printed(new ListDecor(list), flags, width, precision), Matchers.hasToString(text) ); } @ParameterizedTest @MethodSource("params") public void testLogsRight(final Object list, final String text, final int flags, final int width, final int precision) throws DecorException { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Logged(new ListDecor(list), flags, width, precision), Matchers.hasToString(text) ); } /** * Params for this parametrized test. * @return Array of arrays of params for ctor */ @SuppressWarnings("PMD.UnusedPrivateMethod") private static Collection params() { return Arrays.asList( new Object[][] { // @checkstyle MultipleStringLiterals (8 lines) {null, "[NULL]", 0, 0, 0}, {new String[] {}, "[]", 0, 0, 0}, {new String[] {"a"}, "[\"a\"]", 0, 0, 0}, {new Long[] {2L, 1L}, "[\"2\", \"1\"]", 0, 0, 0}, {new Object[] {"b", "c"}, "[\"b\", \"c\"]", 0, 0, 0}, {new Object[] {"foo", 2L}, "[\"foo\", \"2\"]", 0, 0, 0}, {new ArrayList(0), "[]", 0, 0, 0}, {Arrays.asList(new String[] {"x"}), "[\"x\"]", 0, 0, 0}, {Arrays.asList(new Long[] {1L, 2L}), "[\"1\", \"2\"]", 0, 0, 0}, } ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/Logged.java000066400000000000000000000061421376012136000225740ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Formattable; import java.util.FormattableFlags; /** * Logs decor. * * @since 0.1 */ public final class Logged { /** * The decor. */ private final transient Formattable decor; /** * Formatting flas. */ private final transient int flags; /** * Formatting width. */ private final transient int width; /** * Formatting precision. */ private final transient int precision; /** * Public ctor. * @param dcr Decor * @param flgs Flags * @param wdt Width * @param prcs Precission * @checkstyle ParameterNumber (3 lines) */ public Logged(final Formattable dcr, final int flgs, final int wdt, final int prcs) { this.decor = dcr; this.flags = flgs; this.width = wdt; this.precision = prcs; } @Override public String toString() { final StringBuilder format = new StringBuilder(0); format.append('%'); if ((this.flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags .LEFT_JUSTIFY) { format.append('-'); } if (this.width > 0) { format.append(this.width); } if (this.precision > 0) { format.append('.').append(this.precision); } if ((this.flags & FormattableFlags.UPPERCASE) == FormattableFlags .UPPERCASE) { format.append('S'); } else { format.append('s'); } return Logger.format(format.toString(), this.decor); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/LoggerTest.java000066400000000000000000000111331376012136000234460ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import org.apache.log4j.LogManager; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * Test case for {@link Logger}. * @since 0.1 */ public final class LoggerTest { @Test public void detectsLoggerNameCorrectly() throws Exception { // not implemented yet } @Test public void detectsNameOfStaticSource() throws Exception { // not implemented yet } @Test public void setsLoggingLevel() throws Exception { // not implemented yet } @Test public void doesntFormatArraysSinceTheyAreVarArgs() { Assertions.assertThrows( IllegalArgumentException.class, () -> Logger.format("array: %[list]s", new Object[] {"hi", 1}) ); } @Test public void interpretsArraysAsVarArgs() { MatcherAssert.assertThat( Logger.format("array: %s : %d", new Object[] {"hello", 2}), Matchers.is("array: hello : 2") ); } @Test public void providesOutputStream() throws Exception { final OutputStream stream = Logger.stream(Level.INFO, this); final PrintWriter writer = new PrintWriter( new OutputStreamWriter(stream, "UTF-8") ); // @checkstyle LineLength (1 line) writer.print("hello, \u20ac, how're\u040a?\nI'm fine, \u0000\u0007!\n"); writer.flush(); writer.close(); } @Test public void throwsWhenParamsLessThanFormatArgs() { Assertions.assertThrows( ArrayIndexOutOfBoundsException.class, () -> Logger.format("String %s Char %c Number %d", "howdy", 'x') ); } @Test public void throwsWhenParamsMoreThanFormatArgs() { Assertions.assertThrows( IllegalArgumentException.class, () -> Logger.format("String %s Number %d Char %c", "hey", 1, 'x', 2) ); } @Test public void checksLogLevel() throws Exception { LogManager.getRootLogger().setLevel(org.apache.log4j.Level.INFO); TimeUnit.MILLISECONDS.sleep(1L); MatcherAssert.assertThat( Logger.isEnabled(Level.INFO, LogManager.getRootLogger()), Matchers.is(true) ); MatcherAssert.assertThat( Logger.isEnabled(Level.FINEST, LogManager.getRootLogger()), Matchers.is(false) ); } @Test public void usesStringAsLoggerName() { Logger.info("com.jcabi.log...why.not", "hello, %s!", "world!"); } @Test public void findsArgsByPositions() { final String first = "xyz"; final String second = "ddd"; MatcherAssert.assertThat( Logger.format("first: %s, first again: %1$s %s", first, second), Matchers.endsWith( String.format(": %s, first again: %1$s %s", first, second) ) ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/MsDecorTest.java000066400000000000000000000073301376012136000235670ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Arrays; import java.util.Collection; import java.util.FormattableFlags; import java.util.Locale; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Test case for {@link MsDecor}. * * @since 0.1 * @checkstyle ParameterNumberCheck (500 lines) */ public final class MsDecorTest { @ParameterizedTest @MethodSource("params") public void testPrintsRight(final long value, final String text, final int flags, final int width, final int precision) { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Printed(new MsDecor(value), flags, width, precision), Matchers.hasToString(text) ); } @ParameterizedTest @MethodSource("params") public void testLogsRight(final long value, final String text, final int flags, final int width, final int precision) { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Logged(new MsDecor(value), flags, width, precision), Matchers.hasToString(text) ); } @Test public void testPrintsNullRight() { MatcherAssert.assertThat( new Logged(new MsDecor(null), 0, 0, 0), Matchers.hasToString("NULL") ); } /** * Params for this parametrized test. * @return Array of arrays of params for ctor */ @SuppressWarnings("PMD.UnusedPrivateMethod") private static Collection params() { return Arrays.asList( new Object[][] { // @checkstyle LineLength (20 lines) // @checkstyle MagicNumber (20 lines) {13L, "13ms", 0, 0, -1}, {13L, "13.0ms", 0, 0, 1}, {1024L, "1s", 0, 0, 0}, {6001L, "6.0010s", 0, 0, 4}, {122_001L, " 2MIN", FormattableFlags.UPPERCASE, 6, 0}, {3_789_003L, "1hr", 0, 0, 0}, {86_400_000L, "1days", 0, 0, 0}, {864_000_000L, "10days", 0, 0, 0}, } ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/MulticolorLayoutTest.java000066400000000000000000000131211376012136000255550ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import org.apache.commons.text.StringEscapeUtils; import org.apache.log4j.Level; import org.apache.log4j.spi.LoggingEvent; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import org.mockito.Mockito; /** * Test case for {@link MulticolorLayout}. * * @since 0.1 */ public final class MulticolorLayoutTest { /** * Conversation pattern for test case. */ private static final String CONV_PATTERN = "[%color{%p}] %color{%m}"; @Test public void transformsLoggingEventToText() { final MulticolorLayout layout = new MulticolorLayout(); layout.setConversionPattern(MulticolorLayoutTest.CONV_PATTERN); final LoggingEvent event = Mockito.mock(LoggingEvent.class); Mockito.doReturn(Level.DEBUG).when(event).getLevel(); Mockito.doReturn("hello").when(event).getRenderedMessage(); MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo( "[\\u001B[2;37mDEBUG\\u001B[m] \\u001B[2;37mhello\\u001B[m" ) ); } @Test public void overwriteDefaultColor() { final MulticolorLayout layout = new MulticolorLayout(); layout.setConversionPattern(MulticolorLayoutTest.CONV_PATTERN); layout.setLevels("INFO:2;10"); final LoggingEvent event = Mockito.mock(LoggingEvent.class); Mockito.doReturn(Level.INFO).when(event).getLevel(); Mockito.doReturn("change").when(event).getRenderedMessage(); MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo( "[\\u001B[2;10mINFO\\u001B[m] \\u001B[2;10mchange\\u001B[m" ) ); } @Test public void rendersCustomConstantColor() { final MulticolorLayout layout = new MulticolorLayout(); layout.setConversionPattern("%color-red{%p} %m"); final LoggingEvent event = Mockito.mock(LoggingEvent.class); Mockito.doReturn(Level.DEBUG).when(event).getLevel(); Mockito.doReturn("foo").when(event).getRenderedMessage(); MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo("\\u001B[31mDEBUG\\u001B[m foo") ); } @Test public void overwriteCustomConstantColor() { final MulticolorLayout layout = new MulticolorLayout(); layout.setConversionPattern("%color-white{%p} %m"); layout.setColors("white:10"); final LoggingEvent event = Mockito.mock(LoggingEvent.class); Mockito.doReturn(Level.DEBUG).when(event).getLevel(); Mockito.doReturn("const").when(event).getRenderedMessage(); MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo("\\u001B[10mDEBUG\\u001B[m const") ); } @Test public void rendersAnsiConstantColor() { final MulticolorLayout layout = new MulticolorLayout(); layout.setConversionPattern("%color-0;0;31{%p} %m"); final LoggingEvent event = Mockito.mock(LoggingEvent.class); Mockito.doReturn(Level.DEBUG).when(event).getLevel(); Mockito.doReturn("bar").when(event).getRenderedMessage(); MatcherAssert.assertThat( StringEscapeUtils.escapeJava(layout.format(event)), Matchers.equalTo("\\u001B[0;0;31mDEBUG\\u001B[m bar") ); } @Test public void throwsOnIllegalColorName() { Assertions.assertThrows( IllegalArgumentException.class, () -> { final MulticolorLayout layout = new MulticolorLayout(); layout.setConversionPattern("%color-oops{%p} %m"); final LoggingEvent event = Mockito.mock(LoggingEvent.class); Mockito.doReturn(Level.DEBUG).when(event).getLevel(); Mockito.doReturn("text").when(event).getRenderedMessage(); layout.format(event); } ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/NanoDecorTest.java000066400000000000000000000105021376012136000240760ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Arrays; import java.util.Collection; import java.util.FormattableFlags; import java.util.Locale; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Test case for {@link NanoDecor}. * @since 0.1 * @checkstyle ParameterNumberCheck (500 lines) */ public final class NanoDecorTest { @ParameterizedTest @MethodSource("params") public void testPrintsRight(final long nano, final String text, final int flags, final int width, final int precision) throws DecorException { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Printed(new NanoDecor(nano), flags, width, precision), Matchers.hasToString(text) ); } @ParameterizedTest @MethodSource("params") public void testLogsRight(final long nano, final String text, final int flags, final int width, final int precision) throws DecorException { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Logged(new NanoDecor(nano), flags, width, precision), Matchers.hasToString(text) ); } @Test public void testPrintsNullRight() { MatcherAssert.assertThat( new Logged(new NanoDecor(null), 0, 0, 0), Matchers.hasToString("NULL") ); } /** * Params for this parametrized test. * @return Array of arrays of params for ctor */ @SuppressWarnings("PMD.UnusedPrivateMethod") private static Collection params() { return Arrays.asList( new Object[][] { // @checkstyle LineLength (20 lines) // @checkstyle MagicNumber (20 lines) {13L, "13ns", 0, 0, -1}, {13L, "13.0ns", 0, 0, 1}, {25L, "25.00ns", 0, 0, 2}, {234L, "234.0ns", 0, 0, 1}, {1024L, "1µs", 0, 0, 0}, {1056L, "1.056µs", 0, 0, 3}, {9022L, "9.02µs", 0, 0, 2}, {53_111L, "53.11µs ", FormattableFlags.LEFT_JUSTIFY, 10, 2}, {53_156L, " 53µs", 0, 7, 0}, {87_090_432L, " 87ms", 0, 6, 0}, {87_090_543L, "87.09ms", 0, 0, 2}, {87_090_548L, "87.0905ms", 0, 0, 4}, {6_001_001_001L, "6.0010s", 0, 0, 4}, {122_001_001_001L, " 2MIN", FormattableFlags.UPPERCASE, 6, 0}, {3_789_001_001_001L, "63.15002min", 0, 0, 5}, {3_789_002_002_002L, "63.2min", 0, 0, 1}, {3_789_003_003_003L, "63min", 0, 0, 0}, {342_000_004_004_004L, "5700min", 0, 0, 0}, } ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/ObjectDecorTest.java000066400000000000000000000104001376012136000244060ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Arrays; import java.util.Collection; import java.util.Locale; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Test case for {@link ObjectDecor}. * * @since 0.1 * @checkstyle ParameterNumberCheck (500 lines) */ public final class ObjectDecorTest { @ParameterizedTest @MethodSource("params") public void testPrintsRight(final Object obj, final String text, final int flags, final int width, final int precision) throws DecorException { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Printed(new ObjectDecor(obj), flags, width, precision), Matchers.hasToString(text) ); } @ParameterizedTest @MethodSource("params") public void testLogsRight(final Object obj, final String text, final int flags, final int width, final int precision) throws DecorException { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Logged(new ObjectDecor(obj), flags, width, precision), Matchers.hasToString(text) ); } /** * Params for this parametrized test. * @return Array of arrays of params for ctor */ @SuppressWarnings("PMD.UnusedPrivateMethod") private static Collection params() { return Arrays.asList( new Object[][] { {null, "NULL", 0, 0, 0}, {new SecretDecor("x"), "{secret: \"x\"}", 0, 0, 0}, {new Foo(1, "one"), "{num: \"1\", name: \"one\"}", 0, 0, 0}, // @checkstyle MethodBodyComments (6 lines) // @checkstyle LineLength (3 lines) { new Object[]{new Foo(0, "zero"), new Foo(2, "two")}, "[{num: \"0\", name: \"zero\"}, {num: \"2\", name: \"two\"}]", 0, 0, 0, }, { new Object[] {new Object[] {null}, }, "[[NULL]]", 0, 0, 0, }, } ); } /** * Test class for displaying object contents. * * @since 0.1 */ private static final class Foo { /** * The number. */ @SuppressWarnings("unused") private final transient int num; /** * The name. */ @SuppressWarnings("unused") private final transient String name; /** * Ctor. * @param number The number * @param nme The name */ Foo(final int number, final String nme) { this.num = number; this.name = nme; } } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/ParseableInformationTest.java000066400000000000000000000062101376012136000263330ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * ParseableInformation test case. * @since 0.18 */ public class ParseableInformationTest { /** * ParseableInformation can parse if the information correctly if is using * the right pattern. */ @Test @SuppressWarnings("PMD.UseConcurrentHashMap") public final void parsesTheInformationCorrectly() { final Map parsed = new ParseableInformation( "red:10,black:20" ).information(); MatcherAssert.assertThat(parsed, Matchers.hasEntry("red", "10")); MatcherAssert.assertThat(parsed, Matchers.hasEntry("black", "20")); } /** * ParseableInformation can throw an an exception when parsing wrong info. */ @Test public final void throwsAnExceptionWhenParsingSomethingWrong() { final String white = "white"; try { new ParseableInformation(white).information(); Assertions.fail("Should never enter this assert!"); } catch (final IllegalStateException ex) { MatcherAssert.assertThat( ex.getMessage(), Matchers.equalTo( String.format( StringUtils.join( "Information is not using the pattern ", "KEY1:VALUE,KEY2:VALUE %s" ), white ) ) ); } } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/ParseableLevelInformationTest.java000066400000000000000000000074261376012136000273350ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Map; import org.apache.commons.lang3.StringUtils; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * ParseableLevelInformation test case. * @since 0.18 */ public class ParseableLevelInformationTest { /** * ParseableLevelInformation can parse the information correctly when it's * with the right pattern. */ @Test @SuppressWarnings("PMD.UseConcurrentHashMap") public final void parsesCorrectlyTheInformation() { final Map parsed = new ParseableLevelInformation( "INFO:2;10,WARN:2;32" ).information(); MatcherAssert.assertThat(parsed, Matchers.hasEntry("INFO", "2;10")); MatcherAssert.assertThat(parsed, Matchers.hasEntry("WARN", "2;32")); } /** * ParseableLevelInformation can throw an exception when information is * not with the right pattern. */ @Test public final void throwsAnExceptionWhenParsingIncorrectInformation() { final String wrong = "INFO;10,WARN;32"; try { new ParseableLevelInformation(wrong).information(); Assertions.fail("Something was wrong"); } catch (final IllegalStateException ex) { MatcherAssert.assertThat( ex.getMessage(), Matchers.equalTo( String.format( StringUtils.join( "Information is not using the pattern ", "KEY1:VALUE,KEY2:VALUE %s" ), wrong ) ) ); } } /** * ParseableLevelInformation can throw an exception when passing information * with a wrong type of level. */ @Test public final void throwsAnExceptionWhenParsingWrongLevelType() { try { new ParseableLevelInformation( "INFO:2;10,EXTREME:2;32" ).information(); Assertions.fail(""); } catch (final IllegalStateException ex) { MatcherAssert.assertThat( ex.getMessage(), Matchers.equalTo("Unknown level 'EXTREME'") ); } } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/PreFormatterTest.java000066400000000000000000000100241376012136000246370ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; /** * Test case for {@link PreFormatter}. * @since 0.1 */ public final class PreFormatterTest { /** * PreFormatter can format simple texts. */ @Test public void decoratesArguments() { final PreFormatter pre = new PreFormatter( "%[com.jcabi.log.DecorMocker]-5.2f and %1$+.6f", 1.0d ); MatcherAssert.assertThat( pre.getFormat(), Matchers.equalTo("%-5.2f and %1$+.6f") ); MatcherAssert.assertThat( pre.getArguments()[0], Matchers.instanceOf(DecorMocker.class) ); } /** * PreFormatter can handle missed decors. */ @Test public void formatsEvenWithMissedDecors() { final PreFormatter pre = new PreFormatter("ouch: %[missed]s", "test"); MatcherAssert.assertThat( pre.getFormat(), Matchers.equalTo("ouch: %s") ); MatcherAssert.assertThat( pre.getArguments()[0], Matchers.instanceOf(String.class) ); } /** * PreFormatter can handle directly provided decors. */ @Test public void formatsWithDirectlyProvidedDecors() { final DecorMocker decor = new DecorMocker("a"); final PreFormatter pre = new PreFormatter("test: %s", decor); MatcherAssert.assertThat( pre.getArguments()[0], Matchers.equalTo((Object) decor) ); } /** * PreFormatter can handle new line specifier. */ @Test public void handleNewLineSpecifier() { final String fmt = "%s%n%s"; final Object[] args = {"new", "line"}; final PreFormatter pre = new PreFormatter(fmt, args); MatcherAssert.assertThat( pre.getFormat(), Matchers.is(fmt) ); MatcherAssert.assertThat( pre.getArguments(), Matchers.is(args) ); } /** * PreFormatter can handle percent specifier. */ @Test public void handlePercentSpecifier() { final String fmt = "%s%%"; final Object[] args = {"percent: "}; final PreFormatter pre = new PreFormatter(fmt, args); MatcherAssert.assertThat( pre.getFormat(), Matchers.is(fmt) ); MatcherAssert.assertThat( pre.getArguments(), Matchers.is(args) ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/Printed.java000066400000000000000000000053461376012136000230050ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.io.ByteArrayOutputStream; import java.util.Formattable; import java.util.Formatter; /** * Prints decor. * * @since 0.1 */ public final class Printed { /** * The decor. */ private final transient Formattable decor; /** * Formatting flas. */ private final transient int flags; /** * Formatting width. */ private final transient int width; /** * Formatting precision. */ private final transient int precision; /** * Public ctor. * @param dcr Decor * @param flgs Flags * @param wdt Width * @param prcs Precission * @checkstyle ParameterNumber (3 lines) */ public Printed(final Formattable dcr, final int flgs, final int wdt, final int prcs) { this.decor = dcr; this.flags = flgs; this.width = wdt; this.precision = prcs; } @Override public String toString() { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final Formatter fmt = new Formatter(baos); this.decor.formatTo(fmt, this.flags, this.width, this.precision); fmt.flush(); return baos.toString(); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/SecretDecorTest.java000066400000000000000000000065101376012136000244340ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Arrays; import java.util.Collection; import java.util.FormattableFlags; import java.util.Locale; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Test case for {@link SecretDecor}. * * @since 0.1 * @checkstyle ParameterNumberCheck (500 lines) */ public final class SecretDecorTest { @ParameterizedTest @MethodSource("params") public void testPrintsRight(final Object list, final String text, final int flags, final int width, final int precision) { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Printed(new SecretDecor(list), flags, width, precision), Matchers.hasToString(text) ); } @ParameterizedTest @MethodSource("params") public void testLogsRight(final Object list, final String text, final int flags, final int width, final int precision) { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Logged(new SecretDecor(list), flags, width, precision), Matchers.hasToString(text) ); } /** * Params for this parametrized test. * @return Array of arrays of params for ctor */ @SuppressWarnings("PMD.UnusedPrivateMethod") private static Collection params() { return Arrays.asList( new Object[][] { // @checkstyle MagicNumber (4 lines) {"testing", "t***g", 0, 0, 0}, {"ouch", "o***h ", FormattableFlags.LEFT_JUSTIFY, 7, 5}, {"x", " X***X", FormattableFlags.UPPERCASE, 6, 0}, {null, "NULL", FormattableFlags.UPPERCASE, 6, 0}, } ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/SizeDecorTest.java000066400000000000000000000100231376012136000241130ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Arrays; import java.util.Collection; import java.util.FormattableFlags; import java.util.Locale; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Test case for {@link SizeDecor}. * * @since 0.1 * @checkstyle ParameterNumberCheck (500 lines) */ public final class SizeDecorTest { @ParameterizedTest @MethodSource("params") public void testPrintsRight(final long size, final String text, final int flags, final int width, final int precision) throws DecorException { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Printed(new SizeDecor(size), flags, width, precision), Matchers.hasToString(text) ); } @ParameterizedTest @MethodSource("params") public void testLogsRight(final long size, final String text, final int flags, final int width, final int precision) throws DecorException { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Logged(new SizeDecor(size), flags, width, precision), Matchers.hasToString(text) ); } @Test public void testPrintsNullRight() { MatcherAssert.assertThat( new Logged(new SizeDecor(null), 0, 0, 0), Matchers.hasToString("NULL") ); } /** * Params for this parametrized test. * @return Array of arrays of params for ctor */ @SuppressWarnings("PMD.UnusedPrivateMethod") private static Collection params() { return Arrays.asList( new Object[][] { // @checkstyle MagicNumber (14 lines) {1L, "1b", 0, 0, 0}, {123L, " 123b", 0, 6, 0}, {1024L, "1.000Kb", 0, 0, 3}, {5120L, "5Kb", 0, 0, 0}, {12_345L, "12.056Kb", 0, 0, 3}, {12_345L, "12.1Kb ", FormattableFlags.LEFT_JUSTIFY, 8, 1}, {98_765_432L, "94.190MB", FormattableFlags.UPPERCASE, 0, 3}, {98_765_432L, "94.190Mb", 0, 0, 3}, {90L * 1024 * 1024 * 1024, "90Gb", 0, 0, 0}, {13L * 1024 * 1024 * 1024 * 1024, "13Tb", 0, 0, 0}, {33L * 1024 * 1024 * 1024 * 1024 * 1024, "33Pb", 0, 0, 0}, {3L * 1024 * 1024 * 1024 * 1024 * 1024 * 1024, "3Eb", 0, 0, 0}, } ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/SupplierLoggerTest.java000066400000000000000000000160121376012136000251730ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import org.apache.log4j.Level; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** * Test case for {@link SupplierLogger}. * @since 0.18 * @todo #100:30min Some tests here are ignored since they conflict * in multi-threading run. I don't know exactly how to fix them, * but we need to fix and remove the "Ignore" annotations. */ @SuppressWarnings("PMD.MoreThanOneLogger") public final class SupplierLoggerTest { @Test public void debugIsDisabled() { final String name = "nodebug"; final String appender = "nodebugapp"; final org.apache.log4j.Logger logger = this.loggerForTest( name, appender, Level.ERROR ); SupplierLogger.debug( name, "Debug disabled: %s", (Supplier) () -> "test1" ); MatcherAssert.assertThat( ((UnitTestAppender) logger.getAppender(appender)).output(), Matchers.emptyString() ); } @Test @Disabled public void debugIsEnabled() { final String name = "debugen"; final String appender = "debugapp"; final org.apache.log4j.Logger logger = this.loggerForTest( name, appender, Level.DEBUG ); final String text = "test2"; SupplierLogger.debug( name, "Debug enabled: %s", (Supplier) () -> text ); MatcherAssert.assertThat( ((UnitTestAppender) logger.getAppender(appender)).output(), Matchers.containsString(text) ); } @Test public void traceIsDisabled() throws Exception { final String name = "notrace"; final String appender = "notraceapp"; final org.apache.log4j.Logger logger = this.loggerForTest( name, appender, Level.ERROR ); SupplierLogger.trace( name, "Trace disabled: %s", (Supplier) () -> "test3" ); MatcherAssert.assertThat( ((UnitTestAppender) logger.getAppender(appender)).output(), Matchers.emptyString() ); } @Test public void traceIsEnabled() { final String name = "enabledtrace"; final String appender = "traceapp"; final org.apache.log4j.Logger logger = this.loggerForTest( name, appender, Level.TRACE ); final String text = "text4"; SupplierLogger.trace( name, "Trace enabled: %s", (Supplier) () -> text ); MatcherAssert.assertThat( ((UnitTestAppender) logger.getAppender(appender)).output(), Matchers.containsString(text) ); } @Test public void warnIsDisabled() { final String name = "nowarn"; final String appender = "nowarnapp"; final org.apache.log4j.Logger logger = this.loggerForTest( name, appender, Level.ERROR ); SupplierLogger.warn( name, "Warn disabled: %s", (Supplier) () -> "test5" ); MatcherAssert.assertThat( ((UnitTestAppender) logger.getAppender(appender)).output(), Matchers.emptyString() ); } @Test @Disabled public void warnIsEnabled() { final String name = "enwarn"; final String appender = "warnapp"; final org.apache.log4j.Logger logger = this.loggerForTest( name, appender, Level.WARN ); final String text = "test6"; SupplierLogger.warn( name, "Warn enabled: %s", (Supplier) () -> text ); MatcherAssert.assertThat( ((UnitTestAppender) logger.getAppender(appender)).output(), Matchers.containsString(text) ); } @Test public void infoIsDisabled() { final String name = "noinfo"; final String appender = "noinfoapp"; final org.apache.log4j.Logger logger = this.loggerForTest( name, appender, Level.WARN ); SupplierLogger.info( name, "Info disabled: %s", (Supplier) () -> "test7" ); MatcherAssert.assertThat( ((UnitTestAppender) logger.getAppender(appender)).output(), Matchers.emptyString() ); } @Test @Disabled public void infoIsEnabled() { final String name = "withinfo"; final String appender = "infoapp"; final org.apache.log4j.Logger logger = this.loggerForTest( name, appender, Level.INFO ); final String text = "text8"; SupplierLogger.info( name, "Info enabled: %s", (Supplier) () -> text ); MatcherAssert.assertThat( ((UnitTestAppender) logger.getAppender(appender)).output(), Matchers.containsString(text) ); } /** * Builds a logger for each test method. * @param name Logger's name * @param appender Appender's name * @param level Logging level * @return Logger for test */ public org.apache.log4j.Logger loggerForTest( final String name, final String appender, final Level level) { final org.apache.log4j.Logger logger = org.apache.log4j.Logger .getLogger(name); final UnitTestAppender app = new UnitTestAppender(appender); app.activateOptions(); logger.addAppender(app); logger.setLevel(level); return logger; } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/TextDecorTest.java000066400000000000000000000100641376012136000241320ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Arrays; import java.util.Collection; import java.util.Formattable; import java.util.Formatter; import java.util.Locale; import org.apache.commons.lang3.StringUtils; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Test case for {@link TextDecor}. * * @since 0.1 * @checkstyle ParameterNumberCheck (500 lines) */ public final class TextDecorTest { @ParameterizedTest @MethodSource("params") public void testPrintsRight(final String obj, final String text, final int flags, final int width, final int precision) throws DecorException { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Printed(new TextDecor(obj), flags, width, precision), Matchers.hasToString(text) ); } @ParameterizedTest @MethodSource("params") public void testLogsRight(final String obj, final String text, final int flags, final int width, final int precision) throws DecorException { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Logged(new TextDecor(obj), flags, width, precision), Matchers.hasToString(text) ); } /** * Test for a long text. */ @Test public void compressesLongText() { final int len = 1000; final String text = StringUtils.repeat('x', len); final Formattable fmt = new TextDecor(text); final StringBuilder output = new StringBuilder(100); fmt.formatTo(new Formatter(output), 0, 0, 0); MatcherAssert.assertThat( output.length(), Matchers.describedAs( output.toString(), Matchers.equalTo(TextDecor.MAX) ) ); } /** * Params for this parametrized test. * @return Array of arrays of params for ctor */ @SuppressWarnings( { "PMD.AvoidDuplicateLiterals", "PMD.UnusedPrivateMethod" } ) private static Collection params() { return Arrays.asList( new Object[][] { // @checkstyle MultipleStringLiterals (1 line) {"simple text", "simple text", 0, 0, 0}, {null, "NULL", 0, 0, 0}, // @checkstyle MultipleStringLiteralsCheck (1 line) {"\u0433!", "\u0433!", 0, 0, 0}, } ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/TypeDecorTest.java000066400000000000000000000062561376012136000241370ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.Arrays; import java.util.Collection; import java.util.Locale; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; /** * Test case for {@link TypeDecor}. * * @since 0.1 * @checkstyle ParameterNumberCheck (500 lines) */ public final class TypeDecorTest { @ParameterizedTest @MethodSource("params") public void testPrintsRight(final Object list, final String text, final int flags, final int width, final int precision) throws DecorException { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Printed(new TypeDecor(list), flags, width, precision), Matchers.hasToString(text) ); } @ParameterizedTest @MethodSource("params") public void testLogsRight(final Object list, final String text, final int flags, final int width, final int precision) throws DecorException { Locale.setDefault(Locale.US); MatcherAssert.assertThat( new Logged(new TypeDecor(list), flags, width, precision), Matchers.hasToString(text) ); } /** * Params for this parametrized test. * @return Array of arrays of params for ctor */ @SuppressWarnings("PMD.UnusedPrivateMethod") private static Collection params() { return Arrays.asList( new Object[][] { {"testing", "java.lang.String", 0, 0, 0}, {null, "NULL", 0, 0, 0}, {1.0d, "java.lang.Double", 0, 0, 0}, } ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/UnitTestAppender.java000066400000000000000000000054751376012136000246410ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.io.ByteArrayOutputStream; import java.nio.charset.StandardCharsets; import org.apache.log4j.PatternLayout; import org.apache.log4j.WriterAppender; /** * Log4j appender for unit tests. Normally, we could use * slf4j-test, but we * have log4j in the classpath anyway, for {@link MulticolorLayout}. * @since 0.18 */ public final class UnitTestAppender extends WriterAppender { /** * OutputStream where this Appender writes. */ private final transient ByteArrayOutputStream logs; /** * Ctor. * @param name The appender's name */ @SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors") public UnitTestAppender(final String name) { super(); this.setName(name); this.logs = new ByteArrayOutputStream(); } /** * Prepares the appender for use. */ public void activateOptions() { setWriter(createWriter(this.logs)); setLayout(new PatternLayout("%d %c{1} - %m%n")); super.activateOptions(); } /** * Return the logged messages. * @return String logs */ public String output() { return new String(this.logs.toByteArray(), StandardCharsets.UTF_8); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/VerboseCallableTest.java000066400000000000000000000042761376012136000252660ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * Test case for {@link VerboseCallable}. * @since 0.16 */ @SuppressWarnings({ "PMD.DoNotUseThreads", "PMD.TooManyMethods" }) public final class VerboseCallableTest { /** * VerboseCallable can log exceptions inside Callable. */ @Test public void logsExceptionsInCallable() { Assertions.assertThrows( IllegalArgumentException.class, () -> new VerboseCallable( () -> { throw new IllegalArgumentException("oops"); } ).call() ); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/VerboseProcessTest.java000066400000000000000000000366241376012136000252070ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.io.ByteArrayInputStream; import java.io.Closeable; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.SystemUtils; import org.apache.log4j.SimpleLayout; import org.apache.log4j.WriterAppender; import org.apache.log4j.spi.Filter; import org.apache.log4j.spi.LoggingEvent; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assumptions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.mockito.Mockito; /** * Test case for {@link VerboseProcess}. * * @checkstyle MultipleStringLiterals (500 lines) * @checkstyle ClassDataAbstractionCoupling (200 lines) * @todo #18 Locale/encoding problem in two test methods here. I'm not * sure how to fix them, but they should be fixed. They fail on some * machines, while run perfectly on others. They also fail when being * executed from IntelliJ. * @since 0.1 */ @SuppressWarnings({ "PMD.TooManyMethods", "PMD.AvoidDuplicateLiterals" }) public final class VerboseProcessTest { @Test @Disabled public void runsACommandLineScript() { Assumptions.assumeFalse(SystemUtils.IS_OS_WINDOWS, ""); final VerboseProcess process = new VerboseProcess( new ProcessBuilder("echo", "hey \u20ac!").redirectErrorStream(true) ); MatcherAssert.assertThat( process.stdout(), Matchers.containsString("\u20ac!") ); } @Test @Disabled public void echosUnicodeCorrectly() { Assumptions.assumeFalse(SystemUtils.IS_OS_WINDOWS, ""); MatcherAssert.assertThat( new VerboseProcess( new ProcessBuilder( "/bin/bash", "-c", "echo -n \u0442\u0435\u0441\u0442 | hexdump" ) ).stdout(), Matchers.containsString("0000000 d1 82 d0 b5 d1 81 d1 82") ); } @Test public void runsACommandLineScriptWithException() { Assumptions.assumeFalse(SystemUtils.IS_OS_WINDOWS, ""); final VerboseProcess process = new VerboseProcess( new ProcessBuilder("cat", "/non-existing-file.txt") .redirectErrorStream(true) ); try { process.stdout(); Assertions.fail("exception expected"); } catch (final IllegalArgumentException ex) { MatcherAssert.assertThat( ex.getMessage(), Matchers.containsString("No such file or directory") ); } } @Test public void runsACommandLineScriptWithExceptionNoRedir() throws Exception { Assumptions.assumeFalse(SystemUtils.IS_OS_WINDOWS, ""); final VerboseProcess process = new VerboseProcess( new ProcessBuilder("cat", "/non-existing-file.txt") ); final VerboseProcess.Result result = process.waitFor(); MatcherAssert.assertThat( result.code(), Matchers.equalTo(1) ); MatcherAssert.assertThat( result.stderr(), Matchers.containsString("No such file or directory") ); } @Test public void handlesLongRunningCommand() { Assumptions.assumeFalse(SystemUtils.IS_OS_WINDOWS, ""); final VerboseProcess process = new VerboseProcess( new ProcessBuilder("/bin/bash", "-c", "sleep 2; echo 'done'") ); MatcherAssert.assertThat( process.stdout(), Matchers.startsWith("done") ); } @Test public void rejectsNullProcesses() { Assertions.assertThrows( RuntimeException.class, () -> { final ProcessBuilder builder = null; new VerboseProcess(builder); } ); } @Test public void rejectsStdoutWithLevelAll() { try { new VerboseProcess( Mockito.mock(Process.class), Level.ALL, Level.INFO ); Assertions.fail("IllegalArgumentException expected"); } catch (final IllegalArgumentException ex) { MatcherAssert.assertThat( ex.getMessage(), Matchers.equalTo( StringUtils.join( "stdout LEVEL can't be set to ALL because it is ", "intended only for internal configuration" ) ) ); } } @Test public void rejectsStderrWithLevelAll() { try { new VerboseProcess( Mockito.mock(Process.class), Level.INFO, Level.ALL ); Assertions.fail("IllegalArgumentException expected here"); } catch (final IllegalArgumentException ex) { MatcherAssert.assertThat( ex.getMessage(), Matchers.equalTo( StringUtils.join( "stderr LEVEL can't be set to ALL because it is ", "intended only for internal configuration" ) ) ); } } @Test @SuppressWarnings("PMD.DoNotUseThreads") public void quietlyTerminatesLongRunningProcess() throws Exception { Assumptions.assumeFalse(SystemUtils.IS_OS_WINDOWS, ""); final Process proc = new ProcessBuilder("sleep", "10000").start(); final VerboseProcess process = new VerboseProcess(proc); final CountDownLatch start = new CountDownLatch(1); final CountDownLatch done = new CountDownLatch(1); new Thread( new VerboseRunnable( () -> { start.countDown(); process.stdoutQuietly(); done.countDown(); } ) ).start(); start.await(); TimeUnit.SECONDS.sleep(1L); proc.destroy(); MatcherAssert.assertThat( done.await(1L, TimeUnit.MINUTES), Matchers.is(true) ); } @Test public void stdoutQuietlyLogsErrors() { final StringWriter writer = new StringWriter(); org.apache.log4j.Logger.getRootLogger().addAppender( new WriterAppender(new SimpleLayout(), writer) ); final ProcessBuilder builder; final String message = "hello dear friend"; if (SystemUtils.IS_OS_WINDOWS) { builder = new ProcessBuilder("cmd", "/c", "echo", message, "1>&2"); } else { builder = new ProcessBuilder( "cat", String.format("/non-existing-file-%s ", message) ); } final VerboseProcess process = new VerboseProcess( builder, Level.OFF, Level.WARNING ); process.stdoutQuietly(); MatcherAssert.assertThat( writer.toString(), Matchers.containsString(message) ); } @Test @SuppressWarnings("PMD.AvoidFileStream") public void logsErrorWhenUnderlyingStreamIsClosed() throws Exception { final StringWriter writer = new StringWriter(); org.apache.log4j.Logger.getRootLogger().addAppender( new WriterAppender(new SimpleLayout(), writer) ); final Process prc = Mockito.mock(Process.class); final Closeable stdout = new FileInputStream( File.createTempFile("temp", "test") ); stdout.close(); Mockito.doReturn(stdout).when(prc).getInputStream(); Mockito.doReturn(new ByteArrayInputStream(new byte[0])) .when(prc).getErrorStream(); final VerboseProcess process = new VerboseProcess( prc, Level.FINEST, Level.FINEST ); Logger.debug( this, "#logsErrorWhenUnderlyingStreamIsClosed(): vrbPrc.hashCode=%s", process.hashCode() ); process.stdout(); MatcherAssert.assertThat( writer.toString(), Matchers.containsString("Error reading from process stream") ); } @Test public void terminatesMonitorsAndProcessIfClosedInstantly() throws Exception { this.terminatesMonitorsAndProcessIfClosed(0); } @Test public void terminatesMonitorsAndProcessIfClosedShortly() throws Exception { // @checkstyle MagicNumberCheck (1 line) this.terminatesMonitorsAndProcessIfClosed(50); } @Test public void terminatesMonitorsAndProcessIfClosedNormal() throws Exception { final long delay = 400; this.terminatesMonitorsAndProcessIfClosed(delay); } /** * VerboseProcess can terminate its monitors and underlying Process if * closed after specified time since real usage. * @param delay Time in milliseconds between usage of vrbcPrc starts and * its close() issued * @throws Exception If something goes wrong * @checkstyle ExecutableStatementCountCheck (100 lines) */ private void terminatesMonitorsAndProcessIfClosed(final long delay) throws Exception { final InputStream input = new InfiniteInputStream('i'); final InputStream error = new InfiniteInputStream('e'); final Process prc = Mockito.mock(Process.class); Mockito.doReturn(input).when(prc).getInputStream(); Mockito.doReturn(error).when(prc).getErrorStream(); Mockito.doAnswer( invocation -> { input.close(); error.close(); return null; } ).when(prc).destroy(); final VerboseProcess process = new VerboseProcess( prc, Level.FINEST, Level.FINEST ); Logger.debug( this, "terminatesMntrsAndPrcssIfClosed delay=%d vrbPrc.hashCode=%s", delay, process.hashCode() ); final StringWriter writer = new StringWriter(); final WriterAppender appender = new WriterAppender( new SimpleLayout(), writer ); appender.addFilter(new VrbPrcMonitorFilter(process)); org.apache.log4j.Logger.getLogger( VerboseProcess.class ).addAppender(appender); if (delay == 0) { process.close(); } else { new Timer(true).schedule( new TimerTask() { @Override public void run() { process.close(); } }, delay ); } process.stdoutQuietly(); // @checkstyle MagicNumberCheck (1 line) TimeUnit.MILLISECONDS.sleep(1000L); Mockito.verify( prc, Mockito.atLeastOnce() ).destroy(); MatcherAssert.assertThat( writer.toString(), Matchers.not(Matchers .containsString("Error reading from process stream") ) ); } /** * {@link InputStream} returning endless flow of characters. * * @since 0.1 */ private final class InfiniteInputStream extends InputStream { /** * End of line. */ private static final int LINE_FEED = 0xA; /** * Character, endlessly repeated in the stream. */ private final transient char chr; /** * Whether the next char in the stream should be EOL. */ private transient boolean feed; /** * Whether this stream is closed. */ private transient boolean closed; /** * Construct an InputStream returning endless combination of this * character and end of line. * @param character Character to return in the stream */ InfiniteInputStream(final char character) { super(); this.chr = character; } @Override public int read() throws IOException { if (this.closed) { throw new IOException("Stream closed"); } final int next; if (this.feed) { this.feed = false; next = InfiniteInputStream.LINE_FEED; } else { this.feed = true; next = this.chr; } return next; } @Override public void close() { this.closed = true; } } /** * Filter of log messages of {@link VerboseProcess}'s monitor threads. * *

It filters out messages of monitor threads, that doesn't belong to * specific {@link VerboseProcess}. * * @since 0.1 */ private final class VrbPrcMonitorFilter extends Filter { /** * Monitor's log message start. */ private static final String THREADNAME_START = "VrbPrc.Monitor-"; /** * HashCode of {@link VerboseProcess} to filter. */ private final transient int hash; /** * Create filter for this process. * *

The messages from its monitor threads will be filtered in. * @param prc Process */ VrbPrcMonitorFilter(final VerboseProcess prc) { super(); this.hash = prc.hashCode(); } @Override public int decide(final LoggingEvent event) { final String thread = event.getThreadName(); final int decision; if (thread.startsWith(VrbPrcMonitorFilter.THREADNAME_START + this.hash )) { decision = Filter.ACCEPT; } else { decision = Filter.DENY; } return decision; } } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/VerboseRunnableTest.java000066400000000000000000000123021376012136000253220ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.concurrent.Callable; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; /** * Test case for {@link VerboseRunnable}. * @since 0.1 */ @SuppressWarnings({ "PMD.DoNotUseThreads", "PMD.TooManyMethods" }) public final class VerboseRunnableTest { @Test public void logsExceptionsInRunnable() { Assertions.assertThrows( IllegalArgumentException.class, () -> new VerboseRunnable( (Runnable) () -> { throw new IllegalArgumentException("oops"); } ).run() ); } @Test public void swallowsExceptionsInRunnable() { new VerboseRunnable( (Runnable) () -> { throw new IllegalArgumentException("boom"); }, true ).run(); } @Test public void swallowsExceptionsInCallable() { new VerboseRunnable( () -> { throw new IllegalArgumentException("boom-2"); }, true ).run(); } @Test public void translatesToStringFromUnderlyingRunnable() throws Exception { final String text = "some text abc"; final Runnable verbose = new VerboseRunnable( new Runnable() { @Override public void run() { assert true; } @Override public String toString() { return text; } } ); MatcherAssert.assertThat( verbose, Matchers.hasToString(Matchers.containsString(text)) ); } @Test public void translatesToStringFromUnderlyingCallable() throws Exception { final String text = "some text abc-2"; final Runnable verbose = new VerboseRunnable( new Callable() { @Override public Void call() { return null; } @Override public String toString() { return text; } }, true ); MatcherAssert.assertThat( verbose, Matchers.hasToString(Matchers.containsString(text)) ); } @Test public void preservesInterruptedStatus() throws Exception { final ScheduledExecutorService svc = Executors.newSingleThreadScheduledExecutor(); final AtomicReference thread = new AtomicReference<>(); final AtomicInteger runs = new AtomicInteger(); svc.scheduleWithFixedDelay( new VerboseRunnable( () -> { runs.addAndGet(1); thread.set(Thread.currentThread()); TimeUnit.HOURS.sleep(1L); return null; }, true, false ), 1L, 1L, TimeUnit.MICROSECONDS ); while (thread.get() == null) { TimeUnit.MILLISECONDS.sleep(1L); } thread.get().interrupt(); TimeUnit.SECONDS.sleep(1L); svc.shutdown(); MatcherAssert.assertThat( svc.awaitTermination(1L, TimeUnit.SECONDS), Matchers.is(true) ); MatcherAssert.assertThat(runs.get(), Matchers.is(1)); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/VerboseThreadsTest.java000066400000000000000000000053461376012136000251600ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package com.jcabi.log; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; /** * Test case for {@link VerboseThreads}. * @since 0.1 */ @SuppressWarnings("PMD.DoNotUseThreads") public final class VerboseThreadsTest { @Test public void instantiatesThreadsOnDemand() throws Exception { final ExecutorService service = Executors .newSingleThreadExecutor(new VerboseThreads("foo")); service.execute( () -> { throw new IllegalArgumentException("oops"); } ); TimeUnit.SECONDS.sleep(1L); service.shutdown(); } @Test public void logsWhenThreadsAreNotDying() throws Exception { final ExecutorService service = Executors .newSingleThreadExecutor(new VerboseThreads(this)); final Future future = service.submit( (Runnable) () -> { throw new IllegalArgumentException("boom"); } ); while (!future.isDone()) { TimeUnit.SECONDS.sleep(1L); } service.shutdown(); } } jcabi-log-0.19.0/src/test/java/com/jcabi/log/package-info.java000066400000000000000000000031251376012136000237150ustar00rootroot00000000000000/* * Copyright (c) 2012-2020, jcabi.com * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. 2) Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. 3) Neither the name of the jcabi.com nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * Convenient utils, tests. */ package com.jcabi.log; jcabi-log-0.19.0/src/test/resources/000077500000000000000000000000001376012136000172075ustar00rootroot00000000000000jcabi-log-0.19.0/src/test/resources/log4j.properties000066400000000000000000000036011376012136000223440ustar00rootroot00000000000000# Copyright (c) 2012-2020, jcabi.com # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: 1) Redistributions of source code must retain the above # copyright notice, this list of conditions and the following # disclaimer. 2) Redistributions in binary form must reproduce the above # copyright notice, this list of conditions and the following # disclaimer in the documentation and/or other materials provided # with the distribution. 3) Neither the name of the jcabi.com nor # the names of its contributors may be used to endorse or promote # products derived from this software without specific prior written # permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT # NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND # FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL # THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # OF THE POSSIBILITY OF SUCH DAMAGE. # Set root logger level to DEBUG and its only appender to CONSOLE log4j.rootLogger=WARN, CONSOLE # "Console" is set to be a ConsoleAppender. log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender log4j.appender.CONSOLE.layout=com.jcabi.log.MulticolorLayout log4j.appender.CONSOLE.layout.ConversionPattern=[%color{%p}] %t %c: %m%n # Application-specific logging log4j.logger.com.jcabi=DEBUG