001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.util.logging;
019:
020: import java.io.UnsupportedEncodingException;
021: import java.nio.charset.Charset;
022: import java.security.AccessController;
023: import java.security.PrivilegedExceptionAction;
024:
025: import org.apache.harmony.logging.internal.nls.Messages;
026:
027: /**
028: * A <code>Handler</code> object accepts a logging request and exports the
029: * desired messages to a target, for example, a file, the console, etc. It can
030: * be disabled by setting its logging level to <code>Level.OFF</code>.
031: */
032: public abstract class Handler {
033:
034: private static final Level DEFAULT_LEVEL = Level.ALL;
035:
036: // the error manager to report errors during logging
037: private ErrorManager errorMan;
038:
039: // the character encoding used by this handler
040: private String encoding;
041:
042: // the logging level
043: private Level level;
044:
045: // the formatter used to export messages
046: private Formatter formatter;
047:
048: // the filter used to filter undesired messages
049: private Filter filter;
050:
051: // class name, used for property reading
052: private String prefix;
053:
054: /**
055: * Constructs a <code>Handler</code> object with a default error manager,
056: * the default encoding, and the default logging level
057: * <code>Level.ALL</code>. It has no filter and no formatter.
058: */
059: protected Handler() {
060: this .errorMan = new ErrorManager();
061: this .level = DEFAULT_LEVEL;
062: this .encoding = null;
063: this .filter = null;
064: this .formatter = null;
065: this .prefix = this .getClass().getName();
066: }
067:
068: // get a instance from given class name, using Class.forName()
069: private Object getDefaultInstance(String className) {
070: Object result = null;
071: if (null == className) {
072: return result;
073: }
074: try {
075: result = Class.forName(className).newInstance();
076: } catch (Exception e) {
077: // ignore
078: }
079: return result;
080: }
081:
082: // get a instance from given class name, using context classloader
083: private Object getCustomizeInstance(final String className)
084: throws Exception {
085: Class<?> c = AccessController
086: .doPrivileged(new PrivilegedExceptionAction<Class<?>>() {
087: public Class<?> run() throws Exception {
088: ClassLoader loader = Thread.currentThread()
089: .getContextClassLoader();
090: if (null == loader) {
091: loader = ClassLoader.getSystemClassLoader();
092: }
093: return loader.loadClass(className);
094: }
095: });
096: return c.newInstance();
097: }
098:
099: // print error message in some format
100: void printInvalidPropMessage(String key, String value, Exception e) {
101: // logging.12=Invalid property value for
102: String msg = new StringBuilder()
103: .append(Messages.getString("logging.12")) //$NON-NLS-1$
104: .append(prefix)
105: .append(":").append(key).append("/").append( //$NON-NLS-1$//$NON-NLS-2$
106: value).toString();
107: errorMan.error(msg, e, ErrorManager.GENERIC_FAILURE);
108: }
109:
110: /*
111: * init the common properties, including filter, level, formatter, and
112: * encoding
113: */
114: @SuppressWarnings("unused")
115: void initProperties(String defaultLevel, String defaultFilter,
116: String defaultFormatter, String defaultEncoding) {
117: LogManager manager = LogManager.getLogManager();
118:
119: // set filter
120: final String filterName = manager.getProperty(prefix
121: + ".filter"); //$NON-NLS-1$
122: if (null != filterName) {
123: try {
124: filter = (Filter) getCustomizeInstance(filterName);
125: } catch (Exception e1) {
126: printInvalidPropMessage("filter", filterName, e1); //$NON-NLS-1$
127: filter = (Filter) getDefaultInstance(defaultFilter);
128: }
129: } else {
130: filter = (Filter) getDefaultInstance(defaultFilter);
131: }
132:
133: // set level
134: String levelName = manager.getProperty(prefix + ".level"); //$NON-NLS-1$
135: if (null != levelName) {
136: try {
137: level = Level.parse(levelName);
138: } catch (Exception e) {
139: printInvalidPropMessage("level", levelName, e); //$NON-NLS-1$
140: level = Level.parse(defaultLevel);
141: }
142: } else {
143: level = Level.parse(defaultLevel);
144: }
145:
146: // set formatter
147: final String formatterName = manager.getProperty(prefix
148: + ".formatter"); //$NON-NLS-1$
149: if (null != formatterName) {
150: try {
151: formatter = (Formatter) getCustomizeInstance(formatterName);
152: } catch (Exception e) {
153: printInvalidPropMessage("formatter", formatterName, e); //$NON-NLS-1$
154: formatter = (Formatter) getDefaultInstance(defaultFormatter);
155: }
156: } else {
157: formatter = (Formatter) getDefaultInstance(defaultFormatter);
158: }
159:
160: // set encoding
161: final String encodingName = manager.getProperty(prefix
162: + ".encoding"); //$NON-NLS-1$
163: try {
164: internalSetEncoding(encodingName);
165: } catch (UnsupportedEncodingException e) {
166: printInvalidPropMessage("encoding", encodingName, e); //$NON-NLS-1$
167: }
168: }
169:
170: /**
171: * Closes this handler. A flush operation will usually be performed and all
172: * the associated resources will be freed. Client applications should not
173: * use a handler after closing it.
174: *
175: * @throws SecurityException
176: * If a security manager determines that the caller does not
177: * have the required permission.
178: */
179: public abstract void close();
180:
181: /**
182: * Flushes any buffered output.
183: */
184: public abstract void flush();
185:
186: /**
187: * Accepts an actual logging request.
188: *
189: * @param record
190: * the log record to be logged
191: */
192: public abstract void publish(LogRecord record);
193:
194: /**
195: * Gets the character encoding used by this handler.
196: *
197: * @return the character encoding used by this handler
198: */
199: public String getEncoding() {
200: return this .encoding;
201: }
202:
203: /**
204: * Gets the error manager used by this handler to report errors during
205: * logging.
206: *
207: * @return the error manager used by this handler
208: * @throws SecurityException
209: * If a security manager determines that the caller does not
210: * have the required permission.
211: */
212: public ErrorManager getErrorManager() {
213: LogManager.getLogManager().checkAccess();
214: return this .errorMan;
215: }
216:
217: /**
218: * Gets the filter used by this handler.
219: *
220: * @return the filter used by this handler
221: */
222: public Filter getFilter() {
223: return this .filter;
224: }
225:
226: /**
227: * Gets the formatter used by this handler to format the logging messages.
228: *
229: * @return the formatter used by this handler
230: */
231: public Formatter getFormatter() {
232: return this .formatter;
233: }
234:
235: /**
236: * Gets the logging level of this handler.
237: *
238: * @return the logging level of this handler
239: */
240: public Level getLevel() {
241: return this .level;
242: }
243:
244: /**
245: * Determines whether the supplied log record need to be logged. The logging
246: * levels will be checked as well as the filter.
247: *
248: * @param record
249: * the log record to be checked
250: * @return <code>true</code> if the supplied log record need to be logged,
251: * otherwise <code>false</code>
252: */
253: public boolean isLoggable(LogRecord record) {
254: if (null == record) {
255: throw new NullPointerException();
256: }
257: if (this .level.intValue() == Level.OFF.intValue()) {
258: return false;
259: } else if (record.getLevel().intValue() >= this .level
260: .intValue()) {
261: return null == this .filter
262: || this .filter.isLoggable(record);
263: }
264: return false;
265: }
266:
267: /**
268: * Report an error to the error manager associated with this handler.
269: *
270: * @param msg
271: * the error message
272: * @param ex
273: * the associated exception
274: * @param code
275: * the error code
276: */
277: protected void reportError(String msg, Exception ex, int code) {
278: this .errorMan.error(msg, ex, code);
279: }
280:
281: /**
282: * Sets the character encoding used by this handler. A <code>null</code>
283: * value indicates the using of the default encoding. This internal method
284: * does not check security.
285: *
286: * @param newEncoding
287: * the character encoding to set
288: * @throws UnsupportedEncodingException
289: * If the specified encoding is not supported by the runtime.
290: */
291: void internalSetEncoding(String newEncoding)
292: throws UnsupportedEncodingException {
293: // accepts "null" because it indicates using default encoding
294: if (null == newEncoding) {
295: this .encoding = null;
296: } else {
297: if (Charset.isSupported(newEncoding)) {
298: this .encoding = newEncoding;
299: } else {
300: // logging.13=The encoding "{0}" is not supported.
301: throw new UnsupportedEncodingException(Messages
302: .getString("logging.13", //$NON-NLS-1$
303: newEncoding));
304: }
305:
306: }
307: }
308:
309: /**
310: * Sets the character encoding used by this handler. A <code>null</code>
311: * value indicates the using of the default encoding.
312: *
313: * @param encoding
314: * the character encoding to set
315: * @throws SecurityException
316: * If a security manager determines that the caller does not
317: * have the required permission.
318: * @throws UnsupportedEncodingException
319: * If the specified encoding is not supported by the runtime.
320: */
321: public void setEncoding(String encoding) throws SecurityException,
322: UnsupportedEncodingException {
323: LogManager.getLogManager().checkAccess();
324: internalSetEncoding(encoding);
325: }
326:
327: /**
328: * Sets the error manager for this handler.
329: *
330: * @param em
331: * the error manager to set
332: * @throws SecurityException
333: * If a security manager determines that the caller does not
334: * have the required permission.
335: */
336: public void setErrorManager(ErrorManager em) {
337: LogManager.getLogManager().checkAccess();
338: if (null == em) {
339: throw new NullPointerException();
340: }
341: this .errorMan = em;
342: }
343:
344: /**
345: * Sets the filter to be used by this handler.
346: *
347: * @param newFilter
348: * the filter to set
349: * @throws SecurityException
350: * If a security manager determines that the caller does not
351: * have the required permission.
352: */
353: public void setFilter(Filter newFilter) {
354: LogManager.getLogManager().checkAccess();
355: this .filter = newFilter;
356: }
357:
358: /**
359: * Sets the formatter to be used by this handler. This internal method does
360: * not check security.
361: *
362: * @param newFormatter
363: * the formatter to set
364: */
365: void internalSetFormatter(Formatter newFormatter) {
366: if (null == newFormatter) {
367: throw new NullPointerException();
368: }
369: this .formatter = newFormatter;
370: }
371:
372: /**
373: * Sets the formatter to be used by this handler.
374: *
375: * @param newFormatter
376: * the formatter to set
377: * @throws SecurityException
378: * If a security manager determines that the caller does not
379: * have the required permission.
380: */
381: public void setFormatter(Formatter newFormatter) {
382: LogManager.getLogManager().checkAccess();
383: internalSetFormatter(newFormatter);
384: }
385:
386: /**
387: * Sets the logging level of this handler.
388: *
389: * @param newLevel
390: * the logging level to set
391: * @throws SecurityException
392: * If a security manager determines that the caller does not
393: * have the required permission.
394: */
395: public void setLevel(Level newLevel) {
396: if (null == newLevel) {
397: throw new NullPointerException();
398: }
399: LogManager.getLogManager().checkAccess();
400: this.level = newLevel;
401: }
402: }
|