Source Code Cross Referenced for Logging.java in  » GIS » GeoTools-2.4.1 » org » geotools » util » logging » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » GeoTools 2.4.1 » org.geotools.util.logging 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2006, Geotools Project Managment Committee (PMC)
005:         *
006:         *    This library is free software; you can redistribute it and/or
007:         *    modify it under the terms of the GNU Lesser General Public
008:         *    License as published by the Free Software Foundation; either
009:         *    version 2.1 of the License, or (at your option) any later version.
010:         *
011:         *    This library is distributed in the hope that it will be useful,
012:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014:         *    Lesser General Public License for more details.
015:         */
016:        package org.geotools.util.logging;
017:
018:        import java.lang.reflect.InvocationTargetException;
019:        import java.util.Arrays;
020:        import java.util.Comparator;
021:        import java.util.logging.Level;
022:        import java.util.logging.Logger;
023:        import java.util.logging.LogRecord;
024:        import java.lang.reflect.Method;
025:
026:        import org.geotools.resources.XArray;
027:        import org.geotools.resources.Utilities;
028:        import org.geotools.resources.i18n.Errors;
029:        import org.geotools.resources.i18n.ErrorKeys;
030:
031:        /**
032:         * A set of utilities method for configuring loggings in GeoTools. <strong>All GeoTools
033:         * code should fetch their logger through a call to {@link #getLogger(String)}</strong>,
034:         * not {@link Logger#getLogger(String)}. This is necessary in order to give GeoTools a
035:         * chance to redirect log events to an other logging framework, for example
036:         * <A HREF="http://jakarta.apache.org/commons/logging/">commons-logging</A>.
037:         * <p>
038:         * <b>Example:</b> In order to redirect every GeoTools log events to Commons-logging,
039:         * invoke the following once at application startup:
040:         *
041:         * <blockquote><code>
042:         * Logging.{@linkplain #GEOTOOLS}.{@linkplain #setLoggerFactory
043:         * setLoggerFactory}("org.geotools.util.logging.CommonsLoggerFactory");
044:         * </code></blockquote>
045:         *
046:         * @since 2.4
047:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/metadata/src/main/java/org/geotools/util/logging/Logging.java $
048:         * @version $Id: Logging.java 27891 2007-11-14 14:10:48Z desruisseaux $
049:         * @author Martin Desruisseaux
050:         */
051:        public final class Logging {
052:            /**
053:             * Compares {@link Logging} or {@link String} objects for alphabetical order.
054:             */
055:            private static final Comparator COMPARATOR = new Comparator() {
056:                public int compare(final Object o1, final Object o2) {
057:                    final String n1 = (o1 instanceof  Logging) ? ((Logging) o1).name
058:                            : o1.toString();
059:                    final String n2 = (o2 instanceof  Logging) ? ((Logging) o2).name
060:                            : o2.toString();
061:                    return n1.compareTo(n2);
062:                }
063:            };
064:
065:            /**
066:             * An empty array of loggings. Also used for locks.
067:             */
068:            private static final Logging[] EMPTY = new Logging[0];
069:
070:            /**
071:             * Logging configuration that apply to all packages.
072:             */
073:            public static final Logging ALL = new Logging();
074:            // NOTE: ALL must be created before any other static Logging constant.
075:
076:            /**
077:             * Logging configuration that apply only to GeoTools packages.
078:             */
079:            public static final Logging GEOTOOLS = getLogging("org.geotools");
080:
081:            /**
082:             * The name of the base package.
083:             */
084:            final String name;
085:
086:            /**
087:             * The children {@link Logging} objects.
088:             * <p>
089:             * The plain array used there is not efficient for adding new items (an {@code ArrayList}
090:             * would be more efficient), but we assume that very few new items will be added. Furthermore
091:             * a plain array is efficient for reading, and the later is way more common than the former.
092:             */
093:            private Logging[] children = EMPTY;
094:
095:            /**
096:             * The factory for creating loggers.
097:             *
098:             * @see #setLoggerFactory
099:             */
100:            private LoggerFactory factory;
101:
102:            /**
103:             * {@code true} if every {@link Logging} instances use the same {@link LoggerFactory}.
104:             * This is an optimization for a very common case.
105:             */
106:            private static boolean sameLoggerFactory;
107:
108:            /**
109:             * Creates an instance for the root logger. This constructor should not be used
110:             * for anything else than {@link #ALL} construction; use {@link #getLogging} instead.
111:             */
112:            private Logging() {
113:                name = "";
114:            }
115:
116:            /**
117:             * Creates an instance for the specified base logger. This constructor
118:             * should not be public; use {@link #getLogging} instead.
119:             *
120:             * @param parent The parent {@code Logging} instance.
121:             * @param name   The logger name for the new instance.
122:             */
123:            private Logging(final Logging parent, final String name) {
124:                this .name = name;
125:                factory = parent.factory;
126:                assert name.startsWith(parent.name) : name;
127:            }
128:
129:            /**
130:             * Returns a logger for the specified name. If a {@linkplain LoggerFactory logger factory} has
131:             * been set, then this method first {@linkplain LoggerFactory#getLogger ask to the factory}.
132:             * It gives GeoTools a chance to redirect logging events to
133:             * <A HREF="http://jakarta.apache.org/commons/logging/">commons-logging</A>
134:             * or some equivalent framework.
135:             * <p>
136:             * If no factory was found or if the factory choose to not redirect the loggings, then this
137:             * method returns the usual <code>{@linkplain Logger#getLogger Logger.getLogger}(name)</code>.
138:             *
139:             * @param  name The logger name.
140:             * @return A logger for the specified name.
141:             */
142:            public static Logger getLogger(final String name) {
143:                synchronized (EMPTY) {
144:                    final Logging logging = sameLoggerFactory ? ALL
145:                            : getLogging(name, false);
146:                    if (logging != null) {
147:                        final LoggerFactory factory = logging.factory;
148:                        if (factory != null) {
149:                            final Logger logger = factory.getLogger(name);
150:                            if (logger != null) {
151:                                return logger;
152:                            }
153:                        }
154:                    }
155:                }
156:                return Logger.getLogger(name);
157:            }
158:
159:            /**
160:             * Returns a {@code Logging} instance for the specified base logger. This instance is
161:             * used for controlling logging configuration in GeoTools. For example methods like
162:             * {@link #forceMonolineConsoleOutput} are invoked on a {@code Logging} instance.
163:             * <p>
164:             * {@code Logging} instances follow the same hierarchy than {@link Logger}, i.e.
165:             * {@code "org.geotools"} is the parent of {@code "org.geotools.referencing"},
166:             * {@code "org.geotools.metadata"}, <cite>etc</cite>.
167:             *
168:             * @param name The base logger name.
169:             */
170:            public static Logging getLogging(final String name) {
171:                synchronized (EMPTY) {
172:                    return getLogging(name, true);
173:                }
174:            }
175:
176:            /**
177:             * Returns a logging instance for the specified base logger. If no instance if found for
178:             * the specified name and {@code create} is {@code true}, then a new instance will be
179:             * created. Otherwise the nearest parent is returned.
180:             *
181:             * @param root The root logger name.
182:             * @param create {@code true} if this method is allowed to create new {@code Logging} instance.
183:             */
184:            private static Logging getLogging(final String base,
185:                    final boolean create) {
186:                assert Thread.holdsLock(EMPTY);
187:                Logging logging = ALL;
188:                if (base.length() != 0) {
189:                    int offset = 0;
190:                    do {
191:                        Logging[] children = logging.children;
192:                        offset = base.indexOf('.', offset);
193:                        final String name = (offset >= 0) ? base.substring(0,
194:                                offset) : base;
195:                        int i = Arrays.binarySearch(children, name, COMPARATOR);
196:                        if (i < 0) {
197:                            // No exact match found.
198:                            if (!create) {
199:                                // We are not allowed to create new Logging instance.
200:                                // 'logging' is the nearest parent, so stop the loop now.
201:                                break;
202:                            }
203:                            i = ~i;
204:                            children = (Logging[]) XArray
205:                                    .insert(children, i, 1);
206:                            children[i] = new Logging(logging, name);
207:                            logging.children = children;
208:                        }
209:                        logging = children[i];
210:                    } while (++offset != 0);
211:                }
212:                return logging;
213:            }
214:
215:            /**
216:             * Returns the logger factory, or {@code null} if none. This method returns the logger set
217:             * by the last call to {@link #setLoggerFactory} on this {@code Logging} instance or on one
218:             * of its parent.
219:             */
220:            public LoggerFactory getLoggerFactory() {
221:                synchronized (EMPTY) {
222:                    return factory;
223:                }
224:            }
225:
226:            /**
227:             * Sets a new logger factory for this {@code Logging} instance and every children. The
228:             * specified factory will be used by <code>{@linkplain #getLogger getLogger}(name)</code>
229:             * when {@code name} is this {@code Logging} name or one of its children.
230:             */
231:            public void setLoggerFactory(final LoggerFactory factory) {
232:                synchronized (EMPTY) {
233:                    this .factory = factory;
234:                    for (int i = 0; i < children.length; i++) {
235:                        children[i].setLoggerFactory(factory);
236:                    }
237:                    sameLoggerFactory = sameLoggerFactory(ALL.children,
238:                            ALL.factory);
239:                }
240:            }
241:
242:            /**
243:             * Returns {@code true} if all children use the specified factory.
244:             * Used in order to detect a possible optimization for this very common case.
245:             */
246:            private static boolean sameLoggerFactory(final Logging[] children,
247:                    final LoggerFactory factory) {
248:                assert Thread.holdsLock(EMPTY);
249:                for (int i = 0; i < children.length; i++) {
250:                    final Logging logging = children[i];
251:                    if (logging.factory != factory
252:                            || !sameLoggerFactory(logging.children, factory)) {
253:                        return false;
254:                    }
255:                }
256:                return true;
257:            }
258:
259:            /**
260:             * Sets a new logger factory from a fully qualidifed class name. This method should be
261:             * preferred to {@link #setLoggerFactory(LoggerFactory)} when the underlying logging
262:             * framework is not garanteed to be on the classpath.
263:             *
264:             * @param  className The fully qualified factory class name.
265:             * @throws ClassNotFoundException if the specified class was not found.
266:             * @throws IllegalArgumentException if the specified class is not a subclass of
267:             *         {@link LoggerFactory}, or if no public static {@code getInstance()} method
268:             *         has been found or can be executed.
269:             */
270:            public void setLoggerFactory(final String className)
271:                    throws ClassNotFoundException, IllegalArgumentException {
272:                final LoggerFactory factory;
273:                if (className == null) {
274:                    factory = null;
275:                } else {
276:                    final Class factoryClass;
277:                    try {
278:                        factoryClass = Class.forName(className);
279:                    } catch (NoClassDefFoundError error) {
280:                        throw factoryNotFound(className, error);
281:                    }
282:                    if (!LoggerFactory.class.isAssignableFrom(factoryClass)) {
283:                        throw new IllegalArgumentException(Errors.format(
284:                                ErrorKeys.ILLEGAL_CLASS_$2, Utilities
285:                                        .getShortName(factoryClass), Utilities
286:                                        .getShortName(LoggerFactory.class)));
287:                    }
288:                    try {
289:                        final Method method = factoryClass.getMethod(
290:                                "getInstance", (Class[]) null);
291:                        factory = (LoggerFactory) method.invoke(null,
292:                                (Object[]) null);
293:                    } catch (Exception e) {
294:                        /*
295:                         * Catching java.lang.Exception is usually bad practice, but there is really a lot
296:                         * of checked exceptions when using reflection. Unfortunatly there is nothing like
297:                         * a "ReflectionException" parent class that we could catch instead. There is also
298:                         * a few unchecked exception that we want to process here, like ClassCastException.
299:                         */
300:                        Throwable cause = e;
301:                        if (e instanceof  InvocationTargetException) {
302:                            cause = e.getCause(); // Simplify the stack trace.
303:                        }
304:                        if (cause instanceof  ClassNotFoundException) {
305:                            throw (ClassNotFoundException) e;
306:                        }
307:                        if (cause instanceof  NoClassDefFoundError) {
308:                            throw factoryNotFound(className,
309:                                    (NoClassDefFoundError) cause);
310:                        }
311:                        throw new IllegalArgumentException(Errors.format(
312:                                ErrorKeys.CANT_CREATE_FACTORY_$1, className,
313:                                cause));
314:                    }
315:                }
316:                setLoggerFactory(factory);
317:            }
318:
319:            /**
320:             * Wraps a unchecked {@link NoClassDefFoundError} into a checked {@link ClassNotFoundException}.
321:             */
322:            private static ClassNotFoundException factoryNotFound(String name,
323:                    NoClassDefFoundError error) {
324:                return new ClassNotFoundException(Errors.format(
325:                        ErrorKeys.FACTORY_NOT_FOUND_$1, name), error);
326:            }
327:
328:            /**
329:             * Configures the default {@linkplain java.util.logging.ConsoleHandler console handler} in
330:             * order to log records on a single line instead of two lines. More specifically, for each
331:             * {@link java.util.logging.ConsoleHandler} using a {@link java.util.logging.SimpleFormatter},
332:             * this method replaces the simple formatter by an instance of {@link MonolineFormatter}. If
333:             * no {@code ConsoleHandler} are found, then a new one is created.
334:             * <p>
335:             * <b>Note:</b> this method may have no effect if the loggings are redirected to an other
336:             * logging framework, for example if {@link #redirectToCommonsLogging} has been invoked.
337:             */
338:            public void forceMonolineConsoleOutput() {
339:                forceMonolineConsoleOutput(null);
340:            }
341:
342:            /**
343:             * Same as {@link #forceMonolineConsoleOutput()}, but additionnaly set an optional logging
344:             * level. If the specified level is non-null, then all {@link java.util.logging.Handler}s
345:             * using the monoline formatter will be set to the specified level.
346:             * <p>
347:             * <b>Note:</b> Avoid this method as much as possible, since it overrides user's level
348:             * setting. A user trying to configure his logging properties may find confusing to see
349:             * his setting ignored.
350:             *
351:             * @see org.geotools.factory.GeoTools#init
352:             */
353:            public void forceMonolineConsoleOutput(final Level level) {
354:                final Logger logger = Logger.getLogger(name); // Really Java logging, not the redirected one.
355:                synchronized (EMPTY) {
356:                    final MonolineFormatter f = MonolineFormatter
357:                            .configureConsoleHandler(logger, level);
358:                    if (f.getSourceFormat() == null) {
359:                        // Set the source format only if the user didn't specified
360:                        // an explicit one in the jre/lib/logging.properties file.
361:                        f.setSourceFormat("class:short");
362:                    }
363:                }
364:            }
365:
366:            /**
367:             * Invoked when an unexpected error occurs. This method logs a message at the
368:             * {@link Level#WARNING WARNING} level to the specified logger. The originating
369:             * class name and method name are inferred from the error stack trace, using the
370:             * first {@linkplain StackTraceElement stack trace element} for which the class
371:             * name is inside a package or sub-package of the logger name. For example if
372:             * the logger name is {@code "org.geotools.image"}, then this method will uses
373:             * the first stack trace element where the fully qualified class name starts with
374:             * {@code "org.geotools.image"} or {@code "org.geotools.image.io"}, but not
375:             * {@code "org.geotools.imageio"}.
376:             *
377:             * @param  logger Where to log the error.
378:             * @param  error  The error that occured.
379:             * @return {@code true} if the error has been logged, or {@code false} if the logger
380:             *         doesn't log anything at the {@link Level#WARNING WARNING} level.
381:             */
382:            public static boolean unexpectedException(final Logger logger,
383:                    final Throwable error) {
384:                if (logger.isLoggable(Level.WARNING)) {
385:                    unexpectedException(logger.getName(), (String) null, null,
386:                            error);
387:                    return true;
388:                }
389:                return false;
390:            }
391:
392:            /**
393:             * Invoked when an unexpected error occurs. This method logs a message at the
394:             * {@link Level#WARNING WARNING} level to the specified logger. The originating
395:             * class name and method name can optionnaly be specified. If any of them is
396:             * {@code null}, then it will be inferred from the error stack trace as in
397:             * {@link #unexpectedException(Logger, Throwable)}.
398:             * <p>
399:             * Explicit value for class and method names are sometime preferred to automatic
400:             * inference for the following reasons:
401:             *
402:             * <ul>
403:             *   <li><p>Automatic inference is not 100% reliable, since the Java Virtual Machine
404:             *       is free to omit stack frame in optimized code.</p></li>
405:             *   <li><p>When an exception occured in a private method used internally by a public
406:             *       method, we sometime want to log the warning for the public method instead,
407:             *       since the user is not expected to know anything about the existence of the
408:             *       private method. If a developper really want to know about the private method,
409:             *       the stack trace is still available anyway.</p></li>
410:             * </ul>
411:             *
412:             * @param logger  Where to log the error.
413:             * @param classe  The class where the error occurred, or {@code null}.
414:             * @param method  The method where the error occurred, or {@code null}.
415:             * @param error   The error.
416:             */
417:            public static void unexpectedException(final Logger logger,
418:                    final Class classe, final String method,
419:                    final Throwable error) {
420:                // TODO: Refactor in order to use directly the logger after we removed the deprecated method.
421:                unexpectedException(logger.getName(), classe, method, error);
422:            }
423:
424:            /**
425:             * Invoked when an unexpected error occurs. This method logs a message at the
426:             * {@link Level#WARNING WARNING} level to the logger for the specified package
427:             * name. The originating class name and method name can optionnaly be specified.
428:             * If any of them is {@code null}, then it will be inferred from the error stack
429:             * trace as in {@link #unexpectedException(Logger, Throwable)}.
430:             *
431:             * @param paquet  The package where the error occurred, or {@code null}. This
432:             *                information is used for fetching an appropriate {@link Logger}
433:             *                for logging the error.
434:             * @param classe  The class where the error occurred, or {@code null}.
435:             * @param method  The method where the error occurred, or {@code null}.
436:             * @param error   The error.
437:             */
438:            public static void unexpectedException(final String paquet,
439:                    final Class classe, final String method,
440:                    final Throwable error) {
441:                // TODO: use getSimpleName() or getCanonicalName() when we will be allowed to target J2SE 1.5.
442:                unexpectedException(paquet, (classe != null) ? classe.getName()
443:                        : (String) null, method, error);
444:            }
445:
446:            /**
447:             * Same as {@link #unexpectedException(String, Class, String, Throwable)
448:             * unexpectedException(..., Class, ...)} except that the class name is
449:             * specified as a string.
450:             *
451:             * @param paquet  The package where the error occurred, or {@code null}. This
452:             *                information is used for fetching an appropriate {@link Logger}
453:             *                for logging the error.
454:             * @param classe  The class where the error occurred, or {@code null}.
455:             * @param method  The method where the error occurred, or {@code null}.
456:             * @param error   The error.
457:             */
458:            private static void unexpectedException(String paquet,
459:                    String classe, String method, final Throwable error) {
460:                final LogRecord record = Utilities.getLogRecord(error);
461:                if (paquet == null || classe == null || method == null) {
462:                    final StackTraceElement[] elements = error.getStackTrace();
463:                    for (int i = 0; i < elements.length; i++) {
464:                        final StackTraceElement e = elements[i];
465:                        final String c = e.getClassName();
466:                        if (paquet != null) {
467:                            if (!c.startsWith(paquet)) {
468:                                continue;
469:                            }
470:                            final int lg = paquet.length();
471:                            if (c.length() > lg
472:                                    && Character.isJavaIdentifierPart(c
473:                                            .charAt(lg))) {
474:                                continue;
475:                            }
476:                        }
477:                        if (classe != null) {
478:                            if (!c.endsWith(classe)) {
479:                                continue;
480:                            }
481:                            final int lg = c.length() - classe.length() - 1;
482:                            if (c.length() >= 0
483:                                    && Character.isJavaIdentifierPart(c
484:                                            .charAt(lg))) {
485:                                continue;
486:                            }
487:                        }
488:                        final String m = e.getMethodName();
489:                        if (method != null) {
490:                            if (!m.equals(method)) {
491:                                continue;
492:                            }
493:                        }
494:                        final int separator = c.lastIndexOf('.');
495:                        if (paquet == null) {
496:                            paquet = (separator >= 1) ? c.substring(0,
497:                                    separator - 1) : "";
498:                        }
499:                        if (classe == null) {
500:                            classe = c.substring(separator + 1);
501:                        }
502:                        if (method == null) {
503:                            method = m;
504:                        }
505:                        break;
506:                    }
507:                }
508:                record.setSourceClassName(classe);
509:                record.setSourceMethodName(method);
510:                record.setThrown(error);
511:                Logger.getLogger(paquet).log(record);
512:            }
513:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.