1 9 package com.vladium.emma.instr; 10 11 import java.io.File ; 12 import java.io.FileInputStream ; 13 import java.io.FileNotFoundException ; 14 import java.io.FileOutputStream ; 15 import java.io.IOException ; 16 import java.io.InputStream ; 17 import java.io.OutputStream ; 18 import java.io.RandomAccessFile ; 19 import java.util.Date ; 20 import java.util.jar.Attributes ; 21 import java.util.jar.JarFile ; 22 import java.util.jar.JarInputStream ; 23 import java.util.jar.JarOutputStream ; 24 import java.util.jar.Manifest ; 25 import java.util.zip.CRC32 ; 26 import java.util.zip.ZipEntry ; 27 import java.util.zip.ZipInputStream ; 28 import java.util.zip.ZipOutputStream ; 29 30 import com.vladium.jcd.cls.ClassDef; 31 import com.vladium.jcd.compiler.ClassWriter; 32 import com.vladium.jcd.parser.ClassDefParser; 33 import com.vladium.logging.Logger; 34 import com.vladium.util.ByteArrayOStream; 35 import com.vladium.util.Descriptors; 36 import com.vladium.util.Files; 37 import com.vladium.util.IPathEnumerator; 38 import com.vladium.util.IProperties; 39 import com.vladium.util.Property; 41 import com.vladium.util.asserts.$assert; 42 import com.vladium.util.exception.Exceptions; 43 import com.vladium.emma.IAppConstants; 45 import com.vladium.emma.IAppErrorCodes; 46 import com.vladium.emma.EMMAProperties; 47 import com.vladium.emma.EMMARuntimeException; 48 import com.vladium.emma.data.CoverageOptions; 49 import com.vladium.emma.data.CoverageOptionsFactory; 50 import com.vladium.emma.data.DataFactory; 51 import com.vladium.emma.data.IMetaData; 52 53 57 final class InstrProcessorST extends InstrProcessor 58 implements IAppErrorCodes 59 { 60 62 65 66 68 69 public final void handleArchiveStart (final File parentDir, final File archive, final Manifest manifest) 70 { 71 final Logger log = m_log; 72 if (log.atTRACE2 ()) log.trace2 ("handleArchiveStart", "[" + parentDir + "] [" + archive + "]"); 73 74 77 if (DO_DEPENDS_CHECKING) 78 { 79 final File fullArchiveFile = Files.newFile (parentDir, archive); 80 m_currentArchiveTS = fullArchiveFile.lastModified (); 81 82 if ($assert.ENABLED) $assert.ASSERT (m_currentArchiveTS > 0, "invalid ts: " + m_currentArchiveTS); 83 } 84 85 if ((m_outMode == OutMode.OUT_MODE_FULLCOPY) || (m_outMode == OutMode.OUT_MODE_OVERWRITE)) 86 { 87 final Manifest outManifest = manifest != null 88 ? new Manifest (manifest) : new Manifest (); 90 91 93 final Attributes mainAttrs = outManifest.getMainAttributes (); 94 if (manifest == null) mainAttrs.put (Attributes.Name.MANIFEST_VERSION, "1.0"); 95 mainAttrs.put (new Attributes.Name ("Created-By"), IAppConstants.APP_NAME + " v" + IAppConstants.APP_VERSION_WITH_BUILD_ID_AND_TAG); 96 97 99 mainAttrs.put (Attributes.Name.IMPLEMENTATION_TITLE, "instrumented version of [" + archive.getAbsolutePath () + "]"); 100 mainAttrs.put (Attributes.Name.SPECIFICATION_TITLE, "instrumented on " + new Date (m_timeStamp) + " [" + Property.getSystemFingerprint () + "]"); 101 102 104 if (m_outMode == OutMode.OUT_MODE_FULLCOPY) 105 { 106 109 try 110 { 111 final OutputStream out = new FileOutputStream (getFullOutFile (parentDir, archive, IN_LIB)); 112 113 m_archiveOut = outManifest != null ? new JarOutputStream (out, outManifest) : new JarOutputStream (out); 114 } 115 catch (IOException ioe) 116 { 117 throw new EMMARuntimeException (ioe); 119 } 120 } 121 else if (m_outMode == OutMode.OUT_MODE_OVERWRITE) 122 { 123 126 m_origArchiveFile = Files.newFile (parentDir, archive); 127 128 final String archiveName = Files.getFileName (archive) + IAppConstants.APP_NAME_LC; 130 final String archiveExt = EMMAProperties.PROPERTY_TEMP_FILE_EXT; 131 132 try 133 { 134 m_tempArchiveFile = Files.createTempFile (parentDir, archiveName, archiveExt); 135 if (log.atTRACE2 ()) log.trace2 ("handleArchiveStart", "created temp archive [" + m_tempArchiveFile.getAbsolutePath () + "]"); 136 137 final OutputStream out = new FileOutputStream (m_tempArchiveFile); 138 139 m_archiveOut = outManifest != null ? new JarOutputStream (out, outManifest) : new JarOutputStream (out); 140 } 141 catch (IOException ioe) 142 { 143 throw new EMMARuntimeException (ioe); 145 } 146 } 147 } 148 } 149 150 public final void handleArchiveEntry (final JarInputStream in, final ZipEntry entry) 151 { 152 final Logger log = m_log; 153 if (log.atTRACE2 ()) log.trace2 ("handleArchiveEntry", "[" + entry.getName () + "]"); 154 155 final String name = entry.getName (); 156 final String lcName = name.toLowerCase (); 157 158 final boolean notcopymode = (m_outMode == OutMode.OUT_MODE_FULLCOPY) || (m_outMode == OutMode.OUT_MODE_OVERWRITE); 159 160 boolean copyEntry = false; 161 162 if (lcName.endsWith (".class")) 163 { 164 final String className = name.substring (0, name.length () - 6).replace ('/', '.'); 165 166 170 176 if ((m_coverageFilter == null) || m_coverageFilter.included (className)) 177 { 178 InputStream clsin = null; 179 try 180 { 181 File outFile = null; 182 File fullOutFile = null; 183 184 if (DO_DEPENDS_CHECKING) 185 { 186 188 if (m_outMode == OutMode.OUT_MODE_COPY) 189 { 190 outFile = new File (className.replace ('.', File.separatorChar).concat (".class")); 191 fullOutFile = getFullOutFile (null, outFile, IN_CLASSES); 192 193 196 if (m_mdata.hasDescriptor (Descriptors.javaNameToVMName (className))) 197 return; 198 199 final long outTimeStamp = fullOutFile.lastModified (); 203 if (outTimeStamp > 0) 204 { 205 long inTimeStamp = entry.getTime (); if (inTimeStamp < 0) inTimeStamp = m_currentArchiveTS; 208 if ($assert.ENABLED) $assert.ASSERT (inTimeStamp > 0); 209 210 if (inTimeStamp <= outTimeStamp) 211 { 212 if (log.atVERBOSE ()) log.verbose ("destination file [" + outFile + "] skipped: more recent than the source"); 213 return; 214 } 215 } 216 } 217 } 218 219 readZipEntry (in, entry); 220 221 final ClassDef clsDef = ClassDefParser.parseClass (m_readbuf, m_readpos); 222 223 m_visitor.process (clsDef, m_outMode == OutMode.OUT_MODE_OVERWRITE, true, true, m_instrResult); 224 if (m_instrResult.m_instrumented) 225 { 226 if ($assert.ENABLED) $assert.ASSERT (m_instrResult.m_descriptor != null, "no descriptor created for an instrumented class"); 227 228 ++ m_classInstrs; 229 230 232 m_mdata.add (m_instrResult.m_descriptor, false); 233 234 236 m_baos.reset (); 237 ClassWriter.writeClassTable (clsDef, m_baos); 238 239 if (notcopymode) 240 { 241 243 entry.setTime (m_timeStamp); 244 addJob (new EntryWriteJob (m_archiveOut, m_baos.copyByteArray (), entry, false)); 245 } 246 else { 248 250 if (! DO_DEPENDS_CHECKING) { 252 outFile = new File (className.replace ('.', File.separatorChar).concat (".class")); 253 fullOutFile = getFullOutFile (null, outFile, IN_CLASSES); 254 } 255 256 addJob (new FileWriteJob (fullOutFile, m_baos.copyByteArray (), true)); 257 } 258 } 259 else if (notcopymode) 260 { 261 264 final byte [] data = new byte [m_readpos]; 265 System.arraycopy (m_readbuf, 0, data, 0, data.length); 266 ++ m_classCopies; 267 268 entry.setTime (m_timeStamp); 269 addJob (new EntryWriteJob (m_archiveOut, data, entry, true)); 270 } 271 } 272 catch (FileNotFoundException fnfe) 273 { 274 if ($assert.ENABLED) 276 { 277 fnfe.printStackTrace (System.out); 278 } 279 } 280 catch (IOException ioe) 281 { 282 throw new EMMARuntimeException (ioe); 284 } 285 finally 286 { 287 if (clsin != null) 288 try 289 { 290 clsin.close (); 291 } 292 catch (Exception e) 293 { 294 throw new EMMARuntimeException (e); 296 } 297 } 298 } 299 else 300 { 301 copyEntry = notcopymode; 303 } 304 } 305 else 306 { 307 copyEntry = notcopymode; 309 310 313 if (copyEntry && name.equalsIgnoreCase ("META-INF/")) 314 copyEntry = false; 315 if (copyEntry && name.equalsIgnoreCase (JarFile.MANIFEST_NAME)) 316 copyEntry = false; 317 318 } 320 321 if (copyEntry) 322 { 323 try 324 { 325 readZipEntry (in, entry); 326 327 final byte [] data = new byte [m_readpos]; 328 System.arraycopy (m_readbuf, 0, data, 0, data.length); 329 ++ m_classCopies; 330 331 entry.setTime (m_timeStamp); 332 addJob (new EntryWriteJob (m_archiveOut, data, entry, true)); 333 } 334 catch (IOException ioe) 335 { 336 throw new EMMARuntimeException (ioe); 338 } 339 } 340 } 341 342 public final void handleArchiveEnd (final File parentDir, final File archive) 343 { 344 final Logger log = m_log; 345 if (log.atTRACE2 ()) log.trace2 ("handleArchiveEnd", "[" + parentDir + "] [" + archive + "]"); 346 347 m_currentArchiveTS = Long.MAX_VALUE; 348 349 if ((m_outMode == OutMode.OUT_MODE_FULLCOPY) || (m_outMode == OutMode.OUT_MODE_OVERWRITE)) 350 { 351 try 352 { 353 drainJobQueue (); 355 m_archiveOut.flush (); 356 m_archiveOut.close (); 357 m_archiveOut = null; 358 } 359 catch (IOException ioe) 360 { 361 throw new EMMARuntimeException (ioe); 363 } 364 365 367 if (m_outMode == OutMode.OUT_MODE_OVERWRITE) 368 { 369 if (! Files.renameFile (m_tempArchiveFile, m_origArchiveFile, true)) { 371 374 throw new EMMARuntimeException ("could not rename temporary file [" + m_tempArchiveFile + "] to [" + m_origArchiveFile + "]: make sure the original file is not locked and can be deleted"); 376 } 377 else 378 { 379 if (log.atTRACE2 ()) log.trace2 ("handleArchiveEnd", "renamed temp archive [" + m_tempArchiveFile.getAbsolutePath () + "] to [" + m_origArchiveFile + "]"); 380 m_origArchiveFile = m_tempArchiveFile = null; 381 } 382 } 383 } 384 } 385 386 387 public final void handleDirStart (final File pathDir, final File dir) 388 { 389 final Logger log = m_log; 390 if (log.atTRACE2 ()) log.trace2 ("handleDirStart", "[" + pathDir + "] [" + dir + "]"); 391 392 395 if (m_outMode == OutMode.OUT_MODE_FULLCOPY) 396 { 397 final File saveDir = new File (getFullOutDir (pathDir, IN_CLASSES), dir.getPath ()); 398 createDir (saveDir, true); 399 } 400 } 401 402 public final void handleFile (final File pathDir, final File file) 403 { 404 final Logger log = m_log; 405 if (log.atTRACE2 ()) log.trace2 ("handleFile", "[" + pathDir + "] [" + file + "]"); 406 407 final String name = file.getPath (); 408 final String lcName = name.toLowerCase (); 409 410 final boolean fullcopymode = (m_outMode == OutMode.OUT_MODE_FULLCOPY); 411 final boolean mkdir = (m_outMode == OutMode.OUT_MODE_COPY); 412 413 414 boolean copyFile = false; 415 416 if (lcName.endsWith (".class")) 417 { 418 final String className = name.substring (0, name.length () - 6).replace (File.separatorChar, '.'); 419 420 424 430 if ((m_coverageFilter == null) || m_coverageFilter.included (className)) 431 { 432 InputStream clsin = null; 433 try 434 { 435 final File inFile = Files.newFile (pathDir, file.getPath ()); 436 final File fullOutFile = getFullOutFile (pathDir, file, IN_CLASSES); 437 438 if (DO_DEPENDS_CHECKING) 439 { 440 if (m_outMode == OutMode.OUT_MODE_COPY) 441 { 442 445 if (m_mdata.hasDescriptor (Descriptors.javaNameToVMName (className))) 446 return; 447 448 451 final long outTimeStamp = fullOutFile.lastModified (); 453 if (outTimeStamp > 0) 454 { 455 final long inTimeStamp = inFile.lastModified (); 456 457 if (inTimeStamp <= outTimeStamp) 458 { 459 if (log.atVERBOSE ()) log.verbose ("destination file [" + fullOutFile + "] skipped: more recent that the source file"); 460 return; 461 } 462 } 463 } 464 } 465 466 readFile (inFile); 467 468 ClassDef clsDef = ClassDefParser.parseClass (m_readbuf, m_readpos); 469 470 m_visitor.process (clsDef, m_outMode == OutMode.OUT_MODE_OVERWRITE, true, true, m_instrResult); 472 if (m_instrResult.m_instrumented) 473 { 474 if ($assert.ENABLED) $assert.ASSERT (m_instrResult.m_descriptor != null, "no descriptor created for an instrumented class"); 475 476 ++ m_classInstrs; 477 478 480 484 m_mdata.add (m_instrResult.m_descriptor, false); 485 486 488 m_baos.reset (); 489 ClassWriter.writeClassTable (clsDef, m_baos); 490 clsDef = null; 491 492 final byte [] outdata = m_baos.copyByteArray (); 493 494 addJob (new FileWriteJob (fullOutFile, outdata, mkdir)); 495 } 496 else if (fullcopymode) 497 { 498 501 clsDef = null; 502 503 final byte [] outdata = new byte [m_readpos]; 504 System.arraycopy (m_readbuf, 0, outdata, 0, m_readpos); 505 ++ m_classCopies; 506 507 addJob (new FileWriteJob (fullOutFile, outdata, mkdir)); 508 } 509 } 510 catch (FileNotFoundException fnfe) 511 { 512 if ($assert.ENABLED) 514 { 515 fnfe.printStackTrace (System.out); 516 } 517 } 518 catch (IOException ioe) 519 { 520 throw new EMMARuntimeException (ioe); 522 } 523 finally 524 { 525 if (clsin != null) 526 try 527 { 528 clsin.close (); 529 } 530 catch (Exception e) 531 { 532 throw new EMMARuntimeException (e); 534 } 535 } 536 } 537 else 538 { 539 copyFile = fullcopymode; 541 } 542 } 543 else 544 { 545 copyFile = fullcopymode; 547 } 548 549 if (copyFile) 550 { 551 try 552 { 553 final File inFile = Files.newFile (pathDir, file.getPath ()); 554 readFile (inFile); 555 556 final byte [] data = new byte [m_readpos]; 557 System.arraycopy (m_readbuf, 0, data, 0, data.length); 558 ++ m_classCopies; 559 560 final File outFile = getFullOutFile (pathDir, file, IN_CLASSES); 561 562 addJob (new FileWriteJob (outFile, data, mkdir)); 563 } 564 catch (IOException ioe) 565 { 566 throw new EMMARuntimeException (ioe); 568 } 569 } 570 } 571 572 public final void handleDirEnd (final File pathDir, final File dir) 573 { 574 final Logger log = m_log; 575 if (log.atTRACE2 ()) log.trace2 ("handleDirEnd", "[" + pathDir + "] [" + dir + "]"); 576 577 579 if (m_outMode == OutMode.OUT_MODE_OVERWRITE) 580 { 581 try 582 { 583 drainJobQueue (); 584 } 585 catch (IOException ioe) 586 { 587 throw new EMMARuntimeException (ioe); 589 } 590 } 591 } 592 593 595 596 protected void reset () 597 { 598 m_visitor = null; 599 m_mdata = null; 600 m_readbuf = null; 601 m_baos = null; 602 603 for (int j = 0; j < m_jobs.length; ++ j) m_jobs [j] = null; 604 605 if (CLEANUP_TEMP_ARCHIVE_ON_ERRORS) 606 { 607 if (m_archiveOut != null) 608 try { m_archiveOut.close (); } catch (Exception ignore) {} 610 if (m_tempArchiveFile != null) 611 m_tempArchiveFile.delete (); 612 } 613 614 m_archiveOut = null; 615 m_origArchiveFile = null; 616 m_tempArchiveFile = null; 617 618 super.reset (); 619 } 620 621 protected void _run (final IProperties toolProperties) 622 { 623 final Logger log = m_log; 624 625 final boolean verbose = log.atVERBOSE (); 626 if (verbose) 627 { 628 log.verbose (IAppConstants.APP_VERBOSE_BUILD_ID); 629 630 log.verbose ("instrumentation path:"); 632 log.verbose ("{"); 633 for (int p = 0; p < m_instrPath.length; ++ p) 634 { 635 final File f = m_instrPath [p]; 636 final String nonexistent = f.exists () ? "" : "{nonexistent} "; 637 638 log.verbose (" " + nonexistent + f.getAbsolutePath ()); 639 } 640 log.verbose ("}"); 641 642 log.verbose ("instrumentation output mode: " + m_outMode); 644 } 645 else 646 { 647 log.info ("processing instrumentation path ..."); 648 } 649 650 RuntimeException failure = null; 651 try 652 { 653 long start = System.currentTimeMillis (); 654 m_timeStamp = start; 655 656 final IPathEnumerator enumerator = IPathEnumerator.Factory.create (m_instrPath, m_canonical, this); 658 659 { 661 if (m_outMode != OutMode.OUT_MODE_OVERWRITE) createDir (m_outDir, true); 662 663 if ((m_outMode == OutMode.OUT_MODE_FULLCOPY)) 664 { 665 final File classesDir = Files.newFile (m_outDir, CLASSES); 666 createDir (classesDir, false); 668 final File libDir = Files.newFile (m_outDir, LIB); 669 createDir (libDir, false); } 671 } 672 673 File mdataOutFile = m_mdataOutFile; 675 Boolean mdataOutMerge = m_mdataOutMerge; 676 { 677 if (mdataOutFile == null) 678 mdataOutFile = new File (toolProperties.getProperty (EMMAProperties.PROPERTY_META_DATA_OUT_FILE, 679 EMMAProperties.DEFAULT_META_DATA_OUT_FILE)); 680 681 if (mdataOutMerge == null) 682 { 683 final String _dataOutMerge = toolProperties.getProperty (EMMAProperties.PROPERTY_META_DATA_OUT_MERGE, 684 EMMAProperties.DEFAULT_META_DATA_OUT_MERGE.toString ()); 685 mdataOutMerge = Property.toBoolean (_dataOutMerge) ? Boolean.TRUE : Boolean.FALSE; 686 } 687 } 688 689 if (verbose) 690 { 691 log.verbose ("metadata output file: " + mdataOutFile.getAbsolutePath ()); 692 log.verbose ("metadata output merge mode: " + mdataOutMerge); 693 } 694 695 697 m_readbuf = new byte [BUF_SIZE]; m_readpos = 0; 700 m_baos = new ByteArrayOStream (BUF_SIZE); 702 m_jobPos = 0; 704 705 m_currentArchiveTS = Long.MAX_VALUE; 706 707 final CoverageOptions options = CoverageOptionsFactory.create (toolProperties); 708 m_visitor = new InstrVisitor (options); 710 m_mdata = DataFactory.newMetaData (options); 711 712 try 714 { 715 enumerator.enumerate (); 716 drainJobQueue (); 717 } 718 catch (IOException ioe) 719 { 720 throw new EMMARuntimeException (INSTR_IO_FAILURE, ioe); 721 } 722 723 if (log.atINFO ()) 724 { 725 final long end = System.currentTimeMillis (); 726 727 log.info ("instrumentation path processed in " + (end - start) + " ms"); 728 log.info ("[" + m_classInstrs + " class(es) instrumented, " + m_classCopies + " resource(s) copied]"); 729 } 730 731 try 733 { 734 736 if ($assert.ENABLED) $assert.ASSERT (mdataOutFile != null, "m_metadataOutFile is null"); 737 738 if (verbose) 739 { 740 if (m_mdata != null) 741 { 742 log.verbose ("metadata contains " + m_mdata.size () + " entries"); 743 } 744 } 745 746 if (m_mdata.isEmpty ()) 747 { 748 log.info ("no output created: metadata is empty"); 749 } 750 else 751 { 752 start = System.currentTimeMillis (); 753 DataFactory.persist (m_mdata, mdataOutFile, mdataOutMerge.booleanValue ()); 754 final long end = System.currentTimeMillis (); 755 756 if (log.atINFO ()) 757 { 758 log.info ("metadata " + (mdataOutMerge.booleanValue () ? "merged into" : "written to") + " [" + mdataOutFile.getAbsolutePath () + "] {in " + (end - start) + " ms}"); 759 } 760 } 761 } 762 catch (IOException ioe) 763 { 764 throw new EMMARuntimeException (OUT_IO_FAILURE, new Object [] {mdataOutFile.getAbsolutePath ()}, ioe); 765 } 766 } 767 catch (SecurityException se) 768 { 769 failure = new EMMARuntimeException (SECURITY_RESTRICTION, new String [] {IAppConstants.APP_NAME}, se); 770 } 771 catch (RuntimeException re) 772 { 773 failure = re; 774 } 775 finally 776 { 777 reset (); 778 } 779 780 if (failure != null) 781 { 782 if (Exceptions.unexpectedFailure (failure, EXPECTED_FAILURES)) 783 { 784 throw new EMMARuntimeException (UNEXPECTED_FAILURE, 785 new Object [] {failure.toString (), IAppConstants.APP_BUG_REPORT_LINK}, 786 failure); 787 } 788 else 789 throw failure; 790 } 791 } 792 793 795 796 InstrProcessorST () 797 { 798 m_jobs = new Job [JOB_QUEUE_SIZE]; 799 m_instrResult = new InstrVisitor.InstrResult (); 800 } 801 802 803 static void writeFile (final byte [] data, final File outFile, final boolean mkdirs) 804 throws IOException 805 { 806 RandomAccessFile raf = null; 807 try 808 { 809 if (mkdirs) 810 { 811 final File parent = outFile.getParentFile (); 812 if (parent != null) parent.mkdirs (); } 814 815 raf = new RandomAccessFile (outFile, "rw"); 816 if (DO_RAF_EXTENSION) raf.setLength (data.length); 817 818 raf.write (data); 819 } 820 finally 821 { 822 if (raf != null) raf.close (); } 824 } 825 826 static void writeZipEntry (final byte [] data, final ZipOutputStream out, final ZipEntry entry, final boolean isCopy) 827 throws IOException 828 { 829 if (isCopy) 830 { 831 out.putNextEntry (entry); try 833 { 834 out.write (data); 835 } 836 finally 837 { 838 out.closeEntry (); 839 } 840 } 841 else 842 { 843 845 final ZipEntry entryCopy = new ZipEntry (entry.getName ()); 846 entryCopy.setTime (entry.getTime ()); entryCopy.setMethod (ZipOutputStream.STORED); 848 entryCopy.setSize (data.length); 850 entryCopy.setCompressedSize (data.length); 851 852 final CRC32 crc = new CRC32 (); 853 crc.update (data); 854 entryCopy.setCrc (crc.getValue ()); 855 856 out.putNextEntry (entryCopy); 857 try 858 { 859 out.write (data); 860 } 861 finally 862 { 863 out.closeEntry (); 864 } 865 } 866 } 867 868 870 871 private static abstract class Job 872 { 873 protected abstract void run () throws IOException ; 874 875 } 877 878 private static final class FileWriteJob extends Job 879 { 880 protected void run () throws IOException 881 { 882 writeFile (m_data, m_outFile, m_mkdirs); 883 m_data = null; 884 } 885 886 FileWriteJob (final File outFile, final byte [] data, final boolean mkdirs) 887 { 888 m_outFile = outFile; 889 m_data = data; 890 m_mkdirs = mkdirs; 891 } 892 893 894 final File m_outFile; 895 final boolean m_mkdirs; 896 byte [] m_data; 897 898 } 900 901 private static final class EntryWriteJob extends Job 902 { 903 protected void run () throws IOException 904 { 905 writeZipEntry (m_data, m_out, m_entry, m_isCopy); 906 m_data = null; 907 } 908 909 EntryWriteJob (final ZipOutputStream out, final byte [] data, final ZipEntry entry, final boolean isCopy) 910 { 911 m_out = out; 912 m_data = data; 913 m_entry = entry; 914 m_isCopy = isCopy; 915 } 916 917 918 final ZipOutputStream m_out; 919 byte [] m_data; 920 final ZipEntry m_entry; 921 final boolean m_isCopy; 922 923 } 925 926 private void addJob (final Job job) 927 throws FileNotFoundException , IOException 928 { 929 if (m_jobPos == JOB_QUEUE_SIZE) drainJobQueue (); 930 931 m_jobs [m_jobPos ++] = job; 932 } 933 934 private void drainJobQueue () 935 throws IOException 936 { 937 for (int j = 0; j < m_jobPos; ++ j) 938 { 939 final Job job = m_jobs [j]; 940 if (job != null) { 942 m_jobs [j] = null; 943 job.run (); 944 } 945 } 946 947 m_jobPos = 0; 948 } 949 950 953 private void readFile (final File file) 954 throws IOException 955 { 956 final int length = (int) file.length (); 957 958 ensureReadCapacity (length); 959 960 InputStream in = null; 961 try 962 { 963 in = new FileInputStream (file); 964 965 int totalread = 0; 966 for (int read; 967 (totalread < length) && (read = in.read (m_readbuf, totalread, length - totalread)) >= 0; 968 totalread += read); 969 m_readpos = totalread; 970 } 971 finally 972 { 973 if (in != null) try { in.close (); } catch (Exception ignore) {} 974 } 975 } 976 977 980 private void readZipEntry (final ZipInputStream in, final ZipEntry entry) 981 throws IOException 982 { 983 final int length = (int) entry.getSize (); 985 if (length >= 0) 986 { 987 ensureReadCapacity (length); 988 989 int totalread = 0; 990 for (int read; 991 (totalread < length) && (read = in.read (m_readbuf, totalread, length - totalread)) >= 0; 992 totalread += read); 993 m_readpos = totalread; 994 } 995 else 996 { 997 ensureReadCapacity (BUF_SIZE); 998 999 m_baos.reset (); 1000 for (int read; (read = in.read (m_readbuf)) >= 0; m_baos.write (m_readbuf, 0, read)); 1001 1002 m_readbuf = m_baos.copyByteArray (); 1003 m_readpos = m_readbuf.length; 1004 } 1005 } 1006 1007 private void ensureReadCapacity (final int capacity) 1008 { 1009 if (m_readbuf.length < capacity) 1010 { 1011 final int readbuflen = m_readbuf.length; 1012 m_readbuf = null; 1013 m_readbuf = new byte [Math.max (readbuflen << 1, capacity)]; 1014 } 1015 } 1016 1017 1018 1020 private final Job [] m_jobs; 1021 private final InstrVisitor.InstrResult m_instrResult; 1022 1023 private InstrVisitor m_visitor; 1024 private IMetaData m_mdata; 1025 private byte [] m_readbuf; 1026 private int m_readpos; 1027 private ByteArrayOStream m_baos; private int m_jobPos; 1029 private long m_currentArchiveTS; 1030 private File m_origArchiveFile, m_tempArchiveFile; 1031 private JarOutputStream m_archiveOut; 1032 private long m_timeStamp; 1033 1034 1035 private static final int BUF_SIZE = 32 * 1024; 1036 private static final int JOB_QUEUE_SIZE = 128; private static final boolean CLEANUP_TEMP_ARCHIVE_ON_ERRORS = true; 1038 private static final boolean DO_RAF_EXTENSION = true; 1039 1040 private static final boolean DO_DEPENDS_CHECKING = true; 1041 private static final Class [] EXPECTED_FAILURES; 1043 static 1044 { 1045 EXPECTED_FAILURES = new Class [] 1046 { 1047 EMMARuntimeException.class, 1048 IllegalArgumentException .class, 1049 IllegalStateException .class, 1050 }; 1051 } 1052 1053} | Popular Tags |