View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.util.log;
20  
21  import java.util.Properties;
22  
23  /* ------------------------------------------------------------ */
24  /** Abstract Logger.
25   * Manages the atomic registration of the logger by name.
26   */
27  public abstract class AbstractLogger implements Logger
28  {
29      public static final int LEVEL_DEFAULT = -1;
30      public static final int LEVEL_ALL = 0;
31      public static final int LEVEL_DEBUG = 1;
32      public static final int LEVEL_INFO = 2;
33      public static final int LEVEL_WARN = 3;
34      public static final int LEVEL_OFF = 10;
35          
36      @Override
37      public final Logger getLogger(String name)
38      {
39          if (isBlank(name))
40              return this;
41  
42          final String basename = getName();
43          final String fullname = (isBlank(basename) || Log.getRootLogger()==this)?name:(basename + "." + name);
44          
45          Logger logger = Log.getLoggers().get(fullname);
46          if (logger == null)
47          {
48              Logger newlog = newLogger(fullname);
49              
50              logger = Log.getMutableLoggers().putIfAbsent(fullname,newlog);
51              if (logger == null)
52                  logger=newlog;
53          }
54  
55          return logger;
56      }
57      
58  
59      protected abstract Logger newLogger(String fullname);
60  
61      /**
62       * A more robust form of name blank test. Will return true for null names, and names that have only whitespace
63       *
64       * @param name
65       *            the name to test
66       * @return true for null or blank name, false if any non-whitespace character is found.
67       */
68      private static boolean isBlank(String name)
69      {
70          if (name == null)
71          {
72              return true;
73          }
74          int size = name.length();
75          char c;
76          for (int i = 0; i < size; i++)
77          {
78              c = name.charAt(i);
79              if (!Character.isWhitespace(c))
80              {
81                  return false;
82              }
83          }
84          return true;
85      }
86      
87      /**
88       * Get the Logging Level for the provided log name. Using the FQCN first, then each package segment from longest to
89       * shortest.
90       *
91       * @param props
92       *            the properties to check
93       * @param name
94       *            the name to get log for
95       * @return the logging level
96       */
97      public static int lookupLoggingLevel(Properties props, final String name)
98      {
99          if ((props == null) || (props.isEmpty()) || name==null )
100             return LEVEL_DEFAULT;
101         
102         // Calculate the level this named logger should operate under.
103         // Checking with FQCN first, then each package segment from longest to shortest.
104         String nameSegment = name;
105     
106         while ((nameSegment != null) && (nameSegment.length() > 0))
107         {
108             String levelStr = props.getProperty(nameSegment + ".LEVEL");
109             // System.err.printf("[StdErrLog.CONFIG] Checking for property [%s.LEVEL] = %s%n",nameSegment,levelStr);
110             int level = getLevelId(nameSegment + ".LEVEL",levelStr);
111             if (level != (-1))
112             {
113                 return level;
114             }
115     
116             // Trim and try again.
117             int idx = nameSegment.lastIndexOf('.');
118             if (idx >= 0)
119             {
120                 nameSegment = nameSegment.substring(0,idx);
121             }
122             else
123             {
124                 nameSegment = null;
125             }
126         }
127     
128         // Default Logging Level
129         return LEVEL_DEFAULT;
130     }
131 
132 
133     public static String getLoggingProperty(Properties props, String name, String property)
134     {
135         // Calculate the level this named logger should operate under.
136         // Checking with FQCN first, then each package segment from longest to shortest.
137         String nameSegment = name;
138     
139         while ((nameSegment != null) && (nameSegment.length() > 0))
140         {
141             String s = props.getProperty(nameSegment+"."+property);
142             if (s!=null)
143                 return s;
144     
145             // Trim and try again.
146             int idx = nameSegment.lastIndexOf('.');
147             nameSegment = (idx >= 0)?nameSegment.substring(0,idx):null;
148         }
149     
150         return null;
151     }
152 
153 
154     protected static int getLevelId(String levelSegment, String levelName)
155     {
156         if (levelName == null)
157         {
158             return -1;
159         }
160         String levelStr = levelName.trim();
161         if ("ALL".equalsIgnoreCase(levelStr))
162         {
163             return LEVEL_ALL;
164         }
165         else if ("DEBUG".equalsIgnoreCase(levelStr))
166         {
167             return LEVEL_DEBUG;
168         }
169         else if ("INFO".equalsIgnoreCase(levelStr))
170         {
171             return LEVEL_INFO;
172         }
173         else if ("WARN".equalsIgnoreCase(levelStr))
174         {
175             return LEVEL_WARN;
176         }
177         else if ("OFF".equalsIgnoreCase(levelStr))
178         {
179             return LEVEL_OFF;
180         }
181     
182         System.err.println("Unknown StdErrLog level [" + levelSegment + "]=[" + levelStr + "], expecting only [ALL, DEBUG, INFO, WARN, OFF] as values.");
183         return -1;
184     }
185 
186 
187     /**
188      * Condenses a classname by stripping down the package name to just the first character of each package name
189      * segment.Configured
190      *
191      * <pre>
192      * Examples:
193      * "org.eclipse.jetty.test.FooTest"           = "oejt.FooTest"
194      * "org.eclipse.jetty.server.logging.LogTest" = "orjsl.LogTest"
195      * </pre>
196      *
197      * @param classname
198      *            the fully qualified class name
199      * @return the condensed name
200      */
201     protected static String condensePackageString(String classname)
202     {
203         String parts[] = classname.split("\\.");
204         StringBuilder dense = new StringBuilder();
205         for (int i = 0; i < (parts.length - 1); i++)
206         {
207             dense.append(parts[i].charAt(0));
208         }
209         if (dense.length() > 0)
210         {
211             dense.append('.');
212         }
213         dense.append(parts[parts.length - 1]);
214         return dense.toString();
215     }
216 
217 
218     public void debug(String msg, long arg)
219     {
220         if (isDebugEnabled())
221         {
222             debug(msg,new Object[] { new Long(arg) });
223         }
224     }
225 }