KickJava   Java API By Example, From Geeks To Geeks.

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


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: ClassPathProcessorST.java,v 1.1.1.1.2.1 2004/07/16 23:32:03 vlad_r Exp $
8  */

9 package com.vladium.emma.rt;
10
11 import java.io.File JavaDoc;
12 import java.io.FileInputStream JavaDoc;
13 import java.io.FileNotFoundException JavaDoc;
14 import java.io.IOException JavaDoc;
15 import java.io.InputStream JavaDoc;
16 import java.util.Map JavaDoc;
17 import java.util.jar.JarInputStream JavaDoc;
18 import java.util.jar.Manifest JavaDoc;
19 import java.util.zip.ZipEntry JavaDoc;
20 import java.util.zip.ZipInputStream JavaDoc;
21
22 import com.vladium.jcd.cls.ClassDef;
23 import com.vladium.jcd.parser.ClassDefParser;
24 import com.vladium.logging.Logger;
25 import com.vladium.util.ByteArrayOStream;
26 import com.vladium.util.Files;
27 import com.vladium.util.IPathEnumerator;
28 import com.vladium.util.asserts.$assert;
29 import com.vladium.emma.IAppErrorCodes;
30 import com.vladium.emma.EMMARuntimeException;
31 import com.vladium.emma.data.IMetaData;
32 import com.vladium.emma.filter.IInclExclFilter;
33 import com.vladium.emma.instr.InstrVisitor;
34
35 // ----------------------------------------------------------------------------
36
/**
37  * @author Vlad Roubtsov, (C) 2003
38  */

39 public
40 final class ClassPathProcessorST implements IPathEnumerator.IPathHandler, IAppErrorCodes
41 {
42     // public: ................................................................
43

44     public void run ()
45     {
46         long start = System.currentTimeMillis ();
47         
48         // construct instr path enumerator [throws on illegal input only]:
49
final IPathEnumerator enumerator = IPathEnumerator.Factory.create (m_path, m_canonical, this);
50         
51         // allocate I/O buffers:
52
m_readbuf = new byte [BUF_SIZE]; // don't reuse this across run() calls to reset it to the original size
53
m_readpos = 0;
54         m_baos = new ByteArrayOStream (BUF_SIZE); // don't reuse this across run() calls to reset it to the original size
55

56         if (m_log.atINFO ())
57         {
58             m_log.info ("processing classpath ...");
59         }
60         
61         // actual work is driven by the path enumerator:
62
try
63         {
64             enumerator.enumerate ();
65         }
66         catch (IOException JavaDoc ioe)
67         {
68             throw new EMMARuntimeException (INSTR_IO_FAILURE, ioe);
69         }
70         
71         if (m_log.atINFO ())
72         {
73             final long end = System.currentTimeMillis ();
74             
75             m_log.info ("[" + m_classCount + " class(es) processed in " + (end - start) + " ms]");
76         }
77     }
78     
79     // IPathEnumerator.IPathHandler:
80

81     public void handleArchiveStart (final File JavaDoc parentDir, final File JavaDoc archive, final Manifest JavaDoc manifest)
82     {
83         m_archiveFile = Files.newFile (parentDir, archive.getPath ());
84     }
85
86     public void handleArchiveEntry (final JarInputStream JavaDoc in, final ZipEntry JavaDoc entry)
87     {
88         if (m_log.atTRACE2 ()) m_log.trace2 ("handleArchiveEntry", "[" + entry.getName () + "]");
89         
90         final String JavaDoc name = entry.getName ();
91         final String JavaDoc lcName = name.toLowerCase ();
92         
93         if (lcName.endsWith (".class"))
94         {
95             final String JavaDoc className = name.substring (0, name.length () - 6).replace ('/', '.');
96             
97             if ((m_coverageFilter == null) || m_coverageFilter.included (className))
98             {
99                 String JavaDoc srcURL = null;
100                 InputStream JavaDoc clsin = null;
101                 try
102                 {
103                     readZipEntry (in, entry);
104                     
105                     srcURL = "jar:".concat (m_archiveFile.toURL ().toExternalForm ()).concat ("!/").concat (name);
106                 }
107                 catch (FileNotFoundException JavaDoc fnfe)
108                 {
109                     // ignore: this should never happen
110
if ($assert.ENABLED)
111                     {
112                         fnfe.printStackTrace (System.out);
113                     }
114                 }
115                 catch (IOException JavaDoc ioe)
116                 {
117                     // TODO: error code
118
throw new EMMARuntimeException (ioe);
119                 }
120                 finally
121                 {
122                     if (clsin != null)
123                         try
124                         {
125                             clsin.close ();
126                             clsin = null;
127                         }
128                         catch (Exception JavaDoc e)
129                         {
130                             // TODO: error code
131
throw new EMMARuntimeException (e);
132                         }
133                 }
134                 
135                 // [original class def read into m_readbuf]
136

137                 try
138                 {
139                     ClassDef clsDef = ClassDefParser.parseClass (m_readbuf, m_readpos);
140                     if (! clsDef.isInterface ()) ++ m_classCount;
141                     
142                     m_visitor.process (clsDef, false, false, true, m_instrResult); // get metadata only
143
clsDef = null;
144                     
145                     boolean cacheClassDef = true;
146                   
147                     if (m_instrResult.m_descriptor != null)
148                     {
149                         // do not overwrite existing descriptors to support "first
150
// in the classpath wins" semantics:
151

152                         if (! m_mdata.add (m_instrResult.m_descriptor, false))
153                            cacheClassDef = false;
154                     }
155                     
156                     if (cacheClassDef && (m_cache != null))
157                     {
158                         final byte [] bytes = new byte [m_readpos];
159                         System.arraycopy (m_readbuf, 0, bytes, 0, m_readpos);
160                         
161                         m_cache.put (className, new ClassPathCacheEntry (bytes, srcURL));
162                     }
163                 }
164                 catch (IOException JavaDoc ioe)
165                 {
166                     // TODO: error code
167
throw new EMMARuntimeException (ioe);
168                 }
169             }
170         }
171     }
172
173     public void handleArchiveEnd (final File JavaDoc parentDir, final File JavaDoc archive)
174     {
175         m_archiveFile = null;
176     }
177
178
179     public void handleDirStart (final File JavaDoc pathDir, final File JavaDoc dir)
180     {
181         // do nothing
182
}
183
184     public void handleFile (final File JavaDoc pathDir, final File JavaDoc file)
185     {
186         if (m_log.atTRACE2 ()) m_log.trace2 ("handleFile", "[" + pathDir + "] [" + file + "]");
187         
188         final String JavaDoc name = file.getPath ();
189         final String JavaDoc lcName = name.toLowerCase ();
190         
191         if (lcName.endsWith (".class"))
192         {
193             final String JavaDoc className = name.substring (0, name.length () - 6).replace (File.separatorChar, '.');
194             
195             if ((m_coverageFilter == null) || m_coverageFilter.included (className))
196             {
197                 String JavaDoc srcURL = null;
198                 InputStream JavaDoc clsin = null;
199                 try
200                 {
201                     final File JavaDoc inFile = Files.newFile (pathDir, file.getPath ());
202                     readFile (inFile);
203                     
204                     srcURL = inFile.toURL ().toExternalForm ();
205                 }
206                 catch (FileNotFoundException JavaDoc fnfe)
207                 {
208                     // ignore: this should never happen
209
if ($assert.ENABLED)
210                     {
211                         fnfe.printStackTrace (System.out);
212                     }
213                 }
214                 catch (IOException JavaDoc ioe)
215                 {
216                     // TODO: error code
217
throw new EMMARuntimeException (ioe);
218                 }
219                 finally
220                 {
221                     if (clsin != null)
222                         try
223                         {
224                             clsin.close ();
225                             clsin = null;
226                         }
227                         catch (Exception JavaDoc e)
228                         {
229                             // TODO: error code
230
throw new EMMARuntimeException (e);
231                         }
232                 }
233                 
234                 // [original class def read into m_readbuf]
235

236                 try
237                 {
238                     ClassDef clsDef = ClassDefParser.parseClass (m_readbuf, m_readpos);
239                     if (! clsDef.isInterface ()) ++ m_classCount;
240                     
241                     m_visitor.process (clsDef, false, false, true, m_instrResult); // get metadata only
242
clsDef = null;
243                     
244                     
245                     boolean cacheClassDef = true;
246                   
247                     if (m_instrResult.m_descriptor != null)
248                     {
249                         // do not overwrite existing descriptors to support "first
250
// in the classpath wins" semantics:
251

252                         if (! m_mdata.add (m_instrResult.m_descriptor, false))
253                            cacheClassDef = false;
254                     }
255                     
256                     if (cacheClassDef && (m_cache != null))
257                     {
258                         final byte [] bytes = new byte [m_readpos];
259                         System.arraycopy (m_readbuf, 0, bytes, 0, m_readpos);
260                         
261                         m_cache.put (className, new ClassPathCacheEntry (bytes, srcURL));
262                     }
263                 }
264                 catch (IOException JavaDoc ioe)
265                 {
266                     // TODO: error code
267
throw new EMMARuntimeException (ioe);
268                 }
269             }
270         }
271     }
272
273     public void handleDirEnd (final File JavaDoc pathDir, final File JavaDoc dir)
274     {
275         // do nothing
276
}
277
278     // protected: .............................................................
279

280     // package: ...............................................................
281

282
283     /*
284      * null 'cache' indicates to only populate the metadata and not bother with
285      * caching instrumented class defs
286      */

287     ClassPathProcessorST (final File JavaDoc [] path, final boolean canonical,
288                           final IMetaData mdata, final IInclExclFilter filter,
289                           final Map JavaDoc cache)
290     {
291         if (path == null) throw new IllegalArgumentException JavaDoc ("null input: path");
292         if (mdata == null) throw new IllegalArgumentException JavaDoc ("null input: mdata");
293         
294         m_path = path;
295         m_canonical = canonical;
296         m_mdata = mdata;
297         m_coverageFilter = filter;
298         m_cache = cache; // can be null
299
m_visitor = new InstrVisitor (mdata.getOptions ());
300         m_instrResult = new InstrVisitor.InstrResult ();
301         
302         m_log = Logger.getLogger ();
303     }
304
305     // private: ...............................................................
306

307
308     /*
309      * Reads into m_readbuf (m_readpos is updated correspondingly)
310      */

311     private void readFile (final File JavaDoc file)
312         throws IOException JavaDoc
313     {
314         final int length = (int) file.length ();
315         
316         ensureReadCapacity (length);
317         
318         InputStream JavaDoc in = null;
319         try
320         {
321             in = new FileInputStream JavaDoc (file);
322             
323             int totalread = 0;
324             for (int read;
325                  (totalread < length) && (read = in.read (m_readbuf, totalread, length - totalread)) >= 0;
326                  totalread += read);
327             m_readpos = totalread;
328         }
329         finally
330         {
331             if (in != null) try { in.close (); } catch (Exception JavaDoc ignore) {}
332         }
333     }
334     
335     /*
336      * Reads into m_readbuf (m_readpos is updated correspondingly)
337      */

338     private void readZipEntry (final ZipInputStream JavaDoc in, final ZipEntry JavaDoc entry)
339         throws IOException JavaDoc
340     {
341         final int length = (int) entry.getSize (); // can be -1 if unknown
342

343         if (length >= 0)
344         {
345             ensureReadCapacity (length);
346             
347             int totalread = 0;
348             for (int read;
349                  (totalread < length) && (read = in.read (m_readbuf, totalread, length - totalread)) >= 0;
350                  totalread += read);
351             m_readpos = totalread;
352         }
353         else
354         {
355             ensureReadCapacity (BUF_SIZE);
356             
357             m_baos.reset ();
358             for (int read; (read = in.read (m_readbuf)) >= 0; m_baos.write (m_readbuf, 0, read));
359             
360             m_readbuf = m_baos.copyByteArray ();
361             m_readpos = m_readbuf.length;
362         }
363     }
364  
365     private void ensureReadCapacity (final int capacity)
366     {
367         if (m_readbuf.length < capacity)
368         {
369             final int readbuflen = m_readbuf.length;
370             m_readbuf = null;
371             m_readbuf = new byte [Math.max (readbuflen << 1, capacity)];
372         }
373     }
374
375
376     private final File JavaDoc [] m_path; // never null
377
private final boolean m_canonical;
378     private final IMetaData m_mdata; // never null
379
private final IInclExclFilter m_coverageFilter; // can be null
380
private final InstrVisitor m_visitor;
381     private final InstrVisitor.InstrResult m_instrResult;
382     private final Map JavaDoc /* classJavaName:String -> ClassPathCacheEntry */ m_cache; // can be null
383

384     private final Logger m_log; // this class is instantiated and used on a single thread
385

386     private int m_classCount;
387     
388     private byte [] m_readbuf;
389     private int m_readpos;
390     private ByteArrayOStream m_baos; // TODO: code to guard this from becoming too large
391

392     private File JavaDoc m_archiveFile;
393     
394     private static final int BUF_SIZE = 32 * 1024;
395
396 } // end of class
397
// ----------------------------------------------------------------------------
Popular Tags