API Overview API Index Package Overview Direct link to this page
JDK 1.6
  java.util.logging. MemoryHandler View Javadoc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253

/*
 * @(#)MemoryHandler.java	1.26 05/11/17
 *
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package java.util.logging;

/**
 * <tt>Handler</tt> that buffers requests in a circular buffer in memory.
 * <p>
 * Normally this <tt>Handler</tt> simply stores incoming <tt>LogRecords</tt>
 * into its memory buffer and discards earlier records.  This buffering
 * is very cheap and avoids formatting costs.  On certain trigger
 * conditions, the <tt>MemoryHandler</tt> will push out its current buffer
 * contents to a target <tt>Handler</tt>, which will typically publish
 * them to the outside world.
 * <p>
 * There are three main models for triggering a push of the buffer:
 * <ul>
 * <li>
 * An incoming <tt>LogRecord</tt> has a type that is greater than
 * a pre-defined level, the <tt>pushLevel</tt>.
 * <li>
 * An external class calls the <tt>push</tt> method explicitly. 
 * <li>
 * A subclass overrides the <tt>log</tt> method and scans each incoming
 * <tt>LogRecord</tt> and calls <tt>push</tt> if a record matches some
 * desired criteria.
 * </ul>
 * <p>
 * <b>Configuration:</b>
 * By default each <tt>MemoryHandler</tt> is initialized using the following
 * LogManager configuration properties.  If properties are not defined
 * (or have invalid values) then the specified default values are used.
 * If no default value is defined then a RuntimeException is thrown.
 * <ul>
 * <li>   java.util.logging.MemoryHandler.level 
 *	  specifies the level for the <tt>Handler</tt>
 *        (defaults to <tt>Level.ALL</tt>).
 * <li>   java.util.logging.MemoryHandler.filter
 *	  specifies the name of a <tt>Filter</tt> class to use
 *	  (defaults to no <tt>Filter</tt>).
 * <li>   java.util.logging.MemoryHandler.size 
 *	  defines the buffer size (defaults to 1000).
 * <li>   java.util.logging.MemoryHandler.push
 *	  defines the <tt>pushLevel</tt> (defaults to <tt>level.SEVERE</tt>). 
 * <li>   java.util.logging.MemoryHandler.target
 *	  specifies the name of the target <tt>Handler </tt> class.
 *	  (no default).
 * </ul>
 *
 * @version 1.26, 11/17/05
 * @since 1.4
 */

public class MemoryHandler extends Handler {
    private final static int DEFAULT_SIZE = 1000;
    private Level pushLevel;
    private int size;
    private Handler target;
    private LogRecord buffer[];
    int start, count;

    // Private method to configure a ConsoleHandler from LogManager
    // properties and/or default values as specified in the class
    // javadoc.
    private void configure() {
        LogManager manager = LogManager.getLogManager();
	String cname = getClass().getName();

	pushLevel = manager.getLevelProperty(cname +".push", Level.SEVERE);
	size = manager.getIntProperty(cname + ".size", DEFAULT_SIZE);
	if (size <= 0) {
	    size = DEFAULT_SIZE;
	}
	setLevel(manager.getLevelProperty(cname +".level", Level.ALL));
	setFilter(manager.getFilterProperty(cname +".filter", null));
	setFormatter(manager.getFormatterProperty(cname +".formatter", new SimpleFormatter()));
    }

    /**
     * Create a <tt>MemoryHandler</tt> and configure it based on
     * <tt>LogManager</tt> configuration properties.
     */
    public MemoryHandler() {
	sealed = false;
	configure();
	sealed = true;

	String name = "???";
	try {
            LogManager manager = LogManager.getLogManager();
	    name = manager.getProperty("java.util.logging.MemoryHandler.target");
	    Class clz = ClassLoader.getSystemClassLoader().loadClass(name);
	    target = (Handler) clz.newInstance();
	} catch (Exception ex) {
	    throw new RuntimeException("MemoryHandler can't load handler \"" + name + "\"" , ex);
	}
	init();
    }

    // Initialize.  Size is a count of LogRecords.
    private void init() {
	buffer = new LogRecord[size];
	start = 0;
	count = 0;
    }

    /**
     * Create a <tt>MemoryHandler</tt>.
     * <p>
     * The <tt>MemoryHandler</tt> is configured based on <tt>LogManager</tt>
     * properties (or their default values) except that the given <tt>pushLevel</tt>
     * argument and buffer size argument are used.
     *     
     * @param target  the Handler to which to publish output.
     * @param size    the number of log records to buffer (must be greater than zero)
     * @param pushLevel  message level to push on
     *
     * @throws IllegalArgumentException is size is <= 0
     */
    public MemoryHandler(Handler target, int size, Level pushLevel) {
	if (target == null || pushLevel == null) {
	    throw new NullPointerException();
	}
	if (size <= 0) {
	    throw new IllegalArgumentException();
	}
	sealed = false;
	configure();
	sealed = true;
	this.target = target;
	this.pushLevel = pushLevel;
	this.size = size;
	init();
    }

    /**
     * Store a <tt>LogRecord</tt> in an internal buffer.
     * <p>
     * If there is a <tt>Filter</tt>, its <tt>isLoggable</tt>
     * method is called to check if the given log record is loggable.
     * If not we return.  Otherwise the given record is copied into
     * an internal circular buffer.  Then the record's level property is
     * compared with the <tt>pushLevel</tt>. If the given level is
     * greater than or equal to the <tt>pushLevel</tt> then <tt>push</tt>
     * is called to write all buffered records to the target output
     * <tt>Handler</tt>.
     * 
     * @param  record  description of the log event. A null record is
     *                 silently ignored and is not published
     */
    public synchronized void publish(LogRecord record) {
	if (!isLoggable(record)) {
	    return;
	}
	int ix = (start+count)%buffer.length;
	buffer[ix] = record;
	if (count < buffer.length) {
	    count++;
	} else {
	    start++;
	    start %= buffer.length;
	}
	if (record.getLevel().intValue() >= pushLevel.intValue()) {
	    push();
	}
    }

    /**
     * Push any buffered output to the target <tt>Handler</tt>.
     * <p>
     * The buffer is then cleared.
     */
    public synchronized void push() {
	for (int i = 0; i < count; i++) {
	    int ix = (start+i)%buffer.length;
	    LogRecord record = buffer[ix];
	    target.publish(record);
	}
	// Empty the buffer.
	start = 0;
	count = 0;
    }

    /**
     * Causes a flush on the target <tt>Handler</tt>.
     * <p>
     * Note that the current contents of the <tt>MemoryHandler</tt>
     * buffer are <b>not</b> written out.  That requires a "push".
     */
    public void flush() {
	target.flush();
    }

    /**
     * Close the <tt>Handler</tt> and free all associated resources.
     * This will also close the target <tt>Handler</tt>.
     *
     * @exception  SecurityException  if a security manager exists and if
     *             the caller does not have <tt>LoggingPermission("control")</tt>.
     */
    public void close() throws SecurityException {
	target.close();
	setLevel(Level.OFF);
    }

    /** 
     * Set the <tt>pushLevel</tt>.  After a <tt>LogRecord</tt> is copied 
     * into our internal buffer, if its level is greater than or equal to
     * the <tt>pushLevel</tt>, then <tt>push</tt> will be called.
     *
     * @param newLevel the new value of the <tt>pushLevel</tt>
     * @exception  SecurityException  if a security manager exists and if
     *             the caller does not have <tt>LoggingPermission("control")</tt>.
     */
    public void setPushLevel(Level newLevel) throws SecurityException {
	if (newLevel == null) {
	    throw new NullPointerException();
	}
	LogManager manager = LogManager.getLogManager();
        checkAccess();
	pushLevel = newLevel;
    }

    /** 
     * Get the <tt>pushLevel</tt>.
     *
     * @return the value of the <tt>pushLevel</tt>
     */
    public synchronized Level getPushLevel() {
	return pushLevel;
    }

    /**
     * Check if this <tt>Handler</tt> would actually log a given 
     * <tt>LogRecord</tt> into its internal buffer.
     * <p>
     * This method checks if the <tt>LogRecord</tt> has an appropriate level and 
     * whether it satisfies any <tt>Filter</tt>.  However it does <b>not</b>
     * check whether the <tt>LogRecord</tt> would result in a "push" of the
     * buffer contents. It will return false if the <tt>LogRecord</tt> is Null.
     * <p>
     * @param record  a <tt>LogRecord</tt>
     * @return true if the <tt>LogRecord</tt> would be logged.
     *
     */
    public boolean isLoggable(LogRecord record) {
	return super.isLoggable(record);
    }
}

Generated By: JavaOnTracks Doclet 0.1.4     ©Thibaut Colar