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: ClassPathProcessorST.java,v 1.1.1.1.2.1 2004/07/16 23:32:03 vlad_r Exp $
8f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */
9f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpackage com.vladium.emma.rt;
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.IOException;
15f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.io.InputStream;
16f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.Map;
17f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.jar.JarInputStream;
18f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.jar.Manifest;
19f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.zip.ZipEntry;
20f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport java.util.zip.ZipInputStream;
21f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
22f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.cls.ClassDef;
23f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.jcd.parser.ClassDefParser;
24f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.logging.Logger;
25f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.ByteArrayOStream;
26f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.Files;
27f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.IPathEnumerator;
28f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.util.asserts.$assert;
29f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.IAppErrorCodes;
30f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.EMMARuntimeException;
31f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.data.IMetaData;
32f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.filter.IInclExclFilter;
33f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectimport com.vladium.emma.instr.InstrVisitor;
34f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
35f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------
36f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project/**
37f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project * @author Vlad Roubtsov, (C) 2003
38f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project */
39f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectpublic
40f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Projectfinal class ClassPathProcessorST implements IPathEnumerator.IPathHandler, IAppErrorCodes
41f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project{
42f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // public: ................................................................
43f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
44f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public void run ()
45f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
46f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        long start = System.currentTimeMillis ();
47f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
48f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // construct instr path enumerator [throws on illegal input only]:
49f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final IPathEnumerator enumerator = IPathEnumerator.Factory.create (m_path, m_canonical, this);
50f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
51f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // allocate I/O buffers:
52f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_readbuf = new byte [BUF_SIZE]; // don't reuse this across run() calls to reset it to the original size
53f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_readpos = 0;
54f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_baos = new ByteArrayOStream (BUF_SIZE); // don't reuse this across run() calls to reset it to the original size
55f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
56f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (m_log.atINFO ())
57f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
58f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_log.info ("processing classpath ...");
59f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
60f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
61f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // actual work is driven by the path enumerator:
62f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        try
63f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
64f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            enumerator.enumerate ();
65f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
66f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        catch (IOException ioe)
67f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
68f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            throw new EMMARuntimeException (INSTR_IO_FAILURE, ioe);
69f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
70f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
71f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (m_log.atINFO ())
72f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
73f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final long end = System.currentTimeMillis ();
74f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
75f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_log.info ("[" + m_classCount + " class(es) processed in " + (end - start) + " ms]");
76f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
77f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
78f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
79f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // IPathEnumerator.IPathHandler:
80f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
81f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public void handleArchiveStart (final File parentDir, final File archive, final Manifest manifest)
82f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
83f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_archiveFile = Files.newFile (parentDir, archive.getPath ());
84f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
85f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
86f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public void handleArchiveEntry (final JarInputStream in, final ZipEntry entry)
87f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
88f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (m_log.atTRACE2 ()) m_log.trace2 ("handleArchiveEntry", "[" + entry.getName () + "]");
89f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
90f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final String name = entry.getName ();
91f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final String lcName = name.toLowerCase ();
92f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
93f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (lcName.endsWith (".class"))
94f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
95f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String className = name.substring (0, name.length () - 6).replace ('/', '.');
96f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
97f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if ((m_coverageFilter == null) || m_coverageFilter.included (className))
98f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
99f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                String srcURL = null;
100f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                InputStream clsin = null;
101f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                try
102f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
103f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    readZipEntry (in, entry);
104f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
105f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    srcURL = "jar:".concat (m_archiveFile.toURL ().toExternalForm ()).concat ("!/").concat (name);
106f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
107f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                catch (FileNotFoundException fnfe)
108f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
109f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // ignore: this should never happen
110f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if ($assert.ENABLED)
111f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
112f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        fnfe.printStackTrace (System.out);
113f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
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                finally
121f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
122f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (clsin != null)
123f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        try
124f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        {
125f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            clsin.close ();
126f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            clsin = null;
127f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        }
128f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        catch (Exception e)
129f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        {
130f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            // TODO: error code
131f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            throw new EMMARuntimeException (e);
132f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        }
133f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
134f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
135f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // [original class def read into m_readbuf]
136f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
137f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                try
138f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
139f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    ClassDef clsDef = ClassDefParser.parseClass (m_readbuf, m_readpos);
140f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (! clsDef.isInterface ()) ++ m_classCount;
141f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
142f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    m_visitor.process (clsDef, false, false, true, m_instrResult); // get metadata only
143f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    clsDef = null;
144f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
145f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    boolean cacheClassDef = true;
146f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
147f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (m_instrResult.m_descriptor != null)
148f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
149f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        // do not overwrite existing descriptors to support "first
150f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        // in the classpath wins" semantics:
151f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
152f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (! m_mdata.add (m_instrResult.m_descriptor, false))
153f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                           cacheClassDef = false;
154f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
155f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
156f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (cacheClassDef && (m_cache != null))
157f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
158f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        final byte [] bytes = new byte [m_readpos];
159f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        System.arraycopy (m_readbuf, 0, bytes, 0, m_readpos);
160f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
161f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        m_cache.put (className, new ClassPathCacheEntry (bytes, srcURL));
162f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
163f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
164f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                catch (IOException ioe)
165f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
166f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // TODO: error code
167f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    throw new EMMARuntimeException (ioe);
168f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
169f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
170f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
171f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
172f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
173f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public void handleArchiveEnd (final File parentDir, final File archive)
174f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
175f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_archiveFile = null;
176f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
177f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
178f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
179f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public void handleDirStart (final File pathDir, final File dir)
180f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
181f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // do nothing
182f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
183f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
184f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public void handleFile (final File pathDir, final File file)
185f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
186f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (m_log.atTRACE2 ()) m_log.trace2 ("handleFile", "[" + pathDir + "] [" + file + "]");
187f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
188f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final String name = file.getPath ();
189f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final String lcName = name.toLowerCase ();
190f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
191f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (lcName.endsWith (".class"))
192f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
193f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final String className = name.substring (0, name.length () - 6).replace (File.separatorChar, '.');
194f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
195f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if ((m_coverageFilter == null) || m_coverageFilter.included (className))
196f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            {
197f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                String srcURL = null;
198f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                InputStream clsin = null;
199f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                try
200f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
201f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    final File inFile = Files.newFile (pathDir, file.getPath ());
202f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    readFile (inFile);
203f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
204f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    srcURL = inFile.toURL ().toExternalForm ();
205f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
206f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                catch (FileNotFoundException fnfe)
207f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
208f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // ignore: this should never happen
209f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if ($assert.ENABLED)
210f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
211f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        fnfe.printStackTrace (System.out);
212f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
213f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
214f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                catch (IOException ioe)
215f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
216f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // TODO: error code
217f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    throw new EMMARuntimeException (ioe);
218f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
219f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                finally
220f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
221f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (clsin != null)
222f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        try
223f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        {
224f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            clsin.close ();
225f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            clsin = null;
226f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        }
227f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        catch (Exception e)
228f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        {
229f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            // TODO: error code
230f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                            throw new EMMARuntimeException (e);
231f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        }
232f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
233f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
234f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                // [original class def read into m_readbuf]
235f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
236f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                try
237f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
238f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    ClassDef clsDef = ClassDefParser.parseClass (m_readbuf, m_readpos);
239f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (! clsDef.isInterface ()) ++ m_classCount;
240f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
241f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    m_visitor.process (clsDef, false, false, true, m_instrResult); // get metadata only
242f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    clsDef = null;
243f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
244f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
245f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    boolean cacheClassDef = true;
246f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
247f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (m_instrResult.m_descriptor != null)
248f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
249f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        // do not overwrite existing descriptors to support "first
250f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        // in the classpath wins" semantics:
251f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
252f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        if (! m_mdata.add (m_instrResult.m_descriptor, false))
253f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                           cacheClassDef = false;
254f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
255f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
256f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    if (cacheClassDef && (m_cache != null))
257f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    {
258f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        final byte [] bytes = new byte [m_readpos];
259f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        System.arraycopy (m_readbuf, 0, bytes, 0, m_readpos);
260f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
261f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                        m_cache.put (className, new ClassPathCacheEntry (bytes, srcURL));
262f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    }
263f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
264f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                catch (IOException ioe)
265f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                {
266f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    // TODO: error code
267f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                    throw new EMMARuntimeException (ioe);
268f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                }
269f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            }
270f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
271f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
272f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
273f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    public void handleDirEnd (final File pathDir, final File dir)
274f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
275f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        // do nothing
276f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
277f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
278f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // protected: .............................................................
279f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
280f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // package: ...............................................................
281f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
282f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
283f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /*
284f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * null 'cache' indicates to only populate the metadata and not bother with
285f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * caching instrumented class defs
286f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
287f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    ClassPathProcessorST (final File [] path, final boolean canonical,
288f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                          final IMetaData mdata, final IInclExclFilter filter,
289f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                          final Map cache)
290f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
291f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (path == null) throw new IllegalArgumentException ("null input: path");
292f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (mdata == null) throw new IllegalArgumentException ("null input: mdata");
293f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
294f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_path = path;
295f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_canonical = canonical;
296f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_mdata = mdata;
297f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_coverageFilter = filter;
298f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_cache = cache; // can be null
299f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_visitor = new InstrVisitor (mdata.getOptions ());
300f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_instrResult = new InstrVisitor.InstrResult ();
301f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
302f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        m_log = Logger.getLogger ();
303f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
304f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
305f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    // private: ...............................................................
306f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
307f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
308f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /*
309f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * Reads into m_readbuf (m_readpos is updated correspondingly)
310f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
311f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private void readFile (final File file)
312f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        throws IOException
313f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
314f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final int length = (int) file.length ();
315f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
316f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        ensureReadCapacity (length);
317f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
318f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        InputStream in = null;
319f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        try
320f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
321f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            in = new FileInputStream (file);
322f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
323f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            int totalread = 0;
324f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (int read;
325f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 (totalread < length) && (read = in.read (m_readbuf, totalread, length - totalread)) >= 0;
326f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 totalread += read);
327f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_readpos = totalread;
328f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
329f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        finally
330f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
331f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            if (in != null) try { in.close (); } catch (Exception ignore) {}
332f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
333f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
334f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
335f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    /*
336f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     * Reads into m_readbuf (m_readpos is updated correspondingly)
337f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project     */
338f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private void readZipEntry (final ZipInputStream in, final ZipEntry entry)
339f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        throws IOException
340f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
341f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        final int length = (int) entry.getSize (); // can be -1 if unknown
342f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
343f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (length >= 0)
344f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
345f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            ensureReadCapacity (length);
346f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
347f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            int totalread = 0;
348f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (int read;
349f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 (totalread < length) && (read = in.read (m_readbuf, totalread, length - totalread)) >= 0;
350f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project                 totalread += read);
351f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_readpos = totalread;
352f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
353f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        else
354f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
355f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            ensureReadCapacity (BUF_SIZE);
356f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
357f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_baos.reset ();
358f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            for (int read; (read = in.read (m_readbuf)) >= 0; m_baos.write (m_readbuf, 0, read));
359f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
360f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_readbuf = m_baos.copyByteArray ();
361f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_readpos = m_readbuf.length;
362f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
363f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
364f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
365f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private void ensureReadCapacity (final int capacity)
366f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    {
367f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        if (m_readbuf.length < capacity)
368f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        {
369f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            final int readbuflen = m_readbuf.length;
370f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_readbuf = null;
371f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project            m_readbuf = new byte [Math.max (readbuflen << 1, capacity)];
372f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project        }
373f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    }
374f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
375f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
376f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final File [] m_path; // never null
377f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final boolean m_canonical;
378f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final IMetaData m_mdata; // never null
379f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final IInclExclFilter m_coverageFilter; // can be null
380f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final InstrVisitor m_visitor;
381f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final InstrVisitor.InstrResult m_instrResult;
382f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final Map /* classJavaName:String -> ClassPathCacheEntry */ m_cache; // can be null
383f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
384f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private final Logger m_log; // this class is instantiated and used on a single thread
385f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
386f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private int m_classCount;
387f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
388f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private byte [] m_readbuf;
389f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private int m_readpos;
390f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private ByteArrayOStream m_baos; // TODO: code to guard this from becoming too large
391f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
392f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private File m_archiveFile;
393f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
394f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project    private static final int BUF_SIZE = 32 * 1024;
395f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project
396f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project} // end of class
397f6fe897e173f4e4bda72a7dddb091b667066764aThe Android Open Source Project// ----------------------------------------------------------------------------