1
2
3
4
5
6 package gov.nist.secauto.metaschema.databind.codegen;
7
8 import gov.nist.secauto.metaschema.core.model.IModule;
9 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
10 import gov.nist.secauto.metaschema.databind.IBindingContext;
11 import gov.nist.secauto.metaschema.databind.codegen.config.DefaultBindingConfiguration;
12 import gov.nist.secauto.metaschema.databind.codegen.config.IBindingConfiguration;
13
14 import org.apache.logging.log4j.LogManager;
15 import org.apache.logging.log4j.Logger;
16 import org.eclipse.jdt.annotation.Owning;
17
18 import java.io.IOException;
19 import java.lang.module.ModuleDescriptor;
20 import java.net.MalformedURLException;
21 import java.net.URL;
22 import java.net.URLClassLoader;
23 import java.nio.file.Path;
24 import java.security.AccessController;
25 import java.security.PrivilegedAction;
26 import java.util.Arrays;
27 import java.util.List;
28 import java.util.stream.Collectors;
29
30 import javax.tools.DiagnosticCollector;
31
32 import edu.umd.cs.findbugs.annotations.NonNull;
33
34
35
36
37
38
39
40 public final class ModuleCompilerHelper {
41 private static final Logger LOGGER = LogManager.getLogger(ModuleCompilerHelper.class);
42
43 private ModuleCompilerHelper() {
44
45 }
46
47
48
49
50
51
52
53
54
55
56
57
58 @SuppressWarnings("resource")
59 @Owning
60 @NonNull
61 public static ClassLoader newClassLoader(
62 @NonNull final Path classDir,
63 @NonNull final ClassLoader parent) {
64 return ObjectUtils.notNull(AccessController.doPrivileged(
65 (PrivilegedAction<ClassLoader>) () -> {
66 try {
67 return new URLClassLoader(new URL[] { classDir.toUri().toURL() }, parent);
68 } catch (MalformedURLException ex) {
69 throw new IllegalStateException("unable to configure class loader", ex);
70 }
71 }));
72 }
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 @NonNull
88 public static IProduction compileMetaschema(
89 @NonNull IModule module,
90 @NonNull Path classDir)
91 throws IOException {
92 return compileModule(module, classDir, new DefaultBindingConfiguration());
93 }
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111 @NonNull
112 public static IProduction compileModule(
113 @NonNull IModule module,
114 @NonNull Path classDir,
115 @NonNull IBindingConfiguration bindingConfiguration) throws IOException {
116 IProduction production = JavaGenerator.generate(module, classDir, bindingConfiguration);
117 List<IGeneratedClass> classesToCompile = production.getGeneratedClasses().collect(Collectors.toList());
118
119 List<Path> classes = ObjectUtils.notNull(classesToCompile.stream()
120 .map(IGeneratedClass::getClassFile)
121 .collect(Collectors.toUnmodifiableList()));
122
123 JavaCompilerSupport compiler = new JavaCompilerSupport(classDir);
124
125 boolean usingModule = false;
126 Module databindModule = IBindingContext.class.getModule();
127 if (databindModule != null) {
128 ModuleDescriptor descriptor = databindModule.getDescriptor();
129 if (descriptor != null) {
130
131 compiler.addRootModule(ObjectUtils.notNull(descriptor.name()));
132 usingModule = true;
133 }
134 }
135
136 String classPath = System.getProperty("java.class.path");
137 String modulePath = System.getProperty("jdk.module.path");
138 if (usingModule) {
139
140 if (classPath != null) {
141 Arrays.stream(classPath.split(":")).forEachOrdered(compiler::addToClassPath);
142 }
143
144 if (modulePath != null) {
145 Arrays.stream(modulePath.split(":")).forEachOrdered(compiler::addToModulePath);
146 }
147 } else {
148
149 if (classPath != null) {
150 Arrays.stream(classPath.split(":")).forEachOrdered(compiler::addToClassPath);
151 }
152
153 if (modulePath != null) {
154 Arrays.stream(modulePath.split(":")).forEachOrdered(compiler::addToClassPath);
155 }
156 }
157
158 JavaCompilerSupport.CompilationResult result = compiler.compile(classes, null);
159
160 if (!result.isSuccessful()) {
161 DiagnosticCollector<?> diagnostics = new DiagnosticCollector<>();
162 if (LOGGER.isErrorEnabled()) {
163 LOGGER.error(diagnostics.getDiagnostics().toString());
164 }
165 throw new IllegalStateException(String.format("failed to compile classes: %s%nClasspath: %s%nModule Path: %s%n%s",
166 classesToCompile.stream()
167 .map(clazz -> clazz.getClassName().canonicalName())
168 .collect(Collectors.joining(",")),
169 diagnostics.getDiagnostics().toString(),
170 compiler.getClassPath().stream()
171 .collect(Collectors.joining(":")),
172 compiler.getModulePath().stream()
173 .collect(Collectors.joining(":"))));
174 }
175 return production;
176 }
177 }