View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.joran.action;
15  
16  import ch.qos.logback.core.util.ContextUtil;
17  import org.xml.sax.Attributes;
18  
19  import ch.qos.logback.core.joran.spi.InterpretationContext;
20  import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
21  import ch.qos.logback.core.util.Loader;
22  import ch.qos.logback.core.util.OptionHelper;
23  
24  import java.io.FileInputStream;
25  import java.io.FileNotFoundException;
26  import java.io.IOException;
27  import java.io.InputStream;
28  import java.net.URL;
29  
30  import java.util.Properties;
31  
32  /**
33   * This class serves as a base for other actions, which similar to the ANT
34   * <property> task which add/set properties of a given object.
35   * 
36   * This action sets new substitution properties in the logging context by name,
37   * value pair, or adds all the properties passed in "file" or "resource"
38   * attribute.
39   * 
40   * @author Ceki G&uuml;lc&uuml;
41   */
42  public class PropertyAction extends Action {
43  
44    enum Scope {LOCAL, CONTEXT, SYSTEM};
45  
46    static final String RESOURCE_ATTRIBUTE = "resource";
47  
48  
49    static String INVALID_ATTRIBUTES = "In <property> element, either the \"file\" attribute alone, or "
50            + "the \"resource\" element alone, or both the \"name\" and \"value\" attributes must be set.";
51  
52    /**
53     * Add all the properties found in the argument named 'props' to an
54     * InterpretationContext.
55     */
56    public void setProperties(InterpretationContext ec, Properties props, Scope scope) {
57      switch(scope) {
58        case LOCAL: ec.addSubstitutionProperties(props);
59          break;
60        case CONTEXT:
61          ContextUtil cu = new ContextUtil((context));
62          cu.addProperties(props);
63          break;
64        case SYSTEM:
65          OptionHelper.setSystemProperties(this, props);
66      }
67    }
68  
69    public void setProperty(InterpretationContext ec, String key, String value,  Scope scope) {
70       switch(scope) {
71        case LOCAL: ec.addSubstitutionProperty(key, value);
72          break;
73        case CONTEXT:
74          context.putProperty(key, value);
75          break;
76        case SYSTEM:
77          OptionHelper.setSystemProperty(this, key, value);
78      }
79    }
80  
81    /**
82     * Set a new property for the execution context by name, value pair, or adds
83     * all the properties found in the given file.
84     * 
85     */
86    public void begin(InterpretationContext ec, String localName,
87        Attributes attributes) {
88  
89      if ("substitutionProperty".equals(localName)) {
90        addWarn("[substitutionProperty] element has been deprecated. Please use the [property] element instead.");
91      }
92  
93      String name = attributes.getValue(NAME_ATTRIBUTE);
94      String value = attributes.getValue(VALUE_ATTRIBUTE);
95      String scopeStr = attributes.getValue(SCOPE_ATTRIBUTE);
96  
97      Scope scope = stringToScope(scopeStr);
98  
99      if (checkFileAttributeSanity(attributes)) {
100       String file = attributes.getValue(FILE_ATTRIBUTE);
101       file = ec.subst(file);
102       try {
103         FileInputStream istream = new FileInputStream(file);
104         loadAndSetProperties(ec, istream, scope);
105       } catch (FileNotFoundException e) {
106         addError("Could not find properties file [" + file + "].");
107       } catch (IOException e1) {
108         addError("Could not read properties file [" + file + "].", e1);
109       }
110     } else if (checkResourceAttributeSanity(attributes)) {
111       String resource = attributes.getValue(RESOURCE_ATTRIBUTE);
112       resource = ec.subst(resource);
113       URL resourceURL = Loader.getResourceBySelfClassLoader(resource);
114       if (resourceURL == null) {
115         addError("Could not find resource [" + resource + "].");
116       } else {
117         try {
118           InputStream istream = resourceURL.openStream();
119           loadAndSetProperties(ec, istream, scope);
120         } catch (IOException e) {
121           addError("Could not read resource file [" + resource + "].", e);
122         }
123       }
124     } else if (checkValueNameAttributesSanity(attributes)) {
125       value = RegularEscapeUtil.basicEscape(value);
126       // now remove both leading and trailing spaces
127       value = value.trim();
128       value = ec.subst(value);
129       setProperty(ec, name, value, scope);
130 
131     } else {
132       addError(INVALID_ATTRIBUTES);
133     }
134   }
135 
136   private Scope stringToScope(String scopeStr) {
137     if(Scope.SYSTEM.toString().equalsIgnoreCase(scopeStr))
138       return Scope.SYSTEM;
139      if(Scope.CONTEXT.toString().equalsIgnoreCase(scopeStr))
140       return Scope.CONTEXT;
141 
142     return Scope.LOCAL;
143   }
144 
145   void loadAndSetProperties(InterpretationContext ec, InputStream istream, Scope scope)
146       throws IOException {
147     Properties props = new Properties();
148     props.load(istream);
149     istream.close();
150     setProperties(ec, props, scope);
151   }
152 
153   boolean checkFileAttributeSanity(Attributes attributes) {
154     String file = attributes.getValue(FILE_ATTRIBUTE);
155     String name = attributes.getValue(NAME_ATTRIBUTE);
156     String value = attributes.getValue(VALUE_ATTRIBUTE);
157     String resource = attributes.getValue(RESOURCE_ATTRIBUTE);
158 
159     return !(OptionHelper.isEmpty(file))
160         && (OptionHelper.isEmpty(name) && OptionHelper.isEmpty(value) && OptionHelper
161             .isEmpty(resource));
162   }
163 
164   boolean checkResourceAttributeSanity(Attributes attributes) {
165     String file = attributes.getValue(FILE_ATTRIBUTE);
166     String name = attributes.getValue(NAME_ATTRIBUTE);
167     String value = attributes.getValue(VALUE_ATTRIBUTE);
168     String resource = attributes.getValue(RESOURCE_ATTRIBUTE);
169 
170     return !(OptionHelper.isEmpty(resource))
171         && (OptionHelper.isEmpty(name) && OptionHelper.isEmpty(value) && OptionHelper
172             .isEmpty(file));
173   }
174 
175   boolean checkValueNameAttributesSanity(Attributes attributes) {
176     String file = attributes.getValue(FILE_ATTRIBUTE);
177     String name = attributes.getValue(NAME_ATTRIBUTE);
178     String value = attributes.getValue(VALUE_ATTRIBUTE);
179     String resource = attributes.getValue(RESOURCE_ATTRIBUTE);
180 
181     return (!(OptionHelper.isEmpty(name) || OptionHelper.isEmpty(value)) && (OptionHelper
182         .isEmpty(file) && OptionHelper.isEmpty(resource)));
183   }
184 
185   public void end(InterpretationContext ec, String name) {
186   }
187 
188   public void finish(InterpretationContext ec) {
189   }
190 }