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 */ 027package ch.qos.logback.tyler.base; 028 029import ch.qos.logback.classic.joran.JoranConfigurator; 030import ch.qos.logback.classic.model.ConfigurationModel; 031import ch.qos.logback.classic.model.ContextNameModel; 032import ch.qos.logback.classic.model.LoggerModel; 033import ch.qos.logback.classic.model.RootLoggerModel; 034import ch.qos.logback.classic.model.processor.LogbackClassicDefaultNestedComponentRules; 035import ch.qos.logback.core.Context; 036import ch.qos.logback.core.joran.event.SaxEventRecorder; 037import ch.qos.logback.core.joran.spi.JoranException; 038import ch.qos.logback.core.model.AppenderModel; 039import ch.qos.logback.core.model.AppenderRefModel; 040import ch.qos.logback.core.model.ImplicitModel; 041import ch.qos.logback.core.model.ImportModel; 042import ch.qos.logback.core.model.Model; 043import ch.qos.logback.core.model.PropertyModel; 044import ch.qos.logback.core.model.processor.DefaultProcessor; 045import ch.qos.logback.core.model.processor.ImportModelHandler; 046import ch.qos.logback.tyler.base.handler.AppenderRefModelHandler; 047import ch.qos.logback.tyler.base.handler.ContextNameModelHandler; 048 049import ch.qos.logback.tyler.base.handler.AppenderModelHandler; 050import ch.qos.logback.tyler.base.handler.ConfigurationModelHandler; 051import ch.qos.logback.tyler.base.handler.ImplicitModelHandler; 052import ch.qos.logback.tyler.base.handler.LoggerModelHandler; 053import ch.qos.logback.tyler.base.handler.RootLoggerModelHandler; 054import ch.qos.logback.tyler.base.handler.VariableModelHandler; 055import com.squareup.javapoet.JavaFile; 056import com.squareup.javapoet.MethodSpec; 057import com.squareup.javapoet.TypeSpec; 058import org.xml.sax.InputSource; 059 060import java.io.ByteArrayInputStream; 061import java.io.IOException; 062import java.io.InputStream; 063 064public class ModelToJava { 065 066 067 Context context; 068 069 ModelToJava(Context context) { 070 this.context = context; 071 } 072 073 Model extractModel(String input) throws JoranException { 074 InputStream inputStream = new ByteArrayInputStream(input.getBytes()); 075 InputSource inputSource = new InputSource(inputStream); 076 inputSource.setSystemId("UNKNOWN"); 077 078 JoranConfigurator joranConfigurator = new JoranConfigurator(); 079 joranConfigurator.setContext(context); 080 081 SaxEventRecorder recorder = joranConfigurator.populateSaxEventRecorder(inputSource); 082 Model top = joranConfigurator.buildModelFromSaxEventList(recorder.getSaxEventList()); 083 return top; 084 } 085 086 public String toJava(Model topModel) throws IOException { 087 TylerModelInterpretationContext tmic = new TylerModelInterpretationContext(context); 088 tmic.setTopModel(topModel); 089 090 LogbackClassicDefaultNestedComponentRules.addDefaultNestedComponentRegistryRules(tmic.getDefaultNestedComponentRegistry()); 091 092 DefaultProcessor defaultProcessor = new DefaultProcessor(context, tmic); 093 addModelHandlerAssociations(defaultProcessor); 094 095 defaultProcessor.process(topModel); 096 097 098 tmic.configureMethodSpecBuilder.addStatement("return ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY"); 099 MethodSpec configureMethodSpec = tmic.configureMethodSpecBuilder.build(); 100 101 tmic.tylerConfiguratorTSB.methodSpecs.addFirst(configureMethodSpec); 102 103 104 TypeSpec tylerConfiguratorTypeSpec = tmic.tylerConfiguratorTSB.build(); 105 JavaFile javaFile = JavaFile.builder("com.example.helloworld", tylerConfiguratorTypeSpec) 106 .indent(" ") 107 .build(); 108 //StringBuilder sb = new StringBuilder(); 109 StringBuffer sb = new StringBuffer(); 110 javaFile.writeTo(sb); 111 return sb.toString(); 112 } 113 114 private void addModelHandlerAssociations(DefaultProcessor defaultProcessor) { 115 defaultProcessor.addHandler(ConfigurationModel.class, ConfigurationModelHandler::makeInstance); 116 117 defaultProcessor.addHandler(PropertyModel.class, VariableModelHandler::makeInstance); 118 119 120 defaultProcessor.addHandler(ContextNameModel.class, ContextNameModelHandler::makeInstance); 121 defaultProcessor.addHandler(ImportModel.class, ImportModelHandler::makeInstance); 122 defaultProcessor.addHandler(AppenderModel.class, AppenderModelHandler::makeInstance); 123 defaultProcessor.addHandler(ImplicitModel.class, ImplicitModelHandler::makeInstance); 124 defaultProcessor.addHandler(LoggerModel.class, LoggerModelHandler::makeInstance); 125 defaultProcessor.addHandler(RootLoggerModel.class, RootLoggerModelHandler::makeInstance); 126 127 defaultProcessor.addHandler(AppenderRefModel.class, AppenderRefModelHandler::makeInstance); 128 } 129 130}