KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sourceforge > cobertura > coveragedata > ProjectData


1 /*
2  * Cobertura - http://cobertura.sourceforge.net/
3  *
4  * Copyright (C) 2003 jcoverage ltd.
5  * Copyright (C) 2005 Mark Doliner
6  * Copyright (C) 2005 Grzegorz Lukasik
7  * Copyright (C) 2005 Björn Beskow
8  * Copyright (C) 2006 John Lewis
9  *
10  * Cobertura is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published
12  * by the Free Software Foundation; either version 2 of the License,
13  * or (at your option) any later version.
14  *
15  * Cobertura is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Cobertura; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23  * USA
24  */

25
26 package net.sourceforge.cobertura.coveragedata;
27
28 import java.io.File JavaDoc;
29 import java.util.Collection JavaDoc;
30 import java.util.HashMap JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.Map JavaDoc;
33 import java.util.SortedSet JavaDoc;
34 import java.util.TreeSet JavaDoc;
35
36 import net.sourceforge.cobertura.util.FileLocker;
37
38 public class ProjectData extends CoverageDataContainer implements HasBeenInstrumented
39 {
40
41     private static final long serialVersionUID = 6;
42
43     private static ProjectData globalProjectData = null;
44
45     private static SaveTimer saveTimer = null;
46
47     /** This collection is used for quicker access to the list of classes. */
48     private Map JavaDoc classes = new HashMap JavaDoc();
49
50     public void addClassData(ClassData classData)
51     {
52         String JavaDoc packageName = classData.getPackageName();
53         PackageData packageData = (PackageData)children.get(packageName);
54         if (packageData == null)
55         {
56             packageData = new PackageData(packageName);
57             // Each key is a package name, stored as an String object.
58
// Each value is information about the package, stored as a PackageData object.
59
this.children.put(packageName, packageData);
60         }
61         packageData.addClassData(classData);
62         this.classes.put(classData.getName(), classData);
63     }
64
65     public ClassData getClassData(String JavaDoc name)
66     {
67         return (ClassData)this.classes.get(name);
68     }
69
70     /**
71      * This is called by instrumented bytecode.
72      */

73     public ClassData getOrCreateClassData(String JavaDoc name)
74     {
75         ClassData classData = (ClassData)this.classes.get(name);
76         if (classData == null)
77         {
78             classData = new ClassData(name);
79             addClassData(classData);
80         }
81         return classData;
82     }
83
84     public Collection JavaDoc getClasses()
85     {
86         return this.classes.values();
87     }
88
89     public int getNumberOfClasses()
90     {
91         return this.classes.size();
92     }
93
94     public int getNumberOfSourceFiles()
95     {
96         return getSourceFiles().size();
97     }
98
99     public SortedSet JavaDoc getPackages()
100     {
101         return new TreeSet JavaDoc(this.children.values());
102     }
103
104     public Collection JavaDoc getSourceFiles()
105     {
106         SortedSet JavaDoc sourceFileDatas = new TreeSet JavaDoc();
107         Iterator JavaDoc iter = this.children.values().iterator();
108         while (iter.hasNext())
109         {
110             PackageData packageData = (PackageData)iter.next();
111             sourceFileDatas.addAll(packageData.getSourceFiles());
112         }
113         return sourceFileDatas;
114     }
115
116     /**
117      * Get all subpackages of the given package. Includes also specified package if
118      * it exists.
119      *
120      * @param packageName The package name to find subpackages for.
121      * For example, "com.example"
122      * @return A collection containing PackageData objects. Each one
123      * has a name beginning with the given packageName. For
124      * example: "com.example.io", "com.example.io.internal"
125      */

126     public SortedSet JavaDoc getSubPackages(String JavaDoc packageName)
127     {
128         SortedSet JavaDoc subPackages = new TreeSet JavaDoc();
129         Iterator JavaDoc iter = this.children.values().iterator();
130         while (iter.hasNext())
131         {
132             PackageData packageData = (PackageData)iter.next();
133             if (packageData.getName().startsWith(packageName))
134                 subPackages.add(packageData);
135         }
136         return subPackages;
137     }
138
139     public void merge(CoverageData coverageData)
140     {
141         super.merge(coverageData);
142
143         ProjectData projectData = (ProjectData)coverageData;
144         for (Iterator JavaDoc iter = projectData.classes.keySet().iterator(); iter.hasNext();)
145         {
146             Object JavaDoc key = iter.next();
147             if (!this.classes.containsKey(key))
148             {
149                 this.classes.put(key, projectData.classes.get(key));
150             }
151         }
152     }
153
154     /**
155      * Get a reference to a ProjectData object in order to increase the
156      * coverage count for a specific line.
157      *
158      * This method is only called by code that has been instrumented. It
159      * is not called by any of the Cobertura code or ant tasks.
160      */

161     public static ProjectData getGlobalProjectData()
162     {
163         if (globalProjectData != null)
164             return globalProjectData;
165
166         globalProjectData = new ProjectData();
167         initialize();
168         return globalProjectData;
169     }
170
171     // TODO: Is it possible to do this as a static initializer?
172
private static void initialize()
173     {
174         // Hack for Tomcat - by saving project data right now we force loading
175
// of classes involved in this process (like ObjectOutputStream)
176
// so that it won't be necessary to load them on JVM shutdown
177
if (System.getProperty("catalina.home") != null)
178         {
179             saveGlobalProjectData();
180
181             // Force the class loader to load some classes that are
182
// required by our JVM shutdown hook.
183
// TODO: Use ClassLoader.loadClass("whatever"); instead
184
ClassData.class.toString();
185             CoverageData.class.toString();
186             CoverageDataContainer.class.toString();
187             FileLocker.class.toString();
188             HasBeenInstrumented.class.toString();
189             LineData.class.toString();
190             PackageData.class.toString();
191             SourceFileData.class.toString();
192         }
193
194         // Add a hook to save the data when the JVM exits
195
saveTimer = new SaveTimer();
196         Runtime.getRuntime().addShutdownHook(new Thread JavaDoc(saveTimer));
197
198         // Possibly also save the coverage data every x seconds?
199
//Timer timer = new Timer(true);
200
//timer.schedule(saveTimer, 100);
201
}
202
203     public static void saveGlobalProjectData()
204     {
205         ProjectData projectDataToSave = globalProjectData;
206
207         /*
208          * The next statement is not necessary at the moment, because this method is only called
209          * either at the very beginning or at the very end of a test. If the code is changed
210          * to save more frequently, then this will become important.
211          */

212         globalProjectData = new ProjectData();
213
214         /*
215          * Now sleep a bit in case there is a thread still holding a reference to the "old"
216          * globalProjectData (now referenced with projectDataToSave).
217          * We want it to finish its updates. I assume 2 seconds is plenty of time.
218          */

219         try
220         {
221             Thread.sleep(1000);
222         }
223         catch (InterruptedException JavaDoc e)
224         {
225         }
226
227         // Get a file lock
228
File JavaDoc dataFile = CoverageDataFileHandler.getDefaultDataFile();
229         FileLocker fileLocker = new FileLocker(dataFile);
230
231         // Read the old data, merge our current data into it, then
232
// write a new ser file.
233
if (fileLocker.lock())
234         {
235             ProjectData datafileProjectData = loadCoverageDataFromDatafile(dataFile);
236             if (datafileProjectData == null)
237             {
238                 datafileProjectData = projectDataToSave;
239             }
240             else
241             {
242                 datafileProjectData.merge(projectDataToSave);
243             }
244             CoverageDataFileHandler.saveCoverageData(datafileProjectData, dataFile);
245         }
246
247         // Release the file lock
248
fileLocker.release();
249     }
250
251     private static ProjectData loadCoverageDataFromDatafile(File JavaDoc dataFile)
252     {
253         ProjectData projectData = null;
254
255         // Read projectData from the serialized file.
256
if (dataFile.isFile())
257         {
258             projectData = CoverageDataFileHandler.loadCoverageData(dataFile);
259         }
260
261         if (projectData == null)
262         {
263             // We could not read from the serialized file, so use a new object.
264
System.out.println("Cobertura: Coverage data file " + dataFile.getAbsolutePath()
265                     + " either does not exist or is not readable. Creating a new data file.");
266         }
267
268         return projectData;
269     }
270
271 }
272
Popular Tags