View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, 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.spi;
15  
16  import java.util.ArrayList;
17  import java.util.HashMap;
18  import java.util.List;
19  import java.util.Map;
20  import java.util.Properties;
21  import java.util.Stack;
22  
23  import org.xml.sax.Locator;
24  
25  import ch.qos.logback.core.Context;
26  import ch.qos.logback.core.joran.action.Action;
27  import ch.qos.logback.core.joran.event.InPlayListener;
28  import ch.qos.logback.core.joran.event.SaxEvent;
29  import ch.qos.logback.core.spi.ContextAwareBase;
30  import ch.qos.logback.core.spi.PropertyContainer;
31  import ch.qos.logback.core.util.OptionHelper;
32  
33  /**
34   * 
35   * An InterpretationContext contains the contextual state of a Joran parsing
36   * session. {@link Action} objects depend on this context to exchange and store
37   * information.
38   * 
39   * @author Ceki Gülcü
40   */
41  public class InterpretationContext extends ContextAwareBase implements PropertyContainer {
42      Stack<Object> objectStack;
43      Map<String, Object> objectMap;
44      Map<String, String> propertiesMap;
45  
46      Interpreter joranInterpreter;
47      final List<InPlayListener> listenerList = new ArrayList<InPlayListener>();
48      DefaultNestedComponentRegistry defaultNestedComponentRegistry = new DefaultNestedComponentRegistry();
49  
50      public InterpretationContext(Context context, Interpreter joranInterpreter) {
51          this.context = context;
52          this.joranInterpreter = joranInterpreter;
53          objectStack = new Stack<Object>();
54          objectMap = new HashMap<String, Object>(5);
55          propertiesMap = new HashMap<String, String>(5);
56      }
57  
58      public DefaultNestedComponentRegistry getDefaultNestedComponentRegistry() {
59          return defaultNestedComponentRegistry;
60      }
61  
62      public Map<String, String> getCopyOfPropertyMap() {
63          return new HashMap<String, String>(propertiesMap);
64      }
65  
66      void setPropertiesMap(Map<String, String> propertiesMap) {
67          this.propertiesMap = propertiesMap;
68      }
69  
70      String updateLocationInfo(String msg) {
71          Locator locator = joranInterpreter.getLocator();
72  
73          if (locator != null) {
74              return msg + locator.getLineNumber() + ":" + locator.getColumnNumber();
75          } else {
76              return msg;
77          }
78      }
79  
80      public Locator getLocator() {
81          return joranInterpreter.getLocator();
82      }
83  
84      public Interpreter getJoranInterpreter() {
85          return joranInterpreter;
86      }
87  
88      public Stack<Object> getObjectStack() {
89          return objectStack;
90      }
91  
92      public boolean isEmpty() {
93          return objectStack.isEmpty();
94      }
95  
96      public Object peekObject() {
97          return objectStack.peek();
98      }
99  
100     public void pushObject(Object o) {
101         objectStack.push(o);
102     }
103 
104     public Object popObject() {
105         return objectStack.pop();
106     }
107 
108     public Object getObject(int i) {
109         return objectStack.get(i);
110     }
111 
112     public Map<String, Object> getObjectMap() {
113         return objectMap;
114     }
115 
116     /**
117      * Add a property to the properties of this execution context. If the property
118      * exists already, it is overwritten.
119      */
120     public void addSubstitutionProperty(String key, String value) {
121         if (key == null || value == null) {
122             return;
123         }
124         // values with leading or trailing spaces are bad. We remove them now.
125         value = value.trim();
126         propertiesMap.put(key, value);
127     }
128 
129     public void addSubstitutionProperties(Properties props) {
130         if (props == null) {
131             return;
132         }
133         for (Object keyObject : props.keySet()) {
134             String key = (String) keyObject;
135             String val = props.getProperty(key);
136             addSubstitutionProperty(key, val);
137         }
138     }
139 
140     /**
141      * If a key is found in propertiesMap then return it. Otherwise, delegate to
142      * the context.
143      */
144     public String getProperty(String key) {
145         String v = propertiesMap.get(key);
146         if (v != null) {
147             return v;
148         } else {
149             return context.getProperty(key);
150         }
151     }
152 
153     public String subst(String value) {
154         if (value == null) {
155             return null;
156         }
157         return OptionHelper.substVars(value, this, context);
158     }
159 
160     public boolean isListenerListEmpty() {
161         return listenerList.isEmpty();
162     }
163 
164     public void addInPlayListener(InPlayListener ipl) {
165         if (listenerList.contains(ipl)) {
166             addWarn("InPlayListener " + ipl + " has been already registered");
167         } else {
168             listenerList.add(ipl);
169         }
170     }
171 
172     public boolean removeInPlayListener(InPlayListener ipl) {
173         return listenerList.remove(ipl);
174     }
175 
176     void fireInPlay(SaxEvent event) {
177         for (InPlayListener ipl : listenerList) {
178             ipl.inPlay(event);
179         }
180     }
181 }