5
5
6
6
import java .io .BufferedReader ;
7
7
import java .io .IOException ;
8
+ import java .io .StringReader ;
9
+ import java .io .StringWriter ;
8
10
import java .nio .file .Files ;
9
11
import java .nio .file .Path ;
10
12
import java .text .MessageFormat ;
11
13
import java .util .ArrayList ;
12
14
import java .util .HashMap ;
13
15
import java .util .List ;
14
16
import java .util .Map ;
17
+ import java .util .concurrent .Callable ;
15
18
import java .util .regex .Pattern ;
16
19
import java .util .stream .Collectors ;
17
20
21
+ import com .github .mustachejava .DefaultMustacheFactory ;
22
+ import com .github .mustachejava .Mustache ;
23
+ import com .github .mustachejava .MustacheFactory ;
18
24
import com .oracle .weblogic .imagetool .logging .LoggingFacade ;
19
25
import com .oracle .weblogic .imagetool .logging .LoggingFactory ;
20
26
@@ -30,10 +36,16 @@ public class AdditionalBuildCommands {
30
36
public static final String AFTER_WDT = "after-wdt-command" ;
31
37
public static final String FINAL_BLD = "final-build-commands" ;
32
38
33
- private List <NamedPattern > sections ;
34
- private Map <String , List <String >> contents ;
39
+ private final List <NamedPattern > sections ;
40
+ private final Map <String , List <String >> contents ;
35
41
36
- private AdditionalBuildCommands () {
42
+ /**
43
+ * Load the contents of the additional build commands file into this object.
44
+ * Existing data in this instance are replaced.
45
+ * @param file Path to the additional build commands file that should be loaded.
46
+ * @throws IOException if an issue occurs locating or opening the file provided
47
+ */
48
+ public AdditionalBuildCommands (Path file ) throws IOException {
37
49
sections = new ArrayList <>();
38
50
sections .add (getPattern (PACKAGES ));
39
51
sections .add (getPattern (BEFORE_JDK ));
@@ -43,6 +55,8 @@ private AdditionalBuildCommands() {
43
55
sections .add (getPattern (BEFORE_WDT ));
44
56
sections .add (getPattern (AFTER_WDT ));
45
57
sections .add (getPattern (FINAL_BLD ));
58
+ contents = new HashMap <>();
59
+ load (file );
46
60
}
47
61
48
62
private static NamedPattern getPattern (String key ) {
@@ -61,8 +75,38 @@ public int size() {
61
75
return contents .size ();
62
76
}
63
77
64
- public Map <String ,List <String >> getContents () {
65
- return contents ;
78
+ /**
79
+ * Get the contents of the file provided on the command line as additional build commands.
80
+ * The file is parsed into a map based on the sections in the file. The returned map
81
+ * will have one entry per section found in the provided file (such as "final-build-commands").
82
+ * The Callable list value for each entry is for late resolution of the contents. If the user
83
+ * provides mustache placeholders in the file, those placeholders will get resolved when the call
84
+ * method is invoked and not when getContents is returned. This allows getContents to be called
85
+ * before DockerfileOptions is completely populated.
86
+ *
87
+ * @param options The backing file that will be used to resolve any mustache placeholders in the file
88
+ * @return a map by section name of the additional build file contents
89
+ */
90
+ public Map <String , Callable <List <String >>> getContents (DockerfileOptions options ) {
91
+ Map <String , Callable <List <String >>> callableResult = new HashMap <>();
92
+ for (Map .Entry <String , List <String >> entry : contents .entrySet ()) {
93
+ // implements the "call" method so that the contents are resolved at the time they are retrieved
94
+ Callable <List <String >> value = () -> {
95
+ List <String > resolvedLines = new ArrayList <>();
96
+ MustacheFactory mf = new DefaultMustacheFactory ();
97
+ // Parse each line in the file contents using mustache and the provided "options"
98
+ for (String line : entry .getValue ()) {
99
+ StringWriter writer = new StringWriter ();
100
+ Mustache mustache = mf .compile (new StringReader (line ), "x" );
101
+ mustache .execute (writer , options );
102
+ writer .flush ();
103
+ resolvedLines .add (writer .toString ());
104
+ }
105
+ return resolvedLines ;
106
+ };
107
+ callableResult .put (entry .getKey (), value );
108
+ }
109
+ return callableResult ;
66
110
}
67
111
68
112
/**
@@ -80,26 +124,23 @@ public List<String> getSection(String name) {
80
124
* @param file Path to the additional build commands file that should be loaded.
81
125
* @throws IOException if an issue occurs locating or opening the file provided
82
126
*/
83
- public static AdditionalBuildCommands load (Path file ) throws IOException {
127
+ private void load (Path file ) throws IOException {
84
128
logger .entering (file );
85
- AdditionalBuildCommands result = new AdditionalBuildCommands ();
86
- result .contents = new HashMap <>();
87
-
88
129
try (BufferedReader reader = Files .newBufferedReader (file )) {
89
130
List <String > buffer = new ArrayList <>();
90
131
String currentSection = null ;
91
132
String line ;
92
133
while ((line = reader .readLine ()) != null ) {
93
134
logger .finest (line );
94
- String sectionStart = result . checkForSectionHeader (line );
135
+ String sectionStart = checkForSectionHeader (line );
95
136
//skip any lines that come before the first section header
96
137
if (currentSection != null && sectionStart == null ) {
97
138
//collect lines inside current section
98
139
buffer .add (line );
99
140
} else if (currentSection != null ) {
100
141
//while in a section, found next section start (save last section, and start new section)
101
142
logger .fine ("IMG-0015" , buffer .size (), currentSection );
102
- result . contents .put (currentSection , buffer );
143
+ contents .put (currentSection , buffer );
103
144
buffer = new ArrayList <>();
104
145
currentSection = sectionStart ;
105
146
} else if (sectionStart != null ) {
@@ -111,15 +152,14 @@ public static AdditionalBuildCommands load(Path file) throws IOException {
111
152
if (currentSection != null && !buffer .isEmpty ()) {
112
153
//finished reading file, store the remaining lines that were read for the section
113
154
logger .fine ("IMG-0015" , buffer .size (), currentSection );
114
- result . contents .put (currentSection , buffer );
155
+ contents .put (currentSection , buffer );
115
156
}
116
157
} catch (IOException ioe ) {
117
158
logger .severe ("IMG-0013" , file .getFileName ());
118
159
throw ioe ;
119
160
}
120
161
121
162
logger .exiting ();
122
- return result ;
123
163
}
124
164
125
165
private String checkForSectionHeader (String line ) {
0 commit comments