1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.spf4j.maven.plugin.avro.avscp;
17
18 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
19 import java.io.BufferedInputStream;
20 import java.io.BufferedReader;
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.UncheckedIOException;
24 import java.nio.charset.StandardCharsets;
25 import java.nio.file.Files;
26 import java.nio.file.NoSuchFileException;
27 import java.nio.file.Path;
28 import java.util.Collections;
29 import java.util.Map;
30 import java.util.Properties;
31 import org.apache.avro.Schema;
32 import org.apache.avro.SchemaRefWriter;
33 import org.apache.avro.SchemaResolver;
34 import org.apache.avro.SchemaResolvers;
35 import org.apache.maven.execution.MavenSession;
36 import org.apache.maven.plugin.AbstractMojo;
37 import org.apache.maven.plugin.MojoExecutionException;
38 import org.apache.maven.plugin.MojoFailureException;
39 import org.apache.maven.plugins.annotations.Component;
40 import org.apache.maven.plugins.annotations.Parameter;
41 import org.apache.maven.project.MavenProject;
42 import org.eclipse.aether.RepositorySystem;
43 import org.spf4j.avro.SchemaRef;
44 import org.spf4j.maven.MavenSchemaResolver;
45 import static org.spf4j.maven.plugin.avro.avscp.SchemaCompileMojo.SCHEMA_INDEX_FILENAME;
46
47
48
49
50 @SuppressWarnings("checkstyle:VisibilityModifier")
51 @SuppressFBWarnings("AI_ANNOTATION_ISSUES_NEEDS_NULLABLE")
52 abstract class SchemaMojoBase extends AbstractMojo {
53
54
55 @Parameter(defaultValue = "${project}", required = true, readonly = true)
56 protected MavenProject mavenProject;
57
58
59
60
61
62 @Parameter(name = "dependenciesDirectory",
63 defaultValue = "${project.build.directory}/schema-dependencies", readonly = true)
64 protected File dependenciesDirectory;
65
66
67
68
69
70 @Parameter(name = "sourceDirectory", defaultValue = "${basedir}/src/main/avro")
71 protected File sourceDirectory;
72
73
74
75
76
77 @Parameter(name = "generatedJavaTarget",
78 defaultValue = "${project.build.directory}/generated-sources/avro")
79 protected File generatedJavaTarget;
80
81
82
83
84
85 @Parameter(name = "generatedAvscTarget",
86 defaultValue = "${project.build.directory}/generated-sources/avsc")
87 protected File generatedAvscTarget;
88
89
90
91
92
93 @Parameter(name = "target", defaultValue = "${project.build.directory}")
94 protected File target;
95
96
97
98
99 @Parameter(defaultValue = "${session}", required = true, readonly = true)
100 protected MavenSession mavenSession;
101
102
103
104
105
106
107 @Parameter(name = "useSchemaReferencesForAvsc",
108 defaultValue = "false")
109 protected boolean useSchemaReferencesForAvsc = false;
110
111
112
113
114 @Parameter(name = "schemaArtifactClassifier", defaultValue = "avsc")
115 protected String schemaArtifactClassifier = "avsc";
116
117
118
119
120 @Parameter(name = "schemaArtifactExtension", defaultValue = "jar")
121 protected String schemaArtifactExtension = "jar";
122
123
124
125
126
127 @Component
128 protected RepositorySystem repoSystem;
129
130 public final RepositorySystem getRepoSystem() {
131 return repoSystem;
132 }
133
134 public final MavenSession getMavenSession() {
135 return mavenSession;
136 }
137
138 public final MavenProject getMavenProject() {
139 return mavenProject;
140 }
141
142 public final File getGeneratedAvscTarget() {
143 return generatedAvscTarget;
144 }
145
146 public final File getTarget() {
147 return target;
148 }
149
150 private Map<String, String> idx2Name() throws IOException {
151 Path indexFile = generatedAvscTarget.toPath().resolve(SCHEMA_INDEX_FILENAME);
152 Properties result = new Properties();
153 try (BufferedReader br = Files.newBufferedReader(indexFile, StandardCharsets.UTF_8)) {
154 result.load(br);
155 } catch (NoSuchFileException ex) {
156 return Collections.EMPTY_MAP;
157 }
158 return (Map) result;
159 }
160
161
162
163
164
165
166 @Override
167 public void execute() throws MojoExecutionException, MojoFailureException {
168 if (useSchemaReferencesForAvsc && SchemaRefWriter.isSchemaRefsSupported()) {
169 Map<String, String> currentMappings;
170 try {
171 currentMappings = idx2Name();
172 } catch (IOException ex) {
173 throw new MojoExecutionException("Exception loading schema index: "
174 + generatedAvscTarget.toPath().resolve(SCHEMA_INDEX_FILENAME), ex);
175 }
176 MavenSchemaResolver res = new MavenSchemaResolver(repoSystem, getMavenSession().getRepositorySession(),
177 mavenProject.getRemoteProjectRepositories(), schemaArtifactClassifier, schemaArtifactExtension);
178 SchemaResolvers.registerDefault(new SchemaResolver() {
179 @Override
180 public Schema resolveSchema(final String id) {
181 SchemaRef ref = new SchemaRef(id);
182 if (mavenProject.getGroupId().equals(ref.getGroupId())
183 && mavenProject.getArtifactId().equals(ref.getArtifactId())
184 && mavenProject.getVersion().equals(ref.getVersion())) {
185 String name = currentMappings.get(ref.getRef());
186 Path schemaPath = generatedAvscTarget.toPath().resolve(name.replace('.', '/') + ".avsc");
187 try (BufferedInputStream bis = new BufferedInputStream(Files.newInputStream(schemaPath))) {
188 return new Schema.Parser().parse(bis);
189 } catch (IOException ex) {
190 throw new UncheckedIOException(ex);
191 }
192 } else {
193 return res.resolveSchema(id);
194 }
195 }
196
197 @Override
198 public String getId(final Schema schema) {
199 return res.getId(schema);
200 }
201 });
202 }
203 }
204
205
206
207
208
209
210
211 @Override
212 public String toString() {
213 return "SchemaMojoBase{" + "dependenciesDirectory=" + dependenciesDirectory
214 + ", sourceDirectory=" + sourceDirectory + ", generatedJavaTarget="
215 + generatedJavaTarget + ", generatedAvscTarget=" + generatedAvscTarget + ", target=" + target + '}';
216 }
217
218
219
220 }