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) 060 .build(); 061 final ParameterSpec contextParameterSpec = ParameterSpec.builder(LoggerContext.class, 062 LOGGER_CONTEXT_PARAMETER_NAME).build(); 063 final ParameterSpec levelParameterSpec = ParameterSpec.builder(Level.class, LEVEL_FIELD_NAME).build(); 064 065 final List<StaticImportData> staticImportsList = new ArrayList<>(); 066 067 public TylerModelInterpretationContext(Context context) { 068 super(context); 069 this.configureMethodSpecBuilder = initializeConfigureMethodSpecBuilder(); 070 this.tylerConfiguratorTSB = initializeTylerConfiguratorTSB(); 071 } 072 073 public void addStaticImport(StaticImportData sid) { 074 if (!staticImportsList.contains(sid)) 075 staticImportsList.add(sid); 076 } 077 078 TypeSpec.Builder initializeTylerConfiguratorTSB() { 079 //MethodSpec setupLoggerMS = makeSetupLoggerMethodSpec(); 080 081 TypeSpec.Builder tsb = TypeSpec.classBuilder(TylerConstants.TYLER_CONFIGURATOR).addJavadoc(""" 082 083 <p>This file was generated by logback-tyler version %s</p> 084 085 <p>Eventual errors and warnings are appended at the end.</p> 086 087 <p>You may experiment with logback.xml to Java translation, i.e. 088 TylerConfigurator generation, at the following URL:</p> 089 090 <p> https://logback.qos.ch/translator/services/xml2Java.html </p> 091 092 <p>This generated TylerConfigurator class is intended to be copied and integrated 093 into the user's project as a custom configurator. It will configure logback 094 without XML. You are free to rename TylerConfigurator as you wish.</p> 095 096 <p>It requires logback-classic version %s or later at runtime.</p> 097 098 <p>Custom configurators are looked up via Java's service-provide facility. If a 099 custom provider is found, it takes precedence over logback's own configurators, 100 e.g. DefaultJoranConfigurator.</p> 101 102 <p>To install your custom configurator to your project, add a 103 provider-configuration file to the following path:</p> 104 105 <pre> META-INF/services/ch.qos.logback.classic.spi.Configurator</pre> 106 107 <p>This provider-configuration file should contain a line with the fully 108 qualified class name of your tyler configurator.</p> 109 110 <p>See also item 1 of 'Configuration at initialization' section at </p> 111 112 <p> https://logback.qos.ch/manual/configuration.html#auto_configuration</p> 113 114 <p>With recent versions of logback and logback-tyler you can still 115 configure logger levels dynamically using properties files. Note that 116 configuration files in properties format can be watched for 117 changes. See the documentation on PropertiesConfigurator for more details.</p> 118 119 <p>https://logback.qos.ch/manual/configuration.html#propertiesConfigurator</p> 120 121 <p>Keep in mind that by integrating a .properties configuration file info 122 your tyler configurator, you can still change logger levels dynamically, without 123 redeploying your application.</p> 124 125 """.formatted(TYLER_VERSION, REQUIRED_LOGBACK_VERSION)) 126 .addSuperinterface(Configurator.class) 127 .superclass(TylerConfiguratorBase.class); 128 return tsb; 129 } 130 131 private MethodSpec.Builder initializeConfigureMethodSpecBuilder() { 132 MethodSpec.Builder msb = MethodSpec.methodBuilder(CONFIGURE_METHOD_NAME).addJavadoc(""" 133 <p>This method performs configuration per {@link $T} interface.</p> 134 135 <p>If <code>TylerConfigurator</code> is installed as a configurator service, this 136 method will be called by logback-classic during initialization.</p> 137 """, Configurator.class).addAnnotation(Override.class).addModifiers(Modifier.PUBLIC) 138 .addParameter(contextParameterSpec).returns(Configurator.ExecutionStatus.class) 139 .addStatement("$N($N)", TylerConfiguratorBase.SET_CONTEXT_METHOD_NAME, contextParameterSpec); 140 141 return msb; 142 } 143 144 public FieldSpec getContextFieldSpec() { 145 return contextFieldSpec; 146 } 147 }