1 9 package com.vladium.emma.data; 10 11 import java.io.File ; 12 import java.io.IOException ; 13 14 import com.vladium.logging.Logger; 15 import com.vladium.util.Files; 16 import com.vladium.util.IConstants; 17 import com.vladium.util.IProperties; 18 import com.vladium.util.asserts.$assert; 19 import com.vladium.util.exception.Exceptions; 20 import com.vladium.emma.IAppConstants; 21 import com.vladium.emma.IAppErrorCodes; 22 import com.vladium.emma.EMMAProperties; 23 import com.vladium.emma.EMMARuntimeException; 24 import com.vladium.emma.Processor; 25 26 31 34 public 35 final class MergeProcessor extends Processor 36 implements IAppErrorCodes 37 { 38 40 public static MergeProcessor create () 41 { 42 return new MergeProcessor (); 43 } 44 45 49 public synchronized final void setDataPath (final String [] path) 50 { 51 if ((path == null) || (path.length == 0)) 52 m_dataPath = IConstants.EMPTY_FILE_ARRAY; 53 else 54 m_dataPath = Files.pathToFiles (path, true); 55 } 56 57 63 public synchronized final void setSessionOutFile (final String fileName) 64 { 65 if (fileName == null) 66 m_sdataOutFile = null; 67 else 68 { 69 final File _file = new File (fileName); 70 71 if (_file.exists () && ! _file.isFile ()) 72 throw new IllegalArgumentException ("not a file: [" + _file.getAbsolutePath () + "]"); 73 74 m_sdataOutFile = _file; 75 } 76 } 77 78 80 81 protected void validateState () 82 { 83 super.validateState (); 84 85 if (m_dataPath == null) 86 throw new IllegalStateException ("data path not set"); 87 88 90 } 92 93 94 protected void _run (final IProperties toolProperties) 95 { 96 final Logger log = m_log; 97 98 final boolean verbose = m_log.atVERBOSE (); 99 if (verbose) 100 { 101 log.verbose (IAppConstants.APP_VERBOSE_BUILD_ID); 102 103 log.verbose ("input data path:"); 105 log.verbose ("{"); 106 for (int p = 0; p < m_dataPath.length; ++ p) 107 { 108 final File f = m_dataPath [p]; 109 final String nonexistent = f.exists () ? "" : "{nonexistent} "; 110 111 log.verbose (" " + nonexistent + f.getAbsolutePath ()); 112 } 113 log.verbose ("}"); 114 } 115 else 116 { 117 log.info ("processing input files ..."); 118 } 119 120 File sdataOutFile = m_sdataOutFile; 122 { 123 if (sdataOutFile == null) 124 sdataOutFile = new File (toolProperties.getProperty (EMMAProperties.PROPERTY_SESSION_DATA_OUT_FILE, 125 EMMAProperties.DEFAULT_SESSION_DATA_OUT_FILE)); 126 } 127 128 RuntimeException failure = null; 129 try 130 { 131 IMetaData mdata = null; 132 ICoverageData cdata = null; 133 134 try 136 { 137 final long start = log.atINFO () ? System.currentTimeMillis () : 0; 138 139 for (int f = 0; f < m_dataPath.length; ++ f) 140 { 141 final File dataFile = m_dataPath [f]; 142 if (verbose) log.verbose ("processing input file [" + dataFile.getAbsolutePath () + "] ..."); 143 144 final IMergeable [] fileData = DataFactory.load (dataFile); 145 146 final IMetaData _mdata = (IMetaData) fileData [DataFactory.TYPE_METADATA]; 147 if (_mdata != null) 148 { 149 if (verbose) log.verbose (" loaded " + _mdata.size () + " metadata entries"); 150 151 if (mdata == null) 152 mdata = _mdata; 153 else 154 mdata = (IMetaData) mdata.merge (_mdata); } 156 157 final ICoverageData _cdata = (ICoverageData) fileData [DataFactory.TYPE_COVERAGEDATA]; 158 if (_cdata != null) 159 { 160 if (verbose) log.verbose (" loaded " + _cdata.size () + " coverage data entries"); 161 162 if (cdata == null) 163 cdata = _cdata; 164 else 165 cdata = (ICoverageData) cdata.merge (_cdata); } 167 168 ++ m_dataFileCount; 169 } 170 171 if (log.atINFO ()) 172 { 173 final long end = System.currentTimeMillis (); 174 175 log.info (m_dataFileCount + " file(s) read and merged in " + (end - start) + " ms"); 176 } 177 178 if (((mdata == null) || mdata.isEmpty ()) && ((cdata == null) || cdata.isEmpty ())) 179 { 180 log.warning ("nothing to do: no metadata or coverage data found in any of the input files"); 181 182 return; 184 } 185 } 186 catch (IOException ioe) 187 { 188 ioe.printStackTrace (System.out); 190 } 191 192 193 if (verbose) 194 { 195 if (mdata != null) 196 { 197 log.verbose (" merged metadata contains " + mdata.size () + " entries"); 198 } 199 200 if (cdata != null) 201 { 202 log.verbose (" merged coverage data contains " + cdata.size () + " entries"); 203 } 204 } 205 206 { 208 $assert.ASSERT (sdataOutFile != null, "sdataOutFile not null"); 209 210 214 boolean rename = false; 215 File tempDataOutFile = null; 216 217 final File canonicalDataOutFile = Files.canonicalizeFile (sdataOutFile); 218 219 for (int f = 0; f < m_dataPath.length; ++ f) 220 { 221 final File canonicalDataFile = Files.canonicalizeFile (m_dataPath [f]); 222 if (canonicalDataOutFile.equals (canonicalDataFile)) 223 { 224 rename = true; 225 break; 226 } 227 } 228 229 if (rename) { 231 File tempFileDir = canonicalDataOutFile.getParentFile (); 232 if (tempFileDir == null) tempFileDir = new File (""); 233 234 final String tempFileName = Files.getFileName (canonicalDataOutFile) + IAppConstants.APP_NAME_LC; 236 final String tempFileExt = EMMAProperties.PROPERTY_TEMP_FILE_EXT; 237 238 try 239 { 240 tempDataOutFile = Files.createTempFile (tempFileDir, tempFileName, tempFileExt); 241 } 242 catch (IOException ioe) 243 { 244 throw new EMMARuntimeException (ioe); 246 } 247 248 log.warning ("the specified output file is one of the input files [" + canonicalDataOutFile + "]"); 249 log.warning ("all merged data will be written to a temp file first [" + tempDataOutFile.getAbsolutePath () + "]"); 250 } 251 252 { 254 final long start = log.atINFO () ? System.currentTimeMillis () : 0; 255 256 File persistFile = null; 257 try 258 { 259 persistFile = tempDataOutFile != null ? tempDataOutFile : canonicalDataOutFile; 260 261 263 if ((mdata == null) || mdata.isEmpty ()) 264 DataFactory.persist (cdata, persistFile, false); else if ((cdata == null) || cdata.isEmpty ()) 266 DataFactory.persist (mdata, persistFile, false); else 268 DataFactory.persist (new SessionData (mdata, cdata), persistFile, false); } 270 catch (IOException ioe) 271 { 272 if (persistFile != null) persistFile.delete (); 273 274 throw new EMMARuntimeException (ioe); 276 } 277 catch (Error e) 278 { 279 if (persistFile != null) persistFile.delete (); 280 281 throw e; } 283 284 if (rename) { 286 if (! Files.renameFile (tempDataOutFile, canonicalDataOutFile, true)) { 288 throw new EMMARuntimeException ("could not rename temporary file [" + tempDataOutFile.getAbsolutePath () + "] to [" + canonicalDataOutFile + "]: make sure the original file is not locked and can be deleted"); 290 } 291 } 292 293 if (log.atINFO ()) 294 { 295 final long end = System.currentTimeMillis (); 296 297 log.info ("merged/compacted data written to [" + canonicalDataOutFile + "] {in " + (end - start) + " ms}"); 298 } 299 } 300 } 301 } 302 catch (SecurityException se) 303 { 304 failure = new EMMARuntimeException (SECURITY_RESTRICTION, new String [] {IAppConstants.APP_NAME}, se); 305 } 306 catch (RuntimeException re) 307 { 308 failure = re; 309 } 310 finally 311 { 312 reset (); 313 } 314 315 if (failure != null) 316 { 317 if (Exceptions.unexpectedFailure (failure, EXPECTED_FAILURES)) 318 { 319 throw new EMMARuntimeException (UNEXPECTED_FAILURE, 320 new Object [] {failure.toString (), IAppConstants.APP_BUG_REPORT_LINK}, 321 failure); 322 } 323 else 324 throw failure; 325 } 326 } 327 328 329 331 333 334 private MergeProcessor () 335 { 336 m_dataPath = IConstants.EMPTY_FILE_ARRAY; 337 } 338 339 340 private void reset () 341 { 342 m_dataFileCount = 0; 343 } 344 345 346 348 private File [] m_dataPath; private File m_sdataOutFile; 351 353 private int m_dataFileCount; 354 355 private static final Class [] EXPECTED_FAILURES; 357 static 358 { 359 EXPECTED_FAILURES = new Class [] 360 { 361 EMMARuntimeException.class, 362 IllegalArgumentException .class, 363 IllegalStateException .class, 364 }; 365 } 366 367 }
| Popular Tags
|