8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.util.logging;
27
28 /**
29 * <tt>Handler</tt> that buffers requests in a circular buffer in memory.
30 * <p>
31 * Normally this <tt>Handler</tt> simply stores incoming <tt>LogRecords</tt>
32 * into its memory buffer and discards earlier records. This buffering
33 * is very cheap and avoids formatting costs. On certain trigger
34 * conditions, the <tt>MemoryHandler</tt> will push out its current buffer
35 * contents to a target <tt>Handler</tt>, which will typically publish
36 * them to the outside world.
37 * <p>
38 * There are three main models for triggering a push of the buffer:
39 * <ul>
40 * <li>
41 * An incoming <tt>LogRecord</tt> has a type that is greater than
42 * a pre-defined level, the <tt>pushLevel</tt>. </li>
43 * <li>
44 * An external class calls the <tt>push</tt> method explicitly. </li>
45 * <li>
46 * A subclass overrides the <tt>log</tt> method and scans each incoming
47 * <tt>LogRecord</tt> and calls <tt>push</tt> if a record matches some
77 * <li> java.util.logging.MemoryHandler.formatter=java.util.logging.SimpleFormatter </li>
78 * </ul>
79 * <p>
80 * For a custom handler, e.g. com.foo.MyHandler, the properties would be:
81 * <ul>
82 * <li> com.foo.MyHandler.level=INFO </li>
83 * <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li>
84 * </ul>
85 * <p>
86 * @since 1.4
87 */
88
89 public class MemoryHandler extends Handler {
90 private final static int DEFAULT_SIZE = 1000;
91 private volatile Level pushLevel;
92 private int size;
93 private Handler target;
94 private LogRecord buffer[];
95 int start, count;
96
97 // Private method to configure a MemoryHandler from LogManager
98 // properties and/or default values as specified in the class
99 // javadoc.
100 private void configure() {
101 LogManager manager = LogManager.getLogManager();
102 String cname = getClass().getName();
103
104 pushLevel = manager.getLevelProperty(cname +".push", Level.SEVERE);
105 size = manager.getIntProperty(cname + ".size", DEFAULT_SIZE);
106 if (size <= 0) {
107 size = DEFAULT_SIZE;
108 }
109 setLevel(manager.getLevelProperty(cname +".level", Level.ALL));
110 setFilter(manager.getFilterProperty(cname +".filter", null));
111 setFormatter(manager.getFormatterProperty(cname +".formatter", new SimpleFormatter()));
112 }
113
114 /**
115 * Create a <tt>MemoryHandler</tt> and configure it based on
116 * <tt>LogManager</tt> configuration properties.
117 */
118 public MemoryHandler() {
119 sealed = false;
120 configure();
121 sealed = true;
122
123 LogManager manager = LogManager.getLogManager();
124 String handlerName = getClass().getName();
125 String targetName = manager.getProperty(handlerName+".target");
126 if (targetName == null) {
127 throw new RuntimeException("The handler " + handlerName
128 + " does not specify a target");
129 }
130 Class<?> clz;
131 try {
132 clz = ClassLoader.getSystemClassLoader().loadClass(targetName);
133 target = (Handler) clz.newInstance();
134 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
135 throw new RuntimeException("MemoryHandler can't load handler target \"" + targetName + "\"" , e);
136 }
137 init();
138 }
139
140 // Initialize. Size is a count of LogRecords.
141 private void init() {
147 /**
148 * Create a <tt>MemoryHandler</tt>.
149 * <p>
150 * The <tt>MemoryHandler</tt> is configured based on <tt>LogManager</tt>
151 * properties (or their default values) except that the given <tt>pushLevel</tt>
152 * argument and buffer size argument are used.
153 *
154 * @param target the Handler to which to publish output.
155 * @param size the number of log records to buffer (must be greater than zero)
156 * @param pushLevel message level to push on
157 *
158 * @throws IllegalArgumentException if {@code size is <= 0}
159 */
160 public MemoryHandler(Handler target, int size, Level pushLevel) {
161 if (target == null || pushLevel == null) {
162 throw new NullPointerException();
163 }
164 if (size <= 0) {
165 throw new IllegalArgumentException();
166 }
167 sealed = false;
168 configure();
169 sealed = true;
170 this.target = target;
171 this.pushLevel = pushLevel;
172 this.size = size;
173 init();
174 }
175
176 /**
177 * Store a <tt>LogRecord</tt> in an internal buffer.
178 * <p>
179 * If there is a <tt>Filter</tt>, its <tt>isLoggable</tt>
180 * method is called to check if the given log record is loggable.
181 * If not we return. Otherwise the given record is copied into
182 * an internal circular buffer. Then the record's level property is
183 * compared with the <tt>pushLevel</tt>. If the given level is
184 * greater than or equal to the <tt>pushLevel</tt> then <tt>push</tt>
185 * is called to write all buffered records to the target output
186 * <tt>Handler</tt>.
187 *
188 * @param record description of the log event. A null record is
189 * silently ignored and is not published
|
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package java.util.logging;
27
28 import java.security.AccessController;
29 import java.security.PrivilegedAction;
30
31 /**
32 * <tt>Handler</tt> that buffers requests in a circular buffer in memory.
33 * <p>
34 * Normally this <tt>Handler</tt> simply stores incoming <tt>LogRecords</tt>
35 * into its memory buffer and discards earlier records. This buffering
36 * is very cheap and avoids formatting costs. On certain trigger
37 * conditions, the <tt>MemoryHandler</tt> will push out its current buffer
38 * contents to a target <tt>Handler</tt>, which will typically publish
39 * them to the outside world.
40 * <p>
41 * There are three main models for triggering a push of the buffer:
42 * <ul>
43 * <li>
44 * An incoming <tt>LogRecord</tt> has a type that is greater than
45 * a pre-defined level, the <tt>pushLevel</tt>. </li>
46 * <li>
47 * An external class calls the <tt>push</tt> method explicitly. </li>
48 * <li>
49 * A subclass overrides the <tt>log</tt> method and scans each incoming
50 * <tt>LogRecord</tt> and calls <tt>push</tt> if a record matches some
80 * <li> java.util.logging.MemoryHandler.formatter=java.util.logging.SimpleFormatter </li>
81 * </ul>
82 * <p>
83 * For a custom handler, e.g. com.foo.MyHandler, the properties would be:
84 * <ul>
85 * <li> com.foo.MyHandler.level=INFO </li>
86 * <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li>
87 * </ul>
88 * <p>
89 * @since 1.4
90 */
91
92 public class MemoryHandler extends Handler {
93 private final static int DEFAULT_SIZE = 1000;
94 private volatile Level pushLevel;
95 private int size;
96 private Handler target;
97 private LogRecord buffer[];
98 int start, count;
99
100 // Private PrivilegedAction to configure a MemoryHandler from LogManager
101 // properties and/or default values as specified in the class
102 // javadoc.
103 private class ConfigureAction implements PrivilegedAction<Void> {
104 @Override
105 public Void run() {
106 LogManager manager = LogManager.getLogManager();
107 String cname = MemoryHandler.this.getClass().getName();
108
109 pushLevel = manager.getLevelProperty(cname +".push", Level.SEVERE);
110 size = manager.getIntProperty(cname + ".size", DEFAULT_SIZE);
111 if (size <= 0) {
112 size = DEFAULT_SIZE;
113 }
114 setLevel(manager.getLevelProperty(cname +".level", Level.ALL));
115 setFilter(manager.getFilterProperty(cname +".filter", null));
116 setFormatter(manager.getFormatterProperty(cname +".formatter", new SimpleFormatter()));
117 return null;
118 }
119 }
120
121 /**
122 * Create a <tt>MemoryHandler</tt> and configure it based on
123 * <tt>LogManager</tt> configuration properties.
124 */
125 public MemoryHandler() {
126 AccessController.doPrivileged(new ConfigureAction(), null, LogManager.controlPermission);
127
128 LogManager manager = LogManager.getLogManager();
129 String handlerName = getClass().getName();
130 String targetName = manager.getProperty(handlerName+".target");
131 if (targetName == null) {
132 throw new RuntimeException("The handler " + handlerName
133 + " does not specify a target");
134 }
135 Class<?> clz;
136 try {
137 clz = ClassLoader.getSystemClassLoader().loadClass(targetName);
138 target = (Handler) clz.newInstance();
139 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
140 throw new RuntimeException("MemoryHandler can't load handler target \"" + targetName + "\"" , e);
141 }
142 init();
143 }
144
145 // Initialize. Size is a count of LogRecords.
146 private void init() {
152 /**
153 * Create a <tt>MemoryHandler</tt>.
154 * <p>
155 * The <tt>MemoryHandler</tt> is configured based on <tt>LogManager</tt>
156 * properties (or their default values) except that the given <tt>pushLevel</tt>
157 * argument and buffer size argument are used.
158 *
159 * @param target the Handler to which to publish output.
160 * @param size the number of log records to buffer (must be greater than zero)
161 * @param pushLevel message level to push on
162 *
163 * @throws IllegalArgumentException if {@code size is <= 0}
164 */
165 public MemoryHandler(Handler target, int size, Level pushLevel) {
166 if (target == null || pushLevel == null) {
167 throw new NullPointerException();
168 }
169 if (size <= 0) {
170 throw new IllegalArgumentException();
171 }
172 AccessController.doPrivileged(new ConfigureAction(), null, LogManager.controlPermission);
173 this.target = target;
174 this.pushLevel = pushLevel;
175 this.size = size;
176 init();
177 }
178
179 /**
180 * Store a <tt>LogRecord</tt> in an internal buffer.
181 * <p>
182 * If there is a <tt>Filter</tt>, its <tt>isLoggable</tt>
183 * method is called to check if the given log record is loggable.
184 * If not we return. Otherwise the given record is copied into
185 * an internal circular buffer. Then the record's level property is
186 * compared with the <tt>pushLevel</tt>. If the given level is
187 * greater than or equal to the <tt>pushLevel</tt> then <tt>push</tt>
188 * is called to write all buffered records to the target output
189 * <tt>Handler</tt>.
190 *
191 * @param record description of the log event. A null record is
192 * silently ignored and is not published
|