1/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2 *
3 * This program and the accompanying materials are made available under
4 * the terms of the Common Public License v1.0 which accompanies this distribution,
5 * and is available at http://www.eclipse.org/legal/cpl-v10.html
6 *
7 * $Id: RTExitHook.java,v 1.1.1.1.2.2 2004/07/10 03:34:53 vlad_r Exp $
8 */
9package com.vladium.emma.rt;
10
11import java.io.File;
12import java.io.IOException;
13import java.io.InputStream;
14import java.util.Properties;
15import java.util.StringTokenizer;
16
17import com.vladium.emma.data.ICoverageData;
18
19// ----------------------------------------------------------------------------
20/**
21 * @author Vlad Roubtsov, (C) 2003
22 */
23final class RTExitHook implements Runnable
24{
25    // public: ................................................................
26
27
28    public synchronized void run ()
29    {
30        if (m_cdata != null)
31        {
32            RTCoverageDataPersister.dumpCoverageData (m_cdata, true, m_outFile, m_merge);
33
34            m_RT = null;
35            m_cdata = null;
36        }
37    }
38
39    public static void createClassLoaderClosure ()
40    {
41        Properties closureMap = null;
42
43        InputStream in = null;
44        try
45        {
46            // note that this does not use ClassLoaderResolver by design
47            // (closure loading must not load any app classes that are outside
48            /// the closure list)
49
50            in = RTExitHook.class.getResourceAsStream (CLOSURE_RESOURCE);
51            if (in != null)
52            {
53                closureMap = new Properties ();
54                closureMap.load (in);
55            }
56            else
57            {
58                throw new Error ("packaging failure: closure resource not found");
59            }
60        }
61        catch (Exception e)
62        {
63            e.printStackTrace (System.out);
64
65            throw new Error ("packaging failure: " + e.toString ());
66        }
67        finally
68        {
69            if (in != null) try { in.close (); } catch (IOException ignore) { ignore.printStackTrace (); }
70        }
71        in = null;
72
73        final String closureList = closureMap.getProperty ("closure");
74        if (closureList == null)
75        {
76            throw new Error ("packaging failure: no closure mapping");
77        }
78
79        // note that this uses the current classloader (only), consistently
80        // with the getResourceAsStream() above:
81
82        final ClassLoader loader = RTExitHook.class.getClassLoader ();
83
84        final StringTokenizer tokenizer = new StringTokenizer (closureList, ",");
85        while (tokenizer.hasMoreTokens ())
86        {
87            final String className = tokenizer.nextToken ();
88
89            try
90            {
91                Class.forName (className, true, loader);
92            }
93            catch (Exception e)
94            {
95                throw new Error ("packaging failure: class [" + className + "] not found {" + e.toString () + "}");
96            }
97        }
98    }
99
100    // protected: .............................................................
101
102    // package: ...............................................................
103
104
105    RTExitHook (final Class RT, final ICoverageData cdata, final File outFile, final boolean merge)
106    {
107        m_RT = RT;
108        m_cdata = cdata;
109
110        m_outFile = outFile;
111        m_merge = merge;
112    }
113
114    // private: ...............................................................
115
116
117    private final File m_outFile;
118    private final boolean m_merge;
119
120    private Class m_RT; // keep our RT class pinned in memory
121    private ICoverageData m_cdata;
122
123    private static final String CLOSURE_RESOURCE = "RTExitHook.closure"; // relative to this package
124
125} // end of class
126// ----------------------------------------------------------------------------