View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.pool2.impl;
18  
19  import java.io.PrintWriter;
20  import java.text.DateFormat;
21  import java.text.SimpleDateFormat;
22  
23  /**
24   * CallStack strategy that uses the stack trace from a {@link Throwable}. This strategy, while slower than the
25   * SecurityManager implementation, provides call stack method names and other metadata in addition to the call stack
26   * of classes.
27   *
28   * @see Throwable#fillInStackTrace()
29   * @since 2.4.3
30   */
31  public class ThrowableCallStack implements CallStack {
32  
33      /**
34       * A snapshot of a throwable.
35       */
36      private static class Snapshot extends Throwable {
37          private static final long serialVersionUID = 1L;
38          private final long timestampMillis = System.currentTimeMillis();
39      }
40  
41      private final String messageFormat;
42  
43      //@GuardedBy("dateFormat")
44      private final DateFormat dateFormat;
45  
46      private volatile Snapshot snapshot;
47  
48      /**
49       * Creates a new instance.
50       *
51       * @param messageFormat message format
52       * @param useTimestamp whether to format the dates in the output message or not
53       */
54      public ThrowableCallStack(final String messageFormat, final boolean useTimestamp) {
55          this.messageFormat = messageFormat;
56          this.dateFormat = useTimestamp ? new SimpleDateFormat(messageFormat) : null;
57      }
58  
59      @Override
60      public void clear() {
61          snapshot = null;
62      }
63  
64      @Override
65      public void fillInStackTrace() {
66          snapshot = new Snapshot();
67      }
68  
69      @Override
70      public synchronized boolean printStackTrace(final PrintWriter writer) {
71          final Snapshot snapshotRef = this.snapshot;
72          if (snapshotRef == null) {
73              return false;
74          }
75          final String message;
76          if (dateFormat == null) {
77              message = messageFormat;
78          } else {
79              synchronized (dateFormat) {
80                  message = dateFormat.format(Long.valueOf(snapshotRef.timestampMillis));
81              }
82          }
83          writer.println(message);
84          snapshotRef.printStackTrace(writer);
85          return true;
86      }
87  }