001/* 002 * Copyright (c) 2004-2024 QOS.ch 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 025package ch.qos.logback.tyler.base.handler; 026 027import ch.qos.logback.classic.model.PropertiesConfiguratorModel; 028import ch.qos.logback.classic.model.processor.PropertiesConfiguratorModelHandler; 029import ch.qos.logback.core.Context; 030import ch.qos.logback.core.model.IncludeModel; 031import ch.qos.logback.core.model.Model; 032import ch.qos.logback.core.model.processor.IncludeModelHandler; 033import ch.qos.logback.core.model.processor.ModelHandlerBase; 034import ch.qos.logback.core.model.processor.ModelHandlerException; 035import ch.qos.logback.core.model.processor.ModelInterpretationContext; 036import ch.qos.logback.core.util.OptionHelper; 037import ch.qos.logback.tyler.base.TylerModelInterpretationContext; 038import com.squareup.javapoet.MethodSpec; 039import com.squareup.javapoet.ParameterSpec; 040 041import javax.lang.model.element.Modifier; 042 043public class TylerIncludeModelHandler extends ModelHandlerBase { 044 045 final static String INCLUDE_METHOD_NAME = "include"; 046 047 public TylerIncludeModelHandler(Context context) { 048 super(context); 049 } 050 051 static public ModelHandlerBase makeInstance(Context context, ModelInterpretationContext ic) { 052 return new TylerIncludeModelHandler(context); 053 } 054 055 @Override 056 protected Class<IncludeModel> getSupportedModelClass() { 057 return IncludeModel.class; 058 } 059 060 @Override 061 public void handle(ModelInterpretationContext mic, Model model) throws ModelHandlerException { 062 IncludeModel includeModel = (IncludeModel) model; 063 TylerModelInterpretationContext tmic = (TylerModelInterpretationContext) mic; 064 addJavaStatement(tmic, includeModel); 065 } 066 067 protected void addJavaStatement(TylerModelInterpretationContext tmic, IncludeModel originalModel) { 068 069 addIncludeMethod(tmic); 070 tmic.configureMethodSpecBuilder.addStatement("$N($S, $S, $S, $S)", INCLUDE_METHOD_NAME, originalModel.getFile(), originalModel.getUrl(), 071 originalModel.getResource(), originalModel.getOptional()); 072 073 } 074 075 void addIncludeMethod(TylerModelInterpretationContext tmic) { 076 077 078 // insert method at most once 079 if(tmic.mapOfMethodSpecBuilders.containsKey(INCLUDE_METHOD_NAME)) 080 return; 081 082 // code to produce 083 // 084 // void include(String fileStr, String urlStr, String resourceStr, String optionalStr) { 085 086 // IncludeModel includeModel = new IncludeModel(); 087 // 088 // includeModel.setFile(fileStr); // use actual string value of pcModel.getFile() 089 // 090 // includeModel.setUrl(urlStr); // use actual string value of pcModel.getUrl() 091 // includeModel.setResource(resourceStr); 092 // includeModel.setOptional(optionalStr); 093 // IncludeModelHandler includeModelHandler = new IncludeModelHandler(context); 094 // try { 095 // Model modelFromIncludedFile = includeModelHandler.buildModelFromIncludedFile(this, includeModel); 096 // processModelFromIncludedFile(modelFromIncludedFile); 097 // } catch(ModelHandlerException e) { 098 // addError("Failed to process IncludeModelHandler", e); 099 // } 100 // } 101 102 String includeModelVarName = "includeModel"; 103 String imhVarName = "includeModelHandler"; 104 String mfifVarName = "modelFromIncludedFile"; 105 106 final String fileStrVarName = "fileStr"; 107 final String urlStrVarName = "urlStr"; 108 final String resourceStrVarName = "resourceStr"; 109 final String optionalStrVarName = "optionalStr"; 110 111 112 final ParameterSpec fileStr_ParameterSpec = ParameterSpec.builder(String.class, fileStrVarName).build(); 113 final ParameterSpec urStr_ParameterSpec = ParameterSpec.builder(String.class, urlStrVarName).build(); 114 final ParameterSpec resourceStr_ParameterSpec = ParameterSpec.builder(String.class, resourceStrVarName).build(); 115 final ParameterSpec optionalStr_ParameterSpec = ParameterSpec.builder(String.class, optionalStrVarName).build(); 116 117 MethodSpec.Builder msBuilder = MethodSpec.methodBuilder(INCLUDE_METHOD_NAME).addModifiers(Modifier.PRIVATE).addParameter(fileStr_ParameterSpec) 118 .addParameter(urStr_ParameterSpec).addParameter(resourceStr_ParameterSpec).addParameter(optionalStr_ParameterSpec).returns(void.class); 119 120 msBuilder.addStatement("$1T $2N = new $1T()", IncludeModel.class, includeModelVarName); 121 msBuilder.addStatement("$N.setFile(subst($N))", includeModelVarName, fileStrVarName); 122 msBuilder.addStatement("$N.setUrl(subst($N))", includeModelVarName, urlStrVarName); 123 msBuilder.addStatement("$N.setResource(subst($N))", includeModelVarName, resourceStrVarName); 124 msBuilder.addStatement("$N.setOptional(subst($N))", includeModelVarName, optionalStrVarName); 125 msBuilder.addStatement("$1T $2N = new $1T($3N)", IncludeModelHandler.class, imhVarName, tmic.getContextFieldSpec()); 126 127 // "this is the calling TylerConfigurator instance of type ContextAwarePropertyContainer" 128 msBuilder.beginControlFlow("try"); 129 msBuilder.addStatement("$T $N = $N.buildModelFromIncludedFile(this, $N)", Model.class, mfifVarName, imhVarName, includeModelVarName); 130 msBuilder.addStatement("processModelFromIncludedFile($N)", mfifVarName); 131 msBuilder.nextControlFlow("catch($T e)", ModelHandlerException.class); 132 msBuilder.addStatement("addError(\"Failed to process IncludeModelHandler\", e)"); 133 msBuilder.endControlFlow(); 134 135 tmic.mapOfMethodSpecBuilders.put(INCLUDE_METHOD_NAME, msBuilder); 136 137 msBuilder.addJavadoc(""" 138 <p>Warning: please note that at translation time logback-tyler usually does not have 139 access to the included file.<p> 140 141 <p>It follows that the code in this method (produced by logback-tyler) falls back to invoking 142 logback-classic's default configurator, i.e. JoranConfigurator which will invoke an XML 143 parser.</p> 144 145 <p>If you wish to avoid calling <code>JoranConfigurator</code>, then you can insert 146 the contents of the included XML file into the encompassing file manually before performing 147 the translation.</p> 148 149 <p>Also note that PropertiesConfigurator introduced in version 1.5.8, allows for setting 150 logger levels via a properties file. The location of properties files can be specified 151 as a file path as well a URL via HTTP or HTTPS protocols. Watching files and 152 reconfiguration upon change are also supported. Logback-tyler supports 153 <code>PropertiesConfigurator</code>.</p> 154 155 """); 156 } 157}