1
1
/*
2
- * Copyright 2002-2023 the original author or authors.
2
+ * Copyright 2002-2024 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
16
16
17
17
package org .springframework .aot .generate ;
18
18
19
+ import java .util .function .Supplier ;
20
+
19
21
import org .springframework .core .io .InputStreamSource ;
20
22
import org .springframework .javapoet .JavaFile ;
23
+ import org .springframework .lang .Nullable ;
21
24
import org .springframework .util .Assert ;
22
25
import org .springframework .util .ClassUtils ;
23
26
import org .springframework .util .StringUtils ;
36
39
* @see InMemoryGeneratedFiles
37
40
* @see FileSystemGeneratedFiles
38
41
*/
39
- public interface GeneratedFiles {
42
+ public abstract class GeneratedFiles {
40
43
41
44
/**
42
45
* Add a generated {@link Kind#SOURCE source file} with content from the
43
46
* given {@link JavaFile}.
44
47
* @param javaFile the java file to add
45
48
*/
46
- default void addSourceFile (JavaFile javaFile ) {
49
+ public void addSourceFile (JavaFile javaFile ) {
47
50
validatePackage (javaFile .packageName , javaFile .typeSpec .name );
48
51
String className = javaFile .packageName + "." + javaFile .typeSpec .name ;
49
52
addSourceFile (className , javaFile ::writeTo );
@@ -56,7 +59,7 @@ default void addSourceFile(JavaFile javaFile) {
56
59
* of the file
57
60
* @param content the contents of the file
58
61
*/
59
- default void addSourceFile (String className , CharSequence content ) {
62
+ public void addSourceFile (String className , CharSequence content ) {
60
63
addSourceFile (className , appendable -> appendable .append (content ));
61
64
}
62
65
@@ -68,7 +71,7 @@ default void addSourceFile(String className, CharSequence content) {
68
71
* @param content a {@link ThrowingConsumer} that accepts an
69
72
* {@link Appendable} which will receive the file contents
70
73
*/
71
- default void addSourceFile (String className , ThrowingConsumer <Appendable > content ) {
74
+ public void addSourceFile (String className , ThrowingConsumer <Appendable > content ) {
72
75
addFile (Kind .SOURCE , getClassNamePath (className ), content );
73
76
}
74
77
@@ -80,7 +83,7 @@ default void addSourceFile(String className, ThrowingConsumer<Appendable> conten
80
83
* @param content an {@link InputStreamSource} that will provide an input
81
84
* stream containing the file contents
82
85
*/
83
- default void addSourceFile (String className , InputStreamSource content ) {
86
+ public void addSourceFile (String className , InputStreamSource content ) {
84
87
addFile (Kind .SOURCE , getClassNamePath (className ), content );
85
88
}
86
89
@@ -90,7 +93,7 @@ default void addSourceFile(String className, InputStreamSource content) {
90
93
* @param path the relative path of the file
91
94
* @param content the contents of the file
92
95
*/
93
- default void addResourceFile (String path , CharSequence content ) {
96
+ public void addResourceFile (String path , CharSequence content ) {
94
97
addResourceFile (path , appendable -> appendable .append (content ));
95
98
}
96
99
@@ -101,7 +104,7 @@ default void addResourceFile(String path, CharSequence content) {
101
104
* @param content a {@link ThrowingConsumer} that accepts an
102
105
* {@link Appendable} which will receive the file contents
103
106
*/
104
- default void addResourceFile (String path , ThrowingConsumer <Appendable > content ) {
107
+ public void addResourceFile (String path , ThrowingConsumer <Appendable > content ) {
105
108
addFile (Kind .RESOURCE , path , content );
106
109
}
107
110
@@ -112,7 +115,7 @@ default void addResourceFile(String path, ThrowingConsumer<Appendable> content)
112
115
* @param content an {@link InputStreamSource} that will provide an input
113
116
* stream containing the file contents
114
117
*/
115
- default void addResourceFile (String path , InputStreamSource content ) {
118
+ public void addResourceFile (String path , InputStreamSource content ) {
116
119
addFile (Kind .RESOURCE , path , content );
117
120
}
118
121
@@ -123,7 +126,7 @@ default void addResourceFile(String path, InputStreamSource content) {
123
126
* @param content an {@link InputStreamSource} that will provide an input
124
127
* stream containing the file contents
125
128
*/
126
- default void addClassFile (String path , InputStreamSource content ) {
129
+ public void addClassFile (String path , InputStreamSource content ) {
127
130
addFile (Kind .CLASS , path , content );
128
131
}
129
132
@@ -134,7 +137,7 @@ default void addClassFile(String path, InputStreamSource content) {
134
137
* @param path the relative path of the file
135
138
* @param content the contents of the file
136
139
*/
137
- default void addFile (Kind kind , String path , CharSequence content ) {
140
+ public void addFile (Kind kind , String path , CharSequence content ) {
138
141
addFile (kind , path , appendable -> appendable .append (content ));
139
142
}
140
143
@@ -146,7 +149,7 @@ default void addFile(Kind kind, String path, CharSequence content) {
146
149
* @param content a {@link ThrowingConsumer} that accepts an
147
150
* {@link Appendable} which will receive the file contents
148
151
*/
149
- default void addFile (Kind kind , String path , ThrowingConsumer <Appendable > content ) {
152
+ public void addFile (Kind kind , String path , ThrowingConsumer <Appendable > content ) {
150
153
Assert .notNull (content , "'content' must not be null" );
151
154
addFile (kind , path , new AppendableConsumerInputStreamSource (content ));
152
155
}
@@ -159,7 +162,21 @@ default void addFile(Kind kind, String path, ThrowingConsumer<Appendable> conten
159
162
* @param content an {@link InputStreamSource} that will provide an input
160
163
* stream containing the file contents
161
164
*/
162
- void addFile (Kind kind , String path , InputStreamSource content );
165
+ public void addFile (Kind kind , String path , InputStreamSource content ) {
166
+ Assert .notNull (kind , "'kind' must not be null" );
167
+ Assert .hasLength (path , "'path' must not be empty" );
168
+ Assert .notNull (content , "'content' must not be null" );
169
+ handleFile (kind , path , handler -> handler .create (content ));
170
+ }
171
+
172
+ /**
173
+ * Add a generated file of the specified {@link Kind} with the given
174
+ * {@linkplain FileHandler handler}.
175
+ * @param kind the kind of file being written
176
+ * @param path the relative path of the file
177
+ * @param handler a consumer of a {@link FileHandler} for the file
178
+ */
179
+ public abstract void handleFile (Kind kind , String path , ThrowingConsumer <FileHandler > handler );
163
180
164
181
private static String getClassNamePath (String className ) {
165
182
Assert .hasLength (className , "'className' must not be empty" );
@@ -194,7 +211,7 @@ private static boolean isJavaIdentifier(String className) {
194
211
/**
195
212
* The various kinds of generated files that are supported.
196
213
*/
197
- enum Kind {
214
+ public enum Kind {
198
215
199
216
/**
200
217
* A source file containing Java code that should be compiled.
@@ -215,4 +232,62 @@ enum Kind {
215
232
216
233
}
217
234
235
+ /**
236
+ * Provide access to a particular file and offer convenient method to save
237
+ * or override its content.
238
+ */
239
+ public abstract static class FileHandler {
240
+
241
+ private final boolean exists ;
242
+
243
+ private final Supplier <InputStreamSource > existingContent ;
244
+
245
+ protected FileHandler (boolean exists , Supplier <InputStreamSource > existingContent ) {
246
+ this .exists = exists ;
247
+ this .existingContent = existingContent ;
248
+ }
249
+
250
+ /**
251
+ * Specify whether the file already exists.
252
+ * @return {@code true} if the file already exists
253
+ */
254
+ public boolean exists () {
255
+ return this .exists ;
256
+ }
257
+
258
+ /**
259
+ * Return an {@link InputStreamSource} for the content of the file or
260
+ * {@code null} if the file does not exist.
261
+ */
262
+ @ Nullable
263
+ public InputStreamSource getContent () {
264
+ return (exists () ? this .existingContent .get () : null );
265
+ }
266
+
267
+ /**
268
+ * Create a file with the given {@linkplain InputStreamSource content}.
269
+ * @throws IllegalStateException if the file already exists
270
+ */
271
+ public void create (InputStreamSource content ) {
272
+ Assert .notNull (content , "'content' must not be null" );
273
+ if (exists ()) {
274
+ throw new IllegalStateException ("%s already exists" .formatted (this ));
275
+ }
276
+ copy (content , false );
277
+ }
278
+
279
+ /**
280
+ * Override the content of the file handled by this instance using the
281
+ * given {@linkplain InputStreamSource content}. If the file does not
282
+ * exist, it is created.
283
+ */
284
+ public void override (InputStreamSource content ) {
285
+ Assert .notNull (content , "'content' must not be null" );
286
+ copy (content , true );
287
+ }
288
+
289
+ protected abstract void copy (InputStreamSource content , boolean override );
290
+
291
+ }
292
+
218
293
}
0 commit comments