KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > protomatter > syslog > PerClassPolicy


1 package com.protomatter.syslog;
2
3 /**
4  * {{{ The Protomatter Software License, Version 1.0
5  * derived from The Apache Software License, Version 1.1
6  *
7  * Copyright (c) 1998-2002 Nate Sammons. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed for the
24  * Protomatter Software Project
25  * (http://protomatter.sourceforge.net/)."
26  * Alternately, this acknowledgment may appear in the software itself,
27  * if and wherever such third-party acknowledgments normally appear.
28  *
29  * 4. The names "Protomatter" and "Protomatter Software Project" must
30  * not be used to endorse or promote products derived from this
31  * software without prior written permission. For written
32  * permission, please contact support@protomatter.com.
33  *
34  * 5. Products derived from this software may not be called "Protomatter",
35  * nor may "Protomatter" appear in their name, without prior written
36  * permission of the Protomatter Software Project
37  * (support@protomatter.com).
38  *
39  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
40  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42  * DISCLAIMED. IN NO EVENT SHALL THE PROTOMATTER SOFTWARE PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
46  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE. }}}
51  */

52
53 import java.util.*;
54 import java.text.MessageFormat JavaDoc;
55 import org.apache.oro.text.regex.*;
56
57 /**
58  * A policy that can make decision on a per-class basis.
59  * It maintains a default log mask and channel list
60  * itself, but also has a list of "policy groups" that
61  * each have a log mask and channel list of their own
62  * in addition to a list of class names that their
63  * mask and channel list applies to. If a message
64  * coming from a class in one of those lists matches
65  * the mask and channel list, the message is logged. If
66  * not, but the message severity and channel match the
67  * default mask and channel list, it is also logged.
68  * Otherwise, the message is ignored.<P>
69  *
70  * This policy can be used to effectively say that
71  * messages from classes <TT>A</TT> and <TT>B</TT> should be logged
72  * if their severity is <TT>WARNING</TT> or greater, and that
73  * messages from classes <TT>C</TT> and <TT>D</TT> should be logged
74  * if their severity is <TT>INFO</TT> or greater and on a certain
75  * set of channels and that if all else fails, messages at
76  * or above the <TT>INFO</TT> level will be logged. It's
77  * very configurable.<P>
78  *
79  * Each "class name" is actually a Perl5 regular expression,
80  * so you can match things like "<tt>com.protomatter.syslog.*</tt>"
81  * and other stuff. This functionality uses the
82  * <a HREF="http://jakarta.apache.org/oro/index.html">ORO regular expression package</a>,
83  * now part of the
84  * <a HREF="http://jakarta.apache.org">Apache Jakarta</a> project.<P>
85  *
86  * @see com.protomatter.syslog.xml.PerClassPolicy_Helper XML configuration class
87  */

88 public class PerClassPolicy
89 extends SimpleLogPolicy
90 {
91   private List groupList = new ArrayList();
92   private static Perl5Compiler patternCompiler = new Perl5Compiler();
93
94   /**
95    * Default constructor.
96    */

97   public PerClassPolicy()
98   {
99     super();
100   }
101
102   /**
103    * Get the list of policy groups.
104    */

105   public List getGroupList()
106   {
107     return this.groupList;
108   }
109   /**
110    * Set the list of policy groups.
111    */

112   public void setGroupList(List list)
113   {
114     this.groupList = list;
115   }
116
117   /**
118    * Decide if the message should be logged. Each
119    * policy group is asked if it should be logged,
120    * and if none of them say yes, then we defer
121    * to our superclass. Each policy group maintains
122    * a channel list, log mask and a set of class names
123    * -- to decide if it should log the message,
124    * the policy group first checks the message's
125    * severity and channel against its log mask
126    * and channel list. If it passes this test,
127    * the policy group checks to see if the
128    * class name of the logger is in it's list.
129    */

130   public boolean shouldLog(SyslogMessage message)
131   {
132     // if any of the policy groups say yes, let it through
133
if (message.loggerClassname != null)
134     {
135       int size = groupList.size();
136       PolicyGroup group = null;
137       for (int i=0; i<size; i++)
138       {
139         group = (PolicyGroup)groupList.get(i);
140         if (group.shouldLog(message))
141           return true;
142       }
143     }
144
145     // otherwise, defer to the superclass, which
146
// knows about channels and log masks.
147
return super.shouldLog(message);
148   }
149
150   /**
151    * Get the list of policy groups.
152    */

153   public Iterator getPolicyGroups()
154   {
155     return this.groupList.iterator();
156   }
157
158   /**
159    * Add a policy group to our list.
160    */

161   public void addPolicyGroup(PolicyGroup group)
162   {
163     this.groupList.add(group);
164   }
165
166   /**
167    * Remove a policy group from our list.
168    */

169   public void removePolicyGroup(PolicyGroup group)
170   {
171     this.groupList.remove(group);
172   }
173
174   /**
175    * A policy within a policy -- this is exactly like
176    * the SimpleLogPolicy except that it also checks to
177    * see if the class issuing the log message is
178    * in some set.
179    *
180    * @see PerClassPolicy
181    */

182   public static class PolicyGroup
183   extends SimpleLogPolicy
184   {
185     private Set patternSet = new HashSet();
186     private Set classNameSet = new HashSet();
187     private Pattern pattern = null;
188     private Object JavaDoc lock = new Object JavaDoc();
189     private Perl5Matcher patternMatcher = new Perl5Matcher();
190
191     /**
192      * Default constructor.
193      */

194     public PolicyGroup()
195     {
196       super();
197     }
198
199     /**
200      * Get the set of class names (exact matches) we're listing to.
201      */

202     public Iterator getClassSet()
203     {
204       return this.classNameSet.iterator();
205     }
206
207     /**
208      * Clear out the set of class names
209      * we're listing to.
210      */

211     public void clearClassSet()
212     {
213       this.classNameSet = new HashSet();
214     }
215
216     /**
217      * Add a classname to the set of class names
218      * we're listening to.
219      */

220     public void addClass(String JavaDoc classname)
221     {
222       this.classNameSet.add(classname);
223     }
224
225     /**
226      * Remove a class name from the set of
227      * class names we're listening to.
228      */

229     public void removeClass(String JavaDoc classname)
230     {
231       this.classNameSet.remove(classname);
232     }
233
234     /**
235      * Get the set of class patterns we're listing to.
236      */

237     public Iterator getPatternSet()
238     {
239       return this.patternSet.iterator();
240     }
241
242     /**
243      * Clear out the set of class name patterns
244      * we're listing to.
245      */

246     public void clearPatternSet()
247     {
248       this.patternSet = new HashSet();
249       this.pattern = null;
250     }
251
252     /**
253      * Add a classname to the set of class name
254      * patterns we're listening to.
255      */

256     public void addClassPattern(String JavaDoc classname)
257     {
258       this.patternSet.add(classname);
259       generatePattern();
260     }
261
262     /**
263      * Remove a class name pattern from the set of
264      * class name patterns we're listening to.
265      */

266     public void removeClassPattern(String JavaDoc classname)
267     {
268       this.patternSet.remove(classname);
269       generatePattern();
270     }
271
272     /**
273      * Recompile the pattern each time something
274      * about the set of patterns changes.
275      */

276     private void generatePattern()
277     throws IllegalArgumentException JavaDoc
278     {
279       StringBuffer JavaDoc thePattern = new StringBuffer JavaDoc();
280       try
281       {
282         Iterator patterns = getPatternSet();
283         while (patterns.hasNext())
284         {
285           thePattern.append(patterns.next());
286           if (patterns.hasNext())
287             thePattern.append("|");
288         }
289         pattern = patternCompiler.compile(thePattern.toString());
290       }
291       catch (MalformedPatternException x)
292       {
293         throw new IllegalArgumentException JavaDoc(
294           MessageFormat.format(Syslog.getResources().getString(MessageConstants.INVALID_PATTERN_MESSAGE),
295           new Object JavaDoc[] { thePattern }));
296       }
297     }
298
299     /**
300      * Determine if the given message should be
301      * logged. The message severity and channel
302      * are first checked by our superclass, then
303      * we see if the logger class name is in our
304      * set.
305      */

306     public boolean shouldLog(SyslogMessage m)
307     {
308       // passes the channel/level test.
309
if (super.shouldLog(m))
310       {
311         // exact matches...
312
if (classNameSet.contains(m.loggerClassname))
313         {
314           return true;
315         }
316         else if (pattern != null) // pattern matches
317
{
318           synchronized (lock)
319           {
320             if (patternMatcher.contains(m.loggerClassname, pattern))
321             {
322               return true;
323             }
324           }
325         }
326       }
327
328       // if it's not in our list, we don't care about it.
329
return false;
330     }
331   }
332 }
333
Popular Tags