1f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved. 2f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 3f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * This program and the accompanying materials are made available under 4f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * the terms of the Common Public License v1.0 which accompanies this distribution, 5f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * and is available at http://www.eclipse.org/legal/cpl-v10.html 6f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 7f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * $Id: AppRunner.java,v 1.1.1.1.2.2 2004/07/16 23:32:03 vlad_r Exp $ 8f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 9f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpackage com.vladium.emma.rt; 10f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 11f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.File; 12f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.lang.reflect.InvocationTargetException; 13f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.lang.reflect.Method; 14f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.net.MalformedURLException; 15f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.HashMap; 16f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Iterator; 17f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.ArrayList; 18f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.List; 19f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Map; 20f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 21f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.logging.Logger; 22f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.Files; 23f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.IConstants; 24f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.IProperties; 25f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.Property; 26f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.SoftValueMap; 27f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.Strings; 28f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.asserts.$assert; 29f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.exception.Exceptions; 30f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.exit.ExitHookManager; 31f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.AppLoggers; 32f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.IAppConstants; 33f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.IAppErrorCodes; 34f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.EMMAProperties; 35f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.EMMARuntimeException; 36f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.Processor; 37f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.filter.IInclExclFilter; 38f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.CoverageOptionsFactory; 39f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.IMetaData; 40f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.ICoverageData; 41f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.DataFactory; 42f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.ISessionData; 43f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.SessionData; 44f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.report.AbstractReportGenerator; 45f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.report.IReportGenerator; 46f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.report.SourcePathCache; 47f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 48f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ---------------------------------------------------------------------------- 49f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/** 50f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @author Vlad Roubtsov, (C) 2003 51f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 52f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpublic 53f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectfinal class AppRunner extends Processor 54f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project implements IAppErrorCodes 55f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project{ 56f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // public: ................................................................ 57f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 58f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 59f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static AppRunner create (final ClassLoader delegate) 60f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 61f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return new AppRunner (delegate); 62f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 63f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 64f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 65f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized void run () 66f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 67f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project validateState (); 68f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 69f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // disable Runtime's own exit hook: 70f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RTSettings.setStandaloneMode (false); // an optimization to disable RT's static init code [this line must precede any reference to RT] 71f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RT.reset (true, false); // reset RT [RT creates 'cdata' and loads app properties] 72f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 73f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // load tool properties: 74f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IProperties toolProperties; 75f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 76f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project IProperties appProperties = RT.getAppProperties (); // try to use app props consistent with RT's view of them 77f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (appProperties == null) appProperties = EMMAProperties.getAppProperties (); // don't use combine() 78f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 79f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project toolProperties = IProperties.Factory.combine (m_propertyOverrides, appProperties); 80f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 81f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (toolProperties != null, "toolProperties is null"); // can be empty, though 82f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 83f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger current = Logger.getLogger (); 84f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger log = AppLoggers.create (m_appName, toolProperties, current); 85f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 86f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atTRACE1 ()) 87f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 88f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.trace1 ("run", "complete tool properties:"); 89f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project toolProperties.list (log.getWriter ()); 90f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 91f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 92f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 93f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 94f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Logger.push (log); 95f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log = log; 96f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 97f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project _run (toolProperties); 98f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 99f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_log != null) 102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Logger.pop (m_log); 104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log = null; 105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @param path [null is equivalent to empty array] 112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @param canonical 113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized void setCoveragePath (String [] path, final boolean canonical) 115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((path == null) || (path.length == 0)) 117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_coveragePath = IConstants.EMPTY_FILE_ARRAY; 118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_coveragePath = Files.pathToFiles (path, canonical); 120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_canonical = canonical; 122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized void setScanCoveragePath (final boolean scan) 125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_scanCoveragePath = scan; 127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @param path [null is equivalent to no source path] 131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized void setSourcePath (final String [] path) 133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (path == null) 135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_sourcePath = null; 136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_sourcePath = Files.pathToFiles (path, true); // always canonicalize source path 138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @param specs [null is equivalent to no filtering (everything is included)] 143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized final void setInclExclFilter (final String [] specs) 145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (specs == null) 147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_coverageFilter = null; 148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_coverageFilter = IInclExclFilter.Factory.create (specs); 150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @param className [may not be null or empty] 155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @param args [null is equivalent to an empty array] 156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized void setAppClass (final String className, final String [] args) 158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((className == null) || (className.length () == 0)) 160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IllegalArgumentException ("null/empty input: className"); 161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (args != null) 163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String [] _args = (String []) args.clone (); 165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int a = 0; a < _args.length; ++ a) 167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (_args [a] == null) throw new IllegalArgumentException ("null input: args[" + a + "]"); 168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_appArgs = _args; 170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_appArgs = IConstants.EMPTY_STRING_ARRAY; 174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_appClassName = className; 177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized void setDumpSessionData (final boolean dump) 180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_dumpSessionData = dump; 182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @param fileName [null unsets the previous override setting] 187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized final void setSessionOutFile (final String fileName) 189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (fileName == null) 191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_sdataOutFile = null; 192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File _file = new File (fileName); 195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (_file.exists () && ! _file.isFile ()) 197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IllegalArgumentException ("not a file: [" + _file.getAbsolutePath () + "]"); 198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_sdataOutFile = _file; 200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @param merge [null unsets the previous override setting] 206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized final void setSessionOutMerge (final Boolean merge) 208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_sdataOutMerge = merge; 210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @param types [may not be null] 215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized void setReportTypes (final String [] types) 217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (types == null) throw new IllegalArgumentException ("null input: types"); 219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String [] reportTypes = Strings.removeDuplicates (types, true); 221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (reportTypes.length == 0) throw new IllegalArgumentException ("empty input: types"); 222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (reportTypes != null && reportTypes.length > 0); 224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IReportGenerator [] reportGenerators = new IReportGenerator [reportTypes.length]; 227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int t = 0; t < reportTypes.length; ++ t) 228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project reportGenerators [t] = AbstractReportGenerator.create (reportTypes [t]); 230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 231f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 232f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_reportGenerators = reportGenerators; 233f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 234f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 235f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // protected: ............................................................. 236f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 237f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 238f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected void validateState () 239f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 240f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super.validateState (); 241f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 242f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((m_appClassName == null) || (m_appClassName.length () == 0)) 243f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IllegalStateException ("application class name not set"); 244f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 245f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_appArgs == null) 246f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IllegalStateException ("application arguments not set"); 247f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 248f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_coveragePath == null) 249f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IllegalStateException ("coverage path not set"); 250f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 251f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [m_coverageFilter can be null] 252f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 253f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [m_sdataOutFile can be null] 254f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [m_sdataOutMerge can be null] 255f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 256f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((m_reportGenerators == null) || (m_reportGenerators.length == 0)) 257f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IllegalStateException ("report types not set"); 258f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 259f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [m_sourcePath can be null/empty] 260f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 261f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [m_propertyOverrides can be null] 262f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 263f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 264f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 265f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected void _run (final IProperties toolProperties) 266f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 267f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger log = m_log; 268f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 269f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean verbose = log.atVERBOSE (); 270f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (verbose) 271f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 272f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose (IAppConstants.APP_VERBOSE_BUILD_ID); 273f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 274f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [assertion: m_coveragePath != null] 275f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("coverage path:"); 276f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("{"); 277f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int p = 0; p < m_coveragePath.length; ++ p) 278f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 279f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File f = m_coveragePath [p]; 280f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String nonexistent = f.exists () ? "" : "{nonexistent} "; 281f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 282f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose (" " + nonexistent + f.getAbsolutePath ()); 283f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 284f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("}"); 285f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 286f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((m_sourcePath == null) || (m_sourcePath.length == 0)) 287f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 288f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("source path not set"); 289f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 290f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 291f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 292f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("source path:"); 293f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("{"); 294f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int p = 0; p < m_sourcePath.length; ++ p) 295f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 296f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File f = m_sourcePath [p]; 297f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String nonexistent = f.exists () ? "" : "{nonexistent} "; 298f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 299f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose (" " + nonexistent + f.getAbsolutePath ()); 300f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 301f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("}"); 302f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 303f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 304f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 305f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // get the data out settings [note: this is not conditioned on m_dumpRawData]: 306f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project File sdataOutFile = m_sdataOutFile; 307f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Boolean sdataOutMerge = m_sdataOutMerge; 308f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 309f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (sdataOutFile == null) 310f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project sdataOutFile = new File (toolProperties.getProperty (EMMAProperties.PROPERTY_SESSION_DATA_OUT_FILE, 311f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EMMAProperties.DEFAULT_SESSION_DATA_OUT_FILE)); 312f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 313f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (sdataOutMerge == null) 314f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 315f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String _dataOutMerge = toolProperties.getProperty (EMMAProperties.PROPERTY_SESSION_DATA_OUT_MERGE, 316f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EMMAProperties.DEFAULT_SESSION_DATA_OUT_MERGE.toString ()); 317f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project sdataOutMerge = Property.toBoolean (_dataOutMerge) ? Boolean.TRUE : Boolean.FALSE; 318f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 319f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 320f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 321f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (verbose && m_dumpSessionData) 322f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 323f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("session data output file: " + sdataOutFile.getAbsolutePath ()); 324f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("session data output merge mode: " + sdataOutMerge); 325f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 326f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 327f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // get instr class loader delegation filter settings: 328f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IInclExclFilter forcedDelegationFilter 329f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project = IInclExclFilter.Factory.create (toolProperties.getProperty (InstrClassLoader.PROPERTY_FORCED_DELEGATION_FILTER), 330f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project COMMA_DELIMITERS, FORCED_DELEGATION_FILTER_SPECS); 331f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IInclExclFilter throughDelegationFilter 332f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project = IInclExclFilter.Factory.create (toolProperties.getProperty (InstrClassLoader.PROPERTY_THROUGH_DELEGATION_FILTER), 333f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project COMMA_DELIMITERS, null); 334f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 335f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 336f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: consider injecting Runtime straight into appLoader namespace... 337f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: create a thread group for all exit hooks? 338f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 339f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 340f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // get a handle to exit hook manager singleton: 341f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ExitHookManager runnerExitHookManager = null; 342f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 343f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 344f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project runnerExitHookManager = ExitHookManager.getSingleton (); // can throw 345f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 346f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (Exception e) 347f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 348f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: log/handle/warn 349f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project e.printStackTrace (System.out); 350f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 351f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 352f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project AppRunnerExitHook runnerExitHook = null; 353f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RuntimeException failure = null; 354f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 355f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 356f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 357f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project SourcePathCache srcpathCache = null; 358f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_sourcePath != null) srcpathCache = new SourcePathCache (m_sourcePath, true); // ignore non-existent source dirs 359f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 360f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // create session data containers: 361f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ICoverageData cdata = RT.getCoverageData (); 362f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (cdata != null, "cdata is null"); 363f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 364f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project IMetaData mdata = DataFactory.newMetaData (CoverageOptionsFactory.create (toolProperties)); 365f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 366f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project runnerExitHook = new AppRunnerExitHook (log, m_dumpSessionData, sdataOutFile, sdataOutMerge.booleanValue (), mdata, cdata, m_reportGenerators, srcpathCache, toolProperties); 367f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 368f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (runnerExitHookManager != null) 369f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project runnerExitHookManager.addExitHook (runnerExitHook); 370f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 371f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // --------------[ start of exit hook-protected section ]-------------- 372f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 373f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Map classIOCache = null; 374f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 375f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // scan the classpath to populate the initial metadata: 376f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_scanCoveragePath) 377f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 378f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (USE_SOFT_CACHE) 379f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project classIOCache = new SoftValueMap (INIT_CACHE_CAPACITY, 0.75F, SOFT_CACHE_READ_CHK_FREQUENCY, SOFT_CACHE_WRITE_CHK_FREQUENCY); 380f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 381f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project classIOCache = new HashMap (INIT_CACHE_CAPACITY, 0.75F); 382f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 383f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ClassPathProcessorST processor = new ClassPathProcessorST (m_coveragePath, m_canonical, mdata, m_coverageFilter, classIOCache); 384f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 385f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // with a bit of work [ClassPathProcessorST needs to lock on the 386f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // metadata, etc] this could be run concurrently with the app 387f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // itself to improve perceived performance, however, I am not 388f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // going to invest time in this; 389f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 390f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // populate 'cache' [optional] and 'mdata': 391f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project processor.run (); 392f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 393f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atTRACE1 ()) 394f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 395f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.trace1 ("run", "class cache size after cp scan: " + classIOCache.size ()); 396f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.trace1 ("run", "metadata size after cp scan: " + mdata.size ()); 397f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 398f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 399f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 400f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 401f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // app runner does not need these handles anymore [only the exit hook runner maintains them]: 402f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project srcpathCache = null; 403f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project cdata = null; 404f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 405f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ClassLoader appLoader; 406f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 407f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IClassLoadHook loadHook = new InstrClassLoadHook (m_coverageFilter, mdata); 408f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 409f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 410f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 411f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project appLoader = new InstrClassLoader (m_delegate, m_coveragePath, forcedDelegationFilter, throughDelegationFilter, loadHook, classIOCache); 412f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 413f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (SecurityException se) 414f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 415f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (SECURITY_RESTRICTION, new String [] {IAppConstants.APP_NAME}, se); 416f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 417f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (MalformedURLException mue) 418f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 419f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (mue); 420f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 421f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 422f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 423f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // app runner does not need these handles anymore: 424f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project mdata = null; 425f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project classIOCache = null; 426f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 427f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 428f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ClassLoader contextLoader; 429f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean contextLoaderSet = false; 430f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (SET_CURRENT_CONTEXT_LOADER) 431f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 432f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 433f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 434f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Thread currentThread = Thread.currentThread (); 435f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 436f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: rethink if this is the right place to do this 437f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project contextLoader = currentThread.getContextClassLoader (); 438f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project currentThread.setContextClassLoader (appLoader); 439f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 440f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project contextLoaderSet = true; 441f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 442f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (SecurityException se) 443f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 444f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (SECURITY_RESTRICTION, new String [] {IAppConstants.APP_NAME}, se); 445f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 446f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 447f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 448f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 449f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ThreadGroup appThreadGroup = null; 450f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 451f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 452f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // load [and possibly initialize] the app class: 453f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 454f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Class appClass; 455f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 456f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 457f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // load [and force early initialization if INIT_AT_LOAD_TIME is 'true']: 458f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project appClass = Class.forName (m_appClassName, INIT_AT_LOAD_TIME, appLoader); 459f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 460f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (ClassNotFoundException cnfe) 461f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 462f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: dump the classloader tree into the error message as well 463f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (MAIN_CLASS_NOT_FOUND, new String [] {m_appClassName}, cnfe); 464f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 465f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (ExceptionInInitializerError eiie) // this should not happen for INIT_AT_LOAD_TIME=false 466f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 467f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Throwable cause = eiie.getException (); 468f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 469f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (MAIN_CLASS_LOAD_FAILURE, new String [] {m_appClassName, cause.toString ()}, cause); 470f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 471f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (Throwable t) 472f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 473f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (MAIN_CLASS_NOT_FOUND, new String [] {m_appClassName}, t); 474f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 475f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 476f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // ensure that the app is bootstrapped using appLoader: 477f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 478f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ClassLoader actualLoader = appClass.getClassLoader (); 479f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (actualLoader != appLoader) 480f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 481f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String loaderName = actualLoader != null ? actualLoader.getClass ().getName () : "<PRIMORDIAL>"; 482f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 483f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (MAIN_CLASS_BAD_DELEGATION, new String [] {IAppConstants.APP_NAME, m_appClassName, loaderName}); 484f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 485f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 486f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 487f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // run the app's main(): 488f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 489f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Method appMain; 490f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 491f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 492f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // this causes initialization on some non-Sun-compatible JVMs [ignore]: 493f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project appMain = appClass.getMethod ("main", MAIN_TYPE); // Sun JVMs do not seem to require the method to be declared 494f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 495f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (Throwable t) 496f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 497f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (MAIN_METHOD_NOT_FOUND, new String [] {m_appClassName}, t); 498f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 499f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 500f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Invoker invoker = new Invoker (appMain, null, new Object [] {m_appArgs}); 501f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 502f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project appThreadGroup = new ThreadGroup (IAppConstants.APP_NAME + " thread group [" + m_appClassName + "]"); 503f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project appThreadGroup.setDaemon (true); 504f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 505f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Thread appThread = new Thread (appThreadGroup, invoker, IAppConstants.APP_NAME + " main() thread"); 506f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project appThread.setContextClassLoader (appLoader); 507f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 508f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // --- [app start] ---- 509f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 510f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project appThread.start (); 511f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 512f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try {appThread.join (); } catch (InterruptedException ignore) {} 513f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project appThread = null; 514f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 515f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project joinNonDeamonThreads (appThreadGroup); 516f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 517f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // --- [app end] ---- 518f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 519f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atTRACE1 ()) 520f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 521f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (appLoader instanceof InstrClassLoader) ((InstrClassLoader) appLoader).debugDump (log.getWriter ()); 522f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 523f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 524f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Throwable mainFailure = invoker.getFailure (); 525f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project invoker = null; 526f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 527f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (mainFailure != null) 528f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 529f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (mainFailure instanceof InvocationTargetException) 530f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 531f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Throwable cause = ((InvocationTargetException) mainFailure).getTargetException (); 532f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 533f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (MAIN_METHOD_FAILURE, new String [] {m_appClassName, cause.toString ()}, cause); 534f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 535f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else if (mainFailure instanceof ExceptionInInitializerError) 536f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 537f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // this catch block is never entered if INIT_AT_LOAD_TIME is 'true' 538f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Throwable cause = ((ExceptionInInitializerError) mainFailure).getException (); 539f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 540f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (MAIN_METHOD_FAILURE, new String [] {m_appClassName, cause.toString ()}, cause); 541f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 542f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else if ((mainFailure instanceof IllegalAccessException) || 543f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project (mainFailure instanceof IllegalArgumentException) || 544f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project (mainFailure instanceof NullPointerException)) 545f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 546f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (MAIN_METHOD_NOT_FOUND, new String [] {m_appClassName}, mainFailure); 547f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 548f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 549f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 550f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (MAIN_METHOD_FAILURE, new String [] {m_appClassName, mainFailure.toString ()}, mainFailure); 551f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 552f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 553f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 554f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (SecurityException se) 555f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 556f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (SECURITY_RESTRICTION, new String [] {IAppConstants.APP_NAME}, se); 557f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 558f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 559f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 560f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (SET_CURRENT_CONTEXT_LOADER && contextLoaderSet) 561f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 562f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 563f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 564f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Thread.currentThread ().setContextClassLoader (contextLoader); 565f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 566f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (Throwable ignore) {} 567f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 568f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 569f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((appThreadGroup != null) && ! appThreadGroup.isDestroyed ()) 570f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 571f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 572f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project appThreadGroup.destroy (); 573f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project appThreadGroup = null; 574f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 575f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (Throwable ignore) {} 576f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 577f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 578f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (RuntimeException re) 579f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 580f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project failure = re; // should be EMMARuntimeException only if there are no errors above 581f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 582f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 583f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 584f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RT.reset (false, false); 585f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 586f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 587f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (runnerExitHook != null, "reportExitHook = null"); 588f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project runnerExitHook.run (); // that this may be a noop (if the shutdown sequence got there first) 589f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 590f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [assertion: the report exit hook is done] 591f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 592f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (runnerExitHookManager != null) 593f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 594f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project runnerExitHookManager.removeExitHook (runnerExitHook); // Ok if this fails 595f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project runnerExitHookManager = null; 596f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 597f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 598f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // ---------------[ end of exit hook-protected section ]--------------- 599f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 600f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 601f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Throwable exitHookDataDumpFailure = runnerExitHook.getDataDumpFailure (); 602f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final List /* Throwable */ exitHookReportFailures = runnerExitHook.getReportFailures (); 603f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project runnerExitHook = null; 604f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 605f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (failure != null) // 'failure' takes precedence over any possible exit hook's problems 606f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 607f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw wrapFailure (failure); 608f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 609f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else if ((exitHookDataDumpFailure != null) || (exitHookReportFailures != null)) 610f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 611f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (exitHookDataDumpFailure != null) 612f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.log (Logger.SEVERE, "exception while persisting raw session data:", exitHookDataDumpFailure); 613f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 614f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Throwable firstReportFailure = null; 615f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (exitHookReportFailures != null) 616f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 617f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (Iterator i = exitHookReportFailures.iterator (); i.hasNext (); ) 618f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 619f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Throwable reportFailure = (Throwable) i.next (); 620f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (firstReportFailure == null) firstReportFailure = reportFailure; 621f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 622f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.log (Logger.SEVERE, "exception while creating a report:", reportFailure); 623f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 624f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 625f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 626f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (exitHookDataDumpFailure != null) 627f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw wrapFailure (exitHookDataDumpFailure); 628f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else if (firstReportFailure != null) // redundant check 629f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw wrapFailure (firstReportFailure); 630f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 631f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 632f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 633f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 634f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // package: ............................................................... 635f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 636f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // private: ............................................................... 637f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 638f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 639f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final class Invoker implements Runnable 640f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 641f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Invoker (final Method method, final Object target, final Object [] args) 642f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 643f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (method == null) throw new IllegalArgumentException ("null input: method"); 644f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (args == null) throw new IllegalArgumentException ("null input: args"); 645f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 646f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_method = method; 647f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_target = target; 648f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_args = args; 649f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 650f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 651f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public void run () 652f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 653f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 654f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 655f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_method.invoke (m_target, m_args); 656f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 657f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (Throwable t) 658f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 659f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_failure = t; 660f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 661f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 662f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 663f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Throwable getFailure () 664f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 665f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return m_failure; 666f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 667f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 668f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 669f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final Method m_method; 670f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final Object m_target; 671f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final Object [] m_args; 672f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private Throwable m_failure; 673f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 674f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 675f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 676f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 677f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final class AppRunnerExitHook implements Runnable 678f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 679f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized void run () 680f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 681f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 682f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 683f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! m_done) 684f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 685f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // grab data snapshots: 686f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 687f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IMetaData mdataSnashot = m_mdata.shallowCopy (); 688f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_mdata = null; 689f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ICoverageData cdataSnapshot = m_cdata.shallowCopy (); 690f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_cdata = null; 691f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 692f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (mdataSnashot.isEmpty ()) 693f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 694f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log.warning ("no metadata collected at runtime [no reports generated]"); 695f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 696f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return; 697f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 698f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 699f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (cdataSnapshot.isEmpty ()) 700f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 701f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log.warning ("no coverage data collected at runtime [all reports will be empty]"); 702f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 703f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 704f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ISessionData sdata = new SessionData (mdataSnashot, cdataSnapshot); 705f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 706f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // if requested, dump raw data before running report generators: 707f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [note that the raw dumps and reports will be consistent wrt 708f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // the session data they represent] 709f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 710f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_dumpRawData && (m_sdataOutFile != null)) 711f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 712f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 713f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 714f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean info = m_log.atINFO (); 715f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 716f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long start = info ? System.currentTimeMillis () : 0; 717f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 718f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project DataFactory.persist (sdata, m_sdataOutFile, m_sdataOutMerge); 719f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 720f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (info) 721f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 722f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long end = System.currentTimeMillis (); 723f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 724f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log.info ("raw session data " + (m_sdataOutMerge ? "merged into" : "written to") + " [" + m_sdataOutFile.getAbsolutePath () + "] {in " + (end - start) + " ms}"); 725f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 726f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 727f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (Throwable t) 728f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 729f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_dataDumpFailure = t; 730f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 731f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 732f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 733f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int g = 0; g < m_generators.length; ++ g) 734f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 735f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IReportGenerator generator = m_generators [g]; 736f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 737f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (generator != null) 738f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 739f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 740f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 741f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project generator.process (mdataSnashot, cdataSnapshot, m_cache, m_properties); 742f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 743f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (Throwable t) 744f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 745f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_reportFailures == null) m_reportFailures = new ArrayList (); 746f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_reportFailures.add (t); 747f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 748f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project continue; 749f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 750f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 751f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 752f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try { generator.cleanup (); } catch (Throwable ignore) {} 753f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_generators [g] = null; 754f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 755f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 756f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 757f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 758f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 759f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 760f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 761f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_generators = null; 762f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_mdata = null; 763f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_cdata = null; 764f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_properties = null; 765f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_cache = null; 766f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 767f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_done = true; 768f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 769f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 770f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 771f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // note: because ExitHookManager is a lazily created static singleton the 772f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // correct thing to do is to pass an explicit Logger into each exit hook runner 773f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // instead of relying on thread inheritance: 774f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 775f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project AppRunnerExitHook (final Logger log, 776f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean dumpRawData, final File sdataOutFile, final boolean sdataOutMerge, 777f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IMetaData mdata, final ICoverageData cdata, 778f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IReportGenerator [] generators, 779f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final SourcePathCache cache, final IProperties properties) 780f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 781f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log == null) throw new IllegalArgumentException ("null input: log"); 782f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((generators == null) || (generators.length == 0)) throw new IllegalArgumentException ("null/empty input: generators"); 783f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (mdata == null) throw new IllegalArgumentException ("null input: mdata"); 784f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (cdata == null) throw new IllegalArgumentException ("null input: cdata"); 785f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (properties == null) throw new IllegalArgumentException ("null input: properties"); 786f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 787f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_log = log; 788f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 789f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_dumpRawData = dumpRawData; 790f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_sdataOutFile = sdataOutFile; 791f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_sdataOutMerge = sdataOutMerge; 792f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 793f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_generators = (IReportGenerator []) generators.clone (); 794f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_mdata = mdata; 795f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_cdata = cdata; 796f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_cache = cache; 797f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_properties = properties; 798f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 799f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 800f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 801f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project synchronized Throwable getDataDumpFailure () 802f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 803f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return m_dataDumpFailure; 804f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 805f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 806f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project synchronized List /* Throwable */ getReportFailures () 807f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 808f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return m_reportFailures; 809f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 810f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 811f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 812f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final Logger m_log; 813f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final boolean m_dumpRawData; 814f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final File m_sdataOutFile; 815f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final boolean m_sdataOutMerge; 816f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 817f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private IReportGenerator [] m_generators; 818f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private IMetaData m_mdata; 819f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private ICoverageData m_cdata; 820f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private SourcePathCache m_cache; 821f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private IProperties m_properties; 822f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private boolean m_done; 823f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private Throwable m_dataDumpFailure; 824f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private List /* Throwable */ m_reportFailures; 825f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 826f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 827f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 828f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 829f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private AppRunner (final ClassLoader delegate) 830f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 831f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_delegate = delegate; 832f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_coveragePath = IConstants.EMPTY_FILE_ARRAY; 833f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 834f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 835f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 836f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static void joinNonDeamonThreads (final ThreadGroup group) 837f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 838f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (group == null) throw new IllegalArgumentException ("null input: group"); 839f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 840f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final List threads = new ArrayList (); 841f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project while (true) 842f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 843f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project threads.clear (); 844f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 845f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // note: group.activeCount() is only an estimate as more threads 846f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // could get created while we are doing this [if 'aliveThreads' 847f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // array is too short, the extra threads are silently ignored]: 848f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 849f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Thread [] aliveThreads; 850f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int aliveCount; 851f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 852f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // enumerate [recursively] all threads in 'group': 853f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project synchronized (group) 854f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 855f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project aliveThreads = new Thread [group.activeCount () << 1]; 856f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project aliveCount = group.enumerate (aliveThreads, true); 857f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 858f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 859f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int t = 0; t < aliveCount; t++) 860f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 861f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! aliveThreads [t].isDaemon ()) 862f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project threads.add (aliveThreads [t]); 863f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 864f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project aliveThreads = null; 865f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 866f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (threads.isEmpty ()) 867f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; // note: this logic does not work if daemon threads are spawning non-daemon ones 868f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 869f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 870f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (Iterator i = threads.iterator (); i.hasNext (); ) 871f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 872f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 873f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 874f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ((Thread) i.next ()).join (); 875f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 876f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (InterruptedException ignore) {} 877f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 878f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 879f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 880f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 881f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 882f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static RuntimeException wrapFailure (final Throwable t) 883f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 884f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (Exceptions.unexpectedFailure (t, EXPECTED_FAILURES)) 885f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return new EMMARuntimeException (UNEXPECTED_FAILURE, 886f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project new Object [] {t.toString (), IAppConstants.APP_BUG_REPORT_LINK}, 887f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project t); 888f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else if (t instanceof RuntimeException) 889f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return (RuntimeException) t; 890f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 891f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return new EMMARuntimeException (t); 892f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 893f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 894f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 895f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // caller-settable state [scoped to this runner instance]: 896f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 897f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final ClassLoader m_delegate; 898f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 899f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private String m_appClassName; // required to be non-null for run() 900f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private String [] m_appArgs; // required to be non-null for run() 901f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 902f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private File [] m_coveragePath; // required to be non-null/non-empty for run() 903f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private boolean m_canonical; 904f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private boolean m_scanCoveragePath; 905f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private IInclExclFilter m_coverageFilter; // can be null for run() 906f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 907f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private boolean m_dumpSessionData; 908f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private File m_sdataOutFile; // user override; can be null for run() 909f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private Boolean m_sdataOutMerge; // user override; can be null for run() 910f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 911f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private IReportGenerator [] m_reportGenerators; // required to be non-null for run() 912f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private File [] m_sourcePath; // can be null/empty for run() 913f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 914f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // it is attractive to detect errors at load time, but this may allow 915f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // threads created by <clinit> code to escape; on the other hand, classes 916f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // that do not override main() will not get initialized this way and will 917f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // not register with our runtime [which seems a minor problem at this point]: 918f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final boolean INIT_AT_LOAD_TIME = false; 919f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 920f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // setting the context loader on AppRunner's thread should not 921f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // be necessary since the app is run in a dedicated thread group; 922f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // however, if INIT_AT_LOAD_TIME=true the app's <clinit> code 923f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // should run with an adjusted context loader: 924f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final boolean SET_CURRENT_CONTEXT_LOADER = INIT_AT_LOAD_TIME; 925f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 926f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // a soft cache is ideal for managing class definitions that are read during 927f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // the initial classpath scan; however, the default LRU policy parameters for 928f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // clearing SoftReferences in Sun's J2SDK 1.3+ render them next to useless 929f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // in the client HotSpot JVM (in which this tool will probably run most often); 930f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // using a hard cache guarantees 100% cache hit rate but can also raise the 931f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // memory requirements significantly beyond the needs of the original app. 932f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [see bug refs 4471453, 4806720, 4888056, 4239645] 933f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // 934f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // resolution for now: use a soft cache anyway and doc that to make it useful 935f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // for non-trivial apps the user should use -Xms or -XX:SoftRefLRUPolicyMSPerMB 936f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // JVM options or use a server HotSpot JVM 937f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final boolean USE_SOFT_CACHE = true; 938f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 939f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int INIT_CACHE_CAPACITY = 2003; // prime 940f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int SOFT_CACHE_READ_CHK_FREQUENCY = 100; 941f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int SOFT_CACHE_WRITE_CHK_FREQUENCY = 100; 942f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 943f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final String [] FORCED_DELEGATION_FILTER_SPECS; // set in <clinit> 944f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final Class [] MAIN_TYPE = new Class [] {String [].class}; 945f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 946f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final Class [] EXPECTED_FAILURES; // set in <clinit> 947f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 948f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected static final String COMMA_DELIMITERS = "," + Strings.WHITE_SPACE; 949f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected static final String PATH_DELIMITERS = ",".concat (File.pathSeparator); 950f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 951f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static 952f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 953f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EXPECTED_FAILURES = new Class [] 954f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 955f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EMMARuntimeException.class, 956f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project IllegalArgumentException.class, 957f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project IllegalStateException.class, 958f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project }; 959f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 960f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project FORCED_DELEGATION_FILTER_SPECS = new String [] {"+" + IAppConstants.APP_PACKAGE + ".*"}; 961f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 962f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 963f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project} // end of class 964f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------