KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > logging > MemoryHandler


1 /*
2  * @(#)MemoryHandler.java 1.24 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.util.logging;
9
10 /**
11  * <tt>Handler</tt> that buffers requests in a circular buffer in memory.
12  * <p>
13  * Normally this <tt>Handler</tt> simply stores incoming <tt>LogRecords</tt>
14  * into its memory buffer and discards earlier records. This buffering
15  * is very cheap and avoids formatting costs. On certain trigger
16  * conditions, the <tt>MemoryHandler</tt> will push out its current buffer
17  * contents to a target <tt>Handler</tt>, which will typically publish
18  * them to the outside world.
19  * <p>
20  * There are three main models for triggering a push of the buffer:
21  * <ul>
22  * <li>
23  * An incoming <tt>LogRecord</tt> has a type that is greater than
24  * a pre-defined level, the <tt>pushLevel</tt>.
25  * <li>
26  * An external class calls the <tt>push</tt> method explicitly.
27  * <li>
28  * A subclass overrides the <tt>log</tt> method and scans each incoming
29  * <tt>LogRecord</tt> and calls <tt>push</tt> if a record matches some
30  * desired criteria.
31  * </ul>
32  * <p>
33  * <b>Configuration:</b>
34  * By default each <tt>MemoryHandler</tt> is initialized using the following
35  * LogManager configuration properties. If properties are not defined
36  * (or have invalid values) then the specified default values are used.
37  * If no default value is defined then a RuntimeException is thrown.
38  * <ul>
39  * <li> java.util.logging.MemoryHandler.level
40  * specifies the level for the <tt>Handler</tt>
41  * (defaults to <tt>Level.ALL</tt>).
42  * <li> java.util.logging.MemoryHandler.filter
43  * specifies the name of a <tt>Filter</tt> class to use
44  * (defaults to no <tt>Filter</tt>).
45  * <li> java.util.logging.MemoryHandler.size
46  * defines the buffer size (defaults to 1000).
47  * <li> java.util.logging.MemoryHandler.push
48  * defines the <tt>pushLevel</tt> (defaults to <tt>level.SEVERE</tt>).
49  * <li> java.util.logging.MemoryHandler.target
50  * specifies the name of the target <tt>Handler </tt> class.
51  * (no default).
52  * </ul>
53  *
54  * @version 1.24, 12/19/03
55  * @since 1.4
56  */

57
58 public class MemoryHandler extends Handler JavaDoc {
59     private final static int DEFAULT_SIZE = 1000;
60     private Level JavaDoc pushLevel;
61     private int size;
62     private Handler JavaDoc target;
63     private LogRecord JavaDoc buffer[];
64     int start, count;
65
66     // Private method to configure a ConsoleHandler from LogManager
67
// properties and/or default values as specified in the class
68
// javadoc.
69
private void configure() {
70         LogManager JavaDoc manager = LogManager.getLogManager();
71     String JavaDoc cname = getClass().getName();
72
73     pushLevel = manager.getLevelProperty(cname +".push", Level.SEVERE);
74     size = manager.getIntProperty(cname + ".size", DEFAULT_SIZE);
75     if (size <= 0) {
76         size = DEFAULT_SIZE;
77     }
78     setLevel(manager.getLevelProperty(cname +".level", Level.ALL));
79     setFilter(manager.getFilterProperty(cname +".filter", null));
80     setFormatter(manager.getFormatterProperty(cname +".formatter", new SimpleFormatter JavaDoc()));
81     }
82
83     /**
84      * Create a <tt>MemoryHandler</tt> and configure it based on
85      * <tt>LogManager</tt> configuration properties.
86      */

87     public MemoryHandler() {
88     sealed = false;
89     configure();
90     sealed = true;
91
92     String JavaDoc name = "???";
93     try {
94             LogManager JavaDoc manager = LogManager.getLogManager();
95         name = manager.getProperty("java.util.logging.MemoryHandler.target");
96         Class JavaDoc clz = ClassLoader.getSystemClassLoader().loadClass(name);
97         target = (Handler JavaDoc) clz.newInstance();
98     } catch (Exception JavaDoc ex) {
99         throw new RuntimeException JavaDoc("MemoryHandler can't load handler \"" + name + "\"" , ex);
100     }
101     init();
102     }
103
104     // Initialize. Size is a count of LogRecords.
105
private void init() {
106     buffer = new LogRecord JavaDoc[size];
107     start = 0;
108     count = 0;
109     }
110
111     /**
112      * Create a <tt>MemoryHandler</tt>.
113      * <p>
114      * The <tt>MemoryHandler</tt> is configured based on <tt>LogManager</tt>
115      * properties (or their default values) except that the given <tt>pushLevel</tt>
116      * argument and buffer size argument are used.
117      *
118      * @param target the Handler to which to publish output.
119      * @param size the number of log records to buffer (must be greater than zero)
120      * @param pushLevel message level to push on
121      *
122      * @throws IllegalArgumentException is size is <= 0
123      */

124     public MemoryHandler(Handler JavaDoc target, int size, Level JavaDoc pushLevel) {
125     if (target == null || pushLevel == null) {
126         throw new NullPointerException JavaDoc();
127     }
128     if (size <= 0) {
129         throw new IllegalArgumentException JavaDoc();
130     }
131     sealed = false;
132     configure();
133     sealed = true;
134     this.target = target;
135     this.pushLevel = pushLevel;
136     this.size = size;
137     init();
138     }
139
140     /**
141      * Store a <tt>LogRecord</tt> in an internal buffer.
142      * <p>
143      * If there is a <tt>Filter</tt>, its <tt>isLoggable</tt>
144      * method is called to check if the given log record is loggable.
145      * If not we return. Otherwise the given record is copied into
146      * an internal circular buffer. Then the record's level property is
147      * compared with the <tt>pushLevel</tt>. If the given level is
148      * greater than or equal to the <tt>pushLevel</tt> then <tt>push</tt>
149      * is called to write all buffered records to the target output
150      * <tt>Handler</tt>.
151      *
152      * @param record description of the log event. A null record is
153      * silently ignored and is not published
154      */

155     public synchronized void publish(LogRecord JavaDoc record) {
156     if (!isLoggable(record)) {
157         return;
158     }
159     int ix = (start+count)%buffer.length;
160     buffer[ix] = record;
161     if (count < buffer.length) {
162         count++;
163     } else {
164         start++;
165     }
166     if (record.getLevel().intValue() >= pushLevel.intValue()) {
167         push();
168     }
169     }
170
171     /**
172      * Push any buffered output to the target <tt>Handler</tt>.
173      * <p>
174      * The buffer is then cleared.
175      */

176     public synchronized void push() {
177     for (int i = 0; i < count; i++) {
178         int ix = (start+i)%buffer.length;
179         LogRecord JavaDoc record = buffer[ix];
180         target.publish(record);
181     }
182     // Empty the buffer.
183
start = 0;
184     count = 0;
185     }
186
187     /**
188      * Causes a flush on the target <tt>Handler</tt>.
189      * <p>
190      * Note that the current contents of the <tt>MemoryHandler</tt>
191      * buffer are <b>not</b> written out. That requires a "push".
192      */

193     public void flush() {
194     target.flush();
195     }
196
197     /**
198      * Close the <tt>Handler</tt> and free all associated resources.
199      * This will also close the target <tt>Handler</tt>.
200      *
201      * @exception SecurityException if a security manager exists and if
202      * the caller does not have <tt>LoggingPermission("control")</tt>.
203      */

204     public void close() throws SecurityException JavaDoc {
205     target.close();
206     setLevel(Level.OFF);
207     }
208
209     /**
210      * Set the <tt>pushLevel</tt>. After a <tt>LogRecord</tt> is copied
211      * into our internal buffer, if its level is greater than or equal to
212      * the <tt>pushLevel</tt>, then <tt>push</tt> will be called.
213      *
214      * @param newLevel the new value of the <tt>pushLevel</tt>
215      * @exception SecurityException if a security manager exists and if
216      * the caller does not have <tt>LoggingPermission("control")</tt>.
217      */

218     public void setPushLevel(Level JavaDoc newLevel) throws SecurityException JavaDoc {
219     if (newLevel == null) {
220         throw new NullPointerException JavaDoc();
221     }
222     LogManager JavaDoc manager = LogManager.getLogManager();
223         checkAccess();
224     pushLevel = newLevel;
225     }
226
227     /**
228      * Get the <tt>pushLevel</tt>.
229      *
230      * @return the value of the <tt>pushLevel</tt>
231      */

232     public synchronized Level JavaDoc getPushLevel() {
233     return pushLevel;
234     }
235
236     /**
237      * Check if this <tt>Handler</tt> would actually log a given
238      * <tt>LogRecord</tt> into its internal buffer.
239      * <p>
240      * This method checks if the <tt>LogRecord</tt> has an appropriate level and
241      * whether it satisfies any <tt>Filter</tt>. However it does <b>not</b>
242      * check whether the <tt>LogRecord</tt> would result in a "push" of the
243      * buffer contents. It will return false if the <tt>LogRecord</tt> is Null.
244      * <p>
245      * @param record a <tt>LogRecord</tt>
246      * @return true if the <tt>LogRecord</tt> would be logged.
247      *
248      */

249     public boolean isLoggable(LogRecord JavaDoc record) {
250     return super.isLoggable(record);
251     }
252 }
253
Popular Tags