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.spi;
15  
16  import java.util.ArrayList;
17  import java.util.HashMap;
18  import java.util.List;
19  
20  import ch.qos.logback.core.Context;
21  import ch.qos.logback.core.joran.action.Action;
22  import ch.qos.logback.core.spi.ContextAwareBase;
23  import ch.qos.logback.core.util.OptionHelper;
24  
25  /**
26   * This class implements the {@link RuleStore} interface. It is the rule store
27   * implementation used by default in Joran.
28   * 
29   * @author Ceki Gülcü
30   * 
31   */
32  public class SimpleRuleStore extends ContextAwareBase implements RuleStore {
33  
34    static String ANY = "*";
35    
36    // key: Pattern instance, value: ArrayList containing actions
37    HashMap<Pattern, List<Action>> rules = new HashMap<Pattern, List<Action>>();
38  
39    // public SimpleRuleStore() {
40    // }
41  
42    public SimpleRuleStore(Context context) {
43      setContext(context);
44    }
45  
46    /**
47     * Add a new rule, i.e. a pattern, action pair to the rule store. <p> Note
48     * that the added action's LoggerRepository will be set in the process.
49     */
50    public void addRule(Pattern pattern, Action action) {
51      action.setContext(context);
52  
53      List<Action> a4p = rules.get(pattern);
54  
55      if (a4p == null) {
56        a4p = new ArrayList<Action>();
57        rules.put(pattern, a4p);
58      }
59  
60      a4p.add(action);
61    }
62  
63    public void addRule(Pattern pattern, String actionClassName) {
64      Action action = null;
65  
66      try {
67        action = (Action) OptionHelper.instantiateByClassName(actionClassName,
68            Action.class, context);
69      } catch (Exception e) {
70        addError("Could not instantiate class [" + actionClassName + "]", e);
71      }
72      if (action != null) {
73        addRule(pattern, action);
74      }
75    }
76  
77    // exact match has highest priority
78    // if no exact match, check for tail match, i.e matches of type */x/y
79    // tail match for */x/y has higher priority than match for */x
80    // if no tail match, check for prefix match, i.e. matches for x/*
81    // match for x/y/* has higher priority than matches for x/*
82  
83    public List matchActions(Pattern currentPattern) {
84      List actionList;
85  
86      if ((actionList = rules.get(currentPattern)) != null) {
87        return actionList;
88      } else if ((actionList = tailMatch(currentPattern)) != null) {
89        return actionList;
90      } else if ((actionList = prefixMatch(currentPattern)) != null) {
91        return actionList;
92      } else if ((actionList = middleMatch(currentPattern)) != null) { 
93        return actionList;
94      } else {
95        return null;
96      }
97    }
98  
99    List tailMatch(Pattern currentPattern) {
100     int max = 0;
101     Pattern longestMatchingPattern = null;
102 
103     for (Pattern p : rules.keySet()) {
104 
105       if ((p.size() > 1) && p.get(0).equals(ANY)) {
106         int r = currentPattern.getTailMatchLength(p);
107         if (r > max) {
108           max = r;
109           longestMatchingPattern = p;
110         }
111       }
112     }
113 
114     if (longestMatchingPattern != null) {
115       return rules.get(longestMatchingPattern);
116     } else {
117       return null;
118     }
119   }
120 
121   List prefixMatch(Pattern currentPattern) {
122     int max = 0;
123     Pattern longestMatchingPattern = null;
124 
125     for (Pattern p : rules.keySet()) {
126       String last = p.peekLast();
127       if (ANY.equals(last)) {
128         int r = currentPattern.getPrefixMatchLength(p);
129         // to qualify the match length must equal p's size omitting the '*'
130         if ((r == p.size() - 1) && (r > max)) {
131           // System.out.println("New longest prefixMatch "+p);
132           max = r;
133           longestMatchingPattern = p;
134         }
135       }
136     }
137 
138     if (longestMatchingPattern != null) {
139       return rules.get(longestMatchingPattern);
140     } else {
141       return null;
142     }
143   }
144 
145   List middleMatch(Pattern currentPattern) {
146     
147     int max = 0;
148     Pattern longestMatchingPattern = null;
149 
150     for (Pattern p : rules.keySet()) {
151       String last = p.peekLast();
152       String first = null;
153       if(p.size() > 1) {
154         first = p.get(0);
155       }
156       if (ANY.equals(last) && ANY.equals(first)) {
157         List<String> partList = p.getCopyOfPartList();
158         if(partList.size() > 2) {
159           partList.remove(0);
160           partList.remove(partList.size()-1);
161         }
162         
163         int r = 0;
164         Pattern clone = new Pattern(partList);        
165         if(currentPattern.isContained(clone)) {
166           r = clone.size();
167         }
168         if (r > max) {
169           max = r;
170           longestMatchingPattern = p;
171         }
172       }
173     }
174 
175     if (longestMatchingPattern != null) {
176       return rules.get(longestMatchingPattern);
177     } else {
178       return null;
179     }
180   }
181   
182 
183   public String toString() {
184     final String TAB = "  ";
185 
186     StringBuilder retValue = new StringBuilder();
187 
188     retValue.append("SimpleRuleStore ( ").append("rules = ").append(this.rules)
189         .append(TAB).append(" )");
190 
191     return retValue.toString();
192   }
193 
194 }