From 9f4a2bc0cead02e76eb181fb654807407a6071ee Mon Sep 17 00:00:00 2001 From: Ceki Gulcu Date: Wed, 4 Sep 2024 20:47:48 +0200 Subject: [PATCH] further progress on PropertyConfigurator Signed-off-by: Ceki Gulcu --- .../classic/joran/JoranConfigurator.java | 13 +- .../joran/ModelClassToModelHandlerLinker.java | 15 +- .../classic/joran/PropertyConfigurator.java | 6 +- .../action/PropertyConfiguratorAction.java | 33 +++++ .../model/PropertyConfiguratorModel.java | 22 +++ .../PropertyConfiguratorModelHandler.java | 83 +++++++++++ .../propertyConfigurator/smoke.properties | 15 ++ .../joran/propertyConfigurator/smoke.xml | 30 ++++ .../classic/joran/JoranConfiguratorTest.java | 10 ++ .../core/joran/action/IncludeAction.java | 86 +---------- .../core/joran/action/ResourceAction.java | 86 +++++++++++ .../qos/logback/core/model/IncludeModel.java | 45 +----- .../qos/logback/core/model/ResourceModel.java | 59 ++++++++ .../model/processor/IncludeModelHandler.java | 126 +--------------- .../model/processor/ResourceHandlerBase.java | 140 ++++++++++++++++++ 15 files changed, 498 insertions(+), 271 deletions(-) create mode 100644 logback-classic/src/main/java/ch/qos/logback/classic/joran/action/PropertyConfiguratorAction.java create mode 100644 logback-classic/src/main/java/ch/qos/logback/classic/model/PropertyConfiguratorModel.java create mode 100644 logback-classic/src/main/java/ch/qos/logback/classic/model/processor/PropertyConfiguratorModelHandler.java create mode 100644 logback-classic/src/test/input/joran/propertyConfigurator/smoke.properties create mode 100644 logback-classic/src/test/input/joran/propertyConfigurator/smoke.xml create mode 100644 logback-core/src/main/java/ch/qos/logback/core/joran/action/ResourceAction.java create mode 100644 logback-core/src/main/java/ch/qos/logback/core/model/ResourceModel.java create mode 100644 logback-core/src/main/java/ch/qos/logback/core/model/processor/ResourceHandlerBase.java diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java index e07141bf1a..e74c1b0927 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/JoranConfigurator.java @@ -13,15 +13,7 @@ */ package ch.qos.logback.classic.joran; -import ch.qos.logback.classic.joran.action.ConfigurationAction; -import ch.qos.logback.classic.joran.action.ConsolePluginAction; -import ch.qos.logback.classic.joran.action.ContextNameAction; -import ch.qos.logback.classic.joran.action.InsertFromJNDIAction; -import ch.qos.logback.classic.joran.action.LevelAction; -import ch.qos.logback.classic.joran.action.LoggerAction; -import ch.qos.logback.classic.joran.action.LoggerContextListenerAction; -import ch.qos.logback.classic.joran.action.ReceiverAction; -import ch.qos.logback.classic.joran.action.RootLoggerAction; +import ch.qos.logback.classic.joran.action.*; import ch.qos.logback.classic.joran.sanity.IfNestedWithinSecondPhaseElementSC; import ch.qos.logback.classic.model.processor.ConfigurationModelHandlerFull; import ch.qos.logback.classic.model.processor.LogbackClassicDefaultNestedComponentRules; @@ -66,11 +58,12 @@ public void addElementSelectorAndActionAssociations(RuleStore rs) { rs.addRule(new ElementSelector("configuration/root/appender-ref"), () -> new AppenderRefAction()); rs.addRule(new ElementSelector("configuration/include"), () -> new IncludeAction()); - + rs.addRule(new ElementSelector("configuration/propertyConfigurator"), () -> new PropertyConfiguratorAction()); rs.addRule(new ElementSelector("configuration/consolePlugin"), () -> new ConsolePluginAction()); rs.addRule(new ElementSelector("configuration/receiver"), () -> new ReceiverAction()); + } diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/ModelClassToModelHandlerLinker.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/ModelClassToModelHandlerLinker.java index 3c99410cd3..3904a16874 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/ModelClassToModelHandlerLinker.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/ModelClassToModelHandlerLinker.java @@ -14,18 +14,8 @@ package ch.qos.logback.classic.joran; -import ch.qos.logback.classic.model.ConfigurationModel; -import ch.qos.logback.classic.model.ContextNameModel; -import ch.qos.logback.classic.model.LevelModel; -import ch.qos.logback.classic.model.LoggerContextListenerModel; -import ch.qos.logback.classic.model.LoggerModel; -import ch.qos.logback.classic.model.RootLoggerModel; -import ch.qos.logback.classic.model.processor.ConfigurationModelHandler; -import ch.qos.logback.classic.model.processor.ContextNameModelHandler; -import ch.qos.logback.classic.model.processor.LevelModelHandler; -import ch.qos.logback.classic.model.processor.LoggerContextListenerModelHandler; -import ch.qos.logback.classic.model.processor.LoggerModelHandler; -import ch.qos.logback.classic.model.processor.RootLoggerModelHandler; +import ch.qos.logback.classic.model.*; +import ch.qos.logback.classic.model.processor.*; import ch.qos.logback.core.Context; import ch.qos.logback.core.joran.ModelClassToModelHandlerLinkerBase; import ch.qos.logback.core.model.AppenderModel; @@ -63,6 +53,7 @@ public void link(DefaultProcessor defaultProcessor) { defaultProcessor.addHandler(ContextNameModel.class, ContextNameModelHandler::makeInstance); defaultProcessor.addHandler(LoggerContextListenerModel.class, LoggerContextListenerModelHandler::makeInstance); + defaultProcessor.addHandler(PropertyConfiguratorModel.class, PropertyConfiguratorModelHandler::makeInstance); defaultProcessor.addHandler(InsertFromJNDIModel.class, InsertFromJNDIModelHandler::makeInstance); defaultProcessor.addHandler(AppenderModel.class, AppenderModelHandler::makeInstance); diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/PropertyConfigurator.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/PropertyConfigurator.java index c2db2f6aff..b5bef53587 100644 --- a/logback-classic/src/main/java/ch/qos/logback/classic/joran/PropertyConfigurator.java +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/PropertyConfigurator.java @@ -61,7 +61,7 @@ public void setContext(Context context) { super.setContext(context); } - void doConfigure(URL url) throws JoranException { + public void doConfigure(URL url) throws JoranException { try { URLConnection urlConnection = url.openConnection(); // per http://jira.qos.ch/browse/LOGBACK-117 @@ -76,7 +76,7 @@ void doConfigure(URL url) throws JoranException { } } - void doConfigure(String filename) throws JoranException { + public void doConfigure(String filename) throws JoranException { try(FileInputStream fileInputStream = new FileInputStream(filename)) { doConfigure(fileInputStream); } catch (IOException e) { @@ -84,7 +84,7 @@ void doConfigure(String filename) throws JoranException { } } - void doConfigure(InputStream inputStream) throws JoranException { + public void doConfigure(InputStream inputStream) throws JoranException { Properties props = new Properties(); try { props.load(inputStream); diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/PropertyConfiguratorAction.java b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/PropertyConfiguratorAction.java new file mode 100644 index 0000000000..8e6b84c304 --- /dev/null +++ b/logback-classic/src/main/java/ch/qos/logback/classic/joran/action/PropertyConfiguratorAction.java @@ -0,0 +1,33 @@ +/* + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2024, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ + +package ch.qos.logback.classic.joran.action; + +import ch.qos.logback.classic.model.PropertyConfiguratorModel; +import ch.qos.logback.core.joran.action.ResourceAction; +import ch.qos.logback.core.model.IncludeModel; + +/** + * Build an {@link PropertyConfiguratorModel} instance from SAX events. + * + * @author Ceki Gülcü + * @since 1.5.8 + */ +public class PropertyConfiguratorAction extends ResourceAction { + + protected PropertyConfiguratorModel makeNewResourceModel() { + return new PropertyConfiguratorModel(); + } + +} \ No newline at end of file diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/model/PropertyConfiguratorModel.java b/logback-classic/src/main/java/ch/qos/logback/classic/model/PropertyConfiguratorModel.java new file mode 100644 index 0000000000..6157abbe59 --- /dev/null +++ b/logback-classic/src/main/java/ch/qos/logback/classic/model/PropertyConfiguratorModel.java @@ -0,0 +1,22 @@ +/* + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2024, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ + +package ch.qos.logback.classic.model; + +import ch.qos.logback.core.model.ResourceModel; + +public class PropertyConfiguratorModel extends ResourceModel { + + private static final long serialVersionUID = -2009536798661734346L; +} diff --git a/logback-classic/src/main/java/ch/qos/logback/classic/model/processor/PropertyConfiguratorModelHandler.java b/logback-classic/src/main/java/ch/qos/logback/classic/model/processor/PropertyConfiguratorModelHandler.java new file mode 100644 index 0000000000..8eee57133c --- /dev/null +++ b/logback-classic/src/main/java/ch/qos/logback/classic/model/processor/PropertyConfiguratorModelHandler.java @@ -0,0 +1,83 @@ +/* + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2024, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ + +package ch.qos.logback.classic.model.processor; + +import ch.qos.logback.classic.joran.PropertyConfigurator; +import ch.qos.logback.classic.model.PropertyConfiguratorModel; +import ch.qos.logback.core.Context; +import ch.qos.logback.core.joran.spi.JoranException; +import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil; +import ch.qos.logback.core.model.IncludeModel; +import ch.qos.logback.core.model.Model; +import ch.qos.logback.core.model.ResourceModel; +import ch.qos.logback.core.model.processor.ModelHandlerException; +import ch.qos.logback.core.model.processor.ModelInterpretationContext; +import ch.qos.logback.core.model.processor.ResourceHandlerBase; +import ch.qos.logback.core.util.OptionHelper; + +import java.io.InputStream; +import java.net.URL; + +public class PropertyConfiguratorModelHandler extends ResourceHandlerBase { + boolean inError = false; + + public PropertyConfiguratorModelHandler(Context context) { + super(context); + } + + static public PropertyConfiguratorModelHandler makeInstance(Context context, ModelInterpretationContext mic) { + return new PropertyConfiguratorModelHandler(context); + } + + @Override + public void handle(ModelInterpretationContext mic, Model model) throws ModelHandlerException { + PropertyConfiguratorModel propertyConfiguratorModel = (PropertyConfiguratorModel) model; + + this.optional = OptionHelper.toBoolean(propertyConfiguratorModel.getOptional(), false); + + if (!checkAttributes(propertyConfiguratorModel)) { + inError = true; + return; + } + + InputStream in = getInputStream(mic, propertyConfiguratorModel); + if(in == null) { + inError = true; + return; + } + + addInfo("Reading configuration from ["+getAttribureInUse()+"]"); + + PropertyConfigurator propertyConfigurator = new PropertyConfigurator(); + propertyConfigurator.setContext(mic.getContext()); + try { + propertyConfigurator.doConfigure(in); + } catch (JoranException e) { + addError("Could not configure from "+getAttribureInUse()); + throw new ModelHandlerException(e); + } + + } + + protected InputStream getInputStream(ModelInterpretationContext mic, ResourceModel resourceModel) { + URL inputURL = getInputURL(mic, resourceModel); + if (inputURL == null) + return null; + + ConfigurationWatchListUtil.addToWatchList(context, inputURL); + return openURL(inputURL); + } + +} diff --git a/logback-classic/src/test/input/joran/propertyConfigurator/smoke.properties b/logback-classic/src/test/input/joran/propertyConfigurator/smoke.properties new file mode 100644 index 0000000000..f201483db6 --- /dev/null +++ b/logback-classic/src/test/input/joran/propertyConfigurator/smoke.properties @@ -0,0 +1,15 @@ +# +# Logback: the reliable, generic, fast and flexible logging framework. +# Copyright (C) 1999-2024, QOS.ch. All rights reserved. +# +# This program and the accompanying materials are dual-licensed under +# either the terms of the Eclipse Public License v1.0 as published by +# the Eclipse Foundation +# +# or (per the licensee's choosing) +# +# under the terms of the GNU Lesser General Public License version 2.1 +# as published by the Free Software Foundation. +# + +logback.logger.com.toto = WARN \ No newline at end of file diff --git a/logback-classic/src/test/input/joran/propertyConfigurator/smoke.xml b/logback-classic/src/test/input/joran/propertyConfigurator/smoke.xml new file mode 100644 index 0000000000..e9130520bb --- /dev/null +++ b/logback-classic/src/test/input/joran/propertyConfigurator/smoke.xml @@ -0,0 +1,30 @@ + + + + + + + %msg + + + + + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java index fd2a8b57c8..560a6b95b6 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java @@ -692,6 +692,16 @@ public void dateConverterWithLocale() throws JoranException { //StatusPrinter.print(loggerContext); } + @Test + public void propertyConfiguratorSmoke() throws JoranException { + configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "propertyConfigurator/smoke.xml"); + Logger com_foo_Logger = loggerContext.getLogger("com.toto"); + StatusPrinter.print(loggerContext); + assertEquals(Level.WARN, com_foo_Logger.getLevel()); + + + } + @Test public void consoleCharsetTest() throws JoranException { if (EnvUtil.isJDK21OrHigher()) { diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/IncludeAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/IncludeAction.java index b8d2c4b9a6..244cb82c0c 100755 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/action/IncludeAction.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/IncludeAction.java @@ -13,91 +13,19 @@ */ package ch.qos.logback.core.joran.action; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URL; -import java.util.List; - -import org.xml.sax.Attributes; - -import ch.qos.logback.core.joran.event.SaxEvent; -import ch.qos.logback.core.joran.event.SaxEventRecorder; -import ch.qos.logback.core.joran.spi.ActionException; -import ch.qos.logback.core.joran.spi.JoranException; -import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext; -import ch.qos.logback.core.joran.util.ConfigurationWatchListUtil; import ch.qos.logback.core.model.IncludeModel; -import ch.qos.logback.core.model.Model; -import ch.qos.logback.core.util.Loader; -import ch.qos.logback.core.util.OptionHelper; - -import static ch.qos.logback.core.joran.JoranConstants.INCLUDED_TAG; +import ch.qos.logback.core.model.ResourceModel; /** - * - * @author ceki + * Build an {@link IncludeModel} instance from SAX events. + * + * @author Ceki Gülcü * */ -public class IncludeAction extends Action { - - private static final String FILE_ATTR = "file"; - private static final String URL_ATTR = "url"; - private static final String RESOURCE_ATTR = "resource"; - private static final String OPTIONAL_ATTR = "optional"; - - Model parentModel; - IncludeModel includeModel; - boolean inError = false; - - @Override - public void begin(SaxEventInterpretationContext seic, String tagName, Attributes attributes) throws ActionException { - - String optionalStr = attributes.getValue(OPTIONAL_ATTR); +public class IncludeAction extends ResourceAction { - this.includeModel = new IncludeModel(); - this.includeModel.setOptional(optionalStr); - fillInIncludeModelAttributes(includeModel, tagName, attributes); - if (!seic.isModelStackEmpty()) { - parentModel = seic.peekModel(); - } - final int lineNumber = getLineNumber(seic); - this.includeModel.setLineNumber(lineNumber); - seic.pushModel(this.includeModel); + protected ResourceModel makeNewResourceModel() { + return new IncludeModel(); } - private void fillInIncludeModelAttributes(IncludeModel includeModel, String tagName, Attributes attributes) { - this.includeModel.setTag(tagName); - String fileAttribute = attributes.getValue(FILE_ATTR); - String urlAttribute = attributes.getValue(URL_ATTR); - String resourceAttribute = attributes.getValue(RESOURCE_ATTR); - - this.includeModel.setFile(fileAttribute); - this.includeModel.setUrl(urlAttribute); - this.includeModel.setResource(resourceAttribute); - } - - - @Override - public void end(SaxEventInterpretationContext seic, String name) throws ActionException { - - if(inError) - return; - - Model m = seic.peekModel(); - - if (m != includeModel) { - addWarn("The object at the of the stack is not the model [" + includeModel.idString() - + "] pushed earlier."); - addWarn("This is wholly unexpected."); - } - - // do not pop nor add to parent if there is no parent - if (parentModel != null) { - parentModel.addSubModel(includeModel); - seic.popModel(); - } - } } diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/action/ResourceAction.java b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ResourceAction.java new file mode 100644 index 0000000000..cee498b6f0 --- /dev/null +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/action/ResourceAction.java @@ -0,0 +1,86 @@ +/* + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2024, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ + +package ch.qos.logback.core.joran.action; + +import ch.qos.logback.core.joran.spi.ActionException; +import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext; +import ch.qos.logback.core.model.Model; +import ch.qos.logback.core.model.ResourceModel; +import org.xml.sax.Attributes; + +/** + * An action which builds subclass instances of {@link ResourceModel}. + * + * @since 1.5.8 + */ +abstract public class ResourceAction extends Action { + + private static final String FILE_ATTR = "file"; + private static final String URL_ATTR = "url"; + private static final String RESOURCE_ATTR = "resource"; + private static final String OPTIONAL_ATTR = "optional"; + + Model parentModel; + ResourceModel resourceModel; + boolean inError = false; + + abstract protected ResourceModel makeNewResourceModel(); + + @Override + public void begin(SaxEventInterpretationContext seic, String tagName, Attributes attributes) throws ActionException { + String optionalStr = attributes.getValue(OPTIONAL_ATTR); + + this.resourceModel = makeNewResourceModel(); + this.resourceModel.setOptional(optionalStr); + fillInIncludeModelAttributes(resourceModel, tagName, attributes); + if (!seic.isModelStackEmpty()) { + parentModel = seic.peekModel(); + } + final int lineNumber = getLineNumber(seic); + this.resourceModel.setLineNumber(lineNumber); + seic.pushModel(this.resourceModel); + } + + private void fillInIncludeModelAttributes(ResourceModel resourceModel, String tagName, Attributes attributes) { + this.resourceModel.setTag(tagName); + String fileAttribute = attributes.getValue(FILE_ATTR); + String urlAttribute = attributes.getValue(URL_ATTR); + String resourceAttribute = attributes.getValue(RESOURCE_ATTR); + + this.resourceModel.setFile(fileAttribute); + this.resourceModel.setUrl(urlAttribute); + this.resourceModel.setResource(resourceAttribute); + } + + @Override + public void end(SaxEventInterpretationContext seic, String name) throws ActionException { + if(inError) + return; + + Model m = seic.peekModel(); + + if (m != resourceModel) { + addWarn("The object at the of the stack is not the model [" + resourceModel.idString() + + "] pushed earlier."); + addWarn("This is wholly unexpected."); + } + + // do not pop nor add to parent if there is no parent + if (parentModel != null) { + parentModel.addSubModel(resourceModel); + seic.popModel(); + } + } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/model/IncludeModel.java b/logback-core/src/main/java/ch/qos/logback/core/model/IncludeModel.java index 5a62a841c4..520cd464dc 100755 --- a/logback-core/src/main/java/ch/qos/logback/core/model/IncludeModel.java +++ b/logback-core/src/main/java/ch/qos/logback/core/model/IncludeModel.java @@ -1,46 +1,5 @@ package ch.qos.logback.core.model; -import ch.qos.logback.core.joran.spi.ElementPath; - -public class IncludeModel extends Model { - - private static final long serialVersionUID = -7613821942841993495L; - String optional; - String file; - String url; - String resource; - ElementPath elementPath; - - public String getOptional() { - return optional; - } - - public void setOptional(String optional) { - this.optional = optional; - } - - public String getFile() { - return file; - } - - public void setFile(String file) { - this.file = file; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getResource() { - return resource; - } - - public void setResource(String resource) { - this.resource = resource; - } - +public class IncludeModel extends ResourceModel { + private static final long serialVersionUID = -9114108510322703902L; } diff --git a/logback-core/src/main/java/ch/qos/logback/core/model/ResourceModel.java b/logback-core/src/main/java/ch/qos/logback/core/model/ResourceModel.java new file mode 100644 index 0000000000..3391ebab96 --- /dev/null +++ b/logback-core/src/main/java/ch/qos/logback/core/model/ResourceModel.java @@ -0,0 +1,59 @@ +/* + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2024, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ + +package ch.qos.logback.core.model; + + +public class ResourceModel extends Model { + + private static final long serialVersionUID = 2185210901733958800L; + + String file; + String url; + String resource; + String optional; + + public String getOptional() { + return optional; + } + + public void setOptional(String optional) { + this.optional = optional; + } + + public String getFile() { + return file; + } + + public void setFile(String file) { + this.file = file; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getResource() { + return resource; + } + + public void setResource(String resource) { + this.resource = resource; + } + +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/model/processor/IncludeModelHandler.java b/logback-core/src/main/java/ch/qos/logback/core/model/processor/IncludeModelHandler.java index 7775ab009e..fdb29b76de 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/model/processor/IncludeModelHandler.java +++ b/logback-core/src/main/java/ch/qos/logback/core/model/processor/IncludeModelHandler.java @@ -41,10 +41,8 @@ /** * @since 1.5.5 */ -public class IncludeModelHandler extends ModelHandlerBase { +public class IncludeModelHandler extends ResourceHandlerBase { boolean inError = false; - private String attributeInUse; - private boolean optional; public IncludeModelHandler(Context context) { super(context); @@ -87,8 +85,6 @@ public void handle(ModelInterpretationContext mic, Model model) throws ModelHand return; } - //trimHeadAndTail(saxEvents); - Supplier jcSupplier = mic.getConfiguratorSupplier(); if (jcSupplier == null) { addError("null configurator supplier. Abandoning inclusion of [" + attributeInUse + "]"); @@ -119,28 +115,7 @@ public SaxEventRecorder populateSaxEventRecorder(final InputStream inputStream) return recorder; } - private void trimHeadAndTail( List saxEventList) { - // Let's remove the two events before - // adding the events to the player. - - // note saxEventList.size() changes over time as events are removed - - if (saxEventList.size() == 0) { - return; - } - - SaxEvent first = saxEventList.get(0); - if (first != null && first.qName.equalsIgnoreCase(INCLUDED_TAG)) { - saxEventList.remove(0); - } - - SaxEvent last = saxEventList.get(saxEventList.size() - 1); - if (last != null && last.qName.equalsIgnoreCase(INCLUDED_TAG)) { - saxEventList.remove(saxEventList.size() - 1); - } - } - - InputStream getInputStream(ModelInterpretationContext mic, IncludeModel includeModel) { + private InputStream getInputStream(ModelInterpretationContext mic, IncludeModel includeModel) { URL inputURL = getInputURL(mic, includeModel); if (inputURL == null) return null; @@ -149,101 +124,4 @@ InputStream getInputStream(ModelInterpretationContext mic, IncludeModel includeM return openURL(inputURL); } - InputStream openURL(URL url) { - try { - return url.openStream(); - } catch (IOException e) { - optionalWarning("Failed to open [" + url.toString() + "]"); - return null; - } - } - - private boolean checkAttributes(IncludeModel includeModel) { - String fileAttribute = includeModel.getFile(); - String urlAttribute = includeModel.getUrl(); - String resourceAttribute = includeModel.getResource(); - - int count = 0; - - if (!OptionHelper.isNullOrEmptyOrAllSpaces(fileAttribute)) { - count++; - } - if (!OptionHelper.isNullOrEmptyOrAllSpaces(urlAttribute)) { - count++; - } - if (!OptionHelper.isNullOrEmptyOrAllSpaces(resourceAttribute)) { - count++; - } - - if (count == 0) { - addError("One of \"path\", \"resource\" or \"url\" attributes must be set."); - return false; - } else if (count > 1) { - addError("Only one of \"file\", \"url\" or \"resource\" attributes should be set."); - return false; - } else if (count == 1) { - return true; - } - throw new IllegalStateException("Count value [" + count + "] is not expected"); - } - - URL getInputURL(ModelInterpretationContext mic, IncludeModel includeModel) { - String fileAttribute = includeModel.getFile(); - String urlAttribute = includeModel.getUrl(); - String resourceAttribute = includeModel.getResource(); - - if (!OptionHelper.isNullOrEmptyOrAllSpaces(fileAttribute)) { - this.attributeInUse = mic.subst(fileAttribute); - return filePathAsURL(attributeInUse); - } - - if (!OptionHelper.isNullOrEmptyOrAllSpaces(urlAttribute)) { - this.attributeInUse = mic.subst(urlAttribute); - return attributeToURL(attributeInUse); - } - - if (!OptionHelper.isNullOrEmptyOrAllSpaces(resourceAttribute)) { - this.attributeInUse = mic.subst(resourceAttribute); - return resourceAsURL(attributeInUse); - } - // given preceding checkAttributes() check we cannot reach this line - throw new IllegalStateException("A URL stream should have been returned at this stage"); - - } - - URL filePathAsURL(String path) { - URI uri = new File(path).toURI(); - try { - return uri.toURL(); - } catch (MalformedURLException e) { - // impossible to get here - e.printStackTrace(); - return null; - } - } - - URL attributeToURL(String urlAttribute) { - try { - return new URL(urlAttribute); - } catch (MalformedURLException mue) { - String errMsg = "URL [" + urlAttribute + "] is not well formed."; - addError(errMsg, mue); - return null; - } - } - - URL resourceAsURL(String resourceAttribute) { - URL url = Loader.getResourceBySelfClassLoader(resourceAttribute); - if (url == null) { - optionalWarning("Could not find resource corresponding to [" + resourceAttribute + "]"); - return null; - } else - return url; - } - - private void optionalWarning(String msg) { - if (!optional) { - addWarn(msg); - } - } } diff --git a/logback-core/src/main/java/ch/qos/logback/core/model/processor/ResourceHandlerBase.java b/logback-core/src/main/java/ch/qos/logback/core/model/processor/ResourceHandlerBase.java new file mode 100644 index 0000000000..85fdb74f4d --- /dev/null +++ b/logback-core/src/main/java/ch/qos/logback/core/model/processor/ResourceHandlerBase.java @@ -0,0 +1,140 @@ +/* + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2024, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ + +package ch.qos.logback.core.model.processor; + +import ch.qos.logback.core.Context; +import ch.qos.logback.core.model.ResourceModel; +import ch.qos.logback.core.util.Loader; +import ch.qos.logback.core.util.OptionHelper; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; + +abstract public class ResourceHandlerBase extends ModelHandlerBase { + + protected String attributeInUse; + protected boolean optional; + + protected ResourceHandlerBase(Context context) { + super(context); + } + + protected InputStream openURL(URL url) { + try { + return url.openStream(); + } catch (IOException e) { + warnIfRequired("Failed to open [" + url.toString() + "]"); + return null; + } + } + + protected boolean checkAttributes(ResourceModel resourceModel) { + String fileAttribute = resourceModel.getFile(); + String urlAttribute = resourceModel.getUrl(); + String resourceAttribute = resourceModel.getResource(); + + int count = 0; + + if (!OptionHelper.isNullOrEmptyOrAllSpaces(fileAttribute)) { + count++; + } + if (!OptionHelper.isNullOrEmptyOrAllSpaces(urlAttribute)) { + count++; + } + if (!OptionHelper.isNullOrEmptyOrAllSpaces(resourceAttribute)) { + count++; + } + + if (count == 0) { + addError("One of \"path\", \"resource\" or \"url\" attributes must be set."); + return false; + } else if (count > 1) { + addError("Only one of \"file\", \"url\" or \"resource\" attributes should be set."); + return false; + } else if (count == 1) { + return true; + } + throw new IllegalStateException("Count value [" + count + "] is not expected"); + } + + + protected String getAttribureInUse() { + return this.attributeInUse; + } + + protected URL getInputURL(ModelInterpretationContext mic, ResourceModel resourceModel) { + String fileAttribute = resourceModel.getFile(); + String urlAttribute = resourceModel.getUrl(); + String resourceAttribute = resourceModel.getResource(); + + if (!OptionHelper.isNullOrEmptyOrAllSpaces(fileAttribute)) { + this.attributeInUse = mic.subst(fileAttribute); + return filePathAsURL(attributeInUse); + } + + if (!OptionHelper.isNullOrEmptyOrAllSpaces(urlAttribute)) { + this.attributeInUse = mic.subst(urlAttribute); + return attributeToURL(attributeInUse); + } + + if (!OptionHelper.isNullOrEmptyOrAllSpaces(resourceAttribute)) { + this.attributeInUse = mic.subst(resourceAttribute); + return resourceAsURL(attributeInUse); + } + // given preceding checkAttributes() check we cannot reach this line + throw new IllegalStateException("A URL stream should have been returned at this stage"); + + } + + protected URL filePathAsURL(String path) { + URI uri = new File(path).toURI(); + try { + return uri.toURL(); + } catch (MalformedURLException e) { + // impossible to get here + e.printStackTrace(); + return null; + } + } + + protected URL attributeToURL(String urlAttribute) { + try { + return new URL(urlAttribute); + } catch (MalformedURLException mue) { + String errMsg = "URL [" + urlAttribute + "] is not well formed."; + addError(errMsg, mue); + return null; + } + } + + protected URL resourceAsURL(String resourceAttribute) { + URL url = Loader.getResourceBySelfClassLoader(resourceAttribute); + if (url == null) { + warnIfRequired("Could not find resource corresponding to [" + resourceAttribute + "]"); + return null; + } else + return url; + } + + protected void warnIfRequired(String msg) { + if (!optional) { + addWarn(msg); + } + } +}