1
2
3
4
5
6 package gov.nist.secauto.metaschema.maven.plugin;
7
8 import gov.nist.secauto.metaschema.core.model.IModule;
9 import gov.nist.secauto.metaschema.core.model.MetaschemaException;
10 import gov.nist.secauto.metaschema.core.util.ObjectUtils;
11 import gov.nist.secauto.metaschema.databind.codegen.JavaGenerator;
12 import gov.nist.secauto.metaschema.databind.codegen.config.DefaultBindingConfiguration;
13 import gov.nist.secauto.metaschema.databind.model.metaschema.BindingModuleLoader;
14 import gov.nist.secauto.metaschema.databind.model.metaschema.IBindingMetaschemaModule;
15
16 import org.apache.maven.plugin.MojoExecutionException;
17 import org.apache.maven.plugins.annotations.LifecyclePhase;
18 import org.apache.maven.plugins.annotations.Mojo;
19 import org.apache.maven.plugins.annotations.Parameter;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.OutputStream;
24 import java.nio.file.Files;
25 import java.nio.file.StandardOpenOption;
26 import java.util.Arrays;
27 import java.util.Collections;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Set;
31 import java.util.stream.Collectors;
32
33 import edu.umd.cs.findbugs.annotations.NonNull;
34
35
36
37
38 @Mojo(name = "generate-sources", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
39 public class GenerateSourcesMojo
40 extends AbstractMetaschemaMojo {
41 private static final String STALE_FILE_NAME = "generateSourcesStaleFile";
42
43
44
45
46 @Parameter
47 protected File[] configs;
48
49
50
51
52
53
54
55
56
57
58
59 @Override
60 protected String getStaleFileName() {
61 return STALE_FILE_NAME;
62 }
63
64
65
66
67
68
69 protected List<File> getConfigs() {
70 List<File> retval;
71 if (configs == null) {
72 retval = Collections.emptyList();
73 } else {
74 retval = Arrays.asList(configs);
75 }
76 return retval;
77 }
78
79
80
81
82
83
84
85
86
87 protected void generate(@NonNull Set<IModule> modules) throws MojoExecutionException {
88 DefaultBindingConfiguration bindingConfiguration = new DefaultBindingConfiguration();
89 for (File config : getConfigs()) {
90 try {
91 if (getLog().isInfoEnabled()) {
92 getLog().info("Loading binding configuration: " + config.getPath());
93 }
94 bindingConfiguration.load(config);
95 } catch (IOException ex) {
96 throw new MojoExecutionException(
97 String.format("Unable to load binding configuration from '%s'.", config.getPath()), ex);
98 }
99 }
100
101 try {
102 if (getLog().isInfoEnabled()) {
103 getLog().info("Generating Java classes in: " + getOutputDirectory().getPath());
104 }
105 JavaGenerator.generate(modules, ObjectUtils.notNull(getOutputDirectory().toPath()),
106 bindingConfiguration);
107 } catch (IOException ex) {
108 throw new MojoExecutionException("Creation of Java classes failed.", ex);
109 }
110 }
111
112 @Override
113 public void execute() throws MojoExecutionException {
114 File staleFile = getStaleFile();
115 try {
116 staleFile = staleFile.getCanonicalFile();
117 } catch (IOException ex) {
118 if (getLog().isWarnEnabled()) {
119 getLog().warn("Unable to resolve canonical path to stale file. Treating it as not existing.", ex);
120 }
121 }
122
123 boolean generate;
124 if (shouldExecutionBeSkipped()) {
125 if (getLog().isDebugEnabled()) {
126 getLog().debug(String.format("Source file generation is configured to be skipped. Skipping."));
127 }
128 generate = false;
129 } else if (!staleFile.exists()) {
130 if (getLog().isInfoEnabled()) {
131 getLog().info(String.format("Stale file '%s' doesn't exist! Generating source files.", staleFile.getPath()));
132 }
133 generate = true;
134 } else {
135 generate = isGenerationRequired();
136 }
137
138 if (generate) {
139
140 File outputDir = getOutputDirectory();
141 if (getLog().isDebugEnabled()) {
142 getLog().debug(String.format("Using outputDirectory: %s", outputDir.getPath()));
143 }
144
145 if (!outputDir.exists() && !outputDir.mkdirs()) {
146 throw new MojoExecutionException("Unable to create output directory: " + outputDir);
147 }
148
149 BindingModuleLoader loader = newModuleLoader();
150
151
152 final Set<IModule> modules = new HashSet<>();
153 for (File source : getModuleSources().collect(Collectors.toList())) {
154 assert source != null;
155 if (getLog().isInfoEnabled()) {
156 getLog().info("Using metaschema source: " + source.getPath());
157 }
158 IBindingMetaschemaModule module;
159 try {
160 module = loader.load(source);
161 } catch (MetaschemaException | IOException ex) {
162 throw new MojoExecutionException("Loading of metaschema failed", ex);
163 }
164 modules.add(module);
165 }
166
167 generate(modules);
168
169
170 if (!staleFileDirectory.exists() && !staleFileDirectory.mkdirs()) {
171 throw new MojoExecutionException("Unable to create output directory: " + staleFileDirectory);
172 }
173 try (OutputStream os
174 = Files.newOutputStream(staleFile.toPath(), StandardOpenOption.CREATE, StandardOpenOption.WRITE,
175 StandardOpenOption.TRUNCATE_EXISTING)) {
176 os.close();
177 if (getLog().isInfoEnabled()) {
178 getLog().info("Created stale file: " + staleFile);
179 }
180 } catch (IOException ex) {
181 throw new MojoExecutionException("Failed to write stale file: " + staleFile.getPath(), ex);
182 }
183
184
185 getBuildContext().refresh(getOutputDirectory());
186 }
187
188
189 try {
190 getMavenProject().addCompileSourceRoot(getOutputDirectory().getCanonicalFile().getPath());
191 } catch (IOException ex) {
192 throw new MojoExecutionException("Unable to add output directory to maven sources.", ex);
193 }
194 }
195 }