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: IClassLoadHook.java,v 1.1.1.1 2004/05/09 16:57:44 vlad_r Exp $
8 */
9package com.vladium.emma.rt;
10
11import java.io.IOException;
12
13import com.vladium.util.ByteArrayOStream;
14
15// ----------------------------------------------------------------------------
16/**
17 * @author Vlad Roubtsov, 2003
18 */
19public
20interface IClassLoadHook
21{
22    // public: ................................................................
23
24//    /**
25//     * The hook returns 'true' or 'false' based on 'className' only. If it
26//     * returns false, the current loader will load the class bytes itself and
27//     * pass them to ClassLoader.defineClass() unchanged. This is an optimization
28//     * to let the JVM native code do the parsing of class definitions for classes
29//     * that do not match coverage filters instead of doing this in bytecode.
30//     */
31//    boolean interested (String className);
32
33    // TODO: figure out a way to avoid all this excessive copying of byte arrays
34
35    /* TODO: finish
36     *
37     * The hook reads in the original class definition from 'in' and [possibly]
38     * instruments it, returning the modified class definion [which should
39     * correspond to the original class name]. Only class definitions with names
40     * that were successfully filtered via a previous (although not necessarily
41     * <em>immediately</em> so) call to {@link #interested} will be passed to
42     * this method.<P>
43     *
44     * It is possible that the hook will determine that it is not interested in
45     * intrumenting the pending class definition [or is unable to do so] only
46     * after reading some content from 'in'. An example would be when the class
47     * definition turns out to be for an interface and the hook does not process
48     * interfaces. Because 'in' can then be left in an uncertain state, the hook
49     * must follow these rules for the two possible outcomes:
50     * <ol>
51     *  <li> if the hook can successfully recover the unmodified class definion
52     * [perhaps because it cloned the original definition or never modified it]:
53     * it should write it into 'out' and return 'true';
54     *  <li> if the hook has lost the original class definion: it should return 'false'.
55     * Following that, the current loader will close() and discard 'in' and load
56     * the class from another, equivalent in content, data stream instance.
57     * </ol>
58     *
59     * In any case 'in' and 'out' remain owned [and will be close()d] by the caller.
60     *
61     * NOTE: the hook should only write to 'out' after reading the entire
62     * class definition in 'bytes' ('out' could be backed by the same array as
63     * 'bytes')
64     *
65     * @param out [buffered by the caller]
66     */
67    boolean processClassDef (String className,
68                             byte [] bytes, int length,
69                             ByteArrayOStream out)
70        throws IOException;
71
72} // end of interface
73// ----------------------------------------------------------------------------