public static IFile configureModuleSource(IJavaProject javaProject, File projectDir,
			GhidraApplicationLayout ghidraLayout, Set<ModuleTemplateType> moduleTemplateTypes,
			IProgressMonitor monitor) throws CoreException, IOException {

		final String SKELETON_PKG = "skeleton";
		final String SKELETON_CLASS = "Skeleton";

		IProject project = javaProject.getProject();

		// Create a list of files to exclude.  Use the provided templates list to know what
		// source files should be included in the project.
		List<String> excludeRegexes = new ArrayList<>();
		for (ModuleTemplateType moduleTemplateType : ModuleTemplateType.values()) {
			if (!moduleTemplateTypes.contains(moduleTemplateType)) {
				if (moduleTemplateType.equals(ModuleTemplateType.PROCESSOR)) {
					excludeRegexes.add("languages");
					excludeRegexes.add("buildLanguage\\.xml");
					excludeRegexes.add("sleighArgs\\.txt");
				}
				else {
					excludeRegexes.add(SKELETON_CLASS + moduleTemplateType.getName() + "\\.java");
				}
			}
		}

		// Copy the skeleton files
		File ghidraInstallDir = ghidraLayout.getApplicationInstallationDir().getFile(false);
		File skeletonDir = Files.find(ghidraInstallDir.toPath(), 4, (path, attrs) -> {
			return attrs.isDirectory() && path.getFileName().toString().equals("Skeleton");
		}).map(p -> p.toFile()).findFirst().orElse(null);
		if (skeletonDir == null) {
			throw new IOException("Failed to find skeleton directory.");
		}
		try {
			FileUtilities.copyDir(skeletonDir, projectDir, f -> {
				return excludeRegexes.stream().map(r -> Pattern.compile(r)).noneMatch(
					p -> p.matcher(f.getName()).matches());
			}, null);
			File buildTemplateGradleFile = new File(projectDir, "buildTemplate.gradle");
			File buildGradleFile = new File(projectDir, "build.gradle");
			if (!buildTemplateGradleFile.renameTo(buildGradleFile)) {
				throw new IOException("Failed to rename: " + buildTemplateGradleFile);
			}
		}
		catch (CancelledException | IOException e) {
			throw new IOException("Failed to copy skeleton directory: " + projectDir);
		}

		// Refresh project so it sees the new files
		project.refreshLocal(IResource.DEPTH_INFINITE, monitor);

		// Update language ant properties file
		GhidraModuleUtils.writeAntProperties(project, ghidraLayout);

		// Create a README
		try (PrintWriter out = new PrintWriter(new File(projectDir, "README.md"))) {
			out.println("# " + project.getName());
		}

		// Refactor/rename the source files, package, and help files
		String packageName = project.getName().toLowerCase();
		for (ModuleTemplateType moduleTemplateType : moduleTemplateTypes) {
			IType skeletonClass = javaProject.findType(
				SKELETON_PKG + "." + SKELETON_CLASS + moduleTemplateType.getName(), monitor);
			if (skeletonClass != null) {
				renameJavaElement(skeletonClass.getCompilationUnit(),
					project.getName() + moduleTemplateType.getName(), monitor);
			}
		}
		IJavaElement skeletonPackage = javaProject.findElement(new Path(SKELETON_PKG));
		if (skeletonPackage != null) {
			renameJavaElement(skeletonPackage, packageName, monitor);
		}
		IJavaElement helpTopic = javaProject.findElement(new Path("help/topics/skeleton"));
		if (helpTopic != null) {
			renameJavaElement(helpTopic, "help.topics." + packageName, monitor);
		}

		// Return the primary source file in the project (the first java file we see in the package)
		IFolder packageFolder = project.getFolder("/src/main/java").getFolder(packageName);
		if (packageFolder.exists()) {
			for (IResource resource : packageFolder.members()) {
				if (resource instanceof IFile && resource.getName().endsWith(".java")) {
					return (IFile) resource;
				}
			}
		}
		return null;
	}
Manually add in the source from the Skeleton (which should exist in the Ghidra installation 
directory), and then look at what's in the templates set to know what to keep and what to 
discard.

@param javaProject The project whose source is to be configured.
@param projectDir The project's directory.
@param ghidraLayout The Ghidra layout the project is linked to.
@param moduleTemplateTypes The templates to include in the source.
@param monitor The progress monitor to use during source configuration.
@return The primary module source file (which could be opened in an editor by default). 
@throws IOException If there was a file-related problem with configuring the source.
@throws CoreException If there was an Eclipse-related problem with configuring the source.
GhidraBuild/EclipsePlugins/GhidraDev/GhidraDevPlugin/src/main/java/ghidradev/ghidraprojectcreator/utils/GhidraModuleUtils.java