package org.ecgine.gradle;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.ecgine.gradle.extensions.EcgineExtension;
import org.gradle.api.GradleException;
import org.gradle.api.Project;
import org.gradle.api.logging.Logger;
import org.json.JSONArray;
import org.json.JSONObject;
public class EcgineUtils {
public static Map<String, JSONObject> readJarDependencies(Project project) {
File ecgine = getDependenciesFile(project);
if (!ecgine.exists()) {
project.getLogger().debug(".ecgine not found:" + ecgine.getAbsolutePath());
return new HashMap<>();
}
try {
String string = new String(Files.readAllBytes(ecgine.toPath()));
JSONObject json = new JSONObject(string);
Map<String, JSONObject> all = new HashMap<>();
json.keySet().forEach(k -> {
all.put(k, json.getJSONObject(k));
});
return all;
} catch (Exception e) {
throw new GradleException("Unable to read .ecgine file", e);
}
}
private static File getDependenciesFile(Project project) {
EcgineExtension ext = (EcgineExtension) project.getExtensions().getByName(EcgineExtension.NAME);
File plugins = new File(ext.getPlugins());
if (!plugins.exists()) {
plugins.mkdirs();
}
File ecgine = new File(plugins, ".ecgine");
return ecgine;
}
public static void updateJarDependencies(Logger logger, Project project, Map<String, JSONObject> existing) {
File ecgine = getDependenciesFile(project);
JSONObject json = new JSONObject();
existing.forEach(json::put);
try (FileWriter fw = new FileWriter(ecgine)) {
fw.write(json.toString());
} catch (Exception e) {
throw new GradleException("Unable to write file " + ecgine.getName(), e);
}
}
public static void writeProperties(Logger logger, File file, Map<String, String> properties) {
try (FileWriter fw = new FileWriter(file)) {
properties.forEach((n, v) -> {
try {
fw.write(n + "=" + v + "\n");
} catch (Exception e) {
throw new RuntimeException(e);
}
});
} catch (Exception e) {
throw new GradleException("Unable to write file " + file.getName(), e);
}
}
public static Set<String> combineAllJars(Logger logger, Map<String, String> jarDepends,
Map<String, String> dependencies) {
Set<String> jars = new HashSet<>();
dependencies.forEach((n, v) -> {
// add self
jars.add(n + "_" + v);
// Get it's dependencies
String dep = jarDepends.get(n + "_" + v);
if (dep == null) {
return;
}
String[] split = dep.split(",");
for (String jar : split) {
if (jar.trim().isEmpty()) {
continue;
}
jars.add(jar.trim());
}
});
return jars;
}
public static boolean copy(File source, File dest) {
if (!source.exists()) {
return false;
}
try {
Files.copy(source.toPath(), new FileOutputStream(dest));
} catch (IOException e) {
return false;
}
return true;
}
public static EManifest readManifest(Project p) {
File file = new File(p.getProjectDir(), "META-INF/MANIFEST.MF");
if (file.exists()) {
return new EManifest(p, file);
}
return null;
}
public static Set<EManifest> getAllProjects(Project project, Predicate<EManifest> test) {
return project.getAllprojects().stream().map(EcgineUtils::readManifest).filter(Objects::nonNull).filter(test)
.collect(Collectors.toSet());
}
public static Set<Bundle> getBundles(Set<EManifest> allProjects, Project project) {
Map<BundleType, Set<EManifest>> collect = allProjects.stream()
.collect(Collectors.groupingBy(m -> m.getEcgineBundleType(), Collectors.toSet()));
Set<EManifest> server = collect.get("server");
Set<EManifest> shared = collect.get("shared");
Set<EManifest> client = collect.get("client");
Predicate<String> skip = s -> allProjects.stream().anyMatch(m -> m.getSymbolicName().equals(s));
Map<String, String> serverDepends = getDependencies(server, skip, project);
Map<String, String> sharedDepends = getDependencies(shared, skip, project);
Map<String, String> clientDepends = getDependencies(client, skip, project);
sharedDepends.forEach((k, v) -> clientDepends.remove(k));
sharedDepends.forEach((k, v) -> serverDepends.remove(k));
serverDepends.forEach((k, v) -> clientDepends.remove(k));
clientDepends.forEach((k, v) -> serverDepends.remove(k));
Set<Bundle> result = new HashSet<>();
// Now we have unique bundles
serverDepends.forEach((k, v) -> result.add(new Bundle(k, v, BundleType.SERVER)));
sharedDepends.forEach((k, v) -> result.add(new Bundle(k, v, BundleType.SHARED)));
clientDepends.forEach((k, v) -> result.add(new Bundle(k, v, BundleType.CLIENT)));
return result;
}
public static Map<String, String> getDependencies(Set<EManifest> devBundles, Predicate<String> skip,
Project project) {
Map<String, String> result = new HashMap<>();
Map<String, JSONObject> dependencies = readJarDependencies(project);
if (devBundles == null) {
devBundles = new HashSet<>();
}
devBundles.forEach(m -> m.foreachRequiredBundle((n, v) -> addDependencies(n, v, skip, result, dependencies)));
return result;
}
private static void addDependencies(String n, String v, Predicate<String> skip, Map<String, String> result,
Map<String, JSONObject> dependencies) {
if (skip.test(n)) {
return;
}
JSONObject json = dependencies.get(n);
if (json == null) {
return;
}
if (!json.has("version")) {
return;
}
String version = json.getString("specifiedVersion");
if (v != null && !version.equals(v)) {
return;
}
JSONArray array = json.getJSONArray("dependents");
array.forEach(a -> {
addDependencies(a.toString(), null, skip, result, dependencies);
});
}
}