Project Report: fawkez

Packagesummary org.jcoderz.phoenix.jcoverage

org.jcoderz.phoenix.jcoverage.Instrumenter

LineHitsNoteSource
1  /*
2   * $Id: Instrumenter.java 1011 2008-06-16 17:57:36Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33  package org.jcoderz.phoenix.jcoverage;
34  
35  import java.io.File;
36  import java.io.FileFilter;
37  import java.io.IOException;
38  import java.util.ArrayList;
39  import java.util.Iterator;
40  import java.util.List;
41  import java.util.logging.Level;
42  import java.util.logging.Logger;
43  
44  import net.sourceforge.cobertura.instrument.Main;
45  
46  import org.jcoderz.commons.util.FileUtils;
47  import org.jcoderz.commons.util.JarUtils;
48  
49  
50  /**
51   * 
52   * @author Michael Griffel
53   */
54  public final class Instrumenter
55  {
560    private static final String CLASSNAME = Instrumenter.class.getName();
57  
580    private static final Logger logger = Logger.getLogger(CLASSNAME);
59  
60     private final ConfigurationParameters mConfig;
61  
620    private final File mBaseTempDir
63        = new File(System.getProperty("java.io.tmpdir"));
64  
65     /**
66      * Constructor.
67      * @param config the configuration parameters.
68      */
69     public Instrumenter (ConfigurationParameters config)
700    {
710       mConfig = config;
720    }
73  
74     /**
75      * Main method.
76      * @param args command line arguments.
77      */
78     public static void main (String[] args)
79 (1)(2)      throws Exception
80     {
810       Main.main(args);
82  
830       logger.info("Instrumentation of '" + args[0] + "' done.");
840    }
85  
86 (3)   private static void parseArguments (String[] args)
87     {
88        // final List arguments = new ArrayList();
89        try
90        {
910          for (int i = 0; i < args.length; )
92           {
930             logger.info("Parsing argument '"
94                    + args[i] + "' = '" + args[i + 1] + "'");
95              
960(4)            if (args[i].equals("-jcoverage"))
97              {
98 (5)               // FIXME: result.setJcoverage(new File(args[i + 1]));
99              }
1000(6)            else if (args[i].equals("-log4j"))
101              {
102 (7)               // FIXME: result.setLog4j(new File(args[i + 1]));
103              }
1040(8)            else if (args[i].equals("-archive"))
105              {
106 (9)               // FIXME: result.setArchive(new File(args[i + 1]));
107              }
1080(10)            else if (args[i].equals("-loglevel"))
109              {
1100                Logger.getLogger("").setLevel(Level.parse(args[i + 1]));
111              }
112              else
113              {
1140                throw new IllegalArgumentException("Invalid argument '"
115                       + args[i] + "'");
116              }
117              
1180             ++i;
1190             ++i;
120           }
121        }
1220       catch (IndexOutOfBoundsException e)
123        {
1240          final IllegalArgumentException ex = new IllegalArgumentException(
125                 "Missing value for " + args[args.length - 1]);
1260          ex.initCause(e);
1270          throw ex;
1280       }
129        
130 (11)      // FIXME: checkFileExists(result.getArchive());
131 (12)      // FIXME: checkFileExists(result.getLog4j());
132 (13)      // FIXME: checkFileExists(result.getJcoverage());
133        
1340    }
135  
136     /**
137      * Checks if the given file exists.
138      * @param f the file to check
139      * @throws IllegalArgumentException if the file does not exists.
140      */
141 (14)   private static void checkFileExists (File f)
142     {
1430       if (!f.exists())
144        {
1450          throw new IllegalArgumentException("The file '"
146                 + f.getAbsolutePath() + "' does not exists.");
147        }
1480    }
149  
150     /**
151      * Run JCoverage instrumentation on the archive file.
152      * @throws IOException in case of an I/O error.
153      */
154     public void instrument ()
155           throws IOException
156     {
1570       instrument(mConfig.getArchive());
1580    }
159     
160     /**
161      * Run JCoverage instrumentation on file <code>f</code>.
162      * @param f file to instrument.
163      * @throws IOException in case of an I/O error.
164      */
165     public void instrument (File f)
166           throws IOException
167     {
1680       if (isArchive(f))
169        {
1700          final File tempDir
171                 = FileUtils.createTempDir(mBaseTempDir, f.getName());
1720          JarUtils.extractJarArchive(tempDir, f);
173        
1740          instrument(tempDir);
175        
1760          if (!f.delete())
177           {
1780             throw new IOException("Cannot remove file " + f);
179           }
180                    
1810          JarUtils.createJarArchive(tempDir, f);
1820          FileUtils.rmdir(tempDir);
1830          logger.info("Creating new jar " + f);
1840       }
1850       else if (f.isDirectory())
186        {
1870          instrumentClasses(f);
1880          findNestedArchives(f);
189        }
1900    }
191  
192     /**
193      * @param f
194    */
195     private void instrumentClasses (File f)
196           throws IOException
197     {
1980       final List classPath = new ArrayList();
1990       findClassPath(f, classPath);
2000       final List classFiles = new ArrayList();
2010       for (final Iterator pathEntrys = classPath.iterator();
2020             pathEntrys.hasNext();)
203        {
2040          final File originDir = (File) pathEntrys.next();
2050          classFiles.clear();
2060          findClassFiles(originDir, originDir, classFiles);
207  
2080          final File tmpDir = FileUtils.createTempDir(
209                 mBaseTempDir, "instrumented-classes");
210  
2110          instrument(classFiles, originDir, tmpDir);
212  
213           // move back to origin basedir
2140          FileUtils.copySlashStar(tmpDir, originDir);
215  
216           // copy coverage file to jar location
217           // the jcoverage*ser files are written to the current working directory
218           // of the JVM!
219           /*
220           final List jcoverageFiles = FileUtils.findFile(
221                 new File("."), "jcoverage.*\\.ser");
222           for (final Iterator iterator = jcoverageFiles.iterator(); 
223                 iterator.hasNext();)
224           {
225              final File file = (File) iterator.next();
226              FileUtils.copy(file, originDir);
227           }
228           */
229           
230           // add jcoverage.jar/log4j classes
2310          JarUtils.extractJarArchive(originDir, mConfig.getJcoverage());
2320          JarUtils.extractJarArchive(originDir, mConfig.getLog4j());
233  
2340          FileUtils.rmdir(tmpDir);
2350       }
2360    }
237  
238     /**
239      * Calls the Instrument class from the jcoverage package.
240      * 
241      * @param classFiles
242    * @param classpath
243    * @param destinationDir
244    * @throws IOException
245    */
246     private void instrument (
247           List classFiles, File classpath, File destinationDir)
248           throws IOException
249     {
250        // Instrumentation
2510       final List args = new ArrayList();
2520       args.add("-d");
2530       args.add(destinationDir.getCanonicalPath());
2540       args.add("-ignore");
2550       args.add("org.apache.log4j.*");
2560       args.add("-basedir");
2570       args.add(classpath.getCanonicalPath());
2580       args.addAll(classFiles);
259  
2600       logger.finest("Instrument with the following args: " + args);
261             
2620(15)(16)      Main.main((String[]) args.toArray(new String[0]));
2630    }
264     
265     /**
266      * @param pathEntry
267    * @param pathEntry2
268    * @param classFiles
269    */
270     private void findClassFiles (File basePath, File file, List classFiles)
271           throws IOException
272     {
2730       if (file.isFile())
274        {
2750          final String className = FileUtils.getRelativePath(basePath, file);
2760          if (className.endsWith(".class") && className.indexOf('$') == -1
277                 && className.matches(".*org.jcoderz.*"))
278           {
279              //className = className.substring(
280              // 0, className.length() - ".class".length());
281              /*
282              if (File.separator.equals("\\"))
283              {
284                 className = className.replaceAll("\\\\", ".");
285              }
286              else
287              {   
288                 className = className.replaceAll(File.separator, ".");
289              }
290              */
2910             classFiles.add(className);
292           }
2930       }
2940       else if (file.isDirectory())
295        {
2960          final File [] files = file.listFiles();
297          
2980          for (int i = 0; files != null && i < files.length; i++)
299           {
3000             findClassFiles(basePath, files[i], classFiles);
301           }
302        }
3030    }
304  
305     /**
306      * @param f
307    * @param classPath
308    */
309     private void findClassPath (File f, List classPath)
310     {
3110       final File [] files = f.listFiles(new FileFilter()
3120(17)            {
313                 public boolean accept (File pathname)
314                 {
3150                   return pathname.isDirectory();
316                 }
317              });
318  
3190       boolean found = false;
3200       for (int i = 0; !found && i < files.length; i++)
321        {
3220(18)         if (files[i].getName().equals("com")
323               || files[i].getName().equals("junit"))
324           {
3250             classPath.add(files[i].getParentFile());
3260             found = true;
327           }
328        }
3290       if (!found)
330        {
3310          for (int i = 0; i < files.length; i++)
332           {
3330             findClassPath(files[i], classPath);
334           }
335        }
3360    }
337  
338     /**
339      * @param f
340    */
341     private void findNestedArchives (File file)
342           throws IOException
343     {
3440       if (file == null)
345        {
346           // done...
347        }
3480       else if (file.isDirectory())
349        {
3500          final File [] files = file.listFiles();
3510          for (int i = 0; i < files.length; i++)
352           {
3530             findNestedArchives(files[i]);
354           }
3550       }
356        else
357        {
3580          if (isArchive(file))
359           {
3600             instrument(file);
361           }
362        }
3630    }
364  
365     private boolean isArchive (File file)
366           throws IOException
367     {
3680       return file.getCanonicalPath().matches(".*\\.[jerw]ar");
369     }
370     
3710    private static class ConfigurationParameters
372     {
3730       private File mArchive = null;
3740       private File mLog4j = null;
3750       private File mJcoverage = null;
376  
377        /**
378         * Returns the archive.
379         * @return the archive.
380         */
381        public final File getArchive ()
382        {
3830          return mArchive;
384        }
385  
386        /**
387         * Sets the archive to given <code>archive</code>.
388         * @param archive The archive to set.
389         */
390        public final void setArchive (File archive)
391        {
3920          mArchive = archive;
3930       }
394  
395        /**
396         * Returns the jcoverage.
397         * @return the jcoverage.
398         */
399        public final File getJcoverage ()
400        {
4010          return mJcoverage;
402        }
403  
404        /**
405         * Sets the jcoverage to given <code>jcoverage</code>.
406         * @param jcoverage The jcoverage to set.
407         */
408        public final void setJcoverage (File jcoverage)
409        {
4100          mJcoverage = jcoverage;
4110       }
412  
413        /**
414         * Returns the log4j.
415         * @return the log4j.
416         */
417        public final File getLog4j ()
418        {
4190          return mLog4j;
420        }
421  
422        /**
423         * Sets the log4j to given <code>log4j</code>.
424         * @param log4j The log4j to set.
425         */
426        public final void setLog4j (File log4j)
427        {
4280          mLog4j = log4j;
4290       }
430  
431     }
432     
433  }

Findings in this File

c (1) 79 : 14 Expected @throws tag for 'Exception'.
d (2) 79 : 14 A method/constructor shouldn't explicitly throw java.lang.Exception
i (3) 86 : 24 Avoid unused private methods such as 'parseArguments(String)'.
i (4) 96 : 0 method org.jcoderz.phoenix.jcoverage.Instrumenter.parseArguments(String[]) makes literal string comparisons passing the literal as an argument
i (5) 98 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
i (6) 100 : 0 method org.jcoderz.phoenix.jcoverage.Instrumenter.parseArguments(String[]) makes literal string comparisons passing the literal as an argument
i (7) 102 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
i (8) 104 : 0 method org.jcoderz.phoenix.jcoverage.Instrumenter.parseArguments(String[]) makes literal string comparisons passing the literal as an argument
i (9) 106 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
i (10) 108 : 0 method org.jcoderz.phoenix.jcoverage.Instrumenter.parseArguments(String[]) makes literal string comparisons passing the literal as an argument
i (11) 130 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
i (12) 131 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
i (13) 132 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
i (14) 141 : 24 Avoid unused private methods such as 'checkFileExists(File)'.
i (15) 262 : 0 Method org.jcoderz.phoenix.jcoverage.Instrumenter.instrument(List, File, File) uses Collection.toArray() with zero-length array argument
c (16) 262 : 28 This call to Collection.toArray() may be optimizable
i (17) 312 : 0 The class org.jcoderz.phoenix.jcoverage.Instrumenter$1 could be refactored into a named _static_ inner class
i (18) 322 : 0 method org.jcoderz.phoenix.jcoverage.Instrumenter.findClassPath(File, List) makes literal string comparisons passing the literal as an argument