View Javadoc

1   package org.e2etrace.timer;
2   
3   /*
4    * Copyright 2006 Gunther Popp
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * 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, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.lang.reflect.Method;
20  
21  import org.apache.commons.logging.Log;
22  import org.apache.commons.logging.LogFactory;
23  
24  /**
25   * Default Factory class for Timer instances.
26   * <p>
27   *
28   * The factory returns a new Timer instance. In the default configuration, the
29   * new Timer is of the type {@link org.e2etrace.timer.DefaultTimer}. Please refer
30   * to the documentation of this class to learn about the restrictions of the
31   * underlying implementation.
32   * <p>
33   *
34   * However, if e2etrace has been compiled and is executed using JDK 5.0 (or
35   * higher), the factory will return instances of the type
36   * {@link org.e2etrace.timer.ExactTimer}. This Timer implementation uses the
37   * advanced timing features of the new JDK releases and avoids all problems
38   * described in the documentation of <code>DefaultTimer</code>.
39   * <p>
40   *
41   * Please note the different constructors of the factory. You can force the
42   * factory to create specific types of Timers by using the appropriate
43   * constructor. If you use the default constructor, the above described logic
44   * applies.
45   * <p>
46   *
47   * You can use the class {@link org.e2etrace.timer.PrintTimerAccuracy} to determine
48   * which Timer type will be used by e2etrace on your system and which accuracy
49   * the Timers are able to deliver.
50   * <p>
51   *
52   *
53   * @author Gunther Popp
54   *
55   */
56  public class DefaultTimerFactory implements ITimerFactory {
57  
58    private static final Log log = LogFactory.getLog(DefaultTimerFactory.class);
59    private static final boolean supportsExactMeasuring = supportsNanoTime();
60  
61    private Class timerType;
62  
63    /**
64     * Default constructor.
65     * <p>
66     */
67    public DefaultTimerFactory() {
68      if (supportsExactMeasuring) {
69        setTimerType(ExactTimer.class);
70  
71      } else {
72        setTimerType(DefaultTimer.class);
73  
74      }
75  
76    }
77  
78    /**
79     * Constructor using a pre-defined Timer type.
80     * <p>
81     *
82     * @param timerType type of timers the factory will return
83     */
84    public DefaultTimerFactory(Class timerType) {
85      setTimerType(timerType);
86    }
87  
88    /** {@inheritDoc} */
89    public ITimer newInstance() {
90      ITimer timer = null;
91  
92      try {
93        timer = (ITimer) timerType.newInstance();
94      } catch (Exception e) {
95        log.error("Error creating a new Timer of type " + timerType.getName()
96            + ". Will create a DefaultTimer instead.", e);
97        timer = new DefaultTimer();
98      }
99  
100     return timer;
101 
102   }
103 
104   /**
105    * Changes the type of Timer returned by the Factory.
106    *
107    * @param timerType New Timer type
108    */
109   public void setTimerType(Class timerType) {
110     // log.info("TimerFactory uses now Timers of type " +
111     // timerType.getName());
112 
113     this.timerType = timerType;
114   }
115 
116   /**
117    * Returns the type of Timers currently used by the Factory.
118    * <p>
119    *
120    * @return Timer type
121    */
122   public Class getTimerType() {
123     return timerType;
124   }
125 
126   /**
127    * Helper-method: Checks, if the current VM supports the System.nanoTime()
128    * Method.
129    *
130    * @return true: VM supports the exact time measuring
131    */
132   private static boolean supportsNanoTime() {
133     boolean ret = false;
134     Method[] methods = System.class.getDeclaredMethods();
135 
136     for (int i = 0; i < methods.length; i++) {
137       Method method = methods[i];
138 
139       if (method.getName().equals("nanoTime")) {
140         ret = true;
141         break;
142       }
143     }
144 
145     if (ret) {
146       log.info("This VM supports exact time measuring using System.nanoTime()");
147     } else {
148       log
149           .warn("This VM only supports only System.currentTimeMillis(). This may lead to inaccurate results.");
150     }
151 
152     return ret;
153   }
154 
155 }