/*******************************************************************************
 * Copyright (c) 2005, 2007 BEA Systems, Inc.
 * 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:
 *    wharley@bea.com - initial API and implementation
 *******************************************************************************/

package org.eclipse.jdt.apt.core.internal;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

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.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.apt.core.internal.util.FactoryContainer;
import org.eclipse.jdt.apt.core.internal.util.FactoryPath;
import org.eclipse.jdt.apt.core.internal.util.FactoryPathUtil;
import org.eclipse.jdt.apt.core.internal.util.FactoryContainer.FactoryType;
import org.eclipse.jdt.apt.core.internal.util.FactoryPath.Attributes;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;

import com.sun.mirror.apt.AnnotationProcessorFactory;

/**
 * Stores annotation processor factories, and handles mapping from projects
 * to them.  This is a singleton object, created by the first call to getLoader().
 * <p>
 * Factories contained in plugins are loaded at APT initialization time.  
 * Factories contained in jar files are loaded for a given project the first time 
 * getFactoriesForProject() is called, and cached thereafter.  Factories are loaded 
 * from one of two custom classloaders depending on whether the factory container 
 * is to be run in batch processing mode or normal (iterative) mode; the batch
 * classloader for a project is parented by the iterative classloader for that
 * project.
 * <p>
 * <strong>Processor Factories</strong>
 * <p>
 * This class is compilable against a Java 1.5 runtime.  However, it includes
 * support for discovering and loading both Java 5 and Java 6 annotation
 * processors.  Java 5 annotation processors include a factory object, the
 * AnnotationProcessorFactory, so for Java 5 we simply cache the factory; the
 * client code uses the factory to produce an actual AnnotationProcessor.
 * Java 6 processors do not have a separate factory, so we cache the Class
 * object of the processor implementation and use it to produce new instances.
 * This is wrapped within an IServiceFactory interface, for flexibility in
 * loading from various sources.  The actual Processor class does not exist
 * in the Java 1.5 runtime, so all access to it must be done via reflection.
 * <p>
 * <strong>Caches</strong>
 * <p>
 * Factory classes and iterative-mode classloaders are cached for each project,
 * the first time that the classes are needed (e.g., during a build or reconcile).  
 * The cache is cleared when the project's factory path changes, when a resource
 * listed on the factory path is changed, or when the project is deleted.  
 * If a project contains batch-mode processors, the cache is also cleared at
 * the beginning of every full build (batch-mode processors do not run at all 
 * during reconcile).
 * <p>
 * If a project's factory path includes containers which cannot be located on
 * disk, problem markers will be added to the project.  This validation process
 * occurs when the cache for a project is first loaded, and whenever the cache
 * is invalidated.  We do not validate the workspace-level factory path as such; 
 * it is only used to construct a project-specific factory path for projects 
 * that do not have their own factory path.
 * <p>
 * In order to efficiently perform re-validation when resources change, we keep 
 * track of which projects' factory paths mention which containers.  This is
 * stored as a map from canonicalized resource path to project.  Entries are
 * created and updated during factory path validation, and removed upon project 
 * deletion.
 * <p>
 * Resource changes are presented as delta trees which may contain more than
 * one change.  When a change arrives, we build up a list of all potentially
 * affected projects, and then perform re-validation after the list is complete.
 * That way we avoid redundant validations if a project is affected by more 
 * than one change.   
 * <p>
 * Note that markers and factory classes have different lifetimes: they are
 * discarded at the same time (when something changes), but markers are recreated
 * immediately (as a result of validation) while factory classes are not reloaded
 * until the next time a build or reconcile occurs.
 * <p>
 * <strong>Synchronization</strong>
 * <p>
 * The loader is often accessed on multiple threads, e.g., a build thread, a
 * reconcile thread, and a change notification thread all at once.  It is
 * important to maintain consistency across the various cache objects. 
 */
public class AnnotationProcessorFactoryLoader {
	
	/** Loader instance -- holds all workspace and project data */
	private static AnnotationProcessorFactoryLoader LOADER;
	
	private static final String JAR_EXTENSION = "jar"; //$NON-NLS-1$
	
	// Caches the factory classes associated with each project.
	// See class comments for lifecycle of items in this cache.
	private final Map<IJavaProject, Map<AnnotationProcessorFactory, FactoryPath.Attributes>> _project2Java5Factories = 
		new HashMap<IJavaProject, Map<AnnotationProcessorFactory, FactoryPath.Attributes>>();
	
	private final Map<IJavaProject, Map<IServiceFactory, FactoryPath.Attributes>> _project2Java6Factories =
		new HashMap<IJavaProject, Map<IServiceFactory, FactoryPath.Attributes>>();
    
	// Caches the iterative classloaders so that iterative processors
	// are not reloaded on every batch build, unlike batch processors 
	// which are.
	// See class comments for lifecycle of items in this cache.
	private final Map<IJavaProject, ClassLoader> _iterativeLoaders = 
		new HashMap<IJavaProject, ClassLoader>();
	
	private final Map<IJavaProject,ClassLoader> _batchLoaders = 
		new HashMap<IJavaProject,ClassLoader>();
	
	// Caches information about which resources affect which projects'
	// factory paths.
	// See class comments for lifecycle of items in this cache.
	private final Map<String, Set<IJavaProject>> _container2Project =
		new HashMap<String, Set<IJavaProject>>();
	
   
	/**
	 * Listen for changes that would affect the factory caches or
	 * build markers.
	 */
	private class ResourceListener implements IResourceChangeListener {

		public void resourceChanged(IResourceChangeEvent event) {
			Map<IJavaProject, LoadFailureHandler> failureHandlers = new HashMap<IJavaProject, LoadFailureHandler>();
			synchronized (AnnotationProcessorFactoryLoader.this) {
				switch (event.getType()) {
				
				// Project deletion
				case (IResourceChangeEvent.PRE_DELETE) :
					IResource project = event.getResource();
					if (project != null && project instanceof IProject) {
						IJavaProject jproj = JavaCore.create((IProject)project);
						if (jproj != null) {
							uncacheProject(jproj);
						}
					}
					break;
					
				// Changes to jar files or .factorypath files
				case (IResourceChangeEvent.PRE_BUILD) :
					IResourceDelta rootDelta = event.getDelta();
					FactoryPathDeltaVisitor visitor = new FactoryPathDeltaVisitor();
					try {
						rootDelta.accept(visitor);
					} catch (CoreException e) {
						AptPlugin.log(e, "Unable to determine whether resource change affects annotation processor factory path"); //$NON-NLS-1$
					}
					Set<IJavaProject> affected = visitor.getAffectedProjects();
					if (affected != null) {
						processChanges(affected, failureHandlers);
					}
					break;
	
				}
			}
			for (LoadFailureHandler handler : failureHandlers.values()) {
				handler.reportFailureMarkers();
			}
		}
		
	}
	
	/**
	 * Walk the delta tree to see if there have been changes to
	 * a factory path or the containers it references.  If so,
	 * re-validate the affected projects' factory paths.
	 */
	private class FactoryPathDeltaVisitor implements IResourceDeltaVisitor {
		
		// List of projects affected by this change.
		// Lazy construction because we assume most changes won't affect any projects.
		private Set<IJavaProject> _affected = null;
		
		private void addAffected(Set<IJavaProject> projects) {
			if (_affected == null) {
				 _affected = new HashSet<IJavaProject>(5);
			}
			_affected.addAll(projects);
		}
		
		/**
		 * Get the list of IJavaProject affected by the delta we visited.
		 * Not valid until done visiting.
		 * @return null if there were no affected projects, or a non-empty
		 * set of IJavaProject otherwise. 
		 */
		public Set<IJavaProject> getAffectedProjects() {
			return _affected;
		}
		
		/**
		 * @return true to visit children
		 */
		public boolean visit(IResourceDelta delta) {
			switch (delta.getKind()) {
			default:
				return true;
			case IResourceDelta.ADDED :
			case IResourceDelta.REMOVED :
			case IResourceDelta.CHANGED :
				break;
			}
			// If the resource is a factory path file, then the project it
			// belongs to is affected.
			IResource res = delta.getResource();
			if (res == null) {
				return true;
			}
			IProject proj = res.getProject();
			if (FactoryPathUtil.isFactoryPathFile(res)) {
				addAffected(Collections.singleton(JavaCore.create(proj)));
				return true;
			}
			// If the resource is a jar file named in at least one factory
			// path, then the projects owning those factorypaths are affected.
			if (res.getType() != IResource.FILE) {
				return true;
			}
			IPath relativePath = res.getFullPath();
			String ext = relativePath.getFileExtension();
			try {
				if (JAR_EXTENSION.equals(ext)) {
					IPath absolutePath = res.getLocation();
					if (absolutePath == null) {
						// Jar file within a deleted project.  In this case getLocation() 
						// returns null, so we can't get a canonical path.  Bounce every
						// factory path that contains anything resembling this jar.
						for (Entry<String, Set<IJavaProject>> entry : _container2Project.entrySet()) {
							IPath jarPath = new Path(entry.getKey());
							if (relativePath.lastSegment().equals(jarPath.lastSegment())) {
								addAffected(entry.getValue());
							}
						}
					}
					else {
						// Lookup key is the canonical path of the resource
						String key = null;
						key = absolutePath.toFile().getCanonicalPath();
						Set<IJavaProject> projects = _container2Project.get(key);
						if (projects != null) {
							addAffected(projects);
						}
					}
				}
			} catch (Exception e) {
				AptPlugin.log(e, 
					"Couldn't determine whether any factory paths were affected by change to resource " + res.getName()); //$NON-NLS-1$
			}
			return true;
		}
		
	}
	
	/** 
	 * Singleton
	 */
    public static synchronized AnnotationProcessorFactoryLoader getLoader() {
    	if ( LOADER == null ) {
    		LOADER = new AnnotationProcessorFactoryLoader();
    		LOADER.registerListener();
    	}
    	return LOADER;
    }
    
	private void registerListener() {
		ResourcesPlugin.getWorkspace().addResourceChangeListener(
			new ResourceListener(),
			IResourceChangeEvent.PRE_DELETE
			| IResourceChangeEvent.PRE_BUILD);
	}

    /**
     * Called when workspace preferences change.  Resource changes, including
     * changes to project-specific factory paths, are picked up through the
     * ResourceChangedListener mechanism instead.
     */
    public synchronized void resetAll() {
    	removeAptBuildProblemMarkers( null );
    	_project2Java5Factories.clear();
    	_project2Java6Factories.clear();
    	// Need to close the iterative classloaders
    	for (ClassLoader cl : _iterativeLoaders.values()) {
    		if (cl instanceof JarClassLoader)
    			((JarClassLoader)cl).close();
    	}
    	_iterativeLoaders.clear();
    	_container2Project.clear();
    	
    	for (ClassLoader cl : _batchLoaders.values()) {
    		if (cl instanceof JarClassLoader)
    			((JarClassLoader)cl).close();
    	}
    	_batchLoaders.clear();
    	
    	// Validate all projects
		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
		for (IProject proj : root.getProjects()) {
			verifyFactoryPath(JavaCore.create(proj));
		}
    }
    
    /**
     * Called when doing a clean build -- resets
     * the classloaders for the batch processors
     */
    public synchronized void resetBatchProcessors(IJavaProject javaProj) {
    	Iterable<Attributes> attrs = null;
    	Map<AnnotationProcessorFactory, Attributes> factories = _project2Java5Factories.get(javaProj);
    	if (factories != null) {
    		attrs = factories.values();
    	}
    	else {
    		Map<IServiceFactory, Attributes> java6factories = _project2Java6Factories.get(javaProj);
    		if (java6factories != null) {
    			attrs = java6factories.values();
    		}
    		else {
    			// This project's factories have already been cleared.
    			return;
    		}
    	}
    	boolean batchProcsFound = false;
    	for (Attributes attr : attrs) {
    		if (attr.runInBatchMode()) {
    			batchProcsFound = true;
    			break;
    		}
    	}
    	if (batchProcsFound) {
    		_project2Java5Factories.remove(javaProj);
    		_project2Java6Factories.remove(javaProj);
    	}

    	ClassLoader c = _batchLoaders.remove(javaProj);
    	if (c instanceof JarClassLoader) ((JarClassLoader)c).close();
    }
    
    /**
     * @param jproj must not be null
     * @return order preserving map of annotation processor factories to their attributes.
     * The order of the annotation processor factories respects the order of factory 
     * containers in <code>jproj</code>.  The map is unmodifiable, and may be empty but 
     * will not be null.
     */
    public Map<AnnotationProcessorFactory, FactoryPath.Attributes> 
    	getJava5FactoriesAndAttributesForProject(IJavaProject jproj){
    	
    	// We can't create problem markers inside synchronization -- see https://bugs.eclipse.org/bugs/show_bug.cgi?id=184923
    	LoadFailureHandler failureHandler = new LoadFailureHandler(jproj);
    	
    	synchronized (this) {
	    	Map<AnnotationProcessorFactory, FactoryPath.Attributes> factories = _project2Java5Factories.get(jproj);
	    	if( factories != null )
	    		return Collections.unmodifiableMap(factories);
	    	
	    	// Load the project
			FactoryPath fp = FactoryPathUtil.getFactoryPath(jproj);
			Map<FactoryContainer, FactoryPath.Attributes> containers = fp.getEnabledContainers();
			loadFactories(containers, jproj, failureHandler);
    	}
    	
    	failureHandler.reportFailureMarkers();
		return Collections.unmodifiableMap(_project2Java5Factories.get(jproj));
    	
    }
    
    /**
     * @param jproj must not be null
     * @return order preserving map of annotation processor factories to their attributes.
     * The order of the annotation processor factories respects the order of factory 
     * containers in <code>jproj</code>.  The map is unmodifiable, and may be empty but 
     * will not be null.
     */
    public Map<IServiceFactory, FactoryPath.Attributes> 
    	getJava6FactoriesAndAttributesForProject(IJavaProject jproj){
    	
    	// We can't create problem markers inside synchronization -- see https://bugs.eclipse.org/bugs/show_bug.cgi?id=184923
    	LoadFailureHandler failureHandler = new LoadFailureHandler(jproj);
    	
    	synchronized (this) {
    	
	    	Map<IServiceFactory, FactoryPath.Attributes> factories = _project2Java6Factories.get(jproj);
	    	if( factories != null )
	    		return Collections.unmodifiableMap(factories);
	    	
	    	// Load the project
			FactoryPath fp = FactoryPathUtil.getFactoryPath(jproj);
			Map<FactoryContainer, FactoryPath.Attributes> containers = fp.getEnabledContainers();
			loadFactories(containers, jproj, failureHandler);
    	}
    	
    	failureHandler.reportFailureMarkers();
		return Collections.unmodifiableMap(_project2Java6Factories.get(jproj));
    	
    }
    
/**
     * Convenience method: get the key set of the map returned by
     * @see #getJava5FactoriesAndAttributesForProject(IJavaProject) as a List.
     */
    public synchronized List<AnnotationProcessorFactory> getJava5FactoriesForProject( IJavaProject jproj ) {
    	
    	Map<AnnotationProcessorFactory, FactoryPath.Attributes> factoriesAndAttrs = 
    		getJava5FactoriesAndAttributesForProject(jproj);
    	final List<AnnotationProcessorFactory> factories = 
    		new ArrayList<AnnotationProcessorFactory>(factoriesAndAttrs.keySet());
    	return Collections.unmodifiableList(factories);
    }
    
    /**
     * Add the resource/project pair 'key' -> 'jproj' to the 
     * _container2Project map.
     * @param key the canonicalized pathname of the resource
     * @param jproj must not be null
     */
	private void addToResourcesMap(String key, IJavaProject jproj) {
		Set<IJavaProject> s = _container2Project.get(key);
		if (s == null) {
			s = new HashSet<IJavaProject>();
			_container2Project.put(key, s);
		}
		s.add(jproj);
	}

	/**
	 * Wrapper around ClassLoader.loadClass().newInstance() to handle reporting of errors.
	 */
	private Object loadInstance( String factoryName, ClassLoader cl, IJavaProject jproj, LoadFailureHandler failureHandler )
	{
		Object f = null;
		try
		{
			Class<?> c = cl.loadClass( factoryName );
			f = c.newInstance();
		}
		catch( Exception e )
		{
			AptPlugin.trace("Failed to load factory " + factoryName, e); //$NON-NLS-1$
			failureHandler.addFailedFactory(factoryName);
		}
		catch ( NoClassDefFoundError ncdfe )
		{
			AptPlugin.trace("Failed to load " + factoryName, ncdfe); //$NON-NLS-1$
			failureHandler.addFailedFactory(factoryName);
		}
		return f;
	}
	
	/**
	 * Load all Java 5 and Java 6 processors on the factory path.  This also resets the
	 * APT-related build problem markers.  Results are saved in the factory caches.
	 * @param containers an ordered map.
	 */
	private void loadFactories( 
			Map<FactoryContainer, FactoryPath.Attributes> containers, 
			IJavaProject project,
			LoadFailureHandler failureHandler)
	{
		Map<AnnotationProcessorFactory, FactoryPath.Attributes> java5Factories = 
			new LinkedHashMap<AnnotationProcessorFactory, FactoryPath.Attributes>();
		Map<IServiceFactory, FactoryPath.Attributes> java6Factories =
			new LinkedHashMap<IServiceFactory, FactoryPath.Attributes>();
		
		removeAptBuildProblemMarkers(project);
		Set<FactoryContainer> badContainers = verifyFactoryPath(project);
		if (badContainers != null) {
			for (FactoryContainer badFC : badContainers) {
				failureHandler.addFailedFactory(badFC.getId());
				containers.remove(badFC);
			}
		}
		
		// Need to use the cached classloader if we have one
		ClassLoader iterativeClassLoader = _iterativeLoaders.get(project);
		if (iterativeClassLoader == null) {
			iterativeClassLoader = _createIterativeClassLoader(containers);
			_iterativeLoaders.put(project, iterativeClassLoader);
		}
		
		_createBatchClassLoader(containers, project);
		ClassLoader batchClassLoader = _batchLoaders.get(project);
		
		for ( Map.Entry<FactoryContainer, FactoryPath.Attributes> entry : containers.entrySet() )
		{
			try {
				final FactoryContainer fc = entry.getKey();
				final FactoryPath.Attributes attr = entry.getValue();
				assert !attr.runInBatchMode() || (batchClassLoader != null);
				ClassLoader cl = attr.runInBatchMode() ? batchClassLoader : iterativeClassLoader;
				
				// First the Java 5 factories in this container...
				List<AnnotationProcessorFactory> java5FactoriesInContainer;
				java5FactoriesInContainer = loadJava5FactoryClasses(fc, cl, project, failureHandler);
				for ( AnnotationProcessorFactory apf : java5FactoriesInContainer ) {
					java5Factories.put( apf, entry.getValue() );
				}
				
				if (AptPlugin.canRunJava6Processors()) {
					// Now the Java 6 factories.  Use the same classloader for the sake of sanity.
					List<IServiceFactory> java6FactoriesInContainer;
					java6FactoriesInContainer = loadJava6FactoryClasses(fc, cl, project, failureHandler);
					for ( IServiceFactory isf : java6FactoriesInContainer ) {
						java6Factories.put( isf, entry.getValue() );
					}
				}
			}
			catch (FileNotFoundException fnfe) {
				// it would be bizarre to get this, given that we already checked for file existence up above.
				AptPlugin.log(fnfe, Messages.AnnotationProcessorFactoryLoader_jarNotFound + fnfe.getLocalizedMessage());
			}
			catch (IOException ioe) {
				AptPlugin.log(ioe, Messages.AnnotationProcessorFactoryLoader_ioError + ioe.getLocalizedMessage());
			}
		}
		_project2Java5Factories.put(project, java5Factories);
		_project2Java6Factories.put(project, java6Factories);
	}

	private List<AnnotationProcessorFactory> loadJava5FactoryClasses( 
			FactoryContainer fc, ClassLoader classLoader, IJavaProject jproj, LoadFailureHandler failureHandler )
			throws IOException
	{
		Map<String, String> factoryNames = fc.getFactoryNames();
		List<AnnotationProcessorFactory> factories = new ArrayList<AnnotationProcessorFactory>(); 
		for ( Entry<String, String> entry : factoryNames.entrySet() )
		{
			if (AptPlugin.JAVA5_FACTORY_NAME.equals(entry.getValue())) {
				String factoryName = entry.getKey();
				AnnotationProcessorFactory factory;
				if ( fc.getType() == FactoryType.PLUGIN )
					factory = FactoryPluginManager.getJava5FactoryFromPlugin( factoryName );
				else
					factory = (AnnotationProcessorFactory)loadInstance( factoryName, classLoader, jproj, failureHandler );
				
				if ( factory != null )
					factories.add( factory );
			}
		}
		return factories;
	}
	
	private List<IServiceFactory> loadJava6FactoryClasses( 
			FactoryContainer fc, ClassLoader classLoader, IJavaProject jproj, LoadFailureHandler failureHandler )
			throws IOException
	{
		Map<String, String> factoryNames = fc.getFactoryNames();
		List<IServiceFactory> factories = new ArrayList<IServiceFactory>(); 
		for ( Entry<String, String> entry : factoryNames.entrySet() )
		{
			if (AptPlugin.JAVA6_FACTORY_NAME.equals(entry.getValue())) {
				String factoryName = entry.getKey();
				IServiceFactory factory = null;
				if ( fc.getType() == FactoryType.PLUGIN ) {
					factory = FactoryPluginManager.getJava6FactoryFromPlugin( factoryName );
				}
				else {
					Class<?> clazz;
					try {
						clazz = classLoader.loadClass(factoryName);
						factory = new ClassServiceFactory(clazz);
					} catch (ClassNotFoundException e) {
						AptPlugin.trace("Unable to load annotation processor " + factoryName, e); //$NON-NLS-1$
						failureHandler.addFailedFactory(factoryName);
					} 
				}
				
				if ( factory != null )
					factories.add( factory );
			}
		}
		return factories;
	}
	
	/**
	 * Re-validate projects whose factory paths may have been affected
	 * by a resource change (e.g., adding a previously absent jar file).
	 * This will cause build problem markers to be removed and regenerated,
	 * and factory class caches to be cleared.
	 */
	private void processChanges(Set<IJavaProject> affected, Map<IJavaProject,LoadFailureHandler> handlers) {
		for (IJavaProject jproj : affected) {
			removeAptBuildProblemMarkers(jproj);
			uncacheProject(jproj);
		}
		// We will do another clear and re-verify when loadFactories() 
		// is called.  But we have to do it then, because things might
		// have changed in the interim; and if we don't do it here, then
		// we'll have an empty _resources2Project cache, so we'll ignore
		// all resource changes until the next build.  Is that a problem?
		for (IJavaProject jproj : affected) {
			if (jproj.exists()) {
				Set<FactoryContainer> badContainers = verifyFactoryPath(jproj);
				if (badContainers != null) {
					LoadFailureHandler handler = handlers.get(jproj);
					if (handler == null) {
						handler = new LoadFailureHandler(jproj);
						handlers.put(jproj, handler);
					}
					for (FactoryContainer container : badContainers) {
						handler.addMissingLibrary(container.getId());
					}
				}
			}
		}
	
		// TODO: flag the affected projects for rebuild.
	}

	/**
	 * When a project is deleted, remove its factory path information from the loader.
	 * @param jproj
	 */
    private void uncacheProject(IJavaProject jproj) {
		_project2Java5Factories.remove(jproj);
		_project2Java6Factories.remove(jproj);
		ClassLoader c = _iterativeLoaders.remove(jproj);
		if (c instanceof JarClassLoader)
			((JarClassLoader)c).close();
		
		ClassLoader cl = _batchLoaders.remove(jproj);
		if (cl instanceof JarClassLoader) ((JarClassLoader)cl).close();
		
		removeProjectFromResourceMap(jproj);
	}

	/**
	 * Remove APT build problem markers, e.g., "missing factory jar".
	 * @param jproj if null, remove markers from all projects that have
	 * factory paths associated with them.
	 */
	private void removeAptBuildProblemMarkers( IJavaProject jproj ) {
		// note that _project2Java6Factories.keySet() should be same as that for Java5.
		Set<IJavaProject> jprojects = (jproj == null) ? _project2Java5Factories.keySet() : Collections.singleton(jproj);
		try {
			for (IJavaProject jp : jprojects) {
				if (jp.exists()) {
					IProject p = jp.getProject();
					IMarker[] markers = p.findMarkers(AptPlugin.APT_LOADER_PROBLEM_MARKER, false, IResource.DEPTH_ZERO);
					if( markers != null ){
						for( IMarker marker : markers )
							marker.delete();
					}
				}
			}
		}
		catch(CoreException e){
			AptPlugin.log(e, "Unable to delete APT build problem marker"); //$NON-NLS-1$
		}
	}

	/**
	 * Remove references to the project from _container2Project.  This is done
	 * when a project is deleted, or before re-verifying the project's
	 * factory path.
	 */
	private void removeProjectFromResourceMap(IJavaProject jproj) {
		Iterator<Entry<String, Set<IJavaProject>>> i = _container2Project.entrySet().iterator();
		while (i.hasNext()) {
			Entry<String, Set<IJavaProject>> e = i.next();
			Set<IJavaProject> s = e.getValue();
			s.remove(jproj);
			// Remove any resulting orphaned resources.
			if (s.isEmpty()) {
				i.remove();
			}
		}
	}
	
    /**
     * Check the factory path for a project and ensure that all the
     * containers it lists are available.  Adds jar factory container
     * resources to the _container2Project cache, whether or not the
     * resource can actually be found.
     * 
     * @param jproj the project, or null to check all projects that
     * are in the cache.
     * @return a Set of all invalid containers, or null if all containers
     * on the path were valid.
     */
    private Set<FactoryContainer> verifyFactoryPath(IJavaProject jproj) {
    	Set<FactoryContainer> badContainers = null;
		FactoryPath fp = FactoryPathUtil.getFactoryPath(jproj);
		Map<FactoryContainer, FactoryPath.Attributes> containers = fp.getEnabledContainers();
		for (FactoryContainer fc : containers.keySet()) {
			if (fc instanceof JarFactoryContainer) {
				try {
					final File jarFile = ((JarFactoryContainer)fc).getJarFile();
					// if null, will add to bad container set below.
					if( jarFile != null ){
						String key = jarFile.getCanonicalPath();
						addToResourcesMap(key, jproj);
					}
				} catch (IOException e) {
					// If there's something this malformed on the factory path,
					// don't bother putting it on the resources map; we'll never
					// get notified about a change to it anyway.  It should get
					// reported either as a bad container (below) or as a failure
					// to load (later on).
				}
			}
			if ( !fc.exists() ) {
				if (badContainers == null) {
					badContainers = new HashSet<FactoryContainer>();
				}
				badContainers.add(fc);
			}
		}
		return badContainers;
    }
    
	/**
	 * @param containers an ordered map.
	 */
	private ClassLoader _createIterativeClassLoader( Map<FactoryContainer, FactoryPath.Attributes> containers )
	{
		ArrayList<File> fileList = new ArrayList<File>( containers.size() );
		for (Map.Entry<FactoryContainer, FactoryPath.Attributes> entry : containers.entrySet()) {
			FactoryPath.Attributes attr = entry.getValue();
			FactoryContainer fc = entry.getKey();
			if (!attr.runInBatchMode() && fc instanceof JarFactoryContainer) {
				JarFactoryContainer jfc = (JarFactoryContainer)fc;
				fileList.add( jfc.getJarFile() );
			}
		}
		
		ClassLoader cl;
		if ( fileList.size() > 0 ) {
			cl = createClassLoader( fileList, AnnotationProcessorFactoryLoader.class.getClassLoader() );
		}
		else {
			cl = AnnotationProcessorFactoryLoader.class.getClassLoader();
		}
		return cl;
	}
	
	private void _createBatchClassLoader(Map<FactoryContainer, FactoryPath.Attributes> containers,
			IJavaProject p) 
	{
		
		ArrayList<File> fileList = new ArrayList<File>( containers.size() );
		for (Map.Entry<FactoryContainer, FactoryPath.Attributes> entry : containers.entrySet()) {
			FactoryPath.Attributes attr = entry.getValue();
			FactoryContainer fc = entry.getKey();
			if (attr.runInBatchMode() && fc instanceof JarFactoryContainer) {
				
				JarFactoryContainer jfc = (JarFactoryContainer)fc;
				File f = jfc.getJarFile();
				fileList.add( f );
				
			}
		}
		
		// Try to use the iterative CL as parent, so we can resolve classes within it
		ClassLoader parentCL = _iterativeLoaders.get(p);
		if (parentCL == null) {
			parentCL = AnnotationProcessorFactoryLoader.class.getClassLoader();
		}
		
		if ( fileList.size() > 0 ) {
			_batchLoaders.put(p,createClassLoader( fileList, parentCL));
		}
	}
	
	private static ClassLoader createClassLoader(List<File> files, ClassLoader parentCL) {
		//return new JarClassLoader(files, parentCL);
		List<URL> urls = new ArrayList<URL>(files.size());
		for (int i=0;i<files.size();i++) {
			try {
				urls.add(files.get(i).toURI().toURL());
			}
			catch (MalformedURLException mue) {
				// ignore
			}
		}
		URL[] urlArray = urls.toArray(new URL[urls.size()]);
		return new URLClassLoader(urlArray, parentCL);
	}
}
