View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.logging;
20  
21  import java.util.logging.Level;
22  import java.util.logging.LogRecord;
23  
24  /**
25   * Private subclass of LogRecord to hide MyfacesLogger in the stack trace.
26   */
27  class MyfacesLogRecord extends LogRecord 
28  {
29    public MyfacesLogRecord(Level level, String msg)
30    {
31      super(level, (msg == null) ? "" : msg);
32      _needToInferCaller = true;
33    }
34  
35  
36    @Override
37    public String getSourceClassName()
38    {
39      if (_needToInferCaller)
40      {
41          _inferCaller();
42      }
43  
44      return super.getSourceClassName();
45    }
46  
47    @Override
48    public void setSourceClassName(String sourceClassName)
49    {
50      _needToInferCaller = false;
51      super.setSourceClassName(sourceClassName);
52    }
53  
54    @Override
55    public String getSourceMethodName()
56    {
57      if (_needToInferCaller)
58      {
59          _inferCaller();
60      }
61  
62      return super.getSourceMethodName();
63    }
64  
65    @Override
66    public void setSourceMethodName(String sourceMethodName)
67    {
68      _needToInferCaller = false;
69      super.setSourceMethodName(sourceMethodName);
70    }
71  
72    // Private method to infer the caller's class and method names
73    private void _inferCaller()
74    {
75      _needToInferCaller = false;
76      // Get the stack trace.
77      StackTraceElement stack[] = (new Throwable()).getStackTrace();
78      // First, search back to a method in the Logger class.
79      int i = 0;
80  
81      while (i < stack.length)
82      {
83        StackTraceElement frame = stack[i];
84        String cname = frame.getClassName();
85        if (cname.equals(_JDK_LOG_CLASS) ||
86            cname.equals(_MYFACES_LOG_CLASS))
87        {
88            break;
89        }
90  
91        i++;
92      }
93  
94      // Now search for the first frame before the "Logger" class.
95      while (i < stack.length)
96      {
97        StackTraceElement frame = stack[i];
98        String cname = frame.getClassName();
99  
100       if (cname.equals(_JDK_LOG_CLASS) ||
101           cname.equals(_MYFACES_LOG_CLASS))
102       {
103         i++;
104         continue;
105       }
106 
107       String mname = frame.getMethodName();
108       if ("log".equals(mname) ||
109           "_log".equals(mname))
110       {
111         i++;
112         continue;
113       }
114 
115       // We've found the relevant frame.
116       setSourceClassName(cname);
117       setSourceMethodName(mname);
118       return;
119 
120     }
121 
122     // Forcibly set both to null, so the LogRecord superclass
123     // doesn't try to detect them on its own
124     setSourceClassName(null);
125     setSourceMethodName(null);
126   }
127 
128   transient private boolean _needToInferCaller;
129 
130 
131   private static final String _JDK_LOG_CLASS = 
132     "java.util.logging.Logger";
133   
134   private static final String _MYFACES_LOG_CLASS =
135     "org.apache.myfaces.logging.MyfacesLogger";
136 
137   private static final long serialVersionUID = 1L;
138 }
139