001 /* 002 * Copyright (c) 2024 QOS.ch Sarl (Switzerland) 003 * All rights reserved. 004 * 005 * Permission is hereby granted, free of charge, to any person obtaining 006 * a copy of this software and associated documentation files (the 007 * "Software"), to deal in the Software without restriction, including 008 * without limitation the rights to use, copy, modify, merge, publish, 009 * distribute, sublicense, and/or sell copies of the Software, and to 010 * permit persons to whom the Software is furnished to do so, subject to 011 * the following conditions: 012 * 013 * The above copyright notice and this permission notice shall be 014 * included in all copies or substantial portions of the Software. 015 * 016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 017 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 018 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 019 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 020 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 021 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 022 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 023 * 024 * 025 * 026 */ 027 028 package ch.qos.logback.tyler.base; 029 030 import ch.qos.logback.classic.Level; 031 import ch.qos.logback.classic.LoggerContext; 032 import ch.qos.logback.classic.spi.Configurator; 033 import ch.qos.logback.classic.tyler.TylerConfiguratorBase; 034 import ch.qos.logback.core.Context; 035 import ch.qos.logback.core.model.processor.ModelInterpretationContext; 036 import ch.qos.logback.tyler.base.spi.StaticImportData; 037 import com.squareup.javapoet.FieldSpec; 038 import com.squareup.javapoet.MethodSpec; 039 import com.squareup.javapoet.ParameterSpec; 040 import com.squareup.javapoet.TypeSpec; 041 042 import javax.lang.model.element.Modifier; 043 044 import java.util.*; 045 046 import static ch.qos.logback.tyler.base.TylerConstants.CONFIGURE_METHOD_NAME; 047 import static ch.qos.logback.tyler.base.TylerConstants.CONTEXT_FIELD_NAME; 048 import static ch.qos.logback.tyler.base.TylerConstants.LEVEL_FIELD_NAME; 049 import static ch.qos.logback.tyler.base.TylerConstants.LOGGER_CONTEXT_PARAMETER_NAME; 050 import static ch.qos.logback.tyler.base.TylerConstants.REQUIRED_LOGBACK_VERSION; 051 import static ch.qos.logback.tyler.base.TylerConstants.TYLER_VERSION; 052 053 public class TylerModelInterpretationContext extends ModelInterpretationContext { 054 055 final public TypeSpec.Builder tylerConfiguratorTSB; 056 final public MethodSpec.Builder configureMethodSpecBuilder; 057 final public Map<String, MethodSpec.Builder> mapOfMethodSpecBuilders = new LinkedHashMap<>(); 058 059 final FieldSpec contextFieldSpec = FieldSpec.builder(LoggerContext.class, CONTEXT_FIELD_NAME, Modifier.PRIVATE).build(); 060 final ParameterSpec contextParameterSpec = ParameterSpec.builder(LoggerContext.class, LOGGER_CONTEXT_PARAMETER_NAME).build(); 061 final ParameterSpec levelParameterSpec = ParameterSpec.builder(Level.class, LEVEL_FIELD_NAME).build(); 062 063 final List<StaticImportData> staticImportsList = new ArrayList<>(); 064 065 public TylerModelInterpretationContext(Context context) { 066 super(context); 067 this.configureMethodSpecBuilder = initializeConfigureMethodSpecBuilder(); 068 this.tylerConfiguratorTSB = initializeTylerConfiguratorTSB(); 069 } 070 071 public void addStaticImport(StaticImportData sid) { 072 if (!staticImportsList.contains(sid)) 073 staticImportsList.add(sid); 074 } 075 076 TypeSpec.Builder initializeTylerConfiguratorTSB() { 077 //MethodSpec setupLoggerMS = makeSetupLoggerMethodSpec(); 078 079 TypeSpec.Builder tsb = TypeSpec.classBuilder(TylerConstants.TYLER_CONFIGURATOR).addJavadoc(""" 080 081 <p>This file was generated by logback-tyler version %s</p> 082 083 <p>Eventual errors and warnings are appended at the end.</p> 084 085 <p>You may experiment with logback.xml to Java translation, i.e. 086 TylerConfigurator generation, at the following URL:</p> 087 088 <p> https://logback.qos.ch/translator/services/xml2Java.html </p> 089 090 <p>This generated TylerConfigurator class is intended to be copied and integrated 091 into the user's project as a custom configurator. It will configure logback 092 without XML. You are free to rename TylerConfigurator as you wish.</p> 093 094 <p>It requires logback-classic version %s or later at runtime.</p> 095 096 <p>Custom configurators are looked up via Java's service-provide facility. If a 097 custom provider is found, it takes precedence over logback's own configurators, 098 e.g. DefaultJoranConfigurator.</p> 099 100 <p>To install your custom configurator to your project, add a 101 provider-configuration file to the following path:</p> 102 103 <pre> META-INF/services/ch.qos.logback.classic.spi.Configurator</pre> 104 105 <p>This provider-configuration file should contain a line with the fully 106 qualified class name of your tyler configurator.</p> 107 108 <p>See also item 1 of 'Configuration at initialization' section at </p> 109 110 <p> https://logback.qos.ch/manual/configuration.html#auto_configuration</p> 111 112 <p>With recent versions of logback and logback-tyler you can still 113 configure logger levels dynamically using properties files. Note that 114 configuration files in properties format can be watched for 115 changes. See the documentation on PropertiesConfigurator for more details.</p> 116 117 <p>https://logback.qos.ch/manual/configuration.html#propertiesConfigurator</p> 118 119 <p>Keep in mind that by integrating a .properties configuration file info 120 your tyler configurator, you can still change logger levels dynamically, without 121 redeploying your application.</p> 122 123 """.formatted(TYLER_VERSION, REQUIRED_LOGBACK_VERSION)) 124 .addSuperinterface(Configurator.class) 125 .superclass(TylerConfiguratorBase.class) 126 .addModifiers(Modifier.PUBLIC); 127 return tsb; 128 } 129 130 private MethodSpec.Builder initializeConfigureMethodSpecBuilder() { 131 MethodSpec.Builder msb = MethodSpec.methodBuilder(CONFIGURE_METHOD_NAME).addJavadoc(""" 132 <p>This method performs configuration per {@link $T} interface.</p> 133 134 <p>If <code>TylerConfigurator</code> is installed as a configurator service, this 135 method will be called by logback-classic during initialization.</p> 136 """, Configurator.class).addAnnotation(Override.class).addModifiers(Modifier.PUBLIC).addParameter(contextParameterSpec) 137 .returns(Configurator.ExecutionStatus.class) 138 .addStatement("$N($N)", TylerConfiguratorBase.SET_CONTEXT_METHOD_NAME, contextParameterSpec); 139 140 return msb; 141 } 142 143 public FieldSpec getContextFieldSpec() { 144 return contextFieldSpec; 145 } 146 }