/******************************************************************************* * Copyright (c) 2006, 2009 Mountainminds GmbH & Co. KG * This software is provided under the terms of the Eclipse Public License v1.0 * See http://www.eclipse.org/legal/epl-v10.html. * * $Id: EclEmmaCorePlugin.java 523 2009-01-29 20:57:34Z mtnminds $ ******************************************************************************/ package com.mountainminds.eclemma.internal.core; import java.text.MessageFormat; import java.util.Date; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugEvent; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.IDebugEventSetListener; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchListener; import org.eclipse.debug.core.IStatusHandler; import org.eclipse.debug.core.model.IProcess; import org.eclipse.jdt.core.ElementChangedEvent; import org.eclipse.jdt.core.IElementChangedListener; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.osgi.framework.BundleContext; import com.mountainminds.eclemma.core.CoverageTools; import com.mountainminds.eclemma.core.EclEmmaStatus; import com.mountainminds.eclemma.core.IClassFiles; import com.mountainminds.eclemma.core.ICorePreferences; import com.mountainminds.eclemma.core.ICoverageSession; import com.mountainminds.eclemma.core.ISessionManager; import com.mountainminds.eclemma.core.launching.ICoverageLaunchInfo; import com.mountainminds.eclemma.internal.core.instr.ClassFilesStore; import com.mountainminds.eclemma.internal.core.instr.DefaultInstrumentationFilter; /** * Bundle activator for the EclEmma core. * * @author Marc R. Hoffmann * @version $Revision: 523 $ */ public class EclEmmaCorePlugin extends Plugin { public static final String ID = "com.mountainminds.eclemma.core"; //$NON-NLS-1$ /** Status used to trigger user prompts */ private static final IStatus PROMPT_STATUS = new Status(IStatus.INFO, "org.eclipse.debug.ui", 200, "", null); //$NON-NLS-1$//$NON-NLS-2$ public static final IPath EMMA_JAR = new Path("/emma.jar"); //$NON-NLS-1$ private static EclEmmaCorePlugin instance; private ICorePreferences preferences = ICorePreferences.DEFAULT; private ISessionManager sessionManager; private JavaCoverageLoader coverageLoader; private StateFiles stateFiles; private ClassFilesStore allClassFiles = null; private ILaunchListener launchListener = new ILaunchListener() { public void launchRemoved(ILaunch launch) { if (preferences.getAutoRemoveSessions()) { sessionManager.removeSession(launch); } } public void launchAdded(ILaunch launch) { } public void launchChanged(ILaunch launch) { } }; private IDebugEventSetListener debugListener = new IDebugEventSetListener() { public void handleDebugEvents(DebugEvent[] events) { for (int i = 0; i < events.length; i++) { DebugEvent e = events[i]; if (e.getSource() instanceof IProcess && e.getKind() == DebugEvent.TERMINATE) { IProcess proc = (IProcess) e.getSource(); final ILaunch launch = proc.getLaunch(); ICoverageLaunchInfo info = CoverageTools.getLaunchInfo(launch); if (info != null) { IPath coveragedatafile = info.getCoverageFile(); if (checkCoverageDataFile(coveragedatafile)) { Object[] args = new Object[] { launch.getLaunchConfiguration().getName(), new Date() }; String description = MessageFormat.format( CoreMessages.LaunchSessionDescription_value, args); ICoverageSession session = new CoverageSession(description, info .getInstrumentations(), new IPath[] { coveragedatafile }, launch.getLaunchConfiguration()); sessionManager.addSession(session, preferences .getActivateNewSessions(), launch); } info.dispose(); } } } } private boolean checkCoverageDataFile(IPath path) { boolean ok = path.toFile().exists(); if (!ok) { try { showPrompt(EclEmmaStatus.NO_COVERAGE_DATA_ERROR.getStatus(), path); } catch (CoreException e) { getLog().log(e.getStatus()); } } return ok; } }; private IElementChangedListener elementListener = new IElementChangedListener() { public void elementChanged(ElementChangedEvent event) { synchronized (EclEmmaCorePlugin.this) { allClassFiles = null; } } }; public void start(BundleContext context) throws Exception { super.start(context); sessionManager = new SessionManager(); coverageLoader = new JavaCoverageLoader(sessionManager); stateFiles = new StateFiles(getStateLocation()); stateFiles.deleteTemporaryFiles(); DebugPlugin.getDefault().getLaunchManager().addLaunchListener( launchListener); DebugPlugin.getDefault().addDebugEventListener(debugListener); JavaCore.addElementChangedListener(elementListener); instance = this; } public void stop(BundleContext context) throws Exception { instance = null; stateFiles.deleteTemporaryFiles(); JavaCore.removeElementChangedListener(elementListener); DebugPlugin.getDefault().removeDebugEventListener(debugListener); DebugPlugin.getDefault().getLaunchManager().removeLaunchListener( launchListener); stateFiles = null; coverageLoader.dispose(); coverageLoader = null; sessionManager = null; super.stop(context); } public static EclEmmaCorePlugin getInstance() { return instance; } public void setPreferences(ICorePreferences preferences) { this.preferences = preferences; } /** * Returns a new filter instance for default selection of instrumemted * classes. * * @return new filter */ public DefaultInstrumentationFilter createDefaultIntrumentationFilter() { return new DefaultInstrumentationFilter(this.preferences); } public ISessionManager getSessionManager() { return sessionManager; } public JavaCoverageLoader getJavaCoverageLoader() { return coverageLoader; } public StateFiles getStateFiles() { return stateFiles; } /** * Issues an user prompt using the statis handler registered for the given * status. * * @param status * IStatus object to find prompter for * @param info * addional information passed to the handler * @return boolean result returned by the status handler * @throws CoreException * if the status has severity error and no handler is available */ public boolean showPrompt(IStatus status, Object info) throws CoreException { IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler( PROMPT_STATUS); if (prompter == null) { if (status.getSeverity() == IStatus.ERROR) { throw new CoreException(status); } else { return true; } } else { return ((Boolean) prompter.handleStatus(status, info)).booleanValue(); } } /** * Tries to find the absolute path for the given workspace relative path. * * @param path * workspace relative path to resolve * @return absolute path */ public static IPath getAbsolutePath(IPath path) { if (path.getDevice() == null) { IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(path); if (res != null) { return res.getLocation(); } } return path; } /** * Calculates the list of IClassFiles for the given Java project. Basically * for every separate output location a entry will be returned. * * @param project * Java project to calculate IClassFiles for * @return aArray of IClassFiles objects * @throws JavaModelException * thrown when a problem with the underlying Java model occures */ public static IClassFiles[] getClassFiles(IJavaProject project) throws JavaModelException { final ClassFilesStore store = new ClassFilesStore(); store.add(project); return store.getClassFiles(); } public ClassFilesStore getAllClassFiles() throws CoreException { ClassFilesStore store = allClassFiles; if (store == null) { store = new ClassFilesStore(); store.add(JavaCore.create(ResourcesPlugin.getWorkspace().getRoot())); allClassFiles = store; } return store; } }