KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > vladium > emma > rt > RT


1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2  *
3  * This program and the accompanying materials are made available under
4  * the terms of the Common Public License v1.0 which accompanies this distribution,
5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
6  *
7  * $Id: RT.java,v 1.2.2.3 2004/07/16 23:32:03 vlad_r Exp $
8  */

9 package com.vladium.emma.rt;
10
11 import java.io.File JavaDoc;
12
13 import com.vladium.logging.Logger;
14 import com.vladium.util.IProperties;
15 import com.vladium.util.Property;
16 import com.vladium.util.exit.ExitHookManager;
17 import com.vladium.emma.IAppConstants;
18 import com.vladium.emma.EMMAProperties;
19 import com.vladium.emma.data.ICoverageData;
20 import com.vladium.emma.data.DataFactory;
21
22 // ----------------------------------------------------------------------------
23
/**
24  * @author Vlad Roubtsov, (C) 2003
25  */

26 public
27 abstract class RT implements IAppConstants
28 {
29     // public: ................................................................
30

31     
32     public static synchronized ICoverageData reset (final boolean createCoverageData, final boolean createExitHook)
33     {
34         // reload the app properties [needs to be done to accomodate classloader rearrangements]:
35

36         // avoid the call context tricks at runtime in case security causes problems,
37
// use an explicit caller parameter for getAppProperties():
38

39         ClassLoader JavaDoc loader = RT.class.getClassLoader ();
40         if (loader == null) loader = ClassLoader.getSystemClassLoader ();
41         
42         IProperties appProperties = null;
43         try
44         {
45             appProperties = EMMAProperties.getAppProperties (loader);
46         }
47         catch (Throwable JavaDoc t)
48         {
49             // TODO: handle better
50
t.printStackTrace (System.out);
51         }
52         s_appProperties = appProperties;
53
54
55         if (EXIT_HOOK_MANAGER != null)
56         {
57             // disable/remove the current hook, if any:
58

59             if (s_exitHook != null)
60             {
61                  // note: no attempt is made to execute the existing hook, so its coverage
62
// data may be simply discarded
63

64                 EXIT_HOOK_MANAGER.removeExitHook (s_exitHook);
65                 s_exitHook = null;
66             }
67         }
68         
69         ICoverageData cdata = s_cdata; // no sync accessor needed
70
if (createCoverageData)
71         {
72             cdata = DataFactory.newCoverageData ();
73             s_cdata = cdata;
74         }
75         else
76         {
77             s_cdata = null;
78         }
79         
80         if (EXIT_HOOK_MANAGER != null)
81         {
82             if (createExitHook && (cdata != null))
83             {
84                 final Runnable JavaDoc exitHook = new RTExitHook (RT.class, cdata, getCoverageOutFile (), getCoverageOutMerge ());
85
86                 // FR SF978671: fault all classes that we might need to do coverage
87
// data dumping (this forces classdefs to be loaded into classloader
88
// class cache and allows output file writing to succeed even if
89
// the RT classloader is some component loader (e.g, in a J2EE container)
90
// that gets invalidated by the time the exit hook thread is run:
91

92                 RTExitHook.createClassLoaderClosure ();
93                 
94                 if (EXIT_HOOK_MANAGER.addExitHook (exitHook))
95                 {
96                     s_exitHook = exitHook;
97                 }
98                 // else TODO: log/warn
99
}
100         }
101         
102         return cdata;
103     }
104     
105     public static void r (final boolean [][] coverage, final String JavaDoc classVMName, final long stamp)
106     {
107         // note that we use class names, not the actual Class objects, as the keys here. This
108
// is not the best possible solution because it is not capable of supporting
109
// multiply (re)loaded classes within the same app, but the rest of the toolkit
110
// isn't designed to support this anyway. Furthermore, this does not interfere
111
// with class unloading.
112

113         final ICoverageData cdata = getCoverageData (); // need to use accessor for JMM reasons
114

115         // ['cdata' can be null if a previous call to dumpCoverageData() disabled data collection]
116

117         if (cdata != null)
118         {
119             synchronized (cdata.lock ())
120             {
121                 // TODO: could something useful be communicated back to the class
122
// by returning something here [e.g., unique class ID (solves the
123
// issues of class name collisions and class reloading) or RT.class
124
// (to prevent RT reloading)]
125

126                 cdata.addClass (coverage, classVMName, stamp);
127             }
128         }
129     }
130
131     public static synchronized ICoverageData getCoverageData ()
132     {
133         return s_cdata;
134     }
135     
136     public static synchronized IProperties getAppProperties ()
137     {
138         return s_appProperties;
139     }
140     
141     /**
142      * Public API for forcing coverage data dump.
143      *
144      * @param outFile
145      * @param merge
146      * @param stopDataCollection
147      */

148     public static synchronized void dumpCoverageData (File JavaDoc outFile, final boolean merge, final boolean stopDataCollection)
149     {
150         if (DEBUG) System.out.println ("RT::dumpCoverageData() DUMPING " + RT.class.getClassLoader ());
151         outFile = outFile != null ? outFile : getCoverageOutFile ();
152         
153         ICoverageData cdata = s_cdata; // no need to use accessor
154
if (stopDataCollection) s_cdata = null; // TODO: log this NOTE: this does not really stop data collection, merely prevents new class registration
155

156         RTCoverageDataPersister.dumpCoverageData (cdata, ! stopDataCollection, outFile, merge);
157     }
158     
159     public static synchronized void dumpCoverageData (File JavaDoc outFile, final boolean stopDataCollection)
160     {
161         outFile = outFile != null ? outFile : getCoverageOutFile ();
162         
163         ICoverageData cdata = s_cdata; // no need to use accessor
164
if (stopDataCollection) s_cdata = null; // TODO: log this NOTE: this does not really stop data collection, merely prevents new class registration
165

166         RTCoverageDataPersister.dumpCoverageData (cdata, ! stopDataCollection, outFile, getCoverageOutMerge ());
167     }
168     
169     // protected: .............................................................
170

171     // package: ...............................................................
172

173     // private: ...............................................................
174

175     
176     private RT () {} // prevent subclassing
177

178     
179     private static File JavaDoc getCoverageOutFile ()
180     {
181         final IProperties appProperties = getAppProperties (); // sync accessor
182
if (appProperties != null)
183         {
184             final String JavaDoc property = appProperties.getProperty (EMMAProperties.PROPERTY_COVERAGE_DATA_OUT_FILE,
185                                                                EMMAProperties.DEFAULT_COVERAGE_DATA_OUT_FILE);
186             return new File JavaDoc (property);
187         }
188         
189         return new File JavaDoc (EMMAProperties.DEFAULT_COVERAGE_DATA_OUT_FILE);
190     }
191     
192     private static boolean getCoverageOutMerge ()
193     {
194         final IProperties appProperties = getAppProperties (); // sync accessor
195
if (appProperties != null)
196         {
197             // [Boolean.toString (boolean) is J2SDK 1.4+]
198

199             final String JavaDoc property = appProperties.getProperty (EMMAProperties.PROPERTY_COVERAGE_DATA_OUT_MERGE,
200                                                                EMMAProperties.DEFAULT_COVERAGE_DATA_OUT_MERGE.toString ());
201             return Property.toBoolean (property);
202         }
203         
204         return EMMAProperties.DEFAULT_COVERAGE_DATA_OUT_MERGE.booleanValue ();
205     }
206     
207         
208     private static ICoverageData s_cdata;
209     private static Runnable JavaDoc s_exitHook;
210     private static IProperties s_appProperties; // TODO: this is better of as java.util.Properties
211

212     private static final ExitHookManager EXIT_HOOK_MANAGER; // set in <clinit>
213

214     private static final boolean DEBUG = false;
215     
216     static
217     {
218         if (DEBUG) System.out.println ("RT[" + System.identityHashCode (RT.class) + "]::<clinit>: loaded by " + RT.class.getClassLoader ());
219         
220         ExitHookManager temp = null;
221         try
222         {
223             temp = ExitHookManager.getSingleton ();
224         }
225         catch (Throwable JavaDoc t)
226         {
227             // TODO: handle better
228
t.printStackTrace (System.out);
229         }
230         EXIT_HOOK_MANAGER = temp;
231
232          
233         if (RTSettings.isStandaloneMode ())
234         {
235             if (DEBUG) System.out.println ("RT::<clinit>: STANDALONE MODE");
236             
237             // load app props, create coverage data, and register an exit hook for it:
238
reset (true, true);
239             
240             // use method-scoped loggers in RT:
241
final Logger log = Logger.getLogger ();
242             if (log.atINFO ())
243             {
244                 log.info ("collecting runtime coverage data ...");
245             }
246         }
247         else
248         {
249             // load app props only:
250
reset (false, false);
251         }
252     }
253
254 } // end of class
255
// ----------------------------------------------------------------------------
Popular Tags