KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > vladium > emma > rt > InstrClassLoadHook


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: InstrClassLoadHook.java,v 1.1.1.1 2004/05/09 16:57:44 vlad_r Exp $
8  */

9 package com.vladium.emma.rt;
10
11 import java.io.IOException JavaDoc;
12
13 import com.vladium.jcd.cls.ClassDef;
14 import com.vladium.jcd.compiler.ClassWriter;
15 import com.vladium.jcd.parser.ClassDefParser;
16 import com.vladium.util.ByteArrayOStream;
17 import com.vladium.util.Descriptors;
18 import com.vladium.util.asserts.$assert;
19 import com.vladium.emma.filter.IInclExclFilter;
20 import com.vladium.emma.instr.InstrVisitor;
21 import com.vladium.emma.data.CoverageOptions;
22 import com.vladium.emma.data.IMetaData;
23
24 // ----------------------------------------------------------------------------
25
/**
26  * MT-safety ensured by the containing loader
27  *
28  * @author Vlad Roubtsov, (C) 2003
29  */

30 public
31 final class InstrClassLoadHook implements IClassLoadHook
32 {
33     // public: ................................................................
34

35     /**
36      * @param filter [can be null]
37      */

38     public InstrClassLoadHook (final IInclExclFilter filter, final IMetaData mdata)
39     {
40         if (mdata == null) throw new IllegalArgumentException JavaDoc ("null input: mdata");
41         
42         m_filter = filter; // can be null
43
m_metadata = mdata;
44         
45         // important to use the same options as the metadata may have been populated earlier:
46
final CoverageOptions options = mdata.getOptions ();
47         m_classDefProcessor = new InstrVisitor (options);
48         
49         m_instrResult = new InstrVisitor.InstrResult ();
50     }
51     
52         
53     public boolean processClassDef (final String JavaDoc className,
54                                     final byte [] bytes, final int length,
55                                     ByteArrayOStream out)
56         throws IOException JavaDoc
57     {
58         if ($assert.ENABLED)
59         {
60             $assert.ASSERT (className != null, "className is null");
61             $assert.ASSERT (bytes != null, "bytes is null");
62             $assert.ASSERT (bytes != null, "out is null");
63         }
64         
65         final IInclExclFilter filter = m_filter;
66         if ((filter == null) || filter.included (className))
67         {
68             final ClassDef clsDef = ClassDefParser.parseClass (bytes, length);
69             final String JavaDoc classVMName = Descriptors.javaNameToVMName (className);
70             
71             final Object JavaDoc lock = m_metadata.lock ();
72             
73             final boolean metadataExists;
74             synchronized (lock)
75             {
76                 metadataExists = m_metadata.hasDescriptor (classVMName);
77             }
78             
79             // since this is the first [and only] time the parent loader is
80
// loading the class in question, if metadata for 'className' exists
81
// it means it was created during the app runner's classpath scan --
82
// do not overwrite it (the class def should be the same)
83

84             // [this picture breaks down if the design changes so that the same
85
// metadata instance could be associated with more than one app loader]
86

87             m_classDefProcessor.process (clsDef, false, true, ! metadataExists, m_instrResult);
88             
89             boolean useOurs = m_instrResult.m_instrumented;
90             
91             if (m_instrResult.m_descriptor != null) // null means either the metadata existed already or the class is an interface
92
{
93                 // try to update metadata [this supports the "no initial full cp
94
// scan mode" in the app runner and also ensures that we pick up
95
// any dynamically generated classes to support (hacky) apps that
96
// do dynamic source generation/compilation]:
97

98                 synchronized (lock)
99                 {
100                     // do not force overwrites of existing descriptors to support
101
// correct handling of race conditions: if another thread
102
// updates the metadata first, discard our version of the class def
103

104                     // [actually, this guard is redundant here because
105
// right now the hook can only have a single classloader parent
106
// and the parent's loadClass() is a critical section]
107

108                     if (! m_metadata.add (m_instrResult.m_descriptor, false))
109                          useOurs = false;
110                 }
111             }
112             
113             if (useOurs)
114             {
115                 ClassWriter.writeClassTable (clsDef, out);
116                 return true;
117             }
118         }
119
120         return false;
121     }
122     
123     // protected: .............................................................
124

125     // package: ...............................................................
126

127     // private: ...............................................................
128

129     
130     private final IInclExclFilter m_filter; // can be null [equivalent to no filtering]
131
private final IMetaData m_metadata; // never null
132
private final InstrVisitor m_classDefProcessor; // never null
133
private final InstrVisitor.InstrResult m_instrResult;
134
135 } // end of class
136
// ----------------------------------------------------------------------------
Popular Tags