001/* 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2024, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014 015package ch.qos.logback.classic.tyler; 016 017import ch.qos.logback.core.Context; 018import ch.qos.logback.core.joran.action.ActionUtil; 019import ch.qos.logback.core.model.ModelConstants; 020import ch.qos.logback.core.model.PropertyModel; 021import ch.qos.logback.core.model.util.PropertyModelHandlerHelper; 022import ch.qos.logback.core.model.util.VariableSubstitutionsHelper; 023import ch.qos.logback.core.spi.ContextAwareBase; 024import ch.qos.logback.core.util.ContextUtil; 025import ch.qos.logback.core.util.Loader; 026import ch.qos.logback.core.util.OptionHelper; 027 028import java.io.FileInputStream; 029import java.io.FileNotFoundException; 030import java.io.IOException; 031import java.io.InputStream; 032import java.net.URL; 033import java.util.Properties; 034 035public class VariableModelHelper extends ContextAwareBase { 036 037 TylerConfiguratorBase tylerConfiguratorBase; 038 VariableSubstitutionsHelper variableSubstitutionsHelper; 039 040 VariableModelHelper(Context context, TylerConfiguratorBase tylerConfiguratorBase) { 041 super( tylerConfiguratorBase); 042 this.context = context; 043 this.tylerConfiguratorBase = tylerConfiguratorBase; 044 this.variableSubstitutionsHelper = new VariableSubstitutionsHelper(context); 045 } 046 047 void updateProperties(PropertyModel propertyModel) { 048 049 ActionUtil.Scope scope = ActionUtil.stringToScope(propertyModel.getScopeStr()); 050 if (PropertyModelHandlerHelper.checkFileAttributeSanity(propertyModel)) { 051 String file = propertyModel.getFile(); 052 file = tylerConfiguratorBase.subst(file); 053 try (FileInputStream istream = new FileInputStream(file)) { 054 loadAndSetProperties(istream, scope); 055 } catch (FileNotFoundException e) { 056 addError("Could not find properties file [" + file + "]."); 057 } catch (IOException |IllegalArgumentException e1) { // IllegalArgumentException is thrown in case the file 058 // is badly malformed, i.e a binary. 059 addError("Could not read properties file [" + file + "].", e1); 060 } 061 } else if (PropertyModelHandlerHelper.checkResourceAttributeSanity(propertyModel)) { 062 String resource = propertyModel.getResource(); 063 resource = tylerConfiguratorBase.subst(resource); 064 URL resourceURL = Loader.getResourceBySelfClassLoader(resource); 065 if (resourceURL == null) { 066 addError("Could not find resource [" + resource + "]."); 067 } else { 068 try ( InputStream istream = resourceURL.openStream();) { 069 loadAndSetProperties(istream, scope); 070 } catch (IOException e) { 071 addError("Could not read resource file [" + resource + "].", e); 072 } 073 } 074 } else if (PropertyModelHandlerHelper.checkValueNameAttributesSanity(propertyModel)) { 075 // earlier versions performed Java '\' escapes for '\\' '\t' etc. Howevver, there is no 076 // need to do this. See RegularEscapeUtil.__UNUSED__basicEscape 077 String value = propertyModel.getValue(); 078 079 // now remove both leading and trailing spaces 080 value = value.trim(); 081 value = tylerConfiguratorBase.subst(value); 082 setProperty(propertyModel.getName(), value, scope); 083 084 } else { 085 addError(ModelConstants.INVALID_ATTRIBUTES); 086 } 087 } 088 089 void loadAndSetProperties(InputStream istream, ActionUtil.Scope scope) throws IOException { 090 Properties props = new Properties(); 091 props.load(istream); 092 setProperties(props, scope); 093 } 094 095 096 public void setProperties(Properties props, ActionUtil.Scope scope) { 097 switch (scope) { 098 case LOCAL: 099 variableSubstitutionsHelper.addSubstitutionProperties(props); 100 break; 101 case CONTEXT: 102 ContextUtil cu = new ContextUtil(getContext()); 103 cu.addProperties(props); 104 break; 105 case SYSTEM: 106 OptionHelper.setSystemProperties(this, props); 107 } 108 } 109 110 public void setProperty(String key, String value, ActionUtil.Scope scope) { 111 switch (scope) { 112 case LOCAL: 113 variableSubstitutionsHelper.addSubstitutionProperty(key, value); 114 break; 115 case CONTEXT: 116 getContext().putProperty(key, value); 117 break; 118 case SYSTEM: 119 OptionHelper.setSystemProperty(this, key, value); 120 } 121 } 122}