151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project 34ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.util.logging; 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tt>Handler</tt> that buffers requests in a circular buffer in memory. 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Normally this <tt>Handler</tt> simply stores incoming <tt>LogRecords</tt> 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * into its memory buffer and discards earlier records. This buffering 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is very cheap and avoids formatting costs. On certain trigger 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * conditions, the <tt>MemoryHandler</tt> will push out its current buffer 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * contents to a target <tt>Handler</tt>, which will typically publish 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * them to the outside world. 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * There are three main models for triggering a push of the buffer: 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <ul> 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li> 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * An incoming <tt>LogRecord</tt> has a type that is greater than 434ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * a pre-defined level, the <tt>pushLevel</tt>. </li> 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li> 454ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * An external class calls the <tt>push</tt> method explicitly. </li> 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li> 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * A subclass overrides the <tt>log</tt> method and scans each incoming 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tt>LogRecord</tt> and calls <tt>push</tt> if a record matches some 494ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * desired criteria. </li> 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </ul> 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <b>Configuration:</b> 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * By default each <tt>MemoryHandler</tt> is initialized using the following 544ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <tt>LogManager</tt> configuration properties where <tt><handler-name></tt> 554ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * refers to the fully-qualified class name of the handler. 564ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * If properties are not defined 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (or have invalid values) then the specified default values are used. 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If no default value is defined then a RuntimeException is thrown. 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <ul> 604ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <li> <handler-name>.level 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specifies the level for the <tt>Handler</tt> 624ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * (defaults to <tt>Level.ALL</tt>). </li> 634ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <li> <handler-name>.filter 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specifies the name of a <tt>Filter</tt> class to use 654ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * (defaults to no <tt>Filter</tt>). </li> 664ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <li> <handler-name>.size 674ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * defines the buffer size (defaults to 1000). </li> 684ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <li> <handler-name>.push 694ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * defines the <tt>pushLevel</tt> (defaults to <tt>level.SEVERE</tt>). </li> 704ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <li> <handler-name>.target 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * specifies the name of the target <tt>Handler </tt> class. 724ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * (no default). </li> 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </ul> 744ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <p> 754ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * For example, the properties for {@code MemoryHandler} would be: 764ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <ul> 774ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <li> java.util.logging.MemoryHandler.level=INFO </li> 784ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <li> java.util.logging.MemoryHandler.formatter=java.util.logging.SimpleFormatter </li> 794ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * </ul> 804ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <p> 814ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * For a custom handler, e.g. com.foo.MyHandler, the properties would be: 824ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <ul> 834ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <li> com.foo.MyHandler.level=INFO </li> 844ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <li> com.foo.MyHandler.formatter=java.util.logging.SimpleFormatter </li> 854ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * </ul> 864ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * <p> 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.4 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class MemoryHandler extends Handler { 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final static int DEFAULT_SIZE = 1000; 924ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak private volatile Level pushLevel; 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int size; 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Handler target; 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private LogRecord buffer[]; 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int start, count; 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 984ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak // Private method to configure a MemoryHandler from LogManager 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // properties and/or default values as specified in the class 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // javadoc. 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void configure() { 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski LogManager manager = LogManager.getLogManager(); 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String cname = getClass().getName(); 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pushLevel = manager.getLevelProperty(cname +".push", Level.SEVERE); 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski size = manager.getIntProperty(cname + ".size", DEFAULT_SIZE); 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (size <= 0) { 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski size = DEFAULT_SIZE; 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski setLevel(manager.getLevelProperty(cname +".level", Level.ALL)); 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski setFilter(manager.getFilterProperty(cname +".filter", null)); 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski setFormatter(manager.getFormatterProperty(cname +".formatter", new SimpleFormatter())); 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a <tt>MemoryHandler</tt> and configure it based on 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tt>LogManager</tt> configuration properties. 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public MemoryHandler() { 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sealed = false; 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski configure(); 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sealed = true; 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 1244ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak LogManager manager = LogManager.getLogManager(); 1254ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak String handlerName = getClass().getName(); 1264ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak String targetName = manager.getProperty(handlerName+".target"); 1274ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak if (targetName == null) { 1284ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak throw new RuntimeException("The handler " + handlerName 1294ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak + " does not specify a target"); 1304ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak } 1314ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak Class<?> clz; 1324ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski try { 1344ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak clz = ClassLoader.getSystemClassLoader().loadClass(targetName); 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski target = (Handler) clz.newInstance(); 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } catch (Exception ex) { 137adc40417389a57bc7a831f55334bffcc07343eb9Piotr Jastrzebski // Android-changed: Try to load the class from the context class loader. 138adc40417389a57bc7a831f55334bffcc07343eb9Piotr Jastrzebski try { 1394ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak clz = Thread.currentThread().getContextClassLoader() 1404ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak .loadClass(targetName); 141adc40417389a57bc7a831f55334bffcc07343eb9Piotr Jastrzebski target = (Handler) clz.newInstance(); 142adc40417389a57bc7a831f55334bffcc07343eb9Piotr Jastrzebski } catch (Exception innerE) { 1434ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak throw new RuntimeException("MemoryHandler can't load handler target \"" + 1444ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak targetName + "\"" , innerE); 145adc40417389a57bc7a831f55334bffcc07343eb9Piotr Jastrzebski } 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski init(); 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Initialize. Size is a count of LogRecords. 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void init() { 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer = new LogRecord[size]; 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski start = 0; 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count = 0; 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a <tt>MemoryHandler</tt>. 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The <tt>MemoryHandler</tt> is configured based on <tt>LogManager</tt> 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * properties (or their default values) except that the given <tt>pushLevel</tt> 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * argument and buffer size argument are used. 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param target the Handler to which to publish output. 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param size the number of log records to buffer (must be greater than zero) 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param pushLevel message level to push on 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1684ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak * @throws IllegalArgumentException if {@code size is <= 0} 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public MemoryHandler(Handler target, int size, Level pushLevel) { 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (target == null || pushLevel == null) { 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NullPointerException(); 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (size <= 0) { 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IllegalArgumentException(); 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sealed = false; 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski configure(); 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sealed = true; 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.target = target; 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.pushLevel = pushLevel; 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.size = size; 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski init(); 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Store a <tt>LogRecord</tt> in an internal buffer. 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If there is a <tt>Filter</tt>, its <tt>isLoggable</tt> 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * method is called to check if the given log record is loggable. 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If not we return. Otherwise the given record is copied into 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * an internal circular buffer. Then the record's level property is 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * compared with the <tt>pushLevel</tt>. If the given level is 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * greater than or equal to the <tt>pushLevel</tt> then <tt>push</tt> 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * is called to write all buffered records to the target output 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tt>Handler</tt>. 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param record description of the log event. A null record is 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * silently ignored and is not published 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2014ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak @Override 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public synchronized void publish(LogRecord record) { 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (!isLoggable(record)) { 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return; 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int ix = (start+count)%buffer.length; 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski buffer[ix] = record; 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (count < buffer.length) { 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count++; 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski start++; 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski start %= buffer.length; 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (record.getLevel().intValue() >= pushLevel.intValue()) { 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski push(); 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Push any buffered output to the target <tt>Handler</tt>. 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The buffer is then cleared. 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public synchronized void push() { 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < count; i++) { 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int ix = (start+i)%buffer.length; 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski LogRecord record = buffer[ix]; 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski target.publish(record); 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Empty the buffer. 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski start = 0; 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski count = 0; 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Causes a flush on the target <tt>Handler</tt>. 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Note that the current contents of the <tt>MemoryHandler</tt> 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * buffer are <b>not</b> written out. That requires a "push". 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2414ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak @Override 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void flush() { 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski target.flush(); 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Close the <tt>Handler</tt> and free all associated resources. 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This will also close the target <tt>Handler</tt>. 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception SecurityException if a security manager exists and if 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the caller does not have <tt>LoggingPermission("control")</tt>. 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2534ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak @Override 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void close() throws SecurityException { 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski target.close(); 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski setLevel(Level.OFF); 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Set the <tt>pushLevel</tt>. After a <tt>LogRecord</tt> is copied 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * into our internal buffer, if its level is greater than or equal to 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the <tt>pushLevel</tt>, then <tt>push</tt> will be called. 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param newLevel the new value of the <tt>pushLevel</tt> 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @exception SecurityException if a security manager exists and if 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the caller does not have <tt>LoggingPermission("control")</tt>. 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2684ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak public synchronized void setPushLevel(Level newLevel) throws SecurityException { 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (newLevel == null) { 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NullPointerException(); 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski checkPermission(); 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski pushLevel = newLevel; 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Get the <tt>pushLevel</tt>. 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return the value of the <tt>pushLevel</tt> 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2814ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak public Level getPushLevel() { 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return pushLevel; 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Check if this <tt>Handler</tt> would actually log a given 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <tt>LogRecord</tt> into its internal buffer. 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This method checks if the <tt>LogRecord</tt> has an appropriate level and 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * whether it satisfies any <tt>Filter</tt>. However it does <b>not</b> 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * check whether the <tt>LogRecord</tt> would result in a "push" of the 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * buffer contents. It will return false if the <tt>LogRecord</tt> is null. 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p> 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @param record a <tt>LogRecord</tt> 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @return true if the <tt>LogRecord</tt> would be logged. 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2984ff539dbc5a809ef3eacbe2d9f2b97f640b7e9cfPrzemyslaw Szczepaniak @Override 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isLoggable(LogRecord record) { 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return super.isLoggable(record); 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 303