1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
|
/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
*
* This program and the accompanying materials are made available under
* the terms of the Common Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/cpl-v10.html
*
* $Id: RT.java,v 1.2.2.3 2004/07/16 23:32:03 vlad_r Exp $
*/
package com.vladium.emma.rt;
import java.io.File;
import com.vladium.logging.Logger;
import com.vladium.util.IProperties;
import com.vladium.util.Property;
import com.vladium.util.exit.ExitHookManager;
import com.vladium.emma.IAppConstants;
import com.vladium.emma.EMMAProperties;
import com.vladium.emma.data.ICoverageData;
import com.vladium.emma.data.DataFactory;
// ----------------------------------------------------------------------------
/**
* @author Vlad Roubtsov, (C) 2003
*/
public
abstract class RT implements IAppConstants
{
// public: ................................................................
public static synchronized ICoverageData reset (final boolean createCoverageData, final boolean createExitHook)
{
// reload the app properties [needs to be done to accomodate classloader rearrangements]:
// avoid the call context tricks at runtime in case security causes problems,
// use an explicit caller parameter for getAppProperties():
ClassLoader loader = RT.class.getClassLoader ();
if (loader == null) loader = ClassLoader.getSystemClassLoader ();
IProperties appProperties = null;
try
{
appProperties = EMMAProperties.getAppProperties (loader);
}
catch (Throwable t)
{
// TODO: handle better
t.printStackTrace (System.out);
}
s_appProperties = appProperties;
if (EXIT_HOOK_MANAGER != null)
{
// disable/remove the current hook, if any:
if (s_exitHook != null)
{
// note: no attempt is made to execute the existing hook, so its coverage
// data may be simply discarded
EXIT_HOOK_MANAGER.removeExitHook (s_exitHook);
s_exitHook = null;
}
}
ICoverageData cdata = s_cdata; // no sync accessor needed
if (createCoverageData)
{
cdata = DataFactory.newCoverageData ();
s_cdata = cdata;
}
else
{
s_cdata = null;
}
if (EXIT_HOOK_MANAGER != null)
{
if (createExitHook && (cdata != null))
{
final Runnable exitHook = new RTExitHook (RT.class, cdata, getCoverageOutFile (), getCoverageOutMerge ());
// FR SF978671: fault all classes that we might need to do coverage
// data dumping (this forces classdefs to be loaded into classloader
// class cache and allows output file writing to succeed even if
// the RT classloader is some component loader (e.g, in a J2EE container)
// that gets invalidated by the time the exit hook thread is run:
RTExitHook.createClassLoaderClosure ();
if (EXIT_HOOK_MANAGER.addExitHook (exitHook))
{
s_exitHook = exitHook;
}
// else TODO: log/warn
}
}
return cdata;
}
public static void r (final boolean [][] coverage, final String classVMName, final long stamp)
{
// note that we use class names, not the actual Class objects, as the keys here. This
// is not the best possible solution because it is not capable of supporting
// multiply (re)loaded classes within the same app, but the rest of the toolkit
// isn't designed to support this anyway. Furthermore, this does not interfere
// with class unloading.
final ICoverageData cdata = getCoverageData (); // need to use accessor for JMM reasons
// ['cdata' can be null if a previous call to dumpCoverageData() disabled data collection]
if (cdata != null)
{
synchronized (cdata.lock ())
{
// TODO: could something useful be communicated back to the class
// by returning something here [e.g., unique class ID (solves the
// issues of class name collisions and class reloading) or RT.class
// (to prevent RT reloading)]
cdata.addClass (coverage, classVMName, stamp);
}
}
}
public static synchronized ICoverageData getCoverageData ()
{
return s_cdata;
}
public static synchronized IProperties getAppProperties ()
{
return s_appProperties;
}
/**
* Public API for forcing coverage data dump.
*
* @param outFile
* @param merge
* @param stopDataCollection
*/
public static synchronized void dumpCoverageData (File outFile, final boolean merge, final boolean stopDataCollection)
{
if (DEBUG) System.out.println ("RT::dumpCoverageData() DUMPING " + RT.class.getClassLoader ());
outFile = outFile != null ? outFile : getCoverageOutFile ();
ICoverageData cdata = s_cdata; // no need to use accessor
if (stopDataCollection) s_cdata = null; // TODO: log this NOTE: this does not really stop data collection, merely prevents new class registration
RTCoverageDataPersister.dumpCoverageData (cdata, ! stopDataCollection, outFile, merge);
}
public static synchronized void dumpCoverageData (File outFile, final boolean stopDataCollection)
{
outFile = outFile != null ? outFile : getCoverageOutFile ();
ICoverageData cdata = s_cdata; // no need to use accessor
if (stopDataCollection) s_cdata = null; // TODO: log this NOTE: this does not really stop data collection, merely prevents new class registration
RTCoverageDataPersister.dumpCoverageData (cdata, ! stopDataCollection, outFile, getCoverageOutMerge ());
}
// protected: .............................................................
// package: ...............................................................
// private: ...............................................................
private RT () {} // prevent subclassing
private static File getCoverageOutFile ()
{
final IProperties appProperties = getAppProperties (); // sync accessor
if (appProperties != null)
{
final String property = appProperties.getProperty (EMMAProperties.PROPERTY_COVERAGE_DATA_OUT_FILE,
EMMAProperties.DEFAULT_COVERAGE_DATA_OUT_FILE);
return new File (property);
}
return new File (EMMAProperties.DEFAULT_COVERAGE_DATA_OUT_FILE);
}
private static boolean getCoverageOutMerge ()
{
final IProperties appProperties = getAppProperties (); // sync accessor
if (appProperties != null)
{
// [Boolean.toString (boolean) is J2SDK 1.4+]
final String property = appProperties.getProperty (EMMAProperties.PROPERTY_COVERAGE_DATA_OUT_MERGE,
EMMAProperties.DEFAULT_COVERAGE_DATA_OUT_MERGE.toString ());
return Property.toBoolean (property);
}
return EMMAProperties.DEFAULT_COVERAGE_DATA_OUT_MERGE.booleanValue ();
}
private static ICoverageData s_cdata;
private static Runnable s_exitHook;
private static IProperties s_appProperties; // TODO: this is better of as java.util.Properties
private static final ExitHookManager EXIT_HOOK_MANAGER; // set in <clinit>
private static final boolean DEBUG = false;
static
{
if (DEBUG) System.out.println ("RT[" + System.identityHashCode (RT.class) + "]::<clinit>: loaded by " + RT.class.getClassLoader ());
ExitHookManager temp = null;
try
{
temp = ExitHookManager.getSingleton ();
}
catch (Throwable t)
{
// TODO: handle better
t.printStackTrace (System.out);
}
EXIT_HOOK_MANAGER = temp;
if (RTSettings.isStandaloneMode ())
{
if (DEBUG) System.out.println ("RT::<clinit>: STANDALONE MODE");
// load app props, create coverage data, and register an exit hook for it:
reset (true, true);
// use method-scoped loggers in RT:
final Logger log = Logger.getLogger ();
if (log.atINFO ())
{
log.info ("collecting runtime coverage data ...");
}
}
else
{
// load app props only:
reset (false, false);
}
}
} // end of class
// ----------------------------------------------------------------------------
|