use of org.finos.legend.pure.runtime.java.compiled.compiler.MemoryFileManager in project legend-pure by finos.
the class CompiledSupport method dynamicallyEvaluateValueSpecification.
public static Object dynamicallyEvaluateValueSpecification(final CoreInstance valueSpecification, PureMap lambdaOpenVariablesMap, ExecutionSupport es) {
MemoryFileManager fileManager = ((CompiledExecutionSupport) es).getMemoryFileManager();
ClassLoader globalClassLoader = ((CompiledExecutionSupport) es).getClassLoader();
final CompiledProcessorSupport compiledSupport = new CompiledProcessorSupport(globalClassLoader, ((CompiledExecutionSupport) es).getMetadata(), ((CompiledExecutionSupport) es).getExtraSupportedTypes());
final ProcessorContext processorContext = new ProcessorContext(compiledSupport);
// Don't do anything if the ValueSpecification is already resolved ----------------
if (Instance.instanceOf(valueSpecification, M3Paths.InstanceValue, processorContext.getSupport())) {
ListIterable<? extends CoreInstance> l = valueSpecification.getValueForMetaPropertyToMany(M3Properties.values);
if (l.noneSatisfy(instance -> Instance.instanceOf(instance, M3Paths.ValueSpecification, processorContext.getSupport()) || Instance.instanceOf(instance, M3Paths.LambdaFunction, processorContext.getSupport()))) {
ListIterable<Object> result = l.collect(instance -> instance instanceof ValCoreInstance ? ((ValCoreInstance) instance).getValue() : instance);
return result.size() == 1 ? result.get(0) : result;
}
}
// ---------------------------------------------------------------------------------
processorContext.setInLineAllLambda(true);
String processed = ValueSpecificationProcessor.processValueSpecification(valueSpecification, true, processorContext);
String returnType = TypeProcessor.typeToJavaObjectWithMul(valueSpecification.getValueForMetaPropertyToOne(M3Properties.genericType), valueSpecification.getValueForMetaPropertyToOne(M3Properties.multiplicity), false, compiledSupport);
String name = "DynaClass";
RichIterable<Pair<String, CoreInstance>> values = lambdaOpenVariablesMap.getMap().keyValuesView();
final MutableMap<String, Object> openVars = Maps.mutable.of();
String _class = JavaSourceCodeGenerator.imports + "\npublic class " + name + "{\n" + " public static " + returnType + " doProcess(final MapIterable<String, Object> vars, final MutableMap<String, Object> valMap, final IntObjectMap<CoreInstance> localLambdas, final ExecutionSupport es){\n" + values.collect(new Function<Pair<String, CoreInstance>, String>() {
@Override
public String valueOf(Pair<String, CoreInstance> pair) {
final String name = pair.getOne();
CoreInstance valuesCoreInstance = pair.getTwo();
ListIterable<? extends CoreInstance> values = valuesCoreInstance.getValueForMetaPropertyToMany(M3Properties.values).select(coreInstance -> !Instance.instanceOf(coreInstance, "meta::pure::executionPlan::PlanVarPlaceHolder", compiledSupport) && !Instance.instanceOf(coreInstance, "meta::pure::executionPlan::PlanVariablePlaceHolder", compiledSupport));
String type = null;
openVars.put(name, valuesCoreInstance);
if (values.isEmpty()) {
MutableList<CoreInstance> vars = FastList.newList();
collectVars(valueSpecification, vars, compiledSupport);
CoreInstance found = vars.detect(coreInstance -> coreInstance.getValueForMetaPropertyToOne("name").getName().equals(name));
if (found != null) {
type = TypeProcessor.typeToJavaObjectSingle(found.getValueForMetaPropertyToOne(M3Properties.genericType), false, compiledSupport);
return " final " + type + " _" + name + " = null;";
}
return "";
} else {
type = TypeProcessor.pureRawTypeToJava(compiledSupport.getClassifier(values.getFirst()), false, compiledSupport);
final String listImpl = JavaPackageAndImportBuilder.buildImplClassReferenceFromUserPath(M3Paths.List);
return (values.size() == 1) ? (" final " + type + " _" + name + " = (" + type + ")((" + listImpl + ")vars.get(\"" + name + "\"))._values.getFirst();") : (" final RichIterable<" + type + "> _" + name + " = ((" + listImpl + ")vars.get(\"" + name + "\"))._values;");
}
}
}).makeString("\n") + " return " + processed + ";\n" + " }\n" + "}\n";
String javaPackage = JavaPackageAndImportBuilder.buildPackageForPackageableElement(valueSpecification);
ListIterable<StringJavaSource> javaClasses = Lists.immutable.with(StringJavaSource.newStringJavaSource(javaPackage, name, _class));
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
MemoryFileManager manager = new MemoryFileManager(compiler, fileManager, null);
try {
PureJavaCompiler.compile(compiler, javaClasses, manager);
} catch (Exception e) {
StringBuilder message = new StringBuilder("Error dynamically evaluating value specification");
SourceInformation valueSpecSourceInfo = valueSpecification.getSourceInformation();
if (valueSpecSourceInfo != null) {
valueSpecSourceInfo.appendMessage(message.append(" (from ")).append(')');
}
message.append("; error compiling generated Java code:\n").append(_class);
throw new RuntimeException(message.toString(), e);
}
ClassLoader cl = new MemoryClassLoader(manager, globalClassLoader);
try {
Class<?> realClass = cl.loadClass(javaPackage + "." + name);
return realClass.getMethod("doProcess", MapIterable.class, MutableMap.class, IntObjectMap.class, ExecutionSupport.class).invoke(null, openVars, processorContext.getObjectToPassToDynamicallyGeneratedCode(), processorContext.getLocalLambdas(), es);
} catch (Exception e) {
StringBuilder message = new StringBuilder("Error dynamically evaluating value specification");
SourceInformation valueSpecSourceInfo = valueSpecification.getSourceInformation();
if (valueSpecSourceInfo != null) {
valueSpecSourceInfo.appendMessage(message.append(" (from ")).append(')');
}
String errorMessage = e.getMessage();
if (errorMessage != null) {
message.append(": ").append(errorMessage);
}
throw new RuntimeException(message.toString(), e);
}
}
use of org.finos.legend.pure.runtime.java.compiled.compiler.MemoryFileManager in project legend-pure by finos.
the class CompiledSupport method dynamicallyBuildLambdaFunction.
public static Object dynamicallyBuildLambdaFunction(CoreInstance lambdaFunction, ExecutionSupport es) {
ClassLoader globalClassLoader = ((CompiledExecutionSupport) es).getClassLoader();
CompiledProcessorSupport compiledSupport = new CompiledProcessorSupport(globalClassLoader, ((CompiledExecutionSupport) es).getMetadata(), ((CompiledExecutionSupport) es).getExtraSupportedTypes());
ProcessorContext processorContext = new ProcessorContext(compiledSupport);
processorContext.setInLineAllLambda(true);
String name = "DynamicLambdaGeneration";
String _class = JavaSourceCodeGenerator.imports + "\nimport " + JavaPackageAndImportBuilder.rootPackage() + ".*;\npublic class " + name + "{" + " public static PureCompiledLambda build(final MutableMap<String, Object> valMap, final IntObjectMap<CoreInstance> localLambdas){\n" + "return " + ValueSpecificationProcessor.processLambda(null, lambdaFunction, compiledSupport, processorContext) + ";" + "}" + "}";
MemoryFileManager fileManager = ((CompiledExecutionSupport) es).getMemoryFileManager();
MutableList<StringJavaSource> javaClasses = FastList.newList();
javaClasses.add(StringJavaSource.newStringJavaSource("temp", name, _class));
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
MemoryFileManager manager = new MemoryFileManager(compiler, fileManager, null);
try {
PureJavaCompiler.compile(compiler, javaClasses, manager);
} catch (PureJavaCompileException e) {
throw new RuntimeException(e);
}
ClassLoader cl = new MemoryClassLoader(manager, globalClassLoader);
try {
Class<?> realClass = cl.loadClass("temp" + "." + name);
return realClass.getMethod("build", MutableMap.class, IntObjectMap.class).invoke(null, processorContext.getObjectToPassToDynamicallyGeneratedCode(), processorContext.getLocalLambdas());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
use of org.finos.legend.pure.runtime.java.compiled.compiler.MemoryFileManager in project legend-sdlc by finos.
the class TestServiceExecutionClassGenerator method compileGeneratedJavaClass.
private Class<?> compileGeneratedJavaClass(ServiceExecutionClassGenerator.GeneratedJavaClass generatedJavaClass) throws ClassNotFoundException {
// System.out.format("%s%n-------------------------%n%s%n", generatedJavaClass.getName(), generatedJavaClass.getCode());
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>();
MemoryFileManager fileManager = new MemoryFileManager(compiler);
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnosticCollector, Arrays.asList("-classpath", CLASSPATH), null, Collections.singletonList(new GeneratedJavaFileObject(generatedJavaClass)));
if (!task.call()) {
Assert.fail(diagnosticCollector.getDiagnostics().toString());
}
return new MemoryClassLoader(fileManager, Thread.currentThread().getContextClassLoader()).loadClass(generatedJavaClass.getName());
}
use of org.finos.legend.pure.runtime.java.compiled.compiler.MemoryFileManager in project legend-sdlc by finos.
the class TestServiceExecutionGenerator method generateAndCompile.
private ClassLoader generateAndCompile(String packagePrefix, Collection<? extends Service> services) throws IOException {
// Generate
for (Service service : services) {
ServiceExecutionGenerator.newGenerator(service, PURE_MODEL, packagePrefix, this.generatedSourcesDirectory, this.classesDirectory, null, core_relational_relational_router_router_extension.Root_meta_pure_router_extension_defaultRelationalExtensions__RouterExtension_MANY_(PURE_MODEL.getExecutionSupport()), LegendPlanTransformers.transformers, "vX_X_X").generate();
}
// Check generated files
String separator = this.tmpFolder.getRoot().toPath().getFileSystem().getSeparator();
// Check execution plan resources generated
Set<String> expectedResources = services.stream().map(s -> "plans" + separator + getPackagePrefix(packagePrefix, separator) + s.getPath().replace("::", separator) + ".json").collect(Collectors.toSet());
expectedResources.add("META-INF" + separator + "services" + separator + ServiceRunner.class.getCanonicalName());
Set<String> actualResources = Files.walk(this.classesDirectory, Integer.MAX_VALUE).filter(Files::isRegularFile).map(this.classesDirectory::relativize).map(Path::toString).collect(Collectors.toSet());
Assert.assertEquals(expectedResources, actualResources);
// Check class files generated
Set<String> expectedServiceJavaSources = services.stream().map(s -> getPackagePrefix(packagePrefix, separator) + s.getPath().replace("::", separator) + ".java").collect(Collectors.toSet());
Set<String> actualJavaSources = Files.walk(this.generatedSourcesDirectory, Integer.MAX_VALUE).map(this.generatedSourcesDirectory::relativize).map(Path::toString).filter(s -> s.endsWith(".java")).collect(Collectors.toSet());
if (!actualJavaSources.containsAll(expectedServiceJavaSources)) {
Assert.fail(expectedServiceJavaSources.stream().filter(c -> !actualJavaSources.contains(c)).sorted().collect(Collectors.joining(", ", "Missing Java sources: ", "")));
}
// Compile
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<>();
MemoryFileManager fileManager = new MemoryFileManager(compiler);
List<SourceFile> javaSources = Files.walk(this.generatedSourcesDirectory, Integer.MAX_VALUE).filter(p -> p.getFileName().toString().endsWith(".java")).map(SourceFile::new).collect(Collectors.toList());
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnosticCollector, Arrays.asList("-classpath", CLASSPATH), null, javaSources);
if (!task.call()) {
Assert.fail(diagnosticCollector.getDiagnostics().toString());
}
fileManager.writeClassJavaSources(this.classesDirectory, false);
// Create new classloader and check that everything expected is present
ClassLoader classLoader = new URLClassLoader(new URL[] { this.classesDirectory.toUri().toURL() }, Thread.currentThread().getContextClassLoader());
// Check plan resources
List<String> missingPlanResources = services.stream().map(s -> "plans/" + getPackagePrefix(packagePrefix, "/") + s.getPath().replace("::", "/") + ".json").filter(n -> classLoader.getResource(n) == null).sorted().collect(Collectors.toList());
Assert.assertEquals(Collections.emptyList(), missingPlanResources);
// Check service execution classes
List<String> missingServiceExecutionClasses = services.stream().map(s -> getPackagePrefix(packagePrefix, ".") + s.getPath().replace("::", ".")).filter(n -> {
try {
classLoader.loadClass(n);
return false;
} catch (ClassNotFoundException e) {
return true;
}
}).sorted().collect(Collectors.toList());
Assert.assertEquals(Collections.emptyList(), missingServiceExecutionClasses);
// Check ServiceRunner provider configuration file
InputStream serviceRunnerResourceStream = classLoader.getResourceAsStream("META-INF" + separator + "services" + separator + ServiceRunner.class.getCanonicalName());
Assert.assertNotNull("ServiceRunner provider configuration file missing", serviceRunnerResourceStream);
List<String> serviceRunnerProviders = new BufferedReader(new InputStreamReader(serviceRunnerResourceStream)).lines().collect(Collectors.toList());
List<String> missingServiceProviders = services.stream().map(PackageableElement::getPath).filter(path -> !serviceRunnerProviders.contains(getPackagePrefix(packagePrefix, ".") + path.replace("::", "."))).sorted().collect(Collectors.toList());
Assert.assertEquals(Collections.emptyList(), missingServiceProviders);
return classLoader;
}
Aggregations