/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Yevgen Kogan - Bug 403475 - Hot Code Replace drops too much frames in some cases
 *******************************************************************************/
package org.eclipse.jdt.internal.debug.core.hcr;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IResourceDeltaVisitor;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
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.ILaunchManager;
import org.eclipse.debug.core.model.IDebugTarget;
import org.eclipse.debug.core.model.IThread;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.util.IClassFileReader;
import org.eclipse.jdt.core.util.ISourceAttribute;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaHotCodeReplaceListener;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.JDIDebugModel;
import org.eclipse.jdt.internal.core.util.Util;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.core.JavaDebugUtils;
import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget;
import org.eclipse.jdt.internal.debug.core.model.JDIStackFrame;
import org.eclipse.jdt.internal.debug.core.model.JDIThread;

import com.sun.jdi.IncompatibleThreadStateException;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.VMDisconnectedException;
import com.sun.jdi.VirtualMachine;

/**
 * The hot code replace manager listens for changes to class files and notifies
 * running debug targets of the changes.
 * <p>
 * Currently, replacing .jar files has no effect on running targets.
 */
public class JavaHotCodeReplaceManager implements IResourceChangeListener,
		ILaunchListener, IDebugEventSetListener {
	/**
	 * Singleton
	 */
	private static JavaHotCodeReplaceManager fgInstance = null;
	/**
	 * The class file extension
	 */
	private static final String CLASS_FILE_EXTENSION = "class"; //$NON-NLS-1$

	/**
	 * The list of <code>IJavaHotCodeReplaceListeners</code> which this hot code
	 * replace manager will notify about hot code replace attempts.
	 */
	private ListenerList<IJavaHotCodeReplaceListener> fHotCodeReplaceListeners = new ListenerList<>();

	/**
	 * The lists of hot swap targets which support HCR and those which don't
	 */
	private ArrayList<JDIDebugTarget> fHotSwapTargets = new ArrayList<>(1);
	private ArrayList<JDIDebugTarget> fNoHotSwapTargets = new ArrayList<>(1);

	/**
	 * A mapping of the last time projects were built.
	 * <ol>
	 * <li>key: project (IProject)</li>
	 * <li>value: build date (ProjectBuildTime)</li>
	 * </ol>
	 */
	private Map<IProject, ProjectBuildTime> fProjectBuildTimes = new HashMap<>();
	private static Date fStartupDate = new Date();

	/**
	 * Cache of compilation unit deltas renewed on each HCR attempt.
	 */
	private Map<ICompilationUnit, CompilationUnitDelta> fDeltaCache = new HashMap<>();

	/**
	 * Utility object used for tracking build times of projects. The HCR manager
	 * receives notification of builds AFTER the build has occurred but BEFORE
	 * the classfile resource changed deltas are fired. Thus, when the current
	 * build time is set, we need to hang onto the last build time so that we
	 * can use the last build time for comparing changes to compilation units
	 * (for smart drop to frame).
	 */
	class ProjectBuildTime {
		private Date fCurrentDate = new Date();
		private Date fPreviousDate = new Date();

		public void setCurrentBuildDate(Date date) {
			fPreviousDate = fCurrentDate;
			fCurrentDate = date;
		}

		public void setLastBuildDate(Date date) {
			fPreviousDate = date;
			if (fPreviousDate.getTime() > fCurrentDate.getTime()) {
				// If the previous date is set later than the current
				// date, move the current date up to the previous.
				fCurrentDate = fPreviousDate;
			}
		}

		/**
		 * Returns the last build time
		 */
		public Date getLastBuildDate() {
			return fPreviousDate;
		}
	}

	/**
	 * Visitor for resource deltas.
	 */
	protected ChangedClassFilesVisitor fClassfileVisitor = new ChangedClassFilesVisitor();

	/**
	 * Creates a new HCR manager
	 */
	private JavaHotCodeReplaceManager() {
	}

	/**
	 * Returns the singleton HCR manager
	 */
	public static synchronized JavaHotCodeReplaceManager getDefault() {
		if (fgInstance == null) {
			fgInstance = new JavaHotCodeReplaceManager();
		}
		return fgInstance;
	}

	/**
	 * Registers this HCR manager as a resource change listener. This method is
	 * called by the JDI debug model plug-in on startup.
	 */
	public void startup() {
		DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this);
		DebugPlugin.getDefault().addDebugEventListener(this);
	}

	/**
	 * unregisters this HCR manager as a resource change listener. Removes all
	 * hot code replace listeners. This method is called by the JDI debug model
	 * plug-in on shutdown.
	 */
	public void shutdown() {
		DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this);
		DebugPlugin.getDefault().removeDebugEventListener(this);
		getWorkspace().removeResourceChangeListener(this);
		fHotCodeReplaceListeners = new ListenerList<>();
		synchronized (this) {
			fHotSwapTargets.clear();
			fNoHotSwapTargets.clear();
		}
	}

	/**
	 * Returns the workspace.
	 */
	protected IWorkspace getWorkspace() {
		return ResourcesPlugin.getWorkspace();
	}

	/**
	 * Returns the launch manager.
	 */
	protected ILaunchManager getLaunchManager() {
		return DebugPlugin.getDefault().getLaunchManager();
	}

	/**
	 * @see IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
	 */
	@Override
	public void resourceChanged(IResourceChangeEvent event) {
		List<IProject> projects = getBuiltProjects(event);
		if (!projects.isEmpty()) {
			updateProjectBuildTime(projects);
		}
		synchronized (this) {
			if (fHotSwapTargets.isEmpty() && fNoHotSwapTargets.isEmpty()) {
				// If there are no targets to notify, only update the build
				// times.
				return;
			}
		}
		ChangedClassFilesVisitor visitor = getChangedClassFiles(event);
		if (visitor != null) {
			List<IResource> resources = visitor.getChangedClassFiles();
			List<String> names = visitor.getQualifiedNamesList();
			if (!resources.isEmpty()) {
				notifyTargets(resources, names);
			}
		}
	}

	/**
	 * Returns all projects which this event says may have been built.
	 */
	protected List<IProject> getBuiltProjects(IResourceChangeEvent event) {
		IResourceDelta delta = event.getDelta();
		if (event.getType() != IResourceChangeEvent.POST_BUILD || delta == null
				|| event.getBuildKind() == 0) {
			return Collections.EMPTY_LIST;
		}
		if (event.getBuildKind() == IncrementalProjectBuilder.AUTO_BUILD
				&& !ResourcesPlugin.getWorkspace().isAutoBuilding()) {
			// If this is an auto build and the workspace is not autobuilding,
			// no projects will actually be compiled.
			return Collections.EMPTY_LIST;
		}
		Object source = event.getSource();
		if (source instanceof IProject) {
			List<IProject> list = new ArrayList<>();
			list.add((IProject) source);
			return list;
		} else if (source instanceof IWorkspace) {
			IProject[] allProjects = ((IWorkspace) source).getRoot()
					.getProjects();
			return Arrays.asList(allProjects);
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * If the given event contains a build notification, update the last build
	 * time of the corresponding project
	 */
	private void updateProjectBuildTime(List<IProject> projects) {
		Date currentDate = new Date();
		ProjectBuildTime buildTime = null;
		for(IProject project : projects) {
			buildTime = fProjectBuildTimes.get(project);
			if (buildTime == null) {
				buildTime = new ProjectBuildTime();
				fProjectBuildTimes.put(project, buildTime);
			}
			buildTime.setCurrentBuildDate(currentDate);
		}
	}

	/**
	 * Returns the last known build time for the given project. If no build time
	 * is known for the given project, the last known build time for the project
	 * is set to the hot code replace manager's startup time.
	 */
	protected long getLastProjectBuildTime(IProject project) {
		ProjectBuildTime time = fProjectBuildTimes
				.get(project);
		if (time == null) {
			time = new ProjectBuildTime();
			time.setLastBuildDate(fStartupDate);
			fProjectBuildTimes.put(project, time);
		}
		return time.getLastBuildDate().getTime();
	}

	/**
	 * Notifies the targets of the changed types
	 */
	private void notifyTargets(final List<IResource> resources, final List<String> qualifiedNames) {
		final List<JDIDebugTarget> hotSwapTargets = getHotSwapTargets();
		final List<JDIDebugTarget> noHotSwapTargets = getNoHotSwapTargets();
		if (!hotSwapTargets.isEmpty()) {
			Runnable runnable = () -> doHotCodeReplace(hotSwapTargets, resources, qualifiedNames);
			DebugPlugin.getDefault().asyncExec(runnable);
		}
		if (!noHotSwapTargets.isEmpty()) {
			Runnable runnable = () -> notifyUnsupportedHCR(noHotSwapTargets, resources,
					qualifiedNames);
			DebugPlugin.getDefault().asyncExec(runnable);
		}
	}

	/**
	 * Notify the given targets that HCR failed for classes with the given fully
	 * qualified names.
	 */
	protected void notifyUnsupportedHCR(List<JDIDebugTarget> targets, List<IResource> resources,
			List<String> qualifiedNames) {
		Iterator<JDIDebugTarget> iter = targets.iterator();
		JDIDebugTarget target = null;
		while (iter.hasNext()) {
			target = iter.next();
			if (target.isAvailable()) {
				// Make a local copy of the resources/names to swap so we can
				// filter
				// unloaded types on a per-target basis.
				List<IResource> resourcesToReplace = new ArrayList<>(resources);
				List<String> qualifiedNamesToReplace = new ArrayList<>(qualifiedNames);
				target.filterNotLoadedTypes(resourcesToReplace, qualifiedNamesToReplace);

				if (!qualifiedNamesToReplace.isEmpty()) {
					// Don't notify if the changed types aren't loaded.
					fireHCRFailed(target, null);
					notifyFailedHCR(target, qualifiedNamesToReplace);
				}
			} else {
				// Targets should be unregistered when they terminate,
				// but this is a fall-back.
				deregisterTarget(target);
			}
		}
	}

	protected void notifyFailedHCR(JDIDebugTarget target, List<String> qualifiedNames) {
		if (target.isAvailable()) {
			target.addOutOfSynchTypes(qualifiedNames);
			target.fireChangeEvent(DebugEvent.STATE);
		}
	}

	/**
	 * Returns the currently registered debug targets that support hot code
	 * replace.
	 */
	protected synchronized List<JDIDebugTarget> getHotSwapTargets() {
		return new ArrayList<>(fHotSwapTargets);
	}

	/**
	 * Returns the currently registered debug targets that do not support hot
	 * code replace.
	 */
	protected synchronized List<JDIDebugTarget> getNoHotSwapTargets() {
		return new ArrayList<>(fNoHotSwapTargets);
	}

	/**
	 * Perform a hot code replace with the given resources. For a JDK 1.4
	 * compliant VM this involves:
	 * <ol>
	 * <li>Popping all frames from all thread stacks which will be affected by
	 * reloading the given resources</li>
	 * <li>Telling the VirtualMachine to redefine the affected classes</li>
	 * <li>Performing a step-into operation on all threads which were affected
	 * by the class redefinition. This returns execution to the first (deepest)
	 * affected method on the stack</li>
	 * </ol>
	 * For a J9 compliant VM this involves:
	 * <ol>
	 * <li>Telling the VirtualMachine to redefine the affected classes</li>
	 * <li>Popping all frames from all thread stacks which were affected by
	 * reloading the given resources and then performing a step-into operation
	 * on all threads which were affected by the class redefinition.</li>
	 * </ol>
	 *
	 * @param targets
	 *            the targets in which to perform HCR
	 * @param resources
	 *            the resources which correspond to the changed classes
	 */
	private void doHotCodeReplace(List<JDIDebugTarget> targets, List<IResource> resources,
			List<String> qualifiedNames) {

		// Check whether hot code replace is enabled
		if (!Platform.getPreferencesService().getBoolean(
				JDIDebugPlugin.getUniqueIdentifier(),
				JDIDebugPlugin.PREF_ENABLE_HCR,
				true,
				null)) {
			return; // disabled
		}

		MultiStatus ms = new MultiStatus(
				JDIDebugPlugin.getUniqueIdentifier(),
				DebugException.TARGET_REQUEST_FAILED,
				"At least one target failed to drop to frame after successful hot code replace.", null); //$NON-NLS-1$
		Iterator<JDIDebugTarget> iter = targets.iterator();
		while (iter.hasNext()) {
			JDIDebugTarget target = iter.next();
			if (!target.isAvailable()) {
				deregisterTarget(target);
				continue;
			}
			// Make a local copy of the resources/names to swap so we can filter
			// unloaded types on a per-target basis.
			List<IResource> resourcesToReplace = new ArrayList<>(resources);
			List<String> qualifiedNamesToReplace = new ArrayList<>(qualifiedNames);

			// Make sure we only try to replace types from related projects
			target.filterUnrelatedResources(resourcesToReplace, qualifiedNamesToReplace);
			if (qualifiedNamesToReplace.isEmpty()) {
				// If none of the changed types are related to our target, do nothing.
				continue;
			}

			target.filterNotLoadedTypes(resourcesToReplace, qualifiedNamesToReplace);
			if (qualifiedNamesToReplace.isEmpty()) {
				// If none of the changed types are loaded, do nothing.
				continue;
			}

			List<IThread> poppedThreads = new ArrayList<>();
			target.setIsPerformingHotCodeReplace(true);
			try {
				boolean framesPopped = false;
				if (target.canPopFrames()) {
					// JDK 1.4 drop to frame support:
					// JDK 1.4 spec is faulty around methods that have
					// been rendered obsolete after class redefinition.
					// Thus, pop the frames that contain affected methods
					// *before* the class redefinition to avoid problems.
					try {
						attemptPopFrames(target, resourcesToReplace,
								qualifiedNamesToReplace, poppedThreads);
						framesPopped = true; // No exception occurred
					} catch (DebugException de) {
						if (shouldLogHCRException(de)) {
							ms.merge(de.getStatus());
						}
					}
				}
				target.removeOutOfSynchTypes(qualifiedNamesToReplace);
				if (target.supportsJDKHotCodeReplace()) {
					redefineTypesJDK(target, resourcesToReplace,
							qualifiedNamesToReplace);
				} else if (target.supportsJ9HotCodeReplace()) {
					redefineTypesJ9(target, qualifiedNamesToReplace);
				}
				if (containsObsoleteMethods(target)) {
					fireObsoleteMethods(target);
				}
				try {
					if (target.canPopFrames() && framesPopped) {
						// Second half of JDK 1.4 drop to frame support:
						// All affected frames have been popped and the classes
						// have been reloaded. Step into the first changed
						// frame of each affected thread.
						// must re-set 'is doing HCR' to be able to step
						target.setIsPerformingHotCodeReplace(false);
						attemptStepIn(poppedThreads);
					} else {
						// J9 drop to frame support:
						// After redefining classes, drop to frame
						attemptDropToFrame(target, resourcesToReplace,
								qualifiedNamesToReplace);
					}
				} catch (DebugException de) {
					if (shouldLogHCRException(de)) {
						ms.merge(de.getStatus());
					}
				}
				fireHCRSucceeded(target);
			} catch (DebugException de) {
				// target update failed
				fireHCRFailed(target, de);
			}
			// also re-set 'is doing HCR' here in case HCR failed
			target.setIsPerformingHotCodeReplace(false);
			target.fireChangeEvent(DebugEvent.CONTENT);
		}
		if (!ms.isOK()) {
			JDIDebugPlugin.log(ms);
		}
		fDeltaCache.clear();
	}

	/**
	 * Returns whether the given exception, which occurred during HCR, should be
	 * logged. We anticipate that we can get IncompatibleThreadStateExceptions
	 * if the user happens to resume a thread at just the right moment. Since
	 * this has no ill effects for HCR, we don't log these exceptions.
	 */
	private boolean shouldLogHCRException(DebugException exception) {
		return !(exception.getStatus().getException() instanceof IncompatibleThreadStateException
				|| exception.getStatus().getCode() == IJavaThread.ERR_INCOMPATIBLE_THREAD_STATE || exception
				.getStatus().getCode() == IJavaThread.ERR_THREAD_NOT_SUSPENDED);
	}

	/**
	 * Replaces the given types in the given J9 debug target. A fully qualified
	 * name of each type must be supplied.
	 *
	 * Breakpoints are reinstalled automatically when the new types are loaded.
	 *
	 * @exception DebugException
	 *                if this method fails. Reasons include:
	 *                <ul>
	 *                <li>Failure communicating with the VM. The
	 *                DebugException's status code contains the underlying
	 *                exception responsible for the failure.</li>
	 *                <li>The target VM was unable to reload a type due to a
	 *                shape change</li>
	 *                </ul>
	 */
	private void redefineTypesJ9(JDIDebugTarget target, List<String> qualifiedNames)
			throws DebugException {
		String[] typeNames = qualifiedNames
				.toArray(new String[qualifiedNames.size()]);
		if (target.supportsJ9HotCodeReplace()) {
			target.setHCROccurred(true);
			org.eclipse.jdi.hcr.VirtualMachine vm = (org.eclipse.jdi.hcr.VirtualMachine) target
					.getVM();
			if (vm == null) {
				target.requestFailed(
						JDIDebugHCRMessages.JavaHotCodeReplaceManager_Hot_code_replace_failed___VM_disconnected__1,
						new VMDisconnectedException());
			}
			int result = org.eclipse.jdi.hcr.VirtualMachine.RELOAD_FAILURE;
			try {
				result = vm.classesHaveChanged(typeNames);
			} catch (RuntimeException e) {
				target.targetRequestFailed(
						MessageFormat.format(JDIDebugHCRMessages.JavaHotCodeReplaceManager_exception_replacing_types, e.toString()),
						e);
			}
			switch (result) {
			case org.eclipse.jdi.hcr.VirtualMachine.RELOAD_SUCCESS:
				break;
			case org.eclipse.jdi.hcr.VirtualMachine.RELOAD_IGNORED:
				target.targetRequestFailed(
						JDIDebugHCRMessages.JavaHotCodeReplaceManager_hcr_ignored,
						null);
				break;
			case org.eclipse.jdi.hcr.VirtualMachine.RELOAD_FAILURE:
				target.targetRequestFailed(
						JDIDebugHCRMessages.JavaHotCodeReplaceManager_hcr_failed,
						null);
				target.addOutOfSynchTypes(qualifiedNames);
				break;
			}
		} else {
			target.notSupported(JDIDebugHCRMessages.JavaHotCodeReplaceManager_does_not_support_hcr);
			target.addOutOfSynchTypes(qualifiedNames);
		}
	}

	/**
	 * Replaces the given types in the given JDK-compliant debug target.
	 *
	 * This method is to be used for JDK hot code replace.
	 */
	private void redefineTypesJDK(JDIDebugTarget target, List<IResource> resources,
			List<String> qualifiedNames) throws DebugException {
		if (target.supportsJDKHotCodeReplace()) {
			target.setHCROccurred(true);
			Map<ReferenceType, byte[]> typesToBytes = getTypesToBytes(target, resources,
					qualifiedNames);
			try {
				VirtualMachine vm = target.getVM();
				if (vm == null) {
					target.requestFailed(
							JDIDebugHCRMessages.JavaHotCodeReplaceManager_Hot_code_replace_failed___VM_disconnected__2,
							new VMDisconnectedException());
				}
				vm.redefineClasses(typesToBytes);
			} catch (UnsupportedOperationException exception) {
				String detail = exception.getMessage();
				if (detail != null) {
					redefineTypesFailedJDK(
							target,
							qualifiedNames,
							MessageFormat.format(
									JDIDebugHCRMessages.JavaHotCodeReplaceManager_hcr_unsupported_operation,
									detail),
							exception);
				} else {
					redefineTypesFailedJDK(
							target,
							qualifiedNames,
							JDIDebugHCRMessages.JavaHotCodeReplaceManager_hcr_unsupported_redefinition,
							exception);
				}
			} catch (NoClassDefFoundError exception) {
				redefineTypesFailedJDK(
						target,
						qualifiedNames,
						JDIDebugHCRMessages.JavaHotCodeReplaceManager_hcr_bad_bytes,
						exception);
			} catch (VerifyError exception) {
				redefineTypesFailedJDK(
						target,
						qualifiedNames,
						JDIDebugHCRMessages.JavaHotCodeReplaceManager_hcr_verify_error,
						exception);
			} catch (UnsupportedClassVersionError exception) {
				redefineTypesFailedJDK(
						target,
						qualifiedNames,
						JDIDebugHCRMessages.JavaHotCodeReplaceManager_hcr_unsupported_class_version,
						exception);
			} catch (ClassFormatError exception) {
				redefineTypesFailedJDK(
						target,
						qualifiedNames,
						JDIDebugHCRMessages.JavaHotCodeReplaceManager_hcr_class_format_error,
						exception);
			} catch (ClassCircularityError exception) {
				redefineTypesFailedJDK(
						target,
						qualifiedNames,
						JDIDebugHCRMessages.JavaHotCodeReplaceManager_hcr_class_circularity_error,
						exception);
			} catch (RuntimeException exception) {
				redefineTypesFailedJDK(
						target,
						qualifiedNames,
						JDIDebugHCRMessages.JavaHotCodeReplaceManager_hcr_failed,
						exception);
			}
			target.reinstallBreakpointsIn(resources, qualifiedNames);
		} else {
			target.notSupported(JDIDebugHCRMessages.JavaHotCodeReplaceManager_does_not_support_hcr);
		}
	}

	/**
	 * Error handling for JDK hot code replace.
	 *
	 * The given exception occurred when redefinition was attempted for the
	 * given types.
	 */
	private void redefineTypesFailedJDK(JDIDebugTarget target,
			List<String> qualifiedNames, String message, Throwable exception)
			throws DebugException {
		target.addOutOfSynchTypes(qualifiedNames);
		target.jdiRequestFailed(message, exception);
	}

	/**
	 * Returns a mapping of class files to the bytes that make up those class
	 * files.
	 *
	 * @param target
	 *            the debug target to query
	 * @param resources
	 *            the classfiles
	 * @param qualifiedNames
	 *            the fully qualified type names corresponding to the
	 *            classfiles. The typeNames correspond to the resources on a
	 *            one-to-one basis.
	 * @return a mapping of class files to bytes key: class file value: the
	 *         bytes which make up that classfile
	 */
	private Map<ReferenceType, byte[]> getTypesToBytes(JDIDebugTarget target, List<IResource> resources,
			List<String> qualifiedNames) {
		Map<ReferenceType, byte[]> typesToBytes = new HashMap<>(resources.size());
		Iterator<IResource> resourceIter = resources.iterator();
		Iterator<String> nameIter = qualifiedNames.iterator();
		IResource resource;
		String name;
		while (resourceIter.hasNext()) {
			resource = resourceIter.next();
			name = nameIter.next();
			List<ReferenceType> classes = target.jdiClassesByName(name);
			byte[] bytes = null;
			try {
				bytes = Util.getResourceContentsAsByteArray((IFile) resource);
			} catch (JavaModelException jme) {
				continue;
			}
			for(ReferenceType type : classes) {
				typesToBytes.put(type, bytes);
			}
		}
		return typesToBytes;
	}

	/**
	 * Return the listeners to notify for the given target. Target specific
	 * listeners take precedence over generic listeners registered with the
	 * debug model plug-in.
	 *
	 * @param target
	 *            Java debug target
	 * @return hot code replace listeners
	 */
	private ListenerList<IJavaHotCodeReplaceListener> getHotCodeReplaceListeners(IJavaDebugTarget target) {
		ListenerList<IJavaHotCodeReplaceListener> listeners = null;
		if (target instanceof JDIDebugTarget) {
			listeners = ((JDIDebugTarget) target).getHotCodeReplaceListeners();
		}
		if (listeners == null || listeners.size() == 0) {
			listeners = fHotCodeReplaceListeners;
		}
		return listeners;
	}

	/**
	 * Notifies listeners that a hot code replace attempt succeeded
	 */
	private void fireHCRSucceeded(IJavaDebugTarget target) {
		ListenerList<IJavaHotCodeReplaceListener> listeners = getHotCodeReplaceListeners(target);
		for (IJavaHotCodeReplaceListener listener : listeners) {
			listener.hotCodeReplaceSucceeded(target);
		}
	}

	/**
	 * Notifies listeners that a hot code replace attempt failed with the given
	 * exception
	 */
	private void fireHCRFailed(JDIDebugTarget target, DebugException exception) {
		ListenerList<IJavaHotCodeReplaceListener> listeners = getHotCodeReplaceListeners(target);
		for (IJavaHotCodeReplaceListener listener : listeners) {
			listener.hotCodeReplaceFailed(target, exception);
		}
	}

	/**
	 * Notifies listeners that obsolete methods remain on the stack
	 */
	private void fireObsoleteMethods(JDIDebugTarget target) {
		ListenerList<IJavaHotCodeReplaceListener> listeners = getHotCodeReplaceListeners(target);
		for (IJavaHotCodeReplaceListener listener : listeners) {
			listener.obsoleteMethods(target);
		}
	}

	/**
	 * Looks for the deepest affected stack frame in the stack and forces a drop
	 * to frame. Does this for all of the active stack frames in the target.
	 *
	 * @param target
	 *            the debug target in which frames are to be dropped
	 * @param replacedClassNames
	 *            the classes that have been redefined
	 */
	protected void attemptDropToFrame(JDIDebugTarget target, List<IResource> resources,
			List<String> replacedClassNames) throws DebugException {
		List<JDIStackFrame> dropFrames = getAffectedFrames(target.getThreads(), resources,
				replacedClassNames);

		// All threads that want to drop to frame are able. Proceed with the
		// drop
		JDIStackFrame dropFrame = null;
		Iterator<JDIStackFrame> iter = dropFrames.iterator();
		while (iter.hasNext()) {
			try {
				dropFrame = iter.next();
				dropFrame.dropToFrame();
			} catch (DebugException de) {
				notifyFailedDrop(
						((JDIThread) dropFrame.getThread())
								.computeStackFrames(),
						replacedClassNames);
			}
		}
	}

	/**
	 * Looks for the deepest affected stack frame in the stack and forces a drop
	 * to frame. Does this for all of the active stack frames in the target.
	 *
	 * @param target
	 *            the debug target in which frames are to be dropped
	 * @param replacedClassNames
	 *            the classes that have been redefined
	 * @param poppedThreads
	 *            a list of the threads in which frames were popped.This
	 *            parameter may have entries added by this method
	 */
	protected void attemptPopFrames(JDIDebugTarget target, List<IResource> resources,
			List<String> replacedClassNames, List<IThread> poppedThreads) throws DebugException {
		List<JDIStackFrame> popFrames = getAffectedFrames(target.getThreads(), resources,
				replacedClassNames);

		// All threads that want to drop to frame are able. Proceed with the
		// drop
		JDIStackFrame popFrame = null;
		Iterator<JDIStackFrame> iter = popFrames.iterator();
		while (iter.hasNext()) {
			try {
				popFrame = iter.next();
				popFrame.popFrame();
				poppedThreads.add(popFrame.getThread());
			} catch (DebugException de) {
				poppedThreads.remove(popFrame.getThread());
				notifyFailedDrop(
						((JDIThread) popFrame.getThread()).computeStackFrames(),
						replacedClassNames);
			}
		}
	}

	/**
	 * Returns whether or not the given target contains stack frames with
	 * obsolete methods.
	 */
	protected boolean containsObsoleteMethods(JDIDebugTarget target)
			throws DebugException {
		IThread[] threads = target.getThreads();
		List<IJavaStackFrame> frames = null;
		for (IThread thread : threads) {
			frames = ((JDIThread) thread).computeNewStackFrames();
			for(IJavaStackFrame frame : frames) {
				if(frame.isObsolete()) {
					return true;
				}
			}
		}
		return false;
	}

	/**
	 * Returns a list of frames which should be popped in the given threads.
	 */
	protected List<JDIStackFrame> getAffectedFrames(IThread[] threads, List<IResource> resourceList,
			List<String> replacedClassNames) throws DebugException {
		JDIThread thread = null;
		JDIStackFrame affectedFrame = null;
		List<JDIStackFrame> popFrames = new ArrayList<>();
		int numThreads = threads.length;
		IResource[] resources = new IResource[resourceList.size()];
		resourceList.toArray(resources);
		for (int i = 0; i < numThreads; i++) {
			thread = (JDIThread) threads[i];
			if (thread.isSuspended()) {
				affectedFrame = getAffectedFrame(thread, replacedClassNames);
				if (affectedFrame == null) {
					// No frame to drop to in this thread
					continue;
				}
				if (affectedFrame.supportsDropToFrame()) {
					popFrames.add(affectedFrame);
				} else {
					// if any thread that should drop does not support the drop,
					// do not drop in any threads.
					for (int j = 0; j < numThreads; j++) {
						notifyFailedDrop(
								((JDIThread) threads[i]).computeStackFrames(),
								replacedClassNames);
					}
					throw new DebugException(
							new Status(
									IStatus.ERROR,
									JDIDebugModel.getPluginIdentifier(),
									DebugException.NOT_SUPPORTED,
									JDIDebugHCRMessages.JavaHotCodeReplaceManager_Drop_to_frame_not_supported,
									null));
				}
			}
		}
		return popFrames;
	}

	/**
	 * Returns the stack frame that should be dropped to in the given thread
	 * after a hot code replace. This is calculated by determining if the
	 * threads contain stack frames that reside in one of the given replaced
	 * class names. If possible, only stack frames whose methods were directly
	 * affected (and not simply all frames in affected types) will be returned.
	 */
	protected JDIStackFrame getAffectedFrame(JDIThread thread,
			List<String> replacedClassNames) throws DebugException {
		List<IJavaStackFrame> frames = thread.computeStackFrames();
		JDIStackFrame affectedFrame = null;
		JDIStackFrame frame = null;
		ICompilationUnit compilationUnit = null;
		CompilationUnitDelta delta = null;
		IProject project = null;
		for (int j = 0; j < frames.size(); j++) {
			frame = (JDIStackFrame) frames.get(j);
			if (containsChangedType(frame, replacedClassNames)) {
				// smart drop to frame support
				compilationUnit = getCompilationUnit(frame);
				// if we can't find the source, then do type-based drop
				if (compilationUnit != null) {
					try {
						project = compilationUnit.getCorrespondingResource()
								.getProject();
						delta = getDelta(compilationUnit,
								getLastProjectBuildTime(project));

						String typeName = frame.getDeclaringTypeName();
						typeName = typeName.replace('$', '.');

						if (!delta.hasChanged(typeName, frame.getName(),
								frame.getSignature())) {
							continue;
						}
					} catch (CoreException exception) {
						// If smart drop to frame fails, just do type-based drop
					}
				}

				if (frame.supportsDropToFrame()) {
					affectedFrame = frame;
					break;
				}
				// The frame we wanted to drop to cannot be popped.
				// Set the affected frame to the next lowest pop-able
				// frame on the stack.
				while (j > 0) {
					j--;
					frame = (JDIStackFrame) frames.get(j);
					if (frame.supportsDropToFrame()) {
						affectedFrame = frame;
						break;
					}
				}
				break;
			}
		}
		return affectedFrame;
	}

	/**
	 * Returns the delta object for the given compilation unit
	 *
	 * @param cu
	 *            compilation unit
	 * @param time
	 *            time to compare to (i.e. compare to first version before this
	 *            time)
	 * @return delta object
	 */
	private CompilationUnitDelta getDelta(ICompilationUnit cu, long time)
			throws CoreException {
		CompilationUnitDelta delta = fDeltaCache.get(cu);
		if (delta == null) {
			delta = new CompilationUnitDelta(cu, time);
			fDeltaCache.put(cu, delta);
		}
		return delta;
	}

	/**
	 * Returns whether the given frame's declaring type was changed based on the
	 * given list of changed class names.
	 */
	protected boolean containsChangedType(JDIStackFrame frame,
			List<String> replacedClassNames) throws DebugException {
		String declaringTypeName = frame.getDeclaringTypeName();
		// Check if the frame's declaring type was changed
		if (replacedClassNames.contains(declaringTypeName)) {
			return true;
		}
		// Check if one of the frame's declaring type's inner classes have
		// changed
		Iterator<String> iter = replacedClassNames.iterator();
		int index;
		String className = null;
		while (iter.hasNext()) {
			className = iter.next();
			index = className.indexOf('$');
			if (index > -1
					&& declaringTypeName.equals(className.substring(0, index))) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Performs a "step into" operation on the given threads.
	 */
	protected void attemptStepIn(List<IThread> threads) throws DebugException {
		Iterator<IThread> iter = threads.iterator();
		while (iter.hasNext()) {
			((JDIThread) iter.next()).stepInto();
		}
	}

	/**
	 * Returns the compilation unit associated with this Java stack frame.
	 * Returns <code>null</code> for a binary stack frame.
	 */
	protected ICompilationUnit getCompilationUnit(IJavaStackFrame frame) {
		ILaunch launch = frame.getLaunch();
		if (launch == null) {
			return null;
		}
		try {
			IJavaElement sourceElement = JavaDebugUtils.resolveJavaElement(frame, launch);
			if (sourceElement instanceof IType) {
				return ((IType) sourceElement).getCompilationUnit();
			}
			if (sourceElement instanceof ICompilationUnit) {
				return (ICompilationUnit) sourceElement;
			}
			return null;
		}
		catch (CoreException e) {
			return null;
		}
	}

	/**
	 * Returns the method in which this stack frame is suspended or
	 * <code>null</code> if none can be found
	 */
	public IMethod getMethod(JDIStackFrame frame, ICompilationUnit unit)
			throws CoreException {
		String declaringTypeName = frame.getDeclaringTypeName();
		String methodName = frame.getMethodName();
		String[] arguments = null;
		try {
			arguments = Signature.getParameterTypes(frame.getSignature());
		} catch (IllegalArgumentException exception) {
			// If Signature can't parse the signature, we can't
			// create the method
			return null;
		}
		String typeName = getUnqualifiedName(declaringTypeName);
		int index = typeName.indexOf('$');
		IType type = null;
		if (index > 0) {
			String remaining = typeName.substring(index + 1);
			typeName = typeName.substring(0, index);
			type = unit.getType(typeName);
			while (remaining != null) {
				index = remaining.indexOf('$');
				if (index > 0) {
					typeName = remaining.substring(0, index);
					remaining = remaining.substring(index + 1);
				} else {
					typeName = remaining;
					remaining = null;
				}
				type = type.getType(typeName);
			}
		} else {
			type = unit.getType(typeName);
		}
		if (type != null) {
			return type.getMethod(methodName, arguments);
		}
		return null;
	}

	/**
	 * Given a fully qualified name, return the unqualified name.
	 */
	protected String getUnqualifiedName(String qualifiedName) {
		int index = qualifiedName.lastIndexOf('.');
		return qualifiedName.substring(index + 1);
	}

	/**
	 * Notify the given frames that a drop to frame has failed after an HCR with
	 * the given class names.
	 */
	private void notifyFailedDrop(List<IJavaStackFrame> frames, List<String> replacedClassNames)
			throws DebugException {
		for(IJavaStackFrame frame : frames) {
			if (replacedClassNames.contains(frame.getDeclaringTypeName())) {
				((JDIStackFrame)frame).setOutOfSynch(true);
			}
		}
	}

	/**
	 * Returns the class file visitor after visiting the resource change. The
	 * visitor contains the changed class files and qualified type names.
	 * Returns <code>null</code> if the visitor encounters an exception, or the
	 * delta is not a POST_BUILD.
	 */
	protected ChangedClassFilesVisitor getChangedClassFiles(
			IResourceChangeEvent event) {
		IResourceDelta delta = event.getDelta();
		if (event.getType() != IResourceChangeEvent.POST_BUILD || delta == null) {
			return null;
		}
		fClassfileVisitor.reset();
		try {
			delta.accept(fClassfileVisitor);
		} catch (CoreException e) {
			JDIDebugPlugin.log(e);
			return null; // quiet failure
		}
		return fClassfileVisitor;
	}

	/**
	 * A visitor which collects changed class files.
	 */
	class ChangedClassFilesVisitor implements IResourceDeltaVisitor {
		/**
		 * The collection of changed class files.
		 */
		protected List<IResource> fFiles = null;

		/**
		 * Collection of qualified type names, corresponding to class files.
		 */
		protected List<String> fNames = null;

		/**
		 * Answers whether children should be visited.
		 * <p>
		 * If the associated resource is a class file which has been changed,
		 * record it.
		 */
		@Override
		public boolean visit(IResourceDelta delta) {
			if (delta == null
					|| 0 == (delta.getKind() & IResourceDelta.CHANGED)) {
				return false;
			}
			IResource resource = delta.getResource();
			if (resource != null) {
				switch (resource.getType()) {
				case IResource.FILE:
					if (0 == (delta.getFlags() & IResourceDelta.CONTENT)) {
						return false;
					}
					if (CLASS_FILE_EXTENSION.equals(resource.getFullPath()
							.getFileExtension())) {
						IPath localLocation = resource.getLocation();
						if (localLocation != null) {
							String path = localLocation.toOSString();
							IClassFileReader reader = ToolFactory
									.createDefaultClassFileReader(
											path,
											IClassFileReader.CLASSFILE_ATTRIBUTES);
							if (reader != null) {
								// this name is slash-delimited
								String qualifiedName = new String(
										reader.getClassName());
								boolean hasBlockingErrors = false;
								try {
									if (!Platform.getPreferencesService().getBoolean(
											JDIDebugPlugin.getUniqueIdentifier(),
											JDIDebugModel.PREF_HCR_WITH_COMPILATION_ERRORS,
											true,
											null)) {
										// If the user doesn't want to replace
										// classfiles containing
										// compilation errors, get the source
										// file associated with
										// the class file and query it for
										// compilation errors
										IJavaProject pro = JavaCore
												.create(resource.getProject());
										ISourceAttribute sourceAttribute = reader
												.getSourceFileAttribute();
										String sourceName = null;
										if (sourceAttribute != null) {
											sourceName = new String(
													sourceAttribute
															.getSourceFileName());
										}
										IResource sourceFile = getSourceFile(
												pro, qualifiedName, sourceName);
										if (sourceFile != null) {
											IMarker[] problemMarkers = null;
											problemMarkers = sourceFile
													.findMarkers(
															IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER,
															true,
															IResource.DEPTH_INFINITE);
											for (IMarker problemMarker : problemMarkers) {
												if (problemMarker.getAttribute(
														IMarker.SEVERITY, -1) == IMarker.SEVERITY_ERROR) {
													hasBlockingErrors = true;
													break;
												}
											}
										}
									}
								} catch (CoreException e) {
									JDIDebugPlugin.log(e);
								}
								if (!hasBlockingErrors) {
									fFiles.add(resource);
									// dot-delimit the name
									fNames.add(qualifiedName.replace('/', '.'));
								}
							}
						}
					}
					return false;

				default:
					return true;
				}
			}
			return true;
		}

		/**
		 * Resets the file collection to empty
		 */
		public void reset() {
			fFiles = new ArrayList<>();
			fNames = new ArrayList<>();
		}

		/**
		 * Answers a collection of changed class files or <code>null</code>
		 */
		public List<IResource> getChangedClassFiles() {
			return fFiles;
		}

		/**
		 * Returns a collection of qualified type names corresponding to the
		 * changed class files.
		 *
		 * @return List
		 */
		public List<String> getQualifiedNamesList() {
			return fNames;
		}

		/**
		 * Returns the source file associated with the given type, or
		 * <code>null</code> if no source file could be found.
		 *
		 * @param project
		 *            the java project containing the classfile
		 * @param qualifiedName
		 *            fully qualified name of the type, slash delimited
		 * @param sourceAttribute
		 *            debug source attribute, or <code>null</code> if none
		 */
		private IResource getSourceFile(IJavaProject project,
				String qualifiedName, String sourceAttribute) {
			String name = null;
			IJavaElement element = null;
			try {
				if (sourceAttribute == null) {
					element = JavaDebugUtils
							.findElement(qualifiedName, project);
				} else {
					int i = qualifiedName.lastIndexOf('/');
					if (i > 0) {
						name = qualifiedName.substring(0, i + 1);
						name = name + sourceAttribute;
					} else {
						name = sourceAttribute;
					}
					element = project.findElement(new Path(name));
				}
				if (element instanceof ICompilationUnit) {
					ICompilationUnit cu = (ICompilationUnit) element;
					return cu.getCorrespondingResource();
				}
			} catch (CoreException e) {
			}
			return null;
		}
	}

	/**
	 * Adds the given listener to the collection of hot code replace listeners.
	 * Listeners are notified when hot code replace attempts succeed or fail.
	 */
	public void addHotCodeReplaceListener(IJavaHotCodeReplaceListener listener) {
		fHotCodeReplaceListeners.add(listener);
	}

	/**
	 * Removes the given listener from the collection of hot code replace
	 * listeners. Once a listener is removed, it will no longer be notified of
	 * hot code replace attempt successes or failures.
	 */
	public void removeHotCodeReplaceListener(
			IJavaHotCodeReplaceListener listener) {
		fHotCodeReplaceListeners.remove(listener);
	}

	/**
	 * @see ILaunchListener#launchRemoved(ILaunch)
	 */
	@Override
	public void launchRemoved(ILaunch launch) {
		IDebugTarget[] debugTargets = launch.getDebugTargets();
		for (IDebugTarget debugTarget : debugTargets) {
			IJavaDebugTarget jt = debugTarget
					.getAdapter(IJavaDebugTarget.class);
			if (jt != null) {
				deregisterTarget((JDIDebugTarget) jt);
			}
		}
	}

	/**
	 * Begin listening for resource changes when a launch is registered with a
	 * hot swap-able target.
	 *
	 * @see org.eclipse.debug.core.ILaunchListener#launchAdded(org.eclipse.debug.core.ILaunch)
	 */
	@Override
	public void launchAdded(ILaunch launch) {
		IDebugTarget[] debugTargets = launch.getDebugTargets();
		for (IDebugTarget debugTarget : debugTargets) {
			IJavaDebugTarget jt = debugTarget
					.getAdapter(IJavaDebugTarget.class);
			if (jt != null) {
				JDIDebugTarget target = (JDIDebugTarget) jt;
				if (target.supportsHotCodeReplace()) {
					addHotSwapTarget(target);
				} else if (target.isAvailable()) {
					addNonHotSwapTarget(target);
				}
			}
		}
		synchronized (this) {
			if (!fHotSwapTargets.isEmpty() || !fNoHotSwapTargets.isEmpty()) {
				getWorkspace().addResourceChangeListener(this,
						IResourceChangeEvent.POST_BUILD);
			}
		}
	}

	/**
	 * Begin listening for resource changes when a launch is registered with a
	 * hot swap-able target.
	 *
	 * @see ILaunchListener#launchChanged(ILaunch)
	 */
	@Override
	public void launchChanged(ILaunch launch) {
		launchAdded(launch);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * org.eclipse.debug.core.IDebugEventSetListener#handleDebugEvents(org.eclipse
	 * .debug.core.DebugEvent[])
	 */
	@Override
	public void handleDebugEvents(DebugEvent[] events) {
		for (DebugEvent event : events) {
			if (event.getKind() == DebugEvent.TERMINATE) {
				Object source = event.getSource();
				if (source instanceof IAdaptable
						&& source instanceof IDebugTarget) {
					IJavaDebugTarget jt = ((IAdaptable) source)
							.getAdapter(IJavaDebugTarget.class);
					if (jt != null) {
						deregisterTarget((JDIDebugTarget) jt);
					}
				}
			}
		}
	}

	protected void deregisterTarget(JDIDebugTarget target) {
		// Remove the target from its hot swap target cache.
		if (!fHotSwapTargets.remove(target)) {
			fNoHotSwapTargets.remove(target);
		}
		ILaunch[] launches = DebugPlugin.getDefault().getLaunchManager()
				.getLaunches();
		// If there are no more active JDIDebugTargets, stop
		// listening to resource changes.
		for (ILaunch launche : launches) {
			IDebugTarget[] targets = launche.getDebugTargets();
			for (IDebugTarget debugTarget : targets) {
				IJavaDebugTarget jt = debugTarget
						.getAdapter(IJavaDebugTarget.class);
				if (jt != null) {
					if (((JDIDebugTarget) jt).isAvailable()) {
						return;
					}
				}
			}
		}
	}

	/**
	 * Adds the given target to the list of hot-swap-able targets. Has no effect
	 * if the target is already registered.
	 *
	 * @param target
	 *            a target that supports hot swap
	 */
	protected synchronized void addHotSwapTarget(JDIDebugTarget target) {
		if (!fHotSwapTargets.contains(target)) {
			fHotSwapTargets.add(target);
		}
	}

	/**
	 * Adds the given target to the list of non hot-swap-able targets. Has no
	 * effect if the target is already registered.
	 *
	 * @param target
	 *            a target that does not support hot swap
	 */
	protected synchronized void addNonHotSwapTarget(JDIDebugTarget target) {
		if (!fNoHotSwapTargets.contains(target)) {
			fNoHotSwapTargets.add(target);
		}
	}

}
