KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mountainminds > eclemma > core > launching > CoverageLauncher


1 /*******************************************************************************
2  * Copyright (c) 2006 Mountainminds GmbH & Co. KG
3  * This software is provided under the terms of the Eclipse Public License v1.0
4  * See http://www.eclipse.org/legal/epl-v10.html.
5  *
6  * $Id: CoverageLauncher.java 399 2007-08-30 19:12:38Z mtnminds $
7  ******************************************************************************/

8 package com.mountainminds.eclemma.core.launching;
9
10 import java.io.FileOutputStream JavaDoc;
11 import java.io.IOException JavaDoc;
12 import java.util.ArrayList JavaDoc;
13 import java.util.List JavaDoc;
14 import java.util.Map JavaDoc;
15 import java.util.Properties JavaDoc;
16 import java.util.jar.JarOutputStream JavaDoc;
17 import java.util.jar.Manifest JavaDoc;
18 import java.util.zip.ZipEntry JavaDoc;
19
20 import org.eclipse.core.runtime.CoreException;
21 import org.eclipse.core.runtime.IConfigurationElement;
22 import org.eclipse.core.runtime.IExecutableExtension;
23 import org.eclipse.core.runtime.IPath;
24 import org.eclipse.core.runtime.IProgressMonitor;
25 import org.eclipse.core.runtime.IStatus;
26 import org.eclipse.core.runtime.SubProgressMonitor;
27 import org.eclipse.debug.core.DebugPlugin;
28 import org.eclipse.debug.core.ILaunch;
29 import org.eclipse.debug.core.ILaunchConfiguration;
30 import org.eclipse.debug.core.ILaunchConfigurationType;
31 import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
32 import org.eclipse.debug.core.ILaunchManager;
33 import org.eclipse.debug.core.Launch;
34 import org.eclipse.debug.core.model.ILaunchConfigurationDelegate;
35 import org.eclipse.debug.core.model.ILaunchConfigurationDelegate2;
36 import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
37 import org.eclipse.jdt.launching.IRuntimeClasspathProvider;
38 import org.eclipse.jdt.launching.JavaRuntime;
39 import org.eclipse.osgi.util.NLS;
40
41 import com.mountainminds.eclemma.core.CoverageTools;
42 import com.mountainminds.eclemma.core.EclEmmaStatus;
43 import com.mountainminds.eclemma.core.IClassFiles;
44 import com.mountainminds.eclemma.internal.core.CoreMessages;
45 import com.mountainminds.eclemma.internal.core.DebugOptions;
46 import com.mountainminds.eclemma.internal.core.EclEmmaCorePlugin;
47 import com.mountainminds.eclemma.internal.core.instr.InstrMarker;
48 import com.mountainminds.eclemma.internal.core.launching.CoverageLaunchInfo;
49 import com.mountainminds.eclemma.internal.core.launching.InstrumentedClasspathProvider;
50 import com.vladium.emma.AppLoggers;
51 import com.vladium.emma.EMMAProperties;
52
53 /**
54  * Abstract base class for coverage mode launchers. Coverage launchers perform
55  * class instrumentation and then delegate to the corresponding launcher
56  * responsible for the "run" mode.
57  *
58  * @author Marc R. Hoffmann
59  * @version $Revision: 399 $
60  */

61 public abstract class CoverageLauncher implements ICoverageLauncher, IExecutableExtension {
62
63   /**
64    * Name of the file that will EMMA pick from the classpath to reads its
65    * properties.
66    */

67   protected static final String JavaDoc EMMA_PROPERTIES_FILE = "emma.properties"; //$NON-NLS-1$
68

69   /** Launch mode for the launch delegates used internally. */
70   public static final String JavaDoc DELEGATELAUNCHMODE = ILaunchManager.RUN_MODE;
71
72   protected String JavaDoc launchtype;
73
74   protected ILaunchConfigurationDelegate launchdelegate;
75
76   protected ILaunchConfigurationDelegate2 launchdelegate2;
77
78   /**
79    * Hook method to modify the launch configuration before it is passed on to
80    * the delegate launcher.
81    *
82    * @param workingcopy
83    * Configuration to modify
84    * @param info
85    * Info object of this launch
86    * @throws CoreException
87    * may be thrown by implementations
88    */

89   protected void modifyConfiguration(
90       ILaunchConfigurationWorkingCopy workingcopy, ICoverageLaunchInfo info)
91       throws CoreException {
92     // Does nothing by default
93
}
94
95   /**
96    * Returns whether in-place instrumentation should be performed. The default
97    * implementation looks-up the corresponding entry in the passed launch
98    * configuration. Specific launchers may modify this behavior.
99    *
100    * @param configuration
101    * launch configuration for coverage run
102    * @return true, if instrumentation should be performed in-place
103    * @throws CoreException
104    * May be thrown when accessing the launch configuration
105    */

106   protected boolean hasInplaceInstrumentation(ILaunchConfiguration configuration)
107       throws CoreException {
108     return configuration.getAttribute(
109         ICoverageLaunchConfigurationConstants.ATTR_INPLACE_INSTRUMENTATION,
110         false);
111   }
112
113   /**
114    * Creates the a JAR file including the <code>emma.properties</code> file that
115    * will be injected in the class path.
116    *
117    * @param configuration
118    * Configuration object for this launch
119    * @param info
120    * Launch Info object of this launch
121    * @throws CoreException
122    * Thrown when the JAR file cannot be created
123    */

124   private void createPropertiesJAR(ILaunchConfiguration configuration,
125       ICoverageLaunchInfo info) throws CoreException {
126     Properties JavaDoc properties = new Properties JavaDoc();
127     properties.put(EMMAProperties.PROPERTY_COVERAGE_DATA_OUT_FILE, info
128         .getCoverageFile().toOSString());
129     properties.put(AppLoggers.PROPERTY_VERBOSITY_LEVEL,
130         DebugOptions.EMMAVERBOSITYLEVEL);
131     IPath jarfile = info.getPropertiesJARFile();
132     Manifest JavaDoc mf = new Manifest JavaDoc();
133     try {
134       JarOutputStream JavaDoc jar = new JarOutputStream JavaDoc(new FileOutputStream JavaDoc(jarfile
135           .toFile()), mf);
136       jar.putNextEntry(new ZipEntry JavaDoc(EMMA_PROPERTIES_FILE));
137       properties.store(jar,
138           "Created for launch configuration " + configuration.getName()); //$NON-NLS-1$
139
jar.close();
140     } catch (IOException JavaDoc e) {
141       throw new CoreException(EclEmmaStatus.EMMA_PROPERTIES_CREATION_ERROR
142           .getStatus(jarfile, e));
143     }
144   }
145
146   // IExecutableExtension interface:
147

148   public void setInitializationData(IConfigurationElement config,
149       String JavaDoc propertyName, Object JavaDoc data) throws CoreException {
150     launchtype = config.getAttribute("type"); //$NON-NLS-1$
151
launchdelegate = getLaunchDelegate(launchtype);
152     if (launchdelegate instanceof ILaunchConfigurationDelegate2) {
153       launchdelegate2 = (ILaunchConfigurationDelegate2) launchdelegate;
154     }
155   }
156
157   private ILaunchConfigurationDelegate getLaunchDelegate(String JavaDoc launchtype)
158       throws CoreException {
159     ILaunchConfigurationType type = DebugPlugin.getDefault().getLaunchManager()
160         .getLaunchConfigurationType(launchtype);
161     if (type == null) {
162       throw new CoreException(EclEmmaStatus.UNKOWN_LAUNCH_TYPE_ERROR.getStatus(
163           launchtype, null));
164     }
165     return type.getDelegate(DELEGATELAUNCHMODE);
166   }
167
168   // ILaunchConfigurationDelegate interface:
169

170   public void launch(ILaunchConfiguration configuration, String JavaDoc mode,
171       ILaunch launch, IProgressMonitor monitor) throws CoreException {
172     monitor.beginTask(NLS.bind(CoreMessages.Launching_task, configuration
173         .getName()), 2);
174     IRuntimeClasspathProvider provider = JavaRuntime
175         .getClasspathProvider(configuration);
176     ICoverageLaunchInfo info = CoverageTools.getLaunchInfo(launch);
177     if (info == null) {
178       // Must not happen as we should have created the launch
179
throw new CoreException(EclEmmaStatus.MISSING_LAUNCH_INFO_ERROR
180           .getStatus(null));
181     }
182     info.instrument(new SubProgressMonitor(monitor, 1),
183         hasInplaceInstrumentation(configuration));
184     if (monitor.isCanceled()) {
185       return;
186     }
187     createPropertiesJAR(configuration, info);
188     ILaunchConfigurationWorkingCopy wc = configuration.getWorkingCopy();
189     modifyConfiguration(wc, info);
190     InstrumentedClasspathProvider.enable(provider, info);
191     try {
192       launchdelegate.launch(wc, DELEGATELAUNCHMODE, launch,
193           new SubProgressMonitor(monitor, 1));
194     } finally {
195       InstrumentedClasspathProvider.disable();
196     }
197     monitor.done();
198   }
199
200   // ILaunchConfigurationDelegate2 interface:
201

202   public ILaunch getLaunch(ILaunchConfiguration configuration, String JavaDoc mode)
203       throws CoreException {
204     ILaunch launch = new Launch(configuration, CoverageTools.LAUNCH_MODE, null);
205     new CoverageLaunchInfo(launch);
206     return launch;
207   }
208
209   public boolean buildForLaunch(ILaunchConfiguration configuration,
210       String JavaDoc mode, IProgressMonitor monitor) throws CoreException {
211     if (launchdelegate2 == null) {
212       return true;
213     } else {
214       return launchdelegate2.buildForLaunch(configuration, DELEGATELAUNCHMODE,
215           monitor);
216     }
217   }
218
219   public boolean preLaunchCheck(ILaunchConfiguration configuration,
220       String JavaDoc mode, IProgressMonitor monitor) throws CoreException {
221     boolean inplace = hasInplaceInstrumentation(configuration);
222     if (CoverageTools.getClassFilesForInstrumentation(configuration, inplace).length == 0) {
223       IStatus status = EclEmmaStatus.NO_INSTRUMENTED_CLASSES.getStatus();
224       EclEmmaCorePlugin.getInstance().showPrompt(status, configuration);
225       return false;
226     }
227     if (inplace) {
228       // Issue an inplace instrumentation warning:
229
IStatus status = EclEmmaStatus.INPLACE_INSTRUMENTATION_INFO.getStatus();
230       if (!EclEmmaCorePlugin.getInstance().showPrompt(status, configuration)) {
231         return false;
232       }
233     } else {
234       // check whether inpace instrumentation has been performed before
235
if (checkForPreviousInplace(configuration)) {
236         IStatus status = EclEmmaStatus.ALREADY_INSTRUMENTED_ERROR.getStatus();
237         EclEmmaCorePlugin.getInstance().showPrompt(status, configuration);
238         return false;
239       }
240     }
241     // Then allow the delegate's veto:
242
if (launchdelegate2 == null) {
243       return true;
244     } else {
245       return launchdelegate2.preLaunchCheck(configuration, DELEGATELAUNCHMODE,
246           monitor);
247     }
248   }
249
250   private boolean checkForPreviousInplace(ILaunchConfiguration config)
251       throws CoreException {
252     IClassFiles[] classfiles = CoverageTools.getClassFilesForInstrumentation(
253         config, false);
254     for (int i = 0; i < classfiles.length; i++) {
255       if (InstrMarker.isMarked(classfiles[i].getLocation())) {
256         return true;
257       }
258     }
259     return false;
260   }
261
262   public boolean finalLaunchCheck(ILaunchConfiguration configuration,
263       String JavaDoc mode, IProgressMonitor monitor) throws CoreException {
264     if (launchdelegate2 == null) {
265       return true;
266     } else {
267       return launchdelegate2.finalLaunchCheck(configuration,
268           DELEGATELAUNCHMODE, monitor);
269     }
270   }
271   
272   // ICoverageLauncher interface:
273

274   /*
275    * The default implemenation delegates to the classpath provider.
276    */

277   public IClassFiles[] getClassFiles(ILaunchConfiguration configuration, boolean includebinaries) throws CoreException {
278     List JavaDoc l = new ArrayList JavaDoc();
279     IRuntimeClasspathEntry[] entries = JavaRuntime.computeUnresolvedRuntimeClasspath(configuration);
280     entries = JavaRuntime.resolveRuntimeClasspath(entries, configuration);
281     for (int i = 0; i < entries.length; i++) {
282       if (entries[i].getClasspathProperty() == IRuntimeClasspathEntry.USER_CLASSES) {
283         IClassFiles ic = findClassFiles(entries[i].getLocation());
284         if (ic != null && (includebinaries || !ic.isBinary())) {
285           l.add(ic);
286         }
287       }
288     }
289     IClassFiles[] arr = new IClassFiles[l.size()];
290     return (IClassFiles[]) l.toArray(arr);
291   }
292
293
294   /**
295    * Internal utility to find the {@link IClassFiles} descriptor for the given
296    * class path location.
297    *
298    * @param location class path location
299    * @return descriptor or <code>null</code>
300    * @throws CoreException in case of internal inconsistencies
301    */

302   protected IClassFiles findClassFiles(String JavaDoc location) throws CoreException {
303     Map JavaDoc map = EclEmmaCorePlugin.getInstance().getClassFiles();
304     return (IClassFiles) map.get(location);
305   }
306   
307 }
308
Popular Tags