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: InstrProcessorST.java,v 1.1.1.1.2.3 2004/07/16 23:32:28 vlad_r Exp $ 8f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 9f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpackage com.vladium.emma.instr; 10f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 11f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.File; 12f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.FileInputStream; 13f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.FileNotFoundException; 14f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.FileOutputStream; 15f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.IOException; 16f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.InputStream; 17f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.OutputStream; 18f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.RandomAccessFile; 19f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Date; 20f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.jar.Attributes; 21f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.jar.JarFile; 22f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.jar.JarInputStream; 23f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.jar.JarOutputStream; 24f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.jar.Manifest; 25f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.zip.CRC32; 26f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.zip.ZipEntry; 27f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.zip.ZipInputStream; 28f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.zip.ZipOutputStream; 29f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 30f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.cls.ClassDef; 31f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.compiler.ClassWriter; 32f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.parser.ClassDefParser; 33f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.logging.Logger; 34f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.ByteArrayOStream; 35f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.Descriptors; 36f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.Files; 37f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.IPathEnumerator; 38f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.IProperties; 39f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//import com.vladium.util.Profiler; 40f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.Property; 41f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.asserts.$assert; 42f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.exception.Exceptions; 43f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project//import com.vladium.utils.ObjectSizeProfiler; 44f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.IAppConstants; 45f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.IAppErrorCodes; 46f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.EMMAProperties; 47f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.EMMARuntimeException; 48f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.CoverageOptions; 49f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.CoverageOptionsFactory; 50f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.DataFactory; 51f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.IMetaData; 52f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 53f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ---------------------------------------------------------------------------- 54f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/** 55f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @author Vlad Roubtsov, (C) 2003 56f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 57f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectfinal class InstrProcessorST extends InstrProcessor 58f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project implements IAppErrorCodes 59f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project{ 60f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // public: ................................................................ 61f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 62f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: performance of 'copy' mode could be improved by pushing dir filtering 63f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // all the way to the path enumerator [although dir listing is reasonably fast] 64f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 65f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 66f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // IPathEnumerator.IPathHandler: 67f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 68f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 69f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final void handleArchiveStart (final File parentDir, final File archive, final Manifest manifest) 70f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 71f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger log = m_log; 72f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atTRACE2 ()) log.trace2 ("handleArchiveStart", "[" + parentDir + "] [" + archive + "]"); 73f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 74f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: pass manifest into this callback, if any 75f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: detect if manifest corresonds to a previously intrumented archive already ? 76f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 77f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (DO_DEPENDS_CHECKING) 78f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 79f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File fullArchiveFile = Files.newFile (parentDir, archive); 80f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_currentArchiveTS = fullArchiveFile.lastModified (); 81f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 82f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (m_currentArchiveTS > 0, "invalid ts: " + m_currentArchiveTS); 83f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 84f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 85f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((m_outMode == OutMode.OUT_MODE_FULLCOPY) || (m_outMode == OutMode.OUT_MODE_OVERWRITE)) 86f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 87f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Manifest outManifest = manifest != null 88f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ? new Manifest (manifest) // shallow copy 89f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project : new Manifest (); 90f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 91f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // set some basic main attributes: 92f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 93f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Attributes mainAttrs = outManifest.getMainAttributes (); 94f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (manifest == null) mainAttrs.put (Attributes.Name.MANIFEST_VERSION, "1.0"); 95f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project mainAttrs.put (new Attributes.Name ("Created-By"), IAppConstants.APP_NAME + " v" + IAppConstants.APP_VERSION_WITH_BUILD_ID_AND_TAG); 96f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 97f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // note: Manifest makes these 72-char-safe 98f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 99f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project mainAttrs.put (Attributes.Name.IMPLEMENTATION_TITLE, "instrumented version of [" + archive.getAbsolutePath () + "]"); 100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project mainAttrs.put (Attributes.Name.SPECIFICATION_TITLE, "instrumented on " + new Date (m_timeStamp) + " [" + Property.getSystemFingerprint () + "]"); 101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: remove entries related to signing 103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_outMode == OutMode.OUT_MODE_FULLCOPY) 105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // create an identically named artive in outdir/lib [the stream is 107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // closed in the archive end event handler]: 108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final OutputStream out = new FileOutputStream (getFullOutFile (parentDir, archive, IN_LIB)); 112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_archiveOut = outManifest != null ? new JarOutputStream (out, outManifest) : new JarOutputStream (out); 114f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 115f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 116f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 117f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code 118f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (ioe); 119f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 120f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else if (m_outMode == OutMode.OUT_MODE_OVERWRITE) 122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // create a temp file in the same dir [moved into the original one 124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // in the archive end event handler]: 125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_origArchiveFile = Files.newFile (parentDir, archive); 127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // length > 3: 129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String archiveName = Files.getFileName (archive) + IAppConstants.APP_NAME_LC; 130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String archiveExt = EMMAProperties.PROPERTY_TEMP_FILE_EXT; 131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_tempArchiveFile = Files.createTempFile (parentDir, archiveName, archiveExt); 135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atTRACE2 ()) log.trace2 ("handleArchiveStart", "created temp archive [" + m_tempArchiveFile.getAbsolutePath () + "]"); 136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final OutputStream out = new FileOutputStream (m_tempArchiveFile); 138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_archiveOut = outManifest != null ? new JarOutputStream (out, outManifest) : new JarOutputStream (out); 140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code 144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (ioe); 145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final void handleArchiveEntry (final JarInputStream in, final ZipEntry entry) 151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger log = m_log; 153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atTRACE2 ()) log.trace2 ("handleArchiveEntry", "[" + entry.getName () + "]"); 154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String name = entry.getName (); 156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String lcName = name.toLowerCase (); 157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean notcopymode = (m_outMode == OutMode.OUT_MODE_FULLCOPY) || (m_outMode == OutMode.OUT_MODE_OVERWRITE); 159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean copyEntry = false; 161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (lcName.endsWith (".class")) 163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String className = name.substring (0, name.length () - 6).replace ('/', '.'); 165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // it is possible that a class with this name has already been processed; 167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // however, we can't skip it here because there is no guarantee that 168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // the runtime classpath will be identical to the instrumentation path 169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [the metadata will still contain only a single entry for a class with 171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // this name: it is the responsibility of the user to ensure that both 172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // files represent the same class; in the future I might use a more 173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // robust internal strategy that uses something other than a class name 174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // as a metadata key] 175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((m_coverageFilter == null) || m_coverageFilter.included (className)) 177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project InputStream clsin = null; 179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project File outFile = null; 182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project File fullOutFile = null; 183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (DO_DEPENDS_CHECKING) 185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // in 'copy' mode 187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_outMode == OutMode.OUT_MODE_COPY) 189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project outFile = new File (className.replace ('.', File.separatorChar).concat (".class")); 191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project fullOutFile = getFullOutFile (null, outFile, IN_CLASSES); 192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // if we already processed this class name within this instrumentor 194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // run, skip duplicates in copy mode: 195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_mdata.hasDescriptor (Descriptors.javaNameToVMName (className))) 197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return; 198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // BUG_SF989071: using outFile here instead resulted in 200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // a zero result regardless of whether the target existed or not 201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long outTimeStamp = fullOutFile.lastModified (); // 0 if 'fullOutFile' does not exist or if an I/O error occurs 202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (outTimeStamp > 0) 204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project long inTimeStamp = entry.getTime (); // can return -1 206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (inTimeStamp < 0) inTimeStamp = m_currentArchiveTS; // default to the archive file timestamp 207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (inTimeStamp > 0); 209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (inTimeStamp <= outTimeStamp) 211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atVERBOSE ()) log.verbose ("destination file [" + outFile + "] skipped: more recent than the source"); 213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return; 214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project readZipEntry (in, entry); 220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ClassDef clsDef = ClassDefParser.parseClass (m_readbuf, m_readpos); 222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_visitor.process (clsDef, m_outMode == OutMode.OUT_MODE_OVERWRITE, true, true, m_instrResult); 224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_instrResult.m_instrumented) 225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (m_instrResult.m_descriptor != null, "no descriptor created for an instrumented class"); 227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ++ m_classInstrs; 229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // update metadata [if this class has not been seen before]: 231f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 232f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_mdata.add (m_instrResult.m_descriptor, false); 233f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 234f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // class def modified: write it to an array and submit a write job 235f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 236f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_baos.reset (); 237f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ClassWriter.writeClassTable (clsDef, m_baos); 238f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 239f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (notcopymode) 240f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 241f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [destination is a zip entry] 242f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 243f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project entry.setTime (m_timeStamp); 244f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project addJob (new EntryWriteJob (m_archiveOut, m_baos.copyByteArray (), entry, false)); 245f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 246f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else // copy mode 247f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 248f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [destination is a file] 249f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 250f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! DO_DEPENDS_CHECKING) // this block is just a complement to the one above (where fullOutFile is inited) 251f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 252f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project outFile = new File (className.replace ('.', File.separatorChar).concat (".class")); 253f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project fullOutFile = getFullOutFile (null, outFile, IN_CLASSES); 254f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 255f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 256f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project addJob (new FileWriteJob (fullOutFile, m_baos.copyByteArray (), true)); 257f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 258f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 259f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else if (notcopymode) 260f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 261f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // original class def already read into m_readbuf: 262f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // clone the array and submit an entry write job 263f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 264f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final byte [] data = new byte [m_readpos]; 265f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project System.arraycopy (m_readbuf, 0, data, 0, data.length); 266f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ++ m_classCopies; 267f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 268f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project entry.setTime (m_timeStamp); 269f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project addJob (new EntryWriteJob (m_archiveOut, data, entry, true)); 270f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 271f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 272f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (FileNotFoundException fnfe) 273f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 274f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // ignore: this should never happen 275f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) 276f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 277f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project fnfe.printStackTrace (System.out); 278f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 279f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 280f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 281f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 282f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code 283f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (ioe); 284f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 285f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 286f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 287f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (clsin != null) 288f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 289f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 290f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project clsin.close (); 291f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 292f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (Exception e) 293f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 294f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code 295f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (e); 296f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 297f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 298f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 299f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 300f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 301f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // copy excluded .class entries in full copy and overwrite modes: 302f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project copyEntry = notcopymode; 303f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 304f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 305f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 306f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 307f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // copy non-.class entries in full copy and overwrite modes: 308f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project copyEntry = notcopymode; 309f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 310f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // skipping these entries here is important: this is done as a complement 311f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // to Sun jar API workarounds as detailed in PathEnumerator.enumeratePathArchive(): 312f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 313f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (copyEntry && name.equalsIgnoreCase ("META-INF/")) 314f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project copyEntry = false; 315f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (copyEntry && name.equalsIgnoreCase (JarFile.MANIFEST_NAME)) 316f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project copyEntry = false; 317f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 318f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: skip signature-related entries (.SF and .RSA/.DSA/.PGP) 319f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 320f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 321f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (copyEntry) 322f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 323f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 324f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 325f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project readZipEntry (in, entry); 326f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 327f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final byte [] data = new byte [m_readpos]; 328f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project System.arraycopy (m_readbuf, 0, data, 0, data.length); 329f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ++ m_classCopies; 330f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 331f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project entry.setTime (m_timeStamp); 332f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project addJob (new EntryWriteJob (m_archiveOut, data, entry, true)); 333f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 334f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 335f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 336f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code 337f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (ioe); 338f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 339f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 340f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 341f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 342f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final void handleArchiveEnd (final File parentDir, final File archive) 343f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 344f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger log = m_log; 345f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atTRACE2 ()) log.trace2 ("handleArchiveEnd", "[" + parentDir + "] [" + archive + "]"); 346f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 347f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_currentArchiveTS = Long.MAX_VALUE; 348f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 349f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((m_outMode == OutMode.OUT_MODE_FULLCOPY) || (m_outMode == OutMode.OUT_MODE_OVERWRITE)) 350f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 351f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 352f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 353f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project drainJobQueue (); // drain the queue before closing the archive 354f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 355f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_archiveOut.flush (); 356f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_archiveOut.close (); 357f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_archiveOut = null; 358f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 359f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 360f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 361f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code 362f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (ioe); 363f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 364f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 365f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // in overwrite mode replace the original archive with the temp archive: 366f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 367f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_outMode == OutMode.OUT_MODE_OVERWRITE) 368f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 369f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (! Files.renameFile (m_tempArchiveFile, m_origArchiveFile, true)) // overwrite the original archive 370f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 371f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: disable temp file cleanup in this case so that the user 372f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // could do it manually later? 373f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 374f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // error code 375f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 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"); 376f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 377f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 378f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 379f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atTRACE2 ()) log.trace2 ("handleArchiveEnd", "renamed temp archive [" + m_tempArchiveFile.getAbsolutePath () + "] to [" + m_origArchiveFile + "]"); 380f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_origArchiveFile = m_tempArchiveFile = null; 381f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 382f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 383f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 384f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 385f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 386f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 387f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final void handleDirStart (final File pathDir, final File dir) 388f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 389f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger log = m_log; 390f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atTRACE2 ()) log.trace2 ("handleDirStart", "[" + pathDir + "] [" + dir + "]"); 391f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 392f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // in full copy mode, create all dirs here; in copy mode, do it as part 393f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // of writing each individual file: 394f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 395f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_outMode == OutMode.OUT_MODE_FULLCOPY) 396f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 397f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File saveDir = new File (getFullOutDir (pathDir, IN_CLASSES), dir.getPath ()); 398f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project createDir (saveDir, true); 399f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 400f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 401f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 402f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final void handleFile (final File pathDir, final File file) 403f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 404f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger log = m_log; 405f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atTRACE2 ()) log.trace2 ("handleFile", "[" + pathDir + "] [" + file + "]"); 406f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 407f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String name = file.getPath (); 408f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String lcName = name.toLowerCase (); 409f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 410f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean fullcopymode = (m_outMode == OutMode.OUT_MODE_FULLCOPY); 411f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean mkdir = (m_outMode == OutMode.OUT_MODE_COPY); 412f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 413f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 414f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project boolean copyFile = false; 415f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 416f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (lcName.endsWith (".class")) 417f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 418f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String className = name.substring (0, name.length () - 6).replace (File.separatorChar, '.'); 419f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 420f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // it is possible that a class with this name has already been processed; 421f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // however, we can't skip it here because there is no guarantee that 422f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // the runtime classpath will be identical to the instrumentation path 423f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 424f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [the metadata will still contain only a single entry for a class with 425f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // this name: it is the responsibility of the user to ensure that both 426f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // files represent the same class; in the future I might use a more 427f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // robust internal strategy that uses something other than a class name 428f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // as a metadata key] 429f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 430f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((m_coverageFilter == null) || m_coverageFilter.included (className)) 431f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 432f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project InputStream clsin = null; 433f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 434f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 435f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File inFile = Files.newFile (pathDir, file.getPath ()); 436f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File fullOutFile = getFullOutFile (pathDir, file, IN_CLASSES); 437f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 438f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (DO_DEPENDS_CHECKING) 439f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 440f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_outMode == OutMode.OUT_MODE_COPY) 441f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 442f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // if we already processed this class name within this instrumentor 443f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // run, skip duplicates in copy mode: 444f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 445f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_mdata.hasDescriptor (Descriptors.javaNameToVMName (className))) 446f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return; 447f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 448f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // otherwise, instrument only if the dest file is out of date 449f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // wrt to the source file: 450f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 451f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long outTimeStamp = fullOutFile.lastModified (); // 0 if 'fullOutFile' does not exist or if an I/O error occurs 452f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 453f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (outTimeStamp > 0) 454f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 455f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long inTimeStamp = inFile.lastModified (); 456f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 457f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (inTimeStamp <= outTimeStamp) 458f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 459f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atVERBOSE ()) log.verbose ("destination file [" + fullOutFile + "] skipped: more recent that the source file"); 460f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project return; 461f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 462f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 463f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 464f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 465f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 466f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project readFile (inFile); 467f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 468f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ClassDef clsDef = ClassDefParser.parseClass (m_readbuf, m_readpos); 469f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 470f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // in non-overwrite modes, bail if src file already instrumented: 471f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_visitor.process (clsDef, m_outMode == OutMode.OUT_MODE_OVERWRITE, true, true, m_instrResult); 472f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_instrResult.m_instrumented) 473f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 474f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (m_instrResult.m_descriptor != null, "no descriptor created for an instrumented class"); 475f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 476f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ++ m_classInstrs; 477f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 478f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // update metadata [if this class has not been seen before]: 479f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 480f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ObjectSizeProfiler.SizeProfile profile = ObjectSizeProfiler.profile (m_instrResult.m_descriptor, true); 481f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// System.out.println (clsDef.getName () + " metadata:"); 482f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// System.out.println (profile.root ().dump (0.2)); 483f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 484f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_mdata.add (m_instrResult.m_descriptor, false); 485f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 486f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // class def modified: write it to an array and submit a write job 487f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 488f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_baos.reset (); 489f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ClassWriter.writeClassTable (clsDef, m_baos); 490f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project clsDef = null; 491f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 492f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final byte [] outdata = m_baos.copyByteArray (); 493f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 494f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project addJob (new FileWriteJob (fullOutFile, outdata, mkdir)); 495f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 496f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else if (fullcopymode) 497f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 498f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // original class def already read into m_readbuf: 499f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // clone the array and submit a file write job 500f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 501f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project clsDef = null; 502f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 503f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final byte [] outdata = new byte [m_readpos]; 504f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project System.arraycopy (m_readbuf, 0, outdata, 0, m_readpos); 505f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ++ m_classCopies; 506f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 507f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project addJob (new FileWriteJob (fullOutFile, outdata, mkdir)); 508f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 509f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 510f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (FileNotFoundException fnfe) 511f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 512f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // ignore: this should never happen 513f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) 514f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 515f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project fnfe.printStackTrace (System.out); 516f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 517f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 518f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 519f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 520f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code 521f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (ioe); 522f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 523f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 524f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 525f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (clsin != null) 526f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 527f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 528f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project clsin.close (); 529f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 530f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (Exception e) 531f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 532f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code 533f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (e); 534f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 535f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 536f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 537f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 538f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 539f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // copy excluded .class files in full copy mode: 540f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project copyFile = fullcopymode; 541f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 542f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 543f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 544f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 545f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // copy non-.class files in full copy mode: 546f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project copyFile = fullcopymode; 547f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 548f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 549f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (copyFile) 550f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 551f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 552f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 553f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File inFile = Files.newFile (pathDir, file.getPath ()); 554f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project readFile (inFile); 555f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 556f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final byte [] data = new byte [m_readpos]; 557f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project System.arraycopy (m_readbuf, 0, data, 0, data.length); 558f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ++ m_classCopies; 559f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 560f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File outFile = getFullOutFile (pathDir, file, IN_CLASSES); 561f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 562f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project addJob (new FileWriteJob (outFile, data, mkdir)); 563f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 564f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 565f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 566f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code 567f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (ioe); 568f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 569f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 570f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 571f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 572f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project public final void handleDirEnd (final File pathDir, final File dir) 573f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 574f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger log = m_log; 575f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atTRACE2 ()) log.trace2 ("handleDirEnd", "[" + pathDir + "] [" + dir + "]"); 576f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 577f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // in overwrite mode, flush the job queue before going to the next directory: 578f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 579f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_outMode == OutMode.OUT_MODE_OVERWRITE) 580f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 581f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 582f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 583f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project drainJobQueue (); 584f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 585f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 586f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 587f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: error code 588f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (ioe); 589f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 590f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 591f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 592f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 593f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // protected: ............................................................. 594f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 595f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 596f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected void reset () 597f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 598f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_visitor = null; 599f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_mdata = null; 600f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_readbuf = null; 601f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_baos = null; 602f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 603f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int j = 0; j < m_jobs.length; ++ j) m_jobs [j] = null; 604f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 605f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (CLEANUP_TEMP_ARCHIVE_ON_ERRORS) 606f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 607f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_archiveOut != null) 608f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try { m_archiveOut.close (); } catch (Exception ignore) {} // unlock the file descriptor for deletion 609f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 610f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_tempArchiveFile != null) 611f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_tempArchiveFile.delete (); 612f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 613f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 614f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_archiveOut = null; 615f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_origArchiveFile = null; 616f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_tempArchiveFile = null; 617f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 618f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project super.reset (); 619f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 620f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 621f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected void _run (final IProperties toolProperties) 622f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 623f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Logger log = m_log; 624f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 625f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean verbose = log.atVERBOSE (); 626f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (verbose) 627f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 628f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose (IAppConstants.APP_VERBOSE_BUILD_ID); 629f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 630f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [assertion: m_instrPath != null] 631f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("instrumentation path:"); 632f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("{"); 633f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int p = 0; p < m_instrPath.length; ++ p) 634f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 635f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File f = m_instrPath [p]; 636f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String nonexistent = f.exists () ? "" : "{nonexistent} "; 637f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 638f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose (" " + nonexistent + f.getAbsolutePath ()); 639f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 640f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("}"); 641f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 642f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [assertion: m_outMode != null] 643f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("instrumentation output mode: " + m_outMode); 644f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 645f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 646f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 647f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.info ("processing instrumentation path ..."); 648f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 649f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 650f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RuntimeException failure = null; 651f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 652f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 653f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project long start = System.currentTimeMillis (); 654f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_timeStamp = start; 655f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 656f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // construct instr path enumerator [throws on illegal input only]: 657f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final IPathEnumerator enumerator = IPathEnumerator.Factory.create (m_instrPath, m_canonical, this); 658f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 659f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // create out dir(s): 660f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 661f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_outMode != OutMode.OUT_MODE_OVERWRITE) createDir (m_outDir, true); 662f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 663f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ((m_outMode == OutMode.OUT_MODE_FULLCOPY)) 664f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 665f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File classesDir = Files.newFile (m_outDir, CLASSES); 666f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project createDir (classesDir, false); // note: not using mkdirs() here 667f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 668f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File libDir = Files.newFile (m_outDir, LIB); 669f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project createDir (libDir, false); // note: not using mkdirs() here 670f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 671f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 672f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 673f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // get the data out settings [note: this is not conditioned on m_dumpRawData]: 674f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project File mdataOutFile = m_mdataOutFile; 675f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project Boolean mdataOutMerge = m_mdataOutMerge; 676f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 677f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (mdataOutFile == null) 678f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project mdataOutFile = new File (toolProperties.getProperty (EMMAProperties.PROPERTY_META_DATA_OUT_FILE, 679f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EMMAProperties.DEFAULT_META_DATA_OUT_FILE)); 680f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 681f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (mdataOutMerge == null) 682f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 683f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final String _dataOutMerge = toolProperties.getProperty (EMMAProperties.PROPERTY_META_DATA_OUT_MERGE, 684f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EMMAProperties.DEFAULT_META_DATA_OUT_MERGE.toString ()); 685f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project mdataOutMerge = Property.toBoolean (_dataOutMerge) ? Boolean.TRUE : Boolean.FALSE; 686f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 687f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 688f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 689f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (verbose) 690f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 691f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("metadata output file: " + mdataOutFile.getAbsolutePath ()); 692f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("metadata output merge mode: " + mdataOutMerge); 693f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 694f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 695f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: can also register an exit hook to clean up temp files, but this is low value 696f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 697f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // allocate I/O buffers: 698f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_readbuf = new byte [BUF_SIZE]; // don't reuse this across run() calls to reset it to the original size 699f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_readpos = 0; 700f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_baos = new ByteArrayOStream (BUF_SIZE); // don't reuse this across run() calls to reset it to the original size 701f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 702f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // reset job queue position: 703f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_jobPos = 0; 704f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 705f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_currentArchiveTS = Long.MAX_VALUE; 706f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 707f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final CoverageOptions options = CoverageOptionsFactory.create (toolProperties); 708f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_visitor = new InstrVisitor (options); // TODO: reuse this? 709f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 710f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_mdata = DataFactory.newMetaData (options); 711f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 712f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // actual work is driven by the path enumerator: 713f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 714f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 715f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project enumerator.enumerate (); 716f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project drainJobQueue (); 717f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 718f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 719f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 720f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (INSTR_IO_FAILURE, ioe); 721f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 722f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 723f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atINFO ()) 724f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 725f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long end = System.currentTimeMillis (); 726f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 727f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.info ("instrumentation path processed in " + (end - start) + " ms"); 728f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.info ("[" + m_classInstrs + " class(es) instrumented, " + m_classCopies + " resource(s) copied]"); 729f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 730f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 731f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // persist metadata: 732f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 733f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 734f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // TODO: create an empty file earlier to catch any errors sooner? [to avoid scenarios where a user waits throught the entire instr run to find out the file could not be written to] 735f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 736f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if ($assert.ENABLED) $assert.ASSERT (mdataOutFile != null, "m_metadataOutFile is null"); 737f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 738f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (verbose) 739f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 740f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_mdata != null) 741f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 742f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.verbose ("metadata contains " + m_mdata.size () + " entries"); 743f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 744f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 745f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 746f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_mdata.isEmpty ()) 747f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 748f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.info ("no output created: metadata is empty"); 749f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 750f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 751f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 752f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project start = System.currentTimeMillis (); 753f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project DataFactory.persist (m_mdata, mdataOutFile, mdataOutMerge.booleanValue ()); 754f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final long end = System.currentTimeMillis (); 755f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 756f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (log.atINFO ()) 757f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 758f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project log.info ("metadata " + (mdataOutMerge.booleanValue () ? "merged into" : "written to") + " [" + mdataOutFile.getAbsolutePath () + "] {in " + (end - start) + " ms}"); 759f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 760f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 761f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 762f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (IOException ioe) 763f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 764f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (OUT_IO_FAILURE, new Object [] {mdataOutFile.getAbsolutePath ()}, ioe); 765f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 766f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 767f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (SecurityException se) 768f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 769f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project failure = new EMMARuntimeException (SECURITY_RESTRICTION, new String [] {IAppConstants.APP_NAME}, se); 770f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 771f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project catch (RuntimeException re) 772f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 773f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project failure = re; 774f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 775f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 776f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 777f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project reset (); 778f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 779f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 780f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (failure != null) 781f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 782f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (Exceptions.unexpectedFailure (failure, EXPECTED_FAILURES)) 783f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 784f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw new EMMARuntimeException (UNEXPECTED_FAILURE, 785f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project new Object [] {failure.toString (), IAppConstants.APP_BUG_REPORT_LINK}, 786f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project failure); 787f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 788f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 789f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throw failure; 790f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 791f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 792f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 793f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // package: ............................................................... 794f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 795f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 796f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project InstrProcessorST () 797f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 798f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_jobs = new Job [JOB_QUEUE_SIZE]; 799f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_instrResult = new InstrVisitor.InstrResult (); 800f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 801f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 802f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 803f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static void writeFile (final byte [] data, final File outFile, final boolean mkdirs) 804f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 805f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 806f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project RandomAccessFile raf = null; 807f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 808f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 809f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (mkdirs) 810f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 811f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File parent = outFile.getParentFile (); 812f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (parent != null) parent.mkdirs (); // no error checking here [errors will be throw below] 813f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 814f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 815f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf = new RandomAccessFile (outFile, "rw"); 816f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (DO_RAF_EXTENSION) raf.setLength (data.length); 817f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 818f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project raf.write (data); 819f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 820f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 821f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 822f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (raf != null) raf.close (); // note: intentionally letting the exception percolate up 823f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 824f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 825f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 826f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static void writeZipEntry (final byte [] data, final ZipOutputStream out, final ZipEntry entry, final boolean isCopy) 827f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 828f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 829f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (isCopy) 830f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 831f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.putNextEntry (entry); // reusing ' entry' is ok here because we are not changing the data 832f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 833f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 834f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write (data); 835f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 836f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 837f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 838f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.closeEntry (); 839f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 840f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 841f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 842f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 843f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // need to compute the checksum which slows things down quite a bit: 844f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 845f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ZipEntry entryCopy = new ZipEntry (entry.getName ()); 846f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project entryCopy.setTime (entry.getTime ()); // avoid repeated calls to System.currentTimeMillis() inside the zip stream 847f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project entryCopy.setMethod (ZipOutputStream.STORED); 848f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // [directory status is implicit in the name] 849f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project entryCopy.setSize (data.length); 850f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project entryCopy.setCompressedSize (data.length); 851f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 852f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final CRC32 crc = new CRC32 (); 853f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project crc.update (data); 854f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project entryCopy.setCrc (crc.getValue ()); 855f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 856f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.putNextEntry (entryCopy); 857f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 858f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 859f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.write (data); 860f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 861f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 862f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 863f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project out.closeEntry (); 864f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 865f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 866f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 867f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 868f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // private: ............................................................... 869f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 870f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 871f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static abstract class Job 872f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 873f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected abstract void run () throws IOException; 874f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 875f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 876f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 877f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 878f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final class FileWriteJob extends Job 879f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 880f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected void run () throws IOException 881f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 882f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project writeFile (m_data, m_outFile, m_mkdirs); 883f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_data = null; 884f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 885f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 886f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project FileWriteJob (final File outFile, final byte [] data, final boolean mkdirs) 887f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 888f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_outFile = outFile; 889f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_data = data; 890f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_mkdirs = mkdirs; 891f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 892f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 893f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 894f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final File m_outFile; 895f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean m_mkdirs; 896f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project byte [] m_data; 897f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 898f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 899f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 900f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 901f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final class EntryWriteJob extends Job 902f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 903f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project protected void run () throws IOException 904f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 905f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project writeZipEntry (m_data, m_out, m_entry, m_isCopy); 906f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_data = null; 907f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 908f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 909f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EntryWriteJob (final ZipOutputStream out, final byte [] data, final ZipEntry entry, final boolean isCopy) 910f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 911f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_out = out; 912f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_data = data; 913f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_entry = entry; 914f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_isCopy = isCopy; 915f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 916f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 917f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 918f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ZipOutputStream m_out; 919f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project byte [] m_data; 920f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final ZipEntry m_entry; 921f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final boolean m_isCopy; 922f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 923f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } // end of nested class 924f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 925f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 926f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private void addJob (final Job job) 927f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws FileNotFoundException, IOException 928f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 929f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_jobPos == JOB_QUEUE_SIZE) drainJobQueue (); 930f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 931f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_jobs [m_jobPos ++] = job; 932f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 933f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 934f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private void drainJobQueue () 935f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 936f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 937f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int j = 0; j < m_jobPos; ++ j) 938f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 939f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final Job job = m_jobs [j]; 940f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (job != null) // a guard just in case 941f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 942f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_jobs [j] = null; 943f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project job.run (); 944f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 945f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 946f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 947f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_jobPos = 0; 948f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 949f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 950f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /* 951f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * Reads into m_readbuf (m_readpos is updated correspondingly) 952f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 953f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private void readFile (final File file) 954f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 955f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 956f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int length = (int) file.length (); 957f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 958f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ensureReadCapacity (length); 959f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 960f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project InputStream in = null; 961f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project try 962f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 963f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project in = new FileInputStream (file); 964f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 965f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int totalread = 0; 966f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int read; 967f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project (totalread < length) && (read = in.read (m_readbuf, totalread, length - totalread)) >= 0; 968f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project totalread += read); 969f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_readpos = totalread; 970f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 971f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project finally 972f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 973f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (in != null) try { in.close (); } catch (Exception ignore) {} 974f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 975f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 976f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 977f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project /* 978f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * Reads into m_readbuf (m_readpos is updated correspondingly) 979f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */ 980f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private void readZipEntry (final ZipInputStream in, final ZipEntry entry) 981f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project throws IOException 982f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 983f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int length = (int) entry.getSize (); // can be -1 if unknown 984f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 985f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (length >= 0) 986f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 987f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ensureReadCapacity (length); 988f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 989f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project int totalread = 0; 990f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int read; 991f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project (totalread < length) && (read = in.read (m_readbuf, totalread, length - totalread)) >= 0; 992f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project totalread += read); 993f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_readpos = totalread; 994f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 995f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project else 996f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 997f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project ensureReadCapacity (BUF_SIZE); 998f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 999f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_baos.reset (); 1000f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project for (int read; (read = in.read (m_readbuf)) >= 0; m_baos.write (m_readbuf, 0, read)); 1001f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1002f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_readbuf = m_baos.copyByteArray (); 1003f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_readpos = m_readbuf.length; 1004f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1005f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1006f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1007f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private void ensureReadCapacity (final int capacity) 1008f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1009f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project if (m_readbuf.length < capacity) 1010f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1011f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project final int readbuflen = m_readbuf.length; 1012f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_readbuf = null; 1013f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project m_readbuf = new byte [Math.max (readbuflen << 1, capacity)]; 1014f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1015f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1016f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1017f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1018f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project // internal run()-scoped state: 1019f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1020f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final Job [] m_jobs; 1021f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private final InstrVisitor.InstrResult m_instrResult; 1022f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1023f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private InstrVisitor m_visitor; 1024f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private IMetaData m_mdata; 1025f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private byte [] m_readbuf; 1026f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int m_readpos; 1027f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private ByteArrayOStream m_baos; // TODO: code to guard this from becoming too large 1028f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private int m_jobPos; 1029f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private long m_currentArchiveTS; 1030f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private File m_origArchiveFile, m_tempArchiveFile; 1031f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private JarOutputStream m_archiveOut; 1032f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private long m_timeStamp; 1033f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1034f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1035f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int BUF_SIZE = 32 * 1024; 1036f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final int JOB_QUEUE_SIZE = 128; // a reasonable size chosen empirically after testing a few SCSI/IDE machines 1037f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final boolean CLEANUP_TEMP_ARCHIVE_ON_ERRORS = true; 1038f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final boolean DO_RAF_EXTENSION = true; 1039f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1040f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final boolean DO_DEPENDS_CHECKING = true; 1041f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project private static final Class [] EXPECTED_FAILURES; // set in <clinit> 1042f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1043f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project static 1044f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1045f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EXPECTED_FAILURES = new Class [] 1046f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project { 1047f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project EMMARuntimeException.class, 1048f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project IllegalArgumentException.class, 1049f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project IllegalStateException.class, 1050f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project }; 1051f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project } 1052f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project 1053f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project} // end of class 1054f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------