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 }