/*******************************************************************************
 * Copyright (c) 2009, 2010 Nokia and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * Nokia - Initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.debug.edc.internal.services.dsf;

import java.io.File;
import java.io.Serializable;
import java.math.BigInteger;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.debug.core.executables.Executable;
import org.eclipse.cdt.debug.core.executables.ExecutablesManager;
import org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocator;
import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.PathUtils;
import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ExecutionDMC;
import org.eclipse.cdt.debug.edc.internal.snapshot.SnapshotUtils;
import org.eclipse.cdt.debug.edc.internal.symbols.IRuntimeSection;
import org.eclipse.cdt.debug.edc.internal.symbols.ISection;
import org.eclipse.cdt.debug.edc.internal.symbols.RuntimeSection;
import org.eclipse.cdt.debug.edc.internal.symbols.Section;
import org.eclipse.cdt.debug.edc.internal.symbols.files.ExecutableSymbolicsReaderFactory;
import org.eclipse.cdt.debug.edc.services.AbstractEDCService;
import org.eclipse.cdt.debug.edc.services.DMContext;
import org.eclipse.cdt.debug.edc.services.IEDCDMContext;
import org.eclipse.cdt.debug.edc.services.IEDCExecutionDMC;
import org.eclipse.cdt.debug.edc.services.IEDCModuleDMContext;
import org.eclipse.cdt.debug.edc.services.IEDCModules;
import org.eclipse.cdt.debug.edc.snapshot.IAlbum;
import org.eclipse.cdt.debug.edc.snapshot.ISnapshotContributor;
import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader;
import org.eclipse.cdt.debug.edc.tcf.extension.ProtocolConstants.IModuleProperty;
import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.cdt.dsf.debug.service.IModules;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.utils.Addr64;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.sourcelookup.containers.LocalFileStorage;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class Modules extends AbstractEDCService implements IModules, IEDCModules {

	public static final String MODULE = "module";
	public static final String SECTION = "section";
	private static final String ADDRESS_RANGE_CACHE = "_address_range";

	/**
	 * Modules that are loaded for each ISymbolDMContext (process).
	 */
	private final Map<String, List<ModuleDMC>> modules = Collections
			.synchronizedMap(new HashMap<String, List<ModuleDMC>>());

	private ISourceLocator sourceLocator;
	private static int nextModuleID = 100;

	public static class EDCAddressRange implements AddressRange, Serializable {
		
		private static final long serialVersionUID = -6475152211053407789L;
		private IAddress startAddr, endAddr;

		public EDCAddressRange(IAddress start, IAddress end) {
			startAddr = start;
			endAddr = end;
		}

		public IAddress getEndAddress() {
			return endAddr;
		}

		public void setEndAddress(IAddress address) {
			endAddr = address;
		}

		public IAddress getStartAddress() {
			return startAddr;
		}

		public void setStartAddress(IAddress address) {
			startAddr = address;
		}

		@Override
		public String toString() {
			return MessageFormat.format("[{0},{1})", startAddr.toHexAddressString(), endAddr.toHexAddressString());
		}
	}

	public class ModuleDMC extends DMContext implements IEDCModuleDMContext, ISnapshotContributor,
	// This means we'll install existing breakpoints
			// for each newly loaded module
			IBreakpointsTargetDMContext,
			// This means calcAddressInfo() also applies to single module
			// in addition to a process.
			ISymbolDMContext  {
		private final ISymbolDMContext symbolContext;

		private final IPath hostFilePath;
		private IEDCSymbolReader symReader;
		private final List<IRuntimeSection> runtimeSections = new ArrayList<IRuntimeSection>();

		public ModuleDMC(ISymbolDMContext symbolContext, Map<String, Object> props) {
			super(Modules.this, symbolContext == null ? new IDMContext[0] : new IDMContext[] { symbolContext }, Integer
					.toString(getNextModuleID()), props);
			this.symbolContext = symbolContext;

			String filename = "";
			if (props.containsKey(IModuleProperty.PROP_FILE))
				filename = (String) props.get(IModuleProperty.PROP_FILE);

			hostFilePath = locateModuleFileOnHost(filename);
		}

		public ISymbolDMContext getSymbolContext() {
			return symbolContext;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.cdt.debug.edc.services.IEDCModuleDMContext#getSymbolReader()
		 */
		public IEDCSymbolReader getSymbolReader() {
			return symReader;
		}

		public void loadSnapshot(Element element) throws Exception {
			NodeList sectionElements = element.getElementsByTagName(SECTION);

			int numSections = sectionElements.getLength();
			for (int i = 0; i < numSections; i++) {
				Element sectionElement = (Element) sectionElements.item(i);
				Element propElement = (Element) sectionElement.getElementsByTagName(SnapshotUtils.PROPERTIES).item(0);
				HashMap<String, Object> properties = new HashMap<String, Object>();
				SnapshotUtils.initializeFromXML(propElement, properties);

				IAddress linkAddress = new Addr64(sectionElement.getAttribute(ISection.PROPERTY_LINK_ADDRESS));
				int sectionID = Integer.parseInt(sectionElement.getAttribute(ISection.PROPERTY_ID));
				long size = Long.parseLong(sectionElement.getAttribute(ISection.PROPERTY_SIZE));

				RuntimeSection section = new RuntimeSection(new Section(sectionID, size, linkAddress, properties));
				section.relocate(new Addr64(sectionElement.getAttribute(IRuntimeSection.PROPERTY_RUNTIME_ADDRESS)));
				runtimeSections.add(section);
			}

			initializeSymbolReader();
		}

		public Element takeShapshot(IAlbum album, Document document, IProgressMonitor monitor) {
			Element contextElement = document.createElement(MODULE);
			contextElement.setAttribute(PROP_ID, this.getID());
			Element propsElement = SnapshotUtils.makeXMLFromProperties(document, getProperties());
			contextElement.appendChild(propsElement);

			for (IRuntimeSection s : runtimeSections) {
				Element sectionElement = document.createElement(SECTION);
				sectionElement.setAttribute(ISection.PROPERTY_ID, Integer.toString(s.getId()));
				sectionElement.setAttribute(ISection.PROPERTY_SIZE, Long.toString(s.getSize()));
				sectionElement.setAttribute(ISection.PROPERTY_LINK_ADDRESS, s.getLinkAddress().toHexAddressString());
				sectionElement.setAttribute(IRuntimeSection.PROPERTY_RUNTIME_ADDRESS, s.getRuntimeAddress()
						.toHexAddressString());
				propsElement = SnapshotUtils.makeXMLFromProperties(document, s.getProperties());
				sectionElement.appendChild(propsElement);
				contextElement.appendChild(sectionElement);
			}

			if (!hostFilePath.isEmpty()) {
				album.addFile(hostFilePath);
				IPath possibleSymFile = ExecutableSymbolicsReaderFactory.findSymbolicsFile(hostFilePath);
				if (possibleSymFile != null) {
					album.addFile(possibleSymFile);
				}
			}

			return contextElement;
		}

		/**
		 * Relocate sections of the module. This should be called when the
		 * module is loaded.<br>
		 * <br>
		 * The relocation handling is target environment dependent.
		 * Implementation here has been tested for debug applications on
		 * Windows, Linux and Symbian. <br>
		 * 
		 * @param props
		 *            - runtime section properties from OS or from loader.
		 */
		public void relocateSections(Map<String, Object> props) {

			initializeSymbolReader();

			if (symReader != null) {	
				for (ISection section: symReader.getSections())
				{
					runtimeSections.add(new RuntimeSection(section));
				}
			}
			
			if (props.containsKey(IModuleProperty.PROP_IMAGE_BASE_ADDRESS)) {
				// Windows module (PE file)
				//

				Object base = props.get(IModuleProperty.PROP_IMAGE_BASE_ADDRESS);
				IAddress imageBaseAddr = null;
				if (base != null) {
					if (base instanceof Integer)
						imageBaseAddr = new Addr64(base.toString());
					else if (base instanceof Long)
						imageBaseAddr = new Addr64(base.toString());
					else if (base instanceof String) // the string should be hex
						// string
						imageBaseAddr = new Addr64((String) base, 16);
					else
						EDCDebugger.getMessageLogger().logError(
								MessageFormat.format("Module property PROP_ADDRESS has invalid format {0}.", base
										.getClass()), null);
				}

				Number size = 0;
				if (props.containsKey(IModuleProperty.PROP_CODE_SIZE))
					size = (Number) props.get(IModuleProperty.PROP_CODE_SIZE);

				if (symReader != null) {
					// relocate
					//
					IAddress linkBase = symReader.getBaseLinkAddress();
					if (linkBase != null && !linkBase.equals(imageBaseAddr)) {
						BigInteger offset = linkBase.distanceTo(imageBaseAddr);
						for (IRuntimeSection s : runtimeSections) {
							IAddress runtimeB = s.getLinkAddress().add(offset);
							s.relocate(runtimeB);
						}
					}
				} else { // fill in fake section data
					Map<String, Object> pp = new HashMap<String, Object>();
					pp.put(ISection.PROPERTY_NAME, ISection.NAME_TEXT);
					runtimeSections.add(new RuntimeSection(new Section(0, size.longValue(), imageBaseAddr, pp)));
				}
			} else if (props.containsKey(IModuleProperty.PROP_CODE_ADDRESS)) {
				// platforms other than Windows
				//
				Number codeAddr = null, dataAddr = null, bssAddr = null;
				Number codeSize = null, dataSize = null, bssSize = null;

				try {
					codeAddr = (Number) props.get(IModuleProperty.PROP_CODE_ADDRESS);
					dataAddr = (Number) props.get(IModuleProperty.PROP_DATA_ADDRESS);
					bssAddr = (Number) props.get(IModuleProperty.PROP_BSS_ADDRESS);
					codeSize = (Number) props.get(IModuleProperty.PROP_CODE_SIZE);
					dataSize = (Number) props.get(IModuleProperty.PROP_DATA_SIZE);
					bssSize = (Number) props.get(IModuleProperty.PROP_BSS_SIZE);
				} catch (ClassCastException e) {
					EDCDebugger.getMessageLogger().logError("Module property value has invalid format.", null);
				}

				if (symReader != null) {
					// Relocate.
					for (IRuntimeSection s : runtimeSections) {
						if (s.getProperties().get(ISection.PROPERTY_NAME).equals(ISection.NAME_TEXT)
								&& codeAddr != null)
							s.relocate(new Addr64(codeAddr.toString()));
						else if (s.getProperties().get(ISection.PROPERTY_NAME).equals(ISection.NAME_DATA)
								&& dataAddr != null)
							s.relocate(new Addr64(dataAddr.toString()));
						else if (s.getProperties().get(ISection.PROPERTY_NAME).equals(ISection.NAME_BSS)
								&& bssAddr != null)
							s.relocate(new Addr64(bssAddr.toString()));
					}
				} else {
					// binary file not available.
					// fill in our fake sections. If no section size available,
					// don't bother.
					//
					Map<String, Object> pp = new HashMap<String, Object>();

					if (codeAddr != null && codeSize != null) {
						pp.put(ISection.PROPERTY_NAME, ISection.NAME_TEXT);
						runtimeSections.add(new RuntimeSection(new Section(0, codeSize.intValue(), new Addr64(codeAddr.toString()), pp)));
					}
					if (dataAddr != null && dataSize != null) {
						pp.clear();
						pp.put(ISection.PROPERTY_NAME, ISection.NAME_DATA);
						runtimeSections.add(new RuntimeSection(new Section(0, dataSize.intValue(), new Addr64(dataAddr.toString()), pp)));
					}
					if (bssAddr != null && bssSize != null) {
						pp.clear();
						pp.put(ISection.PROPERTY_NAME, ISection.NAME_BSS);
						runtimeSections.add(new RuntimeSection(new Section(0, bssSize.intValue(), new Addr64(bssAddr.toString()), pp)));
					}
				}
			} else {
				// No runtime address info available from target environment.
				// The runtime sections will just be the link-time sections.
				// 
				// This works well for the case where no relocation is needed
				// such as running the main executable (not DLLs nor shared
				// libs)
				// on Windows and Linux.
				// 
				// However, this may also indicate an error that the debug agent
				// (or even the target OS or loader) is not doing its job of
				// telling us the runtime address info.
			}
		}

		private void initializeSymbolReader() {
			if (hostFilePath.toFile().exists()) {
				symReader = Symbols.getSymbolReader(hostFilePath);
				if (symReader == null)
					EDCDebugger.getMessageLogger().log(IStatus.WARNING,
							MessageFormat.format("''{0}'' has no recognized file format.",
									hostFilePath), null);
				else if (! symReader.hasRecognizedDebugInformation()) {
					// Log as INFO, not ERROR.
					EDCDebugger.getMessageLogger().log(IStatus.INFO,
							MessageFormat.format("''{0}'' has no recognized symbolics.",
									hostFilePath), null);
				}
			} else {
				// Binary file not on host. Do we want to prompt user for one ?
			}
		}

		/**
		 * Check if a given runtime address falls in this module
		 * 
		 * @param absoluteAddr
		 *            - absolute runtime address.
		 * @return
		 */
		public boolean containsAddress(IAddress runtimeAddress) {
			for (IRuntimeSection s : runtimeSections) {
				long offset = s.getRuntimeAddress().distanceTo(runtimeAddress).longValue();
				if (offset >= 0 && offset < s.getSize())
					return true;
			}

			return false;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.cdt.debug.edc.services.IEDCModuleDMContext#toLinkAddress(org.eclipse.cdt.core.IAddress)
		 */
		public IAddress toLinkAddress(IAddress runtimeAddress) {
			IAddress ret = null;

			for (IRuntimeSection s : runtimeSections) {
				long offset = s.getRuntimeAddress().distanceTo(runtimeAddress).longValue();
				if (offset >= 0 && offset < s.getSize()) {
					return s.getLinkAddress().add(offset);
				}
			}

			return ret;
		}

		/* (non-Javadoc)
		 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCModuleDMContext#toRuntimeAddress(org.eclipse.cdt.core.IAddress)
		 */
		public IAddress toRuntimeAddress(IAddress linkAddress) {
			IAddress ret = null;

			for (IRuntimeSection s : runtimeSections) {
				long offset = s.getLinkAddress().distanceTo(linkAddress).longValue();
				if (offset >= 0 && offset < s.getSize()) {
					return s.getRuntimeAddress().add(offset);
				}
			}

			return ret;
		}

		/**
		 * Get file name (without path) of the module.
		 * 
		 * @return
		 */
		public String getFile() {
			return hostFilePath.lastSegment();
		}

		@Override
		public String toString() {
			StringBuilder builder = new StringBuilder();
			builder.append("\nModuleDMC [");
			if (hostFilePath != null) {
				builder.append("file=");
				builder.append(hostFilePath.lastSegment());
				builder.append(", ");
			}
			for (IRuntimeSection s : runtimeSections) {
				builder.append("\n");
				builder.append(s);
			}
			return builder.toString();
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = super.hashCode();
			result = prime * result + getOuterType().hashCode();
			result = prime * result + ((hostFilePath == null) ? 0 : hostFilePath.hashCode());
			result = prime * result + ((symbolContext == null) ? 0 : symbolContext.hashCode());
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (!super.equals(obj))
				return false;
			if (getClass() != obj.getClass())
				return false;
			ModuleDMC other = (ModuleDMC) obj;
			if (!getOuterType().equals(other.getOuterType()))
				return false;
			if (hostFilePath == null) {
				if (other.hostFilePath != null)
					return false;
			} else if (!hostFilePath.equals(other.hostFilePath))
				return false;
			if (symbolContext == null) {
				if (other.symbolContext != null)
					return false;
			} else if (!symbolContext.equals(other.symbolContext))
				return false;
			return true;
		}

		private IEDCModules getOuterType() {
			return Modules.this;
		}
	}

	static class ModuleDMData implements IModuleDMData {

		private final Map<String, Object> properties;

		public ModuleDMData(ModuleDMC dmc) {
			properties = dmc.getProperties();
		}

		public String getFile() {
			return (String) properties.get(IModuleProperty.PROP_FILE);
		}

		public String getName() {
			return (String) properties.get(IEDCDMContext.PROP_NAME);
		}

		public long getTimeStamp() {
			return 0;
			// return (String) properties.get(IModuleProperty.PROP_TIME);
		}

		public String getBaseAddress() {
			// return hex string representation.
			//
			Object baseAddress = properties.get(IModuleProperty.PROP_IMAGE_BASE_ADDRESS);
			if (baseAddress == null)
				baseAddress = properties.get(IModuleProperty.PROP_CODE_ADDRESS);

			if (baseAddress != null)
				return baseAddress.toString();
			else
				return "";
		}

		public String getToAddress() {
			// TODO this should return the end address, e.g. base + size
			return getBaseAddress();
		}

		public boolean isSymbolsLoaded() {
			return false;
		}

		public long getSize() {
			Number moduleSize = (Number) properties.get(IModuleProperty.PROP_CODE_SIZE);
			if (moduleSize != null)
				return moduleSize.longValue();
			else
				return 0;
		}

	}

	public static class ModuleLoadedEvent extends AbstractDMEvent<ISymbolDMContext> implements ModuleLoadedDMEvent {

		private final ModuleDMC module;
		private final IExecutionDMContext executionDMC;

		public ModuleLoadedEvent(ISymbolDMContext symbolContext, IExecutionDMContext executionDMC, ModuleDMC module) {
			super(symbolContext);
			this.module = module;
			this.executionDMC = executionDMC;
		}

		public IExecutionDMContext getExecutionDMC() {
			return executionDMC;
		}

		public IModuleDMContext getLoadedModuleContext() {
			return module;
		}

	}

	public static class ModuleUnloadedEvent extends AbstractDMEvent<ISymbolDMContext> implements ModuleUnloadedDMEvent {

		private final ModuleDMC module;
		private final IExecutionDMContext executionDMC;

		public ModuleUnloadedEvent(ISymbolDMContext symbolContext, IExecutionDMContext executionDMC, ModuleDMC module) {
			super(symbolContext);
			this.module = module;
			this.executionDMC = executionDMC;
		}

		public IExecutionDMContext getExecutionDMC() {
			return executionDMC;
		}

		public IModuleDMContext getUnloadedModuleContext() {
			return module;
		}

	}

	public Modules(DsfSession session) {
		super(session, new String[] { IModules.class.getName(), IEDCModules.class.getName(), Modules.class.getName() });
	}

	public void setSourceLocator(ISourceLocator sourceLocator) {
		this.sourceLocator = sourceLocator;
	}

	public ISourceLocator getSourceLocator() {
		return sourceLocator;
	}

	private void addModule(ModuleDMC module) {
		ISymbolDMContext symContext = module.getSymbolContext();
		if (symContext instanceof IEDCDMContext) {
			String symContextID = ((IEDCDMContext) symContext).getID();
			synchronized (modules) {
				List<ModuleDMC> moduleList = modules.get(symContextID);
				if (moduleList == null) {
					moduleList = Collections.synchronizedList(new ArrayList<ModuleDMC>());
					modules.put(symContextID, moduleList);
				}
				moduleList.add(module);
			}
		}
	}

	private void removeModule(ModuleDMC module) {
		ISymbolDMContext symContext = module.getSymbolContext();
		if (symContext instanceof IEDCDMContext) {
			String symContextID = ((IEDCDMContext) symContext).getID();
			synchronized (modules) {
				List<ModuleDMC> moduleList = modules.get(symContextID);
				if (moduleList != null) {
					// other module attributes may not be passed during removal,
					// so remove the module with the same name
					for (ModuleDMC next : moduleList) {
						if (next.getFile().equals(module.getFile())) {
							moduleList.remove(next);
							break;
						}
					}
				}
			}
		}

	}

	/*
	 * The result AddressRange[] will contain absolute runtime addresses. And
	 * the "symCtx" can be a process or a module.
	 */
	@SuppressWarnings("unchecked")
	public void calcAddressInfo(ISymbolDMContext symCtx, String file, int line, int col,
			DataRequestMonitor<AddressRange[]> rm) {
		IModuleDMContext[] moduleList = null;

		if (symCtx instanceof IEDCExecutionDMC) {
			String symContextID = ((IEDCDMContext) symCtx).getID();
			moduleList = getModulesForContext(symContextID);
		} else if (symCtx instanceof IModuleDMContext) {
			moduleList = new IModuleDMContext[1];
			moduleList[0] = (IModuleDMContext) symCtx;
		} else {
			// should not happen
			assert false : "Unknown ISymbolDMContext class.";
			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED, MessageFormat.format(
					"Unknown class implementing ISymbolDMContext : {0}", symCtx.getClass().getName()), null));
			rm.done();
			return;
		}

		List<EDCAddressRange> addrRanges = new ArrayList<EDCAddressRange>(1);
		
		for (IModuleDMContext module : moduleList) {
			ModuleDMC mdmc = (ModuleDMC) module;
			IEDCSymbolReader reader = mdmc.getSymbolReader();

			if (reader != null) {

				Collection<AddressRange> linkAddressRanges = null;
				Map<String, Collection<AddressRange>> cachedRanges = new HashMap<String, Collection<AddressRange>>();
				// Check the persistent cache
				String cacheKey = reader.getSymbolFile().toOSString() + ADDRESS_RANGE_CACHE;
				Map<String, Collection<AddressRange>> cachedData = EDCDebugger.getDefault().getCache().getCachedData(cacheKey, Map.class, reader.getModificationDate());
				if (cachedData != null)
				{
					cachedRanges = cachedData;
					linkAddressRanges = cachedRanges.get(file + line);
				}
				
				if (linkAddressRanges == null)
				{
					linkAddressRanges = LineEntryMapper.getAddressRangesAtSource(  
						reader.getModuleScope().getModuleLineEntryProvider(),
						PathUtils.createPath(file),
						line);
					
					cachedRanges.put(file + line, linkAddressRanges);
					EDCDebugger.getDefault().getCache().putCachedData(cacheKey, (Serializable) cachedRanges, reader.getModificationDate());				
				}
								
				// map addresses
				for (AddressRange linkAddressRange : linkAddressRanges) {
					EDCAddressRange addrRange = new EDCAddressRange(
							mdmc.toRuntimeAddress(linkAddressRange.getStartAddress()),
							mdmc.toRuntimeAddress(linkAddressRange.getEndAddress()));
					addrRanges.add(addrRange);
				}
			}
		}

		if (addrRanges.size() > 0) {
			AddressRange[] ar = addrRanges.toArray(new AddressRange[addrRanges.size()]);
			rm.setData(ar);
		} else {
			/*
			 * we try to set the breakpoint for every module since we don't know
			 * which one the file is in. we report this error though if the file
			 * isn't in the module, and let the caller handle the error.
			 */
			rm.setStatus(new Status(IStatus.ERROR, EDCDebugger.PLUGIN_ID, REQUEST_FAILED, MessageFormat.format(
					"Fail to find address for source line {0}: line# {1}", file, line), null));
		}

		rm.done();
	}

	public void calcLineInfo(ISymbolDMContext symCtx, IAddress address, DataRequestMonitor<LineInfo[]> rm) {
		// TODO Auto-generated method stub

	}

	/**
	 * Get runtime addresses mapped to given source line in given run context.
	 *  
	 * @param context
	 * @param sourceFile
	 * @param lineNumber
	 * @param drm If no address found, holds an empty list.
	 */
	public void getLineAddress(IExecutionDMContext context,
			String sourceFile, int lineNumber, final DataRequestMonitor<List<IAddress>> drm) {
		final List<IAddress> addrs = new ArrayList<IAddress>(1);
		
		final ExecutionDMC dmc = (ExecutionDMC) context;
		if (dmc == null) {
			drm.setData(addrs);
			drm.done();
			return;
		}
		
		ISymbolDMContext symCtx = DMContexts.getAncestorOfType(context, ISymbolDMContext.class);

		calcAddressInfo(symCtx, sourceFile, lineNumber, 0, 
				new DataRequestMonitor<AddressRange[]>(getExecutor(), drm) {

			@Override
			protected void handleCompleted() {
				if (! isSuccess()) {
					drm.setStatus(getStatus());
					drm.done();
					return;
				}

				AddressRange[] addr_ranges = getData();

				for (AddressRange range : addr_ranges) {
					IAddress a = range.getStartAddress();  // this is runtime address
					addrs.add(a);
				}

				drm.setData(addrs);
				drm.done();
			}
		});
	}
		
	public void getModuleData(IModuleDMContext dmc, DataRequestMonitor<IModuleDMData> rm) {
		rm.setData(new ModuleDMData((ModuleDMC) dmc));
		rm.done();
	}

	public void getModules(ISymbolDMContext symCtx, DataRequestMonitor<IModuleDMContext[]> rm) {
		String symContextID = ((IEDCDMContext) symCtx).getID();
		IModuleDMContext[] moduleList = getModulesForContext(symContextID);
		rm.setData(moduleList);
		rm.done();
	}

	public IModuleDMContext[] getModulesForContext(String symContextID) {
		synchronized (modules) {
			List<ModuleDMC> moduleList = modules.get(symContextID);
			if (moduleList == null)
				return new IModuleDMContext[0];
			else
				return moduleList.toArray(new IModuleDMContext[moduleList.size()]);
		}
	}

	private int getNextModuleID() {
		return nextModuleID++;
	}

	public void moduleLoaded(ISymbolDMContext symbolContext, IExecutionDMContext executionDMC, Map<String, Object> moduleProps) {
		ModuleDMC module = new ModuleDMC(symbolContext, moduleProps);
		module.relocateSections(moduleProps);
		addModule(module);
		getSession().dispatchEvent(new ModuleLoadedEvent(symbolContext, executionDMC, module),
				Modules.this.getProperties());
	}

	public void moduleUnloaded(ISymbolDMContext symbolContext, IExecutionDMContext executionDMC,
			Map<String, Object> moduleProps) {
		Object fileName = moduleProps.get(IEDCDMContext.PROP_NAME);
		ModuleDMC module = getModuleByName(symbolContext, fileName);
		if (module == null) {
			EDCDebugger.getMessageLogger().logError("Unexpected unload of module: " + fileName, null);
			return;
		}
		Object requireResumeValue = moduleProps.get("RequireResume");
		if (requireResumeValue != null && requireResumeValue instanceof Boolean)
			module.setProperty("RequireResume", requireResumeValue);
		removeModule(module);
		getSession().dispatchEvent(new ModuleUnloadedEvent(symbolContext, executionDMC, module),
				Modules.this.getProperties());
	}

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.debug.edc.internal.services.dsf.IEDCModules#getModuleByAddress(org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext, org.eclipse.cdt.core.IAddress)
	 */
	public ModuleDMC getModuleByAddress(ISymbolDMContext symCtx, IAddress instructionAddress) {
		ModuleDMC bestMatch = null;
		synchronized (modules) {
			List<ModuleDMC> moduleList = modules.get(((IEDCDMContext) symCtx).getID());
			if (moduleList != null) {
				for (ModuleDMC moduleDMC : moduleList) {
					if (moduleDMC.containsAddress(instructionAddress)) {
						bestMatch = moduleDMC;
						break;
					}
				}

				if (bestMatch == null) {
					// TODO: add a bogus wrap-all module ?
				}
			}
		}
		return bestMatch;
	}

	/**
	 * Find the host file that corresponds to a given module file whose name
	 * comes from target platform.
	 * 
	 * @param originalPath
	 *            path or filename from target platform.
	 * @return the path to an existing file on host, null otherwise.
	 */
	public IPath locateModuleFileOnHost(String originalPath) {
		if (originalPath == null || originalPath.length() == 0)
			return Path.EMPTY;

		// Canonicalize path for the host OS, in hopes of finding a match directly on the host,
		// and for searching sources and executables below.
		//
		IPath path = PathUtils.findExistingPathIfCaseSensitive(PathUtils.createPath(originalPath));
		if (path.toFile().exists())
			return path;

		// Try source locator first, using the host-correct path.
		//
		Object sourceElement = null;
		ISourceLocator locator = getSourceLocator();
		if (locator != null) {
			if (locator instanceof ICSourceLocator || locator instanceof CSourceLookupDirector) {
				if (locator instanceof ICSourceLocator)
					sourceElement = ((ICSourceLocator) locator).findSourceElement(path.toOSString());
				else
					sourceElement = ((CSourceLookupDirector) locator).getSourceElement(path.toOSString());
			}
			if (sourceElement != null) {
				if (sourceElement instanceof LocalFileStorage) {
					return new Path(((LocalFileStorage) sourceElement).getFile().getAbsolutePath());
				}
			}
		}

		// Now looking for the file in executable view.
		//
		// Between the SDK and target, the exact directory and file capitalization may differ.
		//
		// Inject required initial slash so we can confidently use String#endsWith() without
		// matching, e.g. "/path/to/program.exe" with "ram.exe".
		//
		String slashAndLowerFileName = File.separator + path.lastSegment().toLowerCase();
		String absoluteLowerPath = path.makeAbsolute().toOSString().toLowerCase();
		
		Collection<Executable> executables = ExecutablesManager.getExecutablesManager().getExecutables(false);
		for (Executable e : executables) {
			String p = e.getPath().makeAbsolute().toOSString().toLowerCase();
			if (p.endsWith(absoluteLowerPath) || // stricter match first
				p.endsWith(slashAndLowerFileName)) // then only check by name
			{
				return e.getPath();
			}
		}

		return path;
	}

	public void loadModulesForContext(ISymbolDMContext context, Element element) throws Exception {

		List<ModuleDMC> contextModules = Collections.synchronizedList(new ArrayList<ModuleDMC>());

		NodeList moduleElements = element.getElementsByTagName(MODULE);

		int numModules = moduleElements.getLength();
		for (int i = 0; i < numModules; i++) {
			Element moduleElement = (Element) moduleElements.item(i);
			Element propElement = (Element) moduleElement.getElementsByTagName(SnapshotUtils.PROPERTIES).item(0);
			HashMap<String, Object> properties = new HashMap<String, Object>();
			SnapshotUtils.initializeFromXML(propElement, properties);

			ModuleDMC module = new ModuleDMC(context, properties);
			module.loadSnapshot(moduleElement);
			contextModules.add(module);

		}
		modules.put(((IEDCDMContext) context).getID(), contextModules);

	}
	
	/**
	 * get module with given file name
	 * 
	 * @param symCtx
	 * @param fileName
	 *            executable name for module
	 * @return null if not found.
	 */
	public ModuleDMC getModuleByName(ISymbolDMContext symCtx, Object fileName) {
		ModuleDMC module = null;
		synchronized (modules) {
			List<ModuleDMC> moduleList = modules.get(((IEDCDMContext) symCtx).getID());
			if (moduleList != null) {
				for (ModuleDMC moduleDMC : moduleList) {
					if ((moduleDMC.getName().compareToIgnoreCase((String) fileName)) == 0 ) {
						module = moduleDMC;
						break;
					}
				}
			}
		}
		return module;
	}

}
