001package ch.qos.logback.core.model.processor; 002 003import java.io.FileInputStream; 004import java.io.FileNotFoundException; 005import java.io.IOException; 006import java.io.InputStream; 007import java.net.URL; 008import java.util.Properties; 009 010import ch.qos.logback.core.Context; 011import ch.qos.logback.core.joran.action.ActionUtil; 012import ch.qos.logback.core.joran.action.ActionUtil.Scope; 013import ch.qos.logback.core.model.Model; 014import ch.qos.logback.core.model.ModelUtil; 015import ch.qos.logback.core.model.PropertyModel; 016import ch.qos.logback.core.pattern.util.RegularEscapeUtil; 017import ch.qos.logback.core.util.Loader; 018import ch.qos.logback.core.util.OptionHelper; 019 020public class PropertyModelHandler extends ModelHandlerBase { 021 022 public static final String INVALID_ATTRIBUTES = "In <property> element, either the \"file\" attribute alone, or " 023 + "the \"resource\" element alone, or both the \"name\" and \"value\" attributes must be set."; 024 025 public PropertyModelHandler(Context context) { 026 super(context); 027 } 028 029 static public ModelHandlerBase makeInstance(Context context, ModelInterpretationContext ic) { 030 return new PropertyModelHandler(context); 031 } 032 033 @Override 034 protected Class<PropertyModel> getSupportedModelClass() { 035 return PropertyModel.class; 036 } 037 038 @Override 039 public void handle(ModelInterpretationContext interpretationContext, Model model) { 040 041 PropertyModel propertyModel = (PropertyModel) model; 042 043 Scope scope = ActionUtil.stringToScope(propertyModel.getScopeStr()); 044 045 if (checkFileAttributeSanity(propertyModel)) { 046 String file = propertyModel.getFile(); 047 file = interpretationContext.subst(file); 048 try (FileInputStream istream = new FileInputStream(file)) { 049 loadAndSetProperties(interpretationContext, istream, scope); 050 } catch (FileNotFoundException e) { 051 addError("Could not find properties file [" + file + "]."); 052 } catch (IOException|IllegalArgumentException e1) { // IllegalArgumentException is thrown in case the file 053 // is badly malformed, i.e a binary. 054 addError("Could not read properties file [" + file + "].", e1); 055 } 056 } else if (checkResourceAttributeSanity(propertyModel)) { 057 String resource = propertyModel.getResource(); 058 resource = interpretationContext.subst(resource); 059 URL resourceURL = Loader.getResourceBySelfClassLoader(resource); 060 if (resourceURL == null) { 061 addError("Could not find resource [" + resource + "]."); 062 } else { 063 try ( InputStream istream = resourceURL.openStream();) { 064 loadAndSetProperties(interpretationContext, istream, scope); 065 } catch (IOException e) { 066 addError("Could not read resource file [" + resource + "].", e); 067 } 068 } 069 } else if (checkValueNameAttributesSanity(propertyModel)) { 070 // earlier versions performed Java '\' escapes for '\\' '\t' etc. Howevver, there is no 071 // need to do this. See RegularEscapeUtil.__UNUSED__basicEscape 072 String value = propertyModel.getValue(); 073 074 // now remove both leading and trailing spaces 075 value = value.trim(); 076 value = interpretationContext.subst(value); 077 ActionUtil.setProperty(interpretationContext, propertyModel.getName(), value, scope); 078 079 } else { 080 addError(INVALID_ATTRIBUTES); 081 } 082 } 083 084 void loadAndSetProperties(ModelInterpretationContext mic, InputStream istream, Scope scope) throws IOException { 085 Properties props = new Properties(); 086 props.load(istream); 087 ModelUtil.setProperties(mic, props, scope); 088 } 089 090 boolean checkFileAttributeSanity(PropertyModel propertyModel) { 091 String file = propertyModel.getFile(); 092 String name = propertyModel.getName(); 093 String value = propertyModel.getValue(); 094 String resource = propertyModel.getResource(); 095 096 return !(OptionHelper.isNullOrEmpty(file)) && (OptionHelper.isNullOrEmpty(name) 097 && OptionHelper.isNullOrEmpty(value) && OptionHelper.isNullOrEmpty(resource)); 098 } 099 100 boolean checkResourceAttributeSanity(PropertyModel propertyModel) { 101 String file = propertyModel.getFile(); 102 String name = propertyModel.getName(); 103 String value = propertyModel.getValue(); 104 String resource = propertyModel.getResource(); 105 106 return !(OptionHelper.isNullOrEmpty(resource)) && (OptionHelper.isNullOrEmpty(name) 107 && OptionHelper.isNullOrEmpty(value) && OptionHelper.isNullOrEmpty(file)); 108 } 109 110 boolean checkValueNameAttributesSanity(PropertyModel propertyModel) { 111 String file = propertyModel.getFile(); 112 String name = propertyModel.getName(); 113 String value = propertyModel.getValue(); 114 String resource = propertyModel.getResource(); 115 return (!(OptionHelper.isNullOrEmpty(name) || OptionHelper.isNullOrEmpty(value)) 116 && (OptionHelper.isNullOrEmpty(file) && OptionHelper.isNullOrEmpty(resource))); 117 } 118 119}