1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package org.eluder.coveralls.maven.plugin.json;
26
27 import com.fasterxml.jackson.core.JsonEncoding;
28 import com.fasterxml.jackson.core.JsonGenerator;
29 import com.fasterxml.jackson.core.JsonProcessingException;
30 import com.fasterxml.jackson.databind.MappingJsonFactory;
31
32 import java.io.Closeable;
33 import java.io.File;
34 import java.io.IOException;
35 import java.time.Instant;
36 import java.time.ZoneId;
37 import java.time.format.DateTimeFormatter;
38 import java.util.Map.Entry;
39 import java.util.Properties;
40
41 import org.eluder.coveralls.maven.plugin.ProcessingException;
42 import org.eluder.coveralls.maven.plugin.domain.Job;
43 import org.eluder.coveralls.maven.plugin.domain.Source;
44 import org.eluder.coveralls.maven.plugin.source.SourceCallback;
45
46
47
48
49 public class JsonWriter implements SourceCallback, Closeable {
50
51
52 protected static final String TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss Z";
53
54
55 private final Job job;
56
57
58 private final File coverallsFile;
59
60
61 private final JsonGenerator generator;
62
63
64
65
66
67
68
69
70
71
72
73
74 public JsonWriter(final Job job, final File coverallsFile) throws IOException {
75 final var directory = coverallsFile.getParentFile();
76 if (!directory.exists()) {
77 directory.mkdirs();
78 }
79 this.job = job;
80 this.coverallsFile = coverallsFile;
81 this.generator = new MappingJsonFactory().createGenerator(coverallsFile, JsonEncoding.UTF8);
82 }
83
84
85
86
87
88
89 public final Job getJob() {
90 return this.job;
91 }
92
93
94
95
96
97
98 public final File getCoverallsFile() {
99 return this.coverallsFile;
100 }
101
102 @Override
103 public void onBegin() throws ProcessingException, IOException {
104 try {
105 this.generator.writeStartObject();
106 this.writeOptionalString("repo_token", this.job.getRepoToken());
107 this.writeOptionalString("service_name", this.job.getServiceName());
108 this.writeOptionalString("service_job_id", this.job.getServiceJobId());
109 this.writeOptionalString("service_number", this.job.getServiceBuildNumber());
110 this.writeOptionalString("service_build_url", this.job.getServiceBuildUrl());
111 this.writeOptionalString("service_branch", this.job.getBranch());
112 this.writeOptionalString("service_pull_request", this.job.getPullRequest());
113 this.writeOptionalBoolean("parallel", this.job.isParallel());
114 this.writeOptionalTimestamp("run_at", this.job.getTimestamp());
115 this.writeOptionalEnvironment("environment", this.job.getServiceEnvironment());
116 this.writeOptionalObject("git", this.job.getGit());
117 this.generator.writeArrayFieldStart("source_files");
118 } catch (final JsonProcessingException e) {
119 throw new ProcessingException(e);
120 }
121 }
122
123 @Override
124 public void onSource(final Source source) throws ProcessingException, IOException {
125 try {
126 this.generator.writeObject(source);
127 } catch (final JsonProcessingException e) {
128 throw new ProcessingException(e);
129 }
130 }
131
132 @Override
133 public void onComplete() throws ProcessingException, IOException {
134 try {
135 this.generator.writeEndArray();
136 this.generator.writeEndObject();
137 } catch (final JsonProcessingException e) {
138 throw new ProcessingException(e);
139 }
140 }
141
142 @Override
143 public void close() throws IOException {
144 this.generator.close();
145 }
146
147
148
149
150
151
152
153
154
155
156
157
158 private void writeOptionalString(final String field, final String value) throws IOException {
159 if (value != null && !value.isBlank()) {
160 this.generator.writeStringField(field, value);
161 }
162 }
163
164
165
166
167
168
169
170
171
172
173
174
175 private void writeOptionalBoolean(final String field, final boolean value) throws IOException {
176 if (value) {
177 this.generator.writeBooleanField(field, value);
178 }
179 }
180
181
182
183
184
185
186
187
188
189
190
191
192 private void writeOptionalObject(final String field, final Object value) throws IOException {
193 if (value != null) {
194 this.generator.writeObjectField(field, value);
195 }
196 }
197
198
199
200
201
202
203
204
205
206
207
208
209 private void writeOptionalTimestamp(final String field, final Long value) throws IOException {
210 if (value != null) {
211 final var formatter = DateTimeFormatter.ofPattern(JsonWriter.TIMESTAMP_FORMAT)
212 .withZone(ZoneId.systemDefault());
213 this.writeOptionalString(field, formatter.format(Instant.ofEpochMilli(value)));
214 }
215 }
216
217
218
219
220
221
222
223
224
225
226
227
228 private void writeOptionalEnvironment(final String field, final Properties properties) throws IOException {
229 if (properties != null) {
230 this.generator.writeObjectFieldStart(field);
231 for (final Entry<Object, Object> property : properties.entrySet()) {
232 this.writeOptionalString(property.getKey().toString(), property.getValue().toString());
233 }
234 this.generator.writeEndObject();
235 }
236 }
237 }