/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *     Stephan Herrmann - Contribution for
 *								Bug 440687 - [compiler][batch][null] improve command line option for external annotations
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.batch;

import java.io.File;
import java.io.IOException;
import java.nio.file.InvalidPathException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.zip.ZipFile;

import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.internal.compiler.CompilationResult;
import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
import org.eclipse.jdt.internal.compiler.classfmt.ExternalAnnotationDecorator;
import org.eclipse.jdt.internal.compiler.env.AccessRuleSet;
import org.eclipse.jdt.internal.compiler.env.IModulePathEntry;
import org.eclipse.jdt.internal.compiler.env.IModule;
import org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment;
import org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
import org.eclipse.jdt.internal.compiler.lookup.ModuleBinding;
import org.eclipse.jdt.internal.compiler.parser.Parser;
import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
import org.eclipse.jdt.internal.compiler.env.IUpdatableModule;
import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdateKind;
import org.eclipse.jdt.internal.compiler.env.IUpdatableModule.UpdatesByKind;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.util.JRTUtil;
import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
import org.eclipse.jdt.internal.compiler.util.Util;

public class FileSystem implements IModuleAwareNameEnvironment, SuffixConstants {

	// Keep the type as ArrayList and not List as there are clients that are already written to expect ArrayList.
	public static ArrayList<FileSystem.Classpath> EMPTY_CLASSPATH = new ArrayList<>();

	/**
	 * A <code>Classpath</code>, even though an IModuleLocation, can represent a plain
	 * classpath location too. The FileSystem tells the Classpath whether to behave as a module or regular class
	 * path via {@link Classpath#acceptModule(IModule)}.
	 *
	 * Sub types of classpath are responsible for appropriate behavior based on this.
	 */
	public interface Classpath extends IModulePathEntry {
		char[][][] findTypeNames(String qualifiedPackageName, String moduleName);
		NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName);
		NameEnvironmentAnswer findClass(char[] typeName, String qualifiedPackageName, String moduleName, String qualifiedBinaryFileName, boolean asBinaryOnly);
		boolean isPackage(String qualifiedPackageName, /*@Nullable*/String moduleName);
		default boolean hasModule() { return getModule() != null; }
		default boolean hasCUDeclaringPackage(String qualifiedPackageName, Function<CompilationUnit, String> pkgNameExtractor) {
			return hasCompilationUnit(qualifiedPackageName, null);
		}
		/**
		 * Return a list of the jar file names defined in the Class-Path section
		 * of the jar file manifest if any, null else. Only ClasspathJar (and
		 * extending classes) instances may return a non-null result.
		 * @param  problemReporter problem reporter with which potential
		 *         misconfiguration issues are raised
		 * @return a list of the jar file names defined in the Class-Path
		 *         section of the jar file manifest if any
		 */
		List<Classpath> fetchLinkedJars(ClasspathSectionProblemReporter problemReporter);
		/**
		 * This method resets the environment. The resulting state is equivalent to
		 * a new name environment without creating a new object.
		 */
		void reset();
		/**
		 * Return a normalized path for file based classpath entries. This is an
		 * absolute path in which file separators are transformed to the
		 * platform-agnostic '/', ending with a '/' for directories. This is an
		 * absolute path in which file separators are transformed to the
		 * platform-agnostic '/', deprived from the '.jar' (resp. '.zip')
		 * extension for jar (resp. zip) files.
		 * @return a normalized path for file based classpath entries
		 */
		char[] normalizedPath();
		/**
		 * Return the path for file based classpath entries. This is an absolute path
		 * ending with a file separator for directories, an absolute path including the '.jar'
		 * (resp. '.zip') extension for jar (resp. zip) files.
		 * @return the path for file based classpath entries
		 */
		String getPath();
		/**
		 * Initialize the entry
		 */
		void initialize() throws IOException;
		/**
		 * Can the current location provide an external annotation file for the given type?
		 * @param qualifiedTypeName type name in qualified /-separated notation.
		 */
		boolean hasAnnotationFileFor(String qualifiedTypeName);
		/**
		 * Accepts to represent a module location with the given module description.
		 *
		 * @param module
		 */
		public void acceptModule(IModule module);
		public String getDestinationPath();
		Collection<String> getModuleNames(Collection<String> limitModules);
		Collection<String> getModuleNames(Collection<String> limitModules, Function<String,IModule> getModule);
	}
	public interface ClasspathSectionProblemReporter {
		void invalidClasspathSection(String jarFilePath);
		void multipleClasspathSections(String jarFilePath);
	}

	/**
	 * This class is defined how to normalize the classpath entries.
	 * It removes duplicate entries.
	 */
	public static class ClasspathNormalizer {
		/**
		 * Returns the normalized classpath entries (no duplicate).
		 * <p>The given classpath entries are FileSystem.Classpath. We check the getPath() in order to find
		 * duplicate entries.</p>
		 *
		 * @param classpaths the given classpath entries
		 * @return the normalized classpath entries
		 */
		public static ArrayList<Classpath> normalize(ArrayList<Classpath> classpaths) {
			ArrayList<Classpath> normalizedClasspath = new ArrayList<>();
			HashSet<Classpath> cache = new HashSet<>();
			for (Iterator<Classpath> iterator = classpaths.iterator(); iterator.hasNext(); ) {
				FileSystem.Classpath classpath = iterator.next();
				if (!cache.contains(classpath)) {
					normalizedClasspath.add(classpath);
					cache.add(classpath);
				}
			}
			return normalizedClasspath;
		}
	}
	
	protected Classpath[] classpaths;
	// Used only in single-module mode when the module descriptor is
	// provided via command line.
	protected IModule module;
	Set<String> knownFileNames;
	protected boolean annotationsFromClasspath; // should annotation files be read from the classpath (vs. explicit separate path)?
	private static HashMap<File, Classpath> JRT_CLASSPATH_CACHE = null;
	
	Map<String,Classpath> moduleLocations = new HashMap<>();

	/** Tasks resulting from --add-reads or --add-exports command line options. */
	Map<String,UpdatesByKind> moduleUpdates = new HashMap<>();

/*
	classPathNames is a collection is Strings representing the full path of each class path
	initialFileNames is a collection is Strings, the trailing '.java' will be removed if its not already.
*/
public FileSystem(String[] classpathNames, String[] initialFileNames, String encoding) {
	final int classpathSize = classpathNames.length;
	this.classpaths = new Classpath[classpathSize];
	int counter = 0;
	for (int i = 0; i < classpathSize; i++) {
		Classpath classpath = getClasspath(classpathNames[i], encoding, null, null);
		try {
			classpath.initialize();
			for (String moduleName : classpath.getModuleNames(null))
				this.moduleLocations.put(moduleName, classpath);
			this.classpaths[counter++] = classpath;
		} catch (IOException e) {
			// ignore
		}
	}
	if (counter != classpathSize) {
		System.arraycopy(this.classpaths, 0, (this.classpaths = new Classpath[counter]), 0, counter);
	}
	initializeKnownFileNames(initialFileNames);
}
protected FileSystem(Classpath[] paths, String[] initialFileNames, boolean annotationsFromClasspath, Set<String> limitedModules) {
	final int length = paths.length;
	int counter = 0;
	this.classpaths = new FileSystem.Classpath[length];
	for (int i = 0; i < length; i++) {
		final Classpath classpath = paths[i];
		try {
			classpath.initialize();
			this.classpaths[counter++] = classpath;
		} catch(IOException | InvalidPathException exception) {
			// JRE 9 could throw an IAE if the linked JAR paths have invalid chars, such as ":"
			// ignore
		}
	}
	if (counter != length) {
		// should not happen
		System.arraycopy(this.classpaths, 0, (this.classpaths = new FileSystem.Classpath[counter]), 0, counter);
	}
	initializeModuleLocations(limitedModules);
	initializeKnownFileNames(initialFileNames);
	this.annotationsFromClasspath = annotationsFromClasspath;
}
private void initializeModuleLocations(Set<String> limitedModules) {
	// First create the mapping of all module/Classpath
	// since the second iteration of getModuleNames() can't be relied on for 
	// to get the right origin of module
	if (limitedModules == null) {
		for (Classpath c : this.classpaths) {
			for (String moduleName : c.getModuleNames(null))
				this.moduleLocations.put(moduleName, c);
		}
	} else {
		Map<String, Classpath> moduleMap = new HashMap<>();
		for (Classpath c : this.classpaths) {
			for (String moduleName : c.getModuleNames(null)) {
				moduleMap.put(moduleName, c);
			}
		}
		for (Classpath c : this.classpaths) {
			for (String moduleName : c.getModuleNames(limitedModules, m -> getModuleFromEnvironment(m.toCharArray()))) {
				Classpath classpath = moduleMap.get(moduleName);
				this.moduleLocations.put(moduleName, classpath);
			}
		}
	}
}
protected FileSystem(Classpath[] paths, String[] initialFileNames, boolean annotationsFromClasspath) {
	this(paths, initialFileNames, annotationsFromClasspath, null);
}
public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet) {
	return getClasspath(classpathName, encoding, false, accessRuleSet, null, null);
}
public static Classpath getClasspath(String classpathName, String encoding, AccessRuleSet accessRuleSet, Map<String, String> options) {
	return getClasspath(classpathName, encoding, false, accessRuleSet, null, options);
}
public static Classpath getJrtClasspath(String jdkHome, String encoding, AccessRuleSet accessRuleSet, Map<String, String> options) {
	return new ClasspathJrt(new File(convertPathSeparators(jdkHome)), true, accessRuleSet, null);
}
public static Classpath getOlderSystemRelease(String jdkHome, String release, AccessRuleSet accessRuleSet) {
	return new ClasspathJep247(new File(convertPathSeparators(jdkHome)), release, accessRuleSet);
}
public static Classpath getClasspath(String classpathName, String encoding,
		boolean isSourceOnly, AccessRuleSet accessRuleSet,
		String destinationPath, Map<String, String> options) {
	Classpath result = null;
	File file = new File(convertPathSeparators(classpathName));
	if (file.isDirectory()) {
		if (file.exists()) {
			result = new ClasspathDirectory(file, encoding,
					isSourceOnly ? ClasspathLocation.SOURCE :
						ClasspathLocation.SOURCE | ClasspathLocation.BINARY,
					accessRuleSet,
					destinationPath == null || destinationPath == Main.NONE ?
						destinationPath : // keep == comparison valid
						convertPathSeparators(destinationPath), options);
		}
	} else {
		int format = Util.archiveFormat(classpathName);
		if (format == Util.ZIP_FILE) {
			if (isSourceOnly) {
				// source only mode
				result = new ClasspathSourceJar(file, true, accessRuleSet,
					encoding,
					destinationPath == null || destinationPath == Main.NONE ?
						destinationPath : // keep == comparison valid
						convertPathSeparators(destinationPath));
			} else if (destinationPath == null) {
				// class file only mode
				if (classpathName.endsWith(JRTUtil.JRT_FS_JAR)) {
					if (JRT_CLASSPATH_CACHE == null) {
						JRT_CLASSPATH_CACHE = new HashMap<>();
					} else {
						result = JRT_CLASSPATH_CACHE.get(file);
					}
					if (result == null) {
						result = new ClasspathJrt(file, true, accessRuleSet, null);
						try {
							result.initialize();
						} catch (IOException e) {
							// Broken entry, but let clients have it anyway.
						}
						JRT_CLASSPATH_CACHE.put(file, result);
					}
				} else {
					result = new ClasspathJar(file, true, accessRuleSet, null);
				}
			}
		} else if (format == Util.JMOD_FILE) {
			// TODO Java 9: we need new type of classpath to handle Jmod files in batch compiler.
		}

	}
	return result;
}
private void initializeKnownFileNames(String[] initialFileNames) {
	if (initialFileNames == null) {
		this.knownFileNames = new HashSet<>(0);
		return;
	}
	this.knownFileNames = new HashSet<>(initialFileNames.length * 2);
	for (int i = initialFileNames.length; --i >= 0;) {
		File compilationUnitFile = new File(initialFileNames[i]);
		char[] fileName = null;
		try {
			fileName = compilationUnitFile.getCanonicalPath().toCharArray();
		} catch (IOException e) {
			// this should not happen as the file exists
			continue;
		}
		char[] matchingPathName = null;
		final int lastIndexOf = CharOperation.lastIndexOf('.', fileName);
		if (lastIndexOf != -1) {
			fileName = CharOperation.subarray(fileName, 0, lastIndexOf);
		}
		CharOperation.replace(fileName, '\\', '/');
		boolean globalPathMatches = false;
		// the most nested path should be the selected one
		for (int j = 0, max = this.classpaths.length; j < max; j++) {
			char[] matchCandidate = this.classpaths[j].normalizedPath();
			boolean currentPathMatch = false;
			if (this.classpaths[j] instanceof ClasspathDirectory
					&& CharOperation.prefixEquals(matchCandidate, fileName)) {
				currentPathMatch = true;
				if (matchingPathName == null) {
					matchingPathName = matchCandidate;
				} else {
					if (currentPathMatch) {
						// we have a second source folder that matches the path of the source file
						if (matchCandidate.length > matchingPathName.length) {
							// we want to preserve the shortest possible path
							matchingPathName = matchCandidate;
						}
					} else {
						// we want to preserve the shortest possible path
						if (!globalPathMatches && matchCandidate.length < matchingPathName.length) {
							matchingPathName = matchCandidate;
						}
					}
				}
				if (currentPathMatch) {
					globalPathMatches = true;
				}
			}
		}
		if (matchingPathName == null) {
			this.knownFileNames.add(new String(fileName)); // leave as is...
		} else {
			this.knownFileNames.add(new String(CharOperation.subarray(fileName, matchingPathName.length, fileName.length)));
		}
		matchingPathName = null;
	}
}
/** TESTS ONLY */
public void scanForModules(Parser parser) {
	for (int i = 0, max = this.classpaths.length; i < max; i++) {
		File file = new File(this.classpaths[i].getPath());
		IModule iModule = ModuleFinder.scanForModule(this.classpaths[i], file, parser, false);
		if (iModule != null)
			this.moduleLocations.put(String.valueOf(iModule.name()), this.classpaths[i]);
	}
}
public void cleanup() {
	for (int i = 0, max = this.classpaths.length; i < max; i++)
		this.classpaths[i].reset();
}
private static String convertPathSeparators(String path) {
	return File.separatorChar == '/'
		? path.replace('\\', '/')
		 : path.replace('/', '\\');
}
private NameEnvironmentAnswer findClass(String qualifiedTypeName, char[] typeName, boolean asBinaryOnly, /*NonNull*/char[] moduleName) {
	NameEnvironmentAnswer answer = internalFindClass(qualifiedTypeName, typeName, asBinaryOnly, moduleName);
	if (this.annotationsFromClasspath && answer != null && answer.getBinaryType() instanceof ClassFileReader) {
		for (int i = 0, length = this.classpaths.length; i < length; i++) {
			Classpath classpathEntry = this.classpaths[i];
			if (classpathEntry.hasAnnotationFileFor(qualifiedTypeName)) {
				// in case of 'this.annotationsFromClasspath' we indeed search for .eea entries inside the main zipFile of the entry:
				ZipFile zip = classpathEntry instanceof ClasspathJar ? ((ClasspathJar) classpathEntry).zipFile : null;
				boolean shouldClose = false; // don't close classpathEntry.zipFile, which we don't own
				try {
					if (zip == null) {
						zip = ExternalAnnotationDecorator.getAnnotationZipFile(classpathEntry.getPath(), null);
						shouldClose = true;
					}
					answer.setBinaryType(ExternalAnnotationDecorator.create(answer.getBinaryType(), classpathEntry.getPath(), 
							qualifiedTypeName, zip));
					return answer;
				} catch (IOException e) {
					// ignore broken entry, keep searching
				} finally {
					if (shouldClose && zip != null)
						try {
							zip.close();
						} catch (IOException e) { /* nothing */ }
				}
			}
		}
		// globally configured (annotationsFromClasspath), but no .eea found, decorate in order to answer NO_EEA_FILE:
		answer.setBinaryType(new ExternalAnnotationDecorator(answer.getBinaryType(), null));
	}
	return answer;
}
private NameEnvironmentAnswer internalFindClass(String qualifiedTypeName, char[] typeName, boolean asBinaryOnly, /*NonNull*/char[] moduleName) {
	if (this.knownFileNames.contains(qualifiedTypeName)) return null; // looking for a file which we know was provided at the beginning of the compilation

	String qualifiedBinaryFileName = qualifiedTypeName + SUFFIX_STRING_class;
	String qualifiedPackageName =
		qualifiedTypeName.length() == typeName.length
			? Util.EMPTY_STRING
			: qualifiedBinaryFileName.substring(0, qualifiedTypeName.length() - typeName.length - 1);

	LookupStrategy strategy = LookupStrategy.get(moduleName);
	if (strategy == LookupStrategy.Named) {
		if (this.moduleLocations != null) {
			// searching for a specific named module:
			String moduleNameString = String.valueOf(moduleName);
			Classpath classpath = this.moduleLocations.get(moduleNameString);
			if (classpath != null) {
				return classpath.findClass(typeName, qualifiedPackageName, moduleNameString, qualifiedBinaryFileName);
			}
		}
		return null;
	}
	String qp2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
	NameEnvironmentAnswer suggestedAnswer = null;
	if (qualifiedPackageName == qp2) {
		for (int i = 0, length = this.classpaths.length; i < length; i++) {
			if (!strategy.matches(this.classpaths[i], Classpath::hasModule))
				continue;
			NameEnvironmentAnswer answer = this.classpaths[i].findClass(typeName, qualifiedPackageName, null, qualifiedBinaryFileName, asBinaryOnly);
			if (answer != null) {
				if (!answer.ignoreIfBetter()) {
					if (answer.isBetter(suggestedAnswer))
						return answer;
				} else if (answer.isBetter(suggestedAnswer))
					// remember suggestion and keep looking
					suggestedAnswer = answer;
			}
		}
	} else {
		String qb2 = qualifiedBinaryFileName.replace('/', File.separatorChar);
		for (int i = 0, length = this.classpaths.length; i < length; i++) {
			Classpath p = this.classpaths[i];
			if (!strategy.matches(p, Classpath::hasModule))
				continue;
			NameEnvironmentAnswer answer = !(p instanceof ClasspathDirectory)
				? p.findClass(typeName, qualifiedPackageName, null, qualifiedBinaryFileName, asBinaryOnly)
				: p.findClass(typeName, qp2, null, qb2, asBinaryOnly);
			if (answer != null) {
				if (!answer.ignoreIfBetter()) {
					if (answer.isBetter(suggestedAnswer))
						return answer;
				} else if (answer.isBetter(suggestedAnswer))
					// remember suggestion and keep looking
					suggestedAnswer = answer;
			}
		}
	}
	return suggestedAnswer;
}

public NameEnvironmentAnswer findType(char[][] compoundName, char[] moduleName) {
	if (compoundName != null)
		return findClass(
			new String(CharOperation.concatWith(compoundName, '/')),
			compoundName[compoundName.length - 1],
			false,
			moduleName);
	return null;
}
public char[][][] findTypeNames(char[][] packageName) {
	char[][][] result = null;
	if (packageName != null) {
		String qualifiedPackageName = new String(CharOperation.concatWith(packageName, '/'));
		String qualifiedPackageName2 = File.separatorChar == '/' ? qualifiedPackageName : qualifiedPackageName.replace('/', File.separatorChar);
		if (qualifiedPackageName == qualifiedPackageName2) {
			for (int i = 0, length = this.classpaths.length; i < length; i++) {
				char[][][] answers = this.classpaths[i].findTypeNames(qualifiedPackageName, null);
				if (answers != null) {
					// concat with previous answers
					if (result == null) {
						result = answers;
					} else {
						int resultLength = result.length;
						int answersLength = answers.length;
						System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0, resultLength);
						System.arraycopy(answers, 0, result, resultLength, answersLength);
					}
				}
			}
		} else {
			for (int i = 0, length = this.classpaths.length; i < length; i++) {
				Classpath p = this.classpaths[i];
				char[][][] answers = !(p instanceof ClasspathDirectory) ? p.findTypeNames(qualifiedPackageName, null)
						: p.findTypeNames(qualifiedPackageName2, null);
				if (answers != null) {
					// concat with previous answers
					if (result == null) {
						result = answers;
					} else {
						int resultLength = result.length;
						int answersLength = answers.length;
						System.arraycopy(result, 0, (result = new char[answersLength + resultLength][][]), 0,
								resultLength);
						System.arraycopy(answers, 0, result, resultLength, answersLength);
					}
				}
			}
		}
	}
	return result;
}

public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, char[] moduleName) {
	if (typeName != null)
		return findClass(
			new String(CharOperation.concatWith(packageName, typeName, '/')),
			typeName,
			false,
			moduleName);
	return null;
}

public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] packageName, char[] moduleName) {
	String qualifiedPackageName = new String(CharOperation.concatWith(parentPackageName, packageName, '/'));
	String moduleNameString = String.valueOf(moduleName);

	LookupStrategy strategy = LookupStrategy.get(moduleName);
	if (strategy == LookupStrategy.Named) {
		if (this.moduleLocations != null) {
			// specific search in a given module:
			Classpath classpath = this.moduleLocations.get(moduleNameString);
			if (classpath != null) {
				if (classpath.isPackage(qualifiedPackageName, moduleNameString))
					return new char[][] {moduleName};
			}
		}
		return null;
	}
	// search the entire environment and answer which modules declare that package:
	char[][] allNames = null;
	for (Classpath cp : this.classpaths) {
		if (strategy.matches(cp, Classpath::hasModule)) {
			if (strategy == LookupStrategy.Unnamed) {
				// short-cut
				if (cp.isPackage(qualifiedPackageName, moduleNameString))
					return new char[][] { ModuleBinding.UNNAMED };
			} else {
				char[][] declaringModules = cp.getModulesDeclaringPackage(qualifiedPackageName, null);
				if (declaringModules != null) {
					if (allNames == null)
						allNames = declaringModules;
					else
						allNames = CharOperation.arrayConcat(allNames, declaringModules);
				}
			}
		}
	}
	return allNames;
}
private Parser getParser() {
	Map<String,String> opts = new HashMap<String, String>();
	opts.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_9);
	return new Parser(
			new ProblemReporter(DefaultErrorHandlingPolicies.exitOnFirstError(), new CompilerOptions(opts), new DefaultProblemFactory(Locale.getDefault())),
			false);
}
@Override
public boolean hasCompilationUnit(char[][] qualifiedPackageName, char[] moduleName, boolean checkCUs) {
	String qPackageName = String.valueOf(CharOperation.concatWith(qualifiedPackageName, '/'));
	String moduleNameString = String.valueOf(moduleName);
	LookupStrategy strategy = LookupStrategy.get(moduleName);
	Parser parser = checkCUs ? getParser() : null;
	Function<CompilationUnit, String> pkgNameExtractor = (sourceUnit) -> {
		String pkgName = null;	
		CompilationResult compilationResult = new CompilationResult(sourceUnit, 0, 0, 1);
		char[][] name = parser.parsePackageDeclaration(sourceUnit.getContents(), compilationResult);
		if (name != null) {
			pkgName = CharOperation.toString(name);
		}
		return pkgName;
	};
	switch (strategy) {
		case Named:
			if (this.moduleLocations != null) {
				Classpath location = this.moduleLocations.get(moduleNameString);
				if (location != null)
					return checkCUs ? location.hasCUDeclaringPackage(qPackageName, pkgNameExtractor)
							: location.hasCompilationUnit(qPackageName, moduleNameString);
			}
			return false;
		default:
			for (int i = 0; i < this.classpaths.length; i++) {
				Classpath location = this.classpaths[i];
				if (strategy.matches(location, Classpath::hasModule))
					if (location.hasCompilationUnit(qPackageName, moduleNameString))
						return true;
			}
			return false;
	}
}

@Override
public IModule getModule(char[] name) {
	if (this.module != null && CharOperation.equals(name, this.module.name())) {
		return this.module;
	}
	if (this.moduleLocations.containsKey(new String(name))) {
		for (Classpath classpath : this.classpaths) {
			IModule mod = classpath.getModule(name);
			if (mod != null) {
				return mod;
			}
		}
	}
	return null;
}
public IModule getModuleFromEnvironment(char[] name) {
	if (this.module != null && CharOperation.equals(name, this.module.name())) {
		return this.module;
	}
	for (Classpath classpath : this.classpaths) {
		IModule mod = classpath.getModule(name);
		if (mod != null) {
			return mod;
		}
	}
	return null;
}

@Override
public char[][] getAllAutomaticModules() {
	Set<char[]> set = new HashSet<>();
	for (int i = 0, l = this.classpaths.length; i < l; i++) {
		if (this.classpaths[i].isAutomaticModule()) {
			set.add(this.classpaths[i].getModule().name());
		}
	}
	return set.toArray(new char[set.size()][]);
}

void addModuleUpdate(String moduleName, Consumer<IUpdatableModule> update, UpdateKind kind) {
	UpdatesByKind updates = this.moduleUpdates.get(moduleName);
	if (updates == null) {
		this.moduleUpdates.put(moduleName, updates = new UpdatesByKind());
	}
	updates.getList(kind, true).add(update);
}
@Override
public void applyModuleUpdates(IUpdatableModule compilerModule, IUpdatableModule.UpdateKind kind) {
	char[] name = compilerModule.name();
	if (name != ModuleBinding.UNNAMED) { // can't update the unnamed module
		UpdatesByKind updates = this.moduleUpdates.get(String.valueOf(name));
		if (updates != null) {
			for (Consumer<IUpdatableModule> update : updates.getList(kind, false))
				update.accept(compilerModule);
		}
	}
}
}
