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
124 JavaCompilerSupport compiler = new JavaCompilerSupport(classDir);
125 compiler.setLogger(new JavaCompilerSupport.Logger() {
126
127 @Override
128 public boolean isInfoEnabled() {
129 return LOGGER.isInfoEnabled();
130 }
131
132 @Override
133 public boolean isDebugEnabled() {
134 return LOGGER.isDebugEnabled();
135 }
136
137 @Override
138 public void info(String msg) {
139 LOGGER.atInfo().log(msg);
140 }
141
142 @Override
143 public void debug(String msg) {
144 LOGGER.atDebug().log(msg);
145 }
146 });
147
148
149 boolean useModulePath = false;
150 Module databindModule = IBindingContext.class.getModule();
151 if (databindModule != null) {
152 ModuleDescriptor descriptor = databindModule.getDescriptor();
153 if (descriptor != null) {
154
155 compiler.addRootModule(ObjectUtils.notNull(descriptor.name()));
156 useModulePath = true;
157 }
158 }
159
160 handleClassAndModulePath(compiler, useModulePath);
161
162
163 JavaCompilerSupport.CompilationResult result = compiler.compile(classes);
164
165 if (!result.isSuccessful()) {
166
167 DiagnosticCollector<?> diagnostics = new DiagnosticCollector<>();
168 if (LOGGER.isErrorEnabled()) {
169 LOGGER.error(diagnostics.getDiagnostics().toString());
170 }
171 throw new IllegalStateException(String.format("failed to compile classes: %s%nClasspath: %s%nModule Path: %s%n%s",
172 classesToCompile.stream()
173 .map(clazz -> clazz.getClassName().canonicalName())
174 .collect(Collectors.joining(",")),
175 diagnostics.getDiagnostics().toString(),
176 compiler.getClassPath().stream()
177 .collect(Collectors.joining(":")),
178 compiler.getModulePath().stream()
179 .collect(Collectors.joining(":"))));
180 }
181 return production;
182 }
183
184 private static void handleClassAndModulePath(JavaCompilerSupport compiler, boolean useModulePath) {
185 String classPath = System.getProperty("java.class.path");
186 String modulePath = System.getProperty("jdk.module.path");
187 if (useModulePath) {
188
189 if (classPath != null) {
190 Arrays.stream(classPath.split(":")).forEachOrdered(compiler::addToClassPath);
191 }
192
193 if (modulePath != null) {
194 Arrays.stream(modulePath.split(":")).forEachOrdered(compiler::addToModulePath);
195 }
196 } else {
197
198 if (classPath != null) {
199 Arrays.stream(classPath.split(":")).forEachOrdered(compiler::addToClassPath);
200 }
201
202 if (modulePath != null) {
203 Arrays.stream(modulePath.split(":")).forEachOrdered(compiler::addToClassPath);
204 }
205 }
206
207 }
208 }