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// ----------------------------------------------------------------------------