]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | /* |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, | |
13 | * software distributed under the License is distributed on an | |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | * KIND, either express or implied. See the License for the | |
16 | * specific language governing permissions and limitations | |
17 | * under the License. | |
18 | */ | |
19 | ||
20 | package org.apache.thrift.maven; | |
21 | ||
22 | import com.google.common.collect.ImmutableList; | |
23 | import com.google.common.collect.ImmutableSet; | |
24 | import org.codehaus.plexus.util.cli.CommandLineException; | |
25 | import org.codehaus.plexus.util.cli.CommandLineUtils; | |
26 | import org.codehaus.plexus.util.cli.Commandline; | |
27 | import java.io.File; | |
28 | import java.util.List; | |
29 | import java.util.Set; | |
30 | import static com.google.common.base.Preconditions.checkArgument; | |
31 | import static com.google.common.base.Preconditions.checkNotNull; | |
32 | import static com.google.common.base.Preconditions.checkState; | |
33 | import static com.google.common.collect.Lists.newLinkedList; | |
34 | import static com.google.common.collect.Sets.newHashSet; | |
35 | ||
36 | /** | |
37 | * This class represents an invokable configuration of the {@code thrift} | |
38 | * compiler. The actual executable is invoked using the plexus | |
39 | * {@link Commandline}. | |
40 | * <p/> | |
41 | * This class currently only supports generating java source files. | |
42 | */ | |
43 | final class Thrift { | |
44 | ||
45 | final static String GENERATED_JAVA = "gen-java"; | |
46 | ||
47 | private final String executable; | |
48 | private final String generator; | |
49 | private final ImmutableSet<File> thriftPathElements; | |
50 | private final ImmutableSet<File> thriftFiles; | |
51 | private final File javaOutputDirectory; | |
52 | private final CommandLineUtils.StringStreamConsumer output; | |
53 | private final CommandLineUtils.StringStreamConsumer error; | |
54 | ||
55 | /** | |
56 | * Constructs a new instance. This should only be used by the {@link Builder}. | |
57 | * | |
58 | * @param executable The path to the {@code thrift} executable. | |
59 | * @param generator The value for the {@code --gen} option. | |
60 | * @param thriftPath The directories in which to search for imports. | |
61 | * @param thriftFiles The thrift source files to compile. | |
62 | * @param javaOutputDirectory The directory into which the java source files | |
63 | * will be generated. | |
64 | */ | |
65 | private Thrift(String executable, String generator, ImmutableSet<File> thriftPath, | |
66 | ImmutableSet<File> thriftFiles, File javaOutputDirectory) { | |
67 | this.executable = checkNotNull(executable, "executable"); | |
68 | this.generator = checkNotNull(generator, "generator"); | |
69 | this.thriftPathElements = checkNotNull(thriftPath, "thriftPath"); | |
70 | this.thriftFiles = checkNotNull(thriftFiles, "thriftFiles"); | |
71 | this.javaOutputDirectory = checkNotNull(javaOutputDirectory, "javaOutputDirectory"); | |
72 | this.error = new CommandLineUtils.StringStreamConsumer(); | |
73 | this.output = new CommandLineUtils.StringStreamConsumer(); | |
74 | } | |
75 | ||
76 | /** | |
77 | * Invokes the {@code thrift} compiler using the configuration specified at | |
78 | * construction. | |
79 | * | |
80 | * @return The exit status of {@code thrift}. | |
81 | * @throws CommandLineException | |
82 | */ | |
83 | public int compile() throws CommandLineException { | |
84 | ||
85 | for (File thriftFile : thriftFiles) { | |
86 | Commandline cl = new Commandline(); | |
87 | cl.setExecutable(executable); | |
88 | cl.addArguments(buildThriftCommand(thriftFile).toArray(new String[]{})); | |
89 | final int result = CommandLineUtils.executeCommandLine(cl, null, output, error); | |
90 | ||
91 | if (result != 0) { | |
92 | return result; | |
93 | } | |
94 | } | |
95 | ||
96 | // result will always be 0 here. | |
97 | return 0; | |
98 | } | |
99 | ||
100 | /** | |
101 | * Creates the command line arguments. | |
102 | * <p/> | |
103 | * This method has been made visible for testing only. | |
104 | * | |
105 | * @param thriftFile | |
106 | * @return A list consisting of the executable followed by any arguments. | |
107 | */ | |
108 | ImmutableList<String> buildThriftCommand(final File thriftFile) { | |
109 | final List<String> command = newLinkedList(); | |
110 | // add the executable | |
111 | for (File thriftPathElement : thriftPathElements) { | |
112 | command.add("-I"); | |
113 | command.add(thriftPathElement.toString()); | |
114 | } | |
115 | command.add("-out"); | |
116 | command.add(javaOutputDirectory.toString()); | |
117 | command.add("--gen"); | |
118 | command.add(generator); | |
119 | command.add(thriftFile.toString()); | |
120 | return ImmutableList.copyOf(command); | |
121 | } | |
122 | ||
123 | /** | |
124 | * @return the output | |
125 | */ | |
126 | public String getOutput() { | |
127 | return output.getOutput(); | |
128 | } | |
129 | ||
130 | /** | |
131 | * @return the error | |
132 | */ | |
133 | public String getError() { | |
134 | return error.getOutput(); | |
135 | } | |
136 | ||
137 | /** | |
138 | * This class builds {@link Thrift} instances. | |
139 | */ | |
140 | static final class Builder { | |
141 | private final String executable; | |
142 | private final File javaOutputDirectory; | |
143 | private Set<File> thriftPathElements; | |
144 | private Set<File> thriftFiles; | |
145 | private String generator; | |
146 | ||
147 | /** | |
148 | * Constructs a new builder. The two parameters are present as they are | |
149 | * required for all {@link Thrift} instances. | |
150 | * | |
151 | * @param executable The path to the {@code thrift} executable. | |
152 | * @param javaOutputDirectory The directory into which the java source files | |
153 | * will be generated. | |
154 | * @throws NullPointerException If either of the arguments are {@code null}. | |
155 | * @throws IllegalArgumentException If the {@code javaOutputDirectory} is | |
156 | * not a directory. | |
157 | */ | |
158 | public Builder(String executable, File javaOutputDirectory) { | |
159 | this.executable = checkNotNull(executable, "executable"); | |
160 | this.javaOutputDirectory = checkNotNull(javaOutputDirectory); | |
161 | checkArgument(javaOutputDirectory.isDirectory()); | |
162 | this.thriftFiles = newHashSet(); | |
163 | this.thriftPathElements = newHashSet(); | |
164 | } | |
165 | ||
166 | /** | |
167 | * Adds a thrift file to be compiled. Thrift files must be on the thriftpath | |
168 | * and this method will fail if a thrift file is added without first adding a | |
169 | * parent directory to the thriftpath. | |
170 | * | |
171 | * @param thriftFile | |
172 | * @return The builder. | |
173 | * @throws IllegalStateException If a thrift file is added without first | |
174 | * adding a parent directory to the thriftpath. | |
175 | * @throws NullPointerException If {@code thriftFile} is {@code null}. | |
176 | */ | |
177 | public Builder addThriftFile(File thriftFile) { | |
178 | checkNotNull(thriftFile); | |
179 | checkArgument(thriftFile.isFile()); | |
180 | checkArgument(thriftFile.getName().endsWith(".thrift")); | |
181 | checkThriftFileIsInThriftPath(thriftFile); | |
182 | thriftFiles.add(thriftFile); | |
183 | return this; | |
184 | } | |
185 | ||
186 | /** | |
187 | * Adds the option string for the Thrift executable's {@code --gen} parameter. | |
188 | * | |
189 | * @param generator | |
190 | * @return The builder | |
191 | * @throws NullPointerException If {@code generator} is {@code null}. | |
192 | */ | |
193 | public Builder setGenerator(String generator) { | |
194 | checkNotNull(generator); | |
195 | this.generator = generator; | |
196 | return this; | |
197 | } | |
198 | ||
199 | private void checkThriftFileIsInThriftPath(File thriftFile) { | |
200 | assert thriftFile.isFile(); | |
201 | checkState(checkThriftFileIsInThriftPathHelper(thriftFile.getParentFile())); | |
202 | } | |
203 | ||
204 | private boolean checkThriftFileIsInThriftPathHelper(File directory) { | |
205 | assert directory.isDirectory(); | |
206 | if (thriftPathElements.contains(directory)) { | |
207 | return true; | |
208 | } else { | |
209 | final File parentDirectory = directory.getParentFile(); | |
210 | return (parentDirectory == null) ? false | |
211 | : checkThriftFileIsInThriftPathHelper(parentDirectory); | |
212 | } | |
213 | } | |
214 | ||
215 | /** | |
216 | * @see #addThriftFile(File) | |
217 | */ | |
218 | public Builder addThriftFiles(Iterable<File> thriftFiles) { | |
219 | for (File thriftFile : thriftFiles) { | |
220 | addThriftFile(thriftFile); | |
221 | } | |
222 | return this; | |
223 | } | |
224 | ||
225 | /** | |
226 | * Adds the {@code thriftPathElement} to the thriftPath. | |
227 | * | |
228 | * @param thriftPathElement A directory to be searched for imported thrift message | |
229 | * buffer definitions. | |
230 | * @return The builder. | |
231 | * @throws NullPointerException If {@code thriftPathElement} is {@code null}. | |
232 | * @throws IllegalArgumentException If {@code thriftPathElement} is not a | |
233 | * directory. | |
234 | */ | |
235 | public Builder addThriftPathElement(File thriftPathElement) { | |
236 | checkNotNull(thriftPathElement); | |
237 | checkArgument(thriftPathElement.isDirectory()); | |
238 | thriftPathElements.add(thriftPathElement); | |
239 | return this; | |
240 | } | |
241 | ||
242 | /** | |
243 | * @see #addThriftPathElement(File) | |
244 | */ | |
245 | public Builder addThriftPathElements(Iterable<File> thriftPathElements) { | |
246 | for (File thriftPathElement : thriftPathElements) { | |
247 | addThriftPathElement(thriftPathElement); | |
248 | } | |
249 | return this; | |
250 | } | |
251 | ||
252 | /** | |
253 | * @return A configured {@link Thrift} instance. | |
254 | * @throws IllegalStateException If no thrift files have been added. | |
255 | */ | |
256 | public Thrift build() { | |
257 | checkState(!thriftFiles.isEmpty()); | |
258 | return new Thrift(executable, generator, ImmutableSet.copyOf(thriftPathElements), | |
259 | ImmutableSet.copyOf(thriftFiles), javaOutputDirectory); | |
260 | } | |
261 | } | |
262 | } |