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: MergeProcessor.java,v 1.1.1.1.2.2 2004/07/16 23:32:29 vlad_r Exp $ 8f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 9f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpackage com.vladium.emma.data; 10f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 11f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.File; 12f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.IOException; 13f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 14f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.logging.Logger; 15f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.Files; 16f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.IConstants; 17f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.IProperties; 18f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.asserts.$assert; 19f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.exception.Exceptions; 20f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.IAppConstants; 21f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.IAppErrorCodes; 22f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.EMMAProperties; 23f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.EMMARuntimeException; 24f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.Processor; 25f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 26f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ---------------------------------------------------------------------------- 27f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/* 28f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * This class was not meant to be public by design. It is made to to work around 29f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * access bugs in reflective invocations. 30f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 31f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/** 32f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @author Vlad Roubtsov, (C) 2003 33f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 34f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpublic 35f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectfinal class MergeProcessor extends Processor 36f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project implements IAppErrorCodes 37f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project{ 38f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // public: ................................................................ 39f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 40f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public static MergeProcessor create () 41f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 42f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return new MergeProcessor (); 43f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 44f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 45f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 46f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 47f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @param path [null is equivalent to an empty array] 48f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 49f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized final void setDataPath (final String [] path) 50f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 51f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((path == null) || (path.length == 0)) 52f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_dataPath = IConstants.EMPTY_FILE_ARRAY; 53f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 54f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_dataPath = Files.pathToFiles (path, true); 55f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 56f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 57f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /** 58f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * NOTE: there is no setter for merge attribute because this processor 59f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * always overwrites the out file [to ensure compaction] 60f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * 61f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @param fileName [null unsets the previous override setting] 62f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 63f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public synchronized final void setSessionOutFile (final String fileName) 64f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 65f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (fileName == null) 66f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_sdataOutFile = null; 67f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 68f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 69f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File _file = new File (fileName); 70f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 71f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (_file.exists () && ! _file.isFile ()) 72f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IllegalArgumentException ("not a file: [" + _file.getAbsolutePath () + "]"); 73f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 74f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_sdataOutFile = _file; 75f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 76f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 77f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 78f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // protected: ............................................................. 79f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 80f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 81f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected void validateState () 82f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 83f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super.validateState (); 84f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 85f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_dataPath == null) 86f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new IllegalStateException ("data path not set"); 87f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 88f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [m_sdataOutFile can be null] 89f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 90f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [m_propertyOverrides can be null] 91f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 92f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 93f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 94f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected void _run (final IProperties toolProperties) 95f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 96f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger log = m_log; 97f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 98f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean verbose = m_log.atVERBOSE (); 99f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (verbose) 100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose (IAppConstants.APP_VERBOSE_BUILD_ID); 102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [assertion: m_dataPath != null] 104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("input data path:"); 105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("{"); 106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int p = 0; p < m_dataPath.length; ++ p) 107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File f = m_dataPath [p]; 109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String nonexistent = f.exists () ? "" : "{nonexistent} "; 110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose (" " + nonexistent + f.getAbsolutePath ()); 112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("}"); 114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.info ("processing input files ..."); 118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // get the data out settings: 121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project File sdataOutFile = m_sdataOutFile; 122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (sdataOutFile == null) 124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project sdataOutFile = new File (toolProperties.getProperty (EMMAProperties.PROPERTY_SESSION_DATA_OUT_FILE, 125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EMMAProperties.DEFAULT_SESSION_DATA_OUT_FILE)); 126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RuntimeException failure = null; 129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project IMetaData mdata = null; 132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ICoverageData cdata = null; 133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // merge all data files: 135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long start = log.atINFO () ? System.currentTimeMillis () : 0; 138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int f = 0; f < m_dataPath.length; ++ f) 140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File dataFile = m_dataPath [f]; 142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (verbose) log.verbose ("processing input file [" + dataFile.getAbsolutePath () + "] ..."); 143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IMergeable [] fileData = DataFactory.load (dataFile); 145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IMetaData _mdata = (IMetaData) fileData [DataFactory.TYPE_METADATA]; 147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (_mdata != null) 148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (verbose) log.verbose (" loaded " + _mdata.size () + " metadata entries"); 150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (mdata == null) 152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project mdata = _mdata; 153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project mdata = (IMetaData) mdata.merge (_mdata); // note: later datapath entries override earlier ones 155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ICoverageData _cdata = (ICoverageData) fileData [DataFactory.TYPE_COVERAGEDATA]; 158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (_cdata != null) 159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (verbose) log.verbose (" loaded " + _cdata.size () + " coverage data entries"); 161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (cdata == null) 163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project cdata = _cdata; 164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project cdata = (ICoverageData) cdata.merge (_cdata); // note: later datapath entries override earlier ones 166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ++ m_dataFileCount; 169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atINFO ()) 172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long end = System.currentTimeMillis (); 174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.info (m_dataFileCount + " file(s) read and merged in " + (end - start) + " ms"); 176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (((mdata == null) || mdata.isEmpty ()) && ((cdata == null) || cdata.isEmpty ())) 179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.warning ("nothing to do: no metadata or coverage data found in any of the input files"); 181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: throw exception or exit quietly? 183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return; 184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: handle 189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ioe.printStackTrace (System.out); 190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (verbose) 194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (mdata != null) 196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose (" merged metadata contains " + mdata.size () + " entries"); 198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (cdata != null) 201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose (" merged coverage data contains " + cdata.size () + " entries"); 203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // write merged data into output file: 207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project $assert.ASSERT (sdataOutFile != null, "sdataOutFile not null"); 209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // the case of the output file being one of the input files is 211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // supported; however, for safety reasons we create output in 212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // a temp file and rename it only when the data is safely persisted: 213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean rename = false; 215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project File tempDataOutFile = null; 216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File canonicalDataOutFile = Files.canonicalizeFile (sdataOutFile); 218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int f = 0; f < m_dataPath.length; ++ f) 220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File canonicalDataFile = Files.canonicalizeFile (m_dataPath [f]); 222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (canonicalDataOutFile.equals (canonicalDataFile)) 223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project rename = true; 225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project break; 226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (rename) // create a temp out file 230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 231f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project File tempFileDir = canonicalDataOutFile.getParentFile (); 232f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (tempFileDir == null) tempFileDir = new File (""); 233f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 234f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // length > 3: 235f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String tempFileName = Files.getFileName (canonicalDataOutFile) + IAppConstants.APP_NAME_LC; 236f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String tempFileExt = EMMAProperties.PROPERTY_TEMP_FILE_EXT; 237f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 238f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 239f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 240f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project tempDataOutFile = Files.createTempFile (tempFileDir, tempFileName, tempFileExt); 241f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 242f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 243f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 244f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code 245f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (ioe); 246f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 247f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 248f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.warning ("the specified output file is one of the input files [" + canonicalDataOutFile + "]"); 249f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.warning ("all merged data will be written to a temp file first [" + tempDataOutFile.getAbsolutePath () + "]"); 250f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 251f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 252f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // persist merged session data: 253f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 254f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long start = log.atINFO () ? System.currentTimeMillis () : 0; 255f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 256f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project File persistFile = null; 257f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 258f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 259f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project persistFile = tempDataOutFile != null ? tempDataOutFile : canonicalDataOutFile; 260f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 261f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: the persister API is ugly, redesign 262f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 263f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((mdata == null) || mdata.isEmpty ()) 264f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project DataFactory.persist (cdata, persistFile, false); // never merge to enforce compaction behavior 265f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else if ((cdata == null) || cdata.isEmpty ()) 266f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project DataFactory.persist (mdata, persistFile, false); // never merge to enforce compaction behavior 267f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 268f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project DataFactory.persist (new SessionData (mdata, cdata), persistFile, false); // never merge to enforce compaction behavior 269f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 270f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 271f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 272f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (persistFile != null) persistFile.delete (); 273f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 274f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code 275f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (ioe); 276f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 277f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (Error e) 278f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 279f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (persistFile != null) persistFile.delete (); 280f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 281f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw e; // re-throw 282f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 283f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 284f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (rename) // rename-with-delete temp out file into the desired out file 285f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 286f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! Files.renameFile (tempDataOutFile, canonicalDataOutFile, true)) // overwrite the original archive 287f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 288f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // error code 289f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException ("could not rename temporary file [" + tempDataOutFile.getAbsolutePath () + "] to [" + canonicalDataOutFile + "]: make sure the original file is not locked and can be deleted"); 290f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 291f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 292f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 293f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atINFO ()) 294f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 295f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long end = System.currentTimeMillis (); 296f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 297f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.info ("merged/compacted data written to [" + canonicalDataOutFile + "] {in " + (end - start) + " ms}"); 298f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 299f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 300f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 301f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 302f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (SecurityException se) 303f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 304f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project failure = new EMMARuntimeException (SECURITY_RESTRICTION, new String [] {IAppConstants.APP_NAME}, se); 305f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 306f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (RuntimeException re) 307f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 308f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project failure = re; 309f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 310f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 311f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 312f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project reset (); 313f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 314f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 315f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (failure != null) 316f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 317f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (Exceptions.unexpectedFailure (failure, EXPECTED_FAILURES)) 318f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 319f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (UNEXPECTED_FAILURE, 320f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project new Object [] {failure.toString (), IAppConstants.APP_BUG_REPORT_LINK}, 321f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project failure); 322f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 323f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 324f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw failure; 325f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 326f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 327f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 328f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 329f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // package: ............................................................... 330f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 331f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // private: ............................................................... 332f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 333f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 334f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private MergeProcessor () 335f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 336f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_dataPath = IConstants.EMPTY_FILE_ARRAY; 337f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 338f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 339f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 340f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private void reset () 341f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 342f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_dataFileCount = 0; 343f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 344f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 345f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 346f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // caller-settable state [scoped to this runner instance]: 347f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 348f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private File [] m_dataPath; // required to be non-null for run() [is set to canonicalized form] 349f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private File m_sdataOutFile; // user override; can be null for run() 350f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 351f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // internal run()-scoped state: 352f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 353f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int m_dataFileCount; 354f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 355f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final Class [] EXPECTED_FAILURES; // set in <clinit> 356f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 357f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static 358f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 359f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EXPECTED_FAILURES = new Class [] 360f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 361f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EMMARuntimeException.class, 362f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project IllegalArgumentException.class, 363f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project IllegalStateException.class, 364f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project }; 365f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 366f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 367f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project} // end of class 368f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------