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.trinidad.logging;
20  
21  import java.util.logging.Level;
22  import java.util.logging.LogRecord;
23  
24  /**
25   * Private subclass of LogRecord to hide TrinidadLogger in the stack trace.
26   */
27  class TrinidadLogRecord extends LogRecord 
28  {
29    public TrinidadLogRecord(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        _inferCaller();
41  
42      return super.getSourceClassName();
43    }
44  
45    @Override
46    public void setSourceClassName(String sourceClassName)
47    {
48      _needToInferCaller = false;
49      super.setSourceClassName(sourceClassName);
50    }
51  
52    @Override
53    public String getSourceMethodName()
54    {
55      if (_needToInferCaller)
56        _inferCaller();
57  
58      return super.getSourceMethodName();
59    }
60  
61    @Override
62    public void setSourceMethodName(String sourceMethodName)
63    {
64      _needToInferCaller = false;
65      super.setSourceMethodName(sourceMethodName);
66    }
67  
68    // Private method to infer the caller's class and method names
69    private void _inferCaller()
70    {
71      _needToInferCaller = false;
72      // Get the stack trace.
73      StackTraceElement stack[] = (new Throwable()).getStackTrace();
74      // First, search back to a method in the Logger class.
75      int i = 0;
76  
77      while (i < stack.length)
78      {
79        StackTraceElement frame = stack[i];
80        String cname = frame.getClassName();
81        if (cname.equals(_JDK_LOG_CLASS) ||
82            cname.equals(_TRINIDAD_LOG_CLASS))
83          break;
84  
85        i++;
86      }
87  
88      // Now search for the first frame before the "Logger" class.
89      while (i < stack.length)
90      {
91        StackTraceElement frame = stack[i];
92        String cname = frame.getClassName();
93  
94        if (cname.equals(_JDK_LOG_CLASS) ||
95            cname.equals(_TRINIDAD_LOG_CLASS))
96        {
97          i++;
98          continue;
99        }
100 
101       String mname = frame.getMethodName();
102       if ("log".equals(mname) ||
103           "_log".equals(mname))
104       {
105         i++;
106         continue;
107       }
108 
109       // We've found the relevant frame.
110       setSourceClassName(cname);
111       setSourceMethodName(mname);
112       return;
113 
114     }
115 
116     // Forcibly set both to null, so the LogRecord superclass
117     // doesn't try to detect them on its own
118     setSourceClassName(null);
119     setSourceMethodName(null);
120   }
121 
122   transient private boolean _needToInferCaller;
123 
124 
125   private static final String _JDK_LOG_CLASS = 
126     "java.util.logging.Logger";
127   
128   private static final String _TRINIDAD_LOG_CLASS =
129     "org.apache.myfaces.trinidad.logging.TrinidadLogger";
130 
131   private static final long serialVersionUID = 1L;
132 }
133