Brian O'Connor
Committed by Gerrit Code Review

Enhancing OnosJar to build OSGi jars and wars if required.

Also, simplifying onos.bucklet by using the rule

Change-Id: If89633db2d83cbfc56a8e70d2bea665ffaf186ff
...@@ -114,6 +114,7 @@ def osgi_jar( ...@@ -114,6 +114,7 @@ def osgi_jar(
114 api_description = NONE, 114 api_description = NONE,
115 resources = NONE, 115 resources = NONE,
116 resources_root = None, 116 resources_root = None,
117 + tests = None,
117 **kwargs 118 **kwargs
118 ): 119 ):
119 120
...@@ -134,76 +135,42 @@ def osgi_jar( ...@@ -134,76 +135,42 @@ def osgi_jar(
134 resources_root = RESOURCES_ROOT 135 resources_root = RESOURCES_ROOT
135 136
136 if api_title != NONE: 137 if api_title != NONE:
137 - r = 'WEB-INF/classes/apidoc/swagger.json=bin/swagger.json' 138 + r = 'WEB-INF/classes/apidoc/swagger.json=swagger.json'
138 include_resources = include_resources + ',' + r if include_resources != NONE else r 139 include_resources = include_resources + ',' + r if include_resources != NONE else r
139 140
140 - bare_jar_name = name + '-jar'
141 - osgi_jar_name = name + '-osgi'
142 mvn_coords = group_id + ':' + name + ':' + version 141 mvn_coords = group_id + ':' + name + ':' + version
143 142
144 -
145 onos_jar( 143 onos_jar(
146 - name = bare_jar_name, 144 + name = name,
147 - srcs = srcs, 145 + srcs = srcs + glob(['src/main/webapp/**']),
148 deps = deps, 146 deps = deps,
149 - visibility = [], #intentially, not visible 147 + visibility = visibility,
150 resources = resources, 148 resources = resources,
151 resources_root = resources_root, 149 resources_root = resources_root,
150 + bundle_name = name,
151 + group_id = group_id,
152 + bundle_version = version,
153 + bundle_license = license,
154 + bundle_description = description,
155 + import_packages = import_packages,
156 + export_packages = export_packages,
157 + include_resources = include_resources,
158 + dynamicimport_packages = dynamicimport_packages,
152 web_context = web_context, 159 web_context = web_context,
153 api_title = api_title, 160 api_title = api_title,
154 api_version = api_version, 161 api_version = api_version,
155 api_package = api_package, 162 api_package = api_package,
156 api_description = api_description, 163 api_description = api_description,
157 - **kwargs 164 + tests = tests,
158 - )
159 -
160 - cp = ':'.join(['$(classpath %s)' % c for c in deps]) if deps else '""'
161 -
162 - args = ( '$(location :%s)' % bare_jar_name, #input jar
163 - '$OUT', #output jar
164 - cp, #classpath
165 - name, #bundle name
166 - group_id, #group id
167 - version, #version
168 - license, #license url
169 - "'%s'" % import_packages, #packages to import
170 - "'%s'" % export_packages, #packages to export
171 - include_resources, #custom includes to classpath
172 - web_context, #web context (REST API only)
173 - "'%s'" % dynamicimport_packages, #DynamicImport-Package
174 - description, #description
175 - )
176 -
177 - #TODO stage_jar is a horrendous hack
178 - stage_jar = 'pushd $SRCDIR; mkdir bin; cd bin; jar xf $(location :%s); ls; popd; ' % bare_jar_name
179 - wrap_jar = '$(exe //utils/osgiwrap:osgi-jar) ' + ' '.join(args)
180 - bash = stage_jar + wrap_jar
181 - if debug:
182 - bash = stage_jar + DEBUG_ARG + ' ' + wrap_jar
183 - print bash
184 -
185 - # FIXME: make sure that /swagger.json gets filtered
186 - genrule(
187 - name = osgi_jar_name,
188 - bash = bash,
189 - out = '%s-%s.jar' % (name, version), #FIXME add version to jar file
190 - srcs = glob(['src/main/webapp/**']),
191 - visibility = [], #intentially, not visible
192 - )
193 -
194 - # TODO we really should shade the jar with maven flavor
195 - prebuilt_jar(
196 - name = name,
197 maven_coords = mvn_coords, 165 maven_coords = mvn_coords,
198 - binary_jar = ':' + osgi_jar_name, 166 + **kwargs
199 - visibility = visibility,
200 ) 167 )
201 168
202 ### Checkstyle 169 ### Checkstyle
203 checkstyle( 170 checkstyle(
204 name = name + '-checkstyle-files', 171 name = name + '-checkstyle-files',
205 srcs = srcs, 172 srcs = srcs,
206 - jar_target = ':'+ bare_jar_name, 173 + jar_target = ':'+ name,
207 ) 174 )
208 175
209 java_doc( 176 java_doc(
...@@ -219,7 +186,7 @@ def osgi_jar( ...@@ -219,7 +186,7 @@ def osgi_jar(
219 186
220 # TODO add project config for intellij 187 # TODO add project config for intellij
221 # project_config( 188 # project_config(
222 - # src_target = ':' + bare_jar_name, 189 + # src_target = ':' + name,
223 # src_roots = [ 'src/main/java' ], 190 # src_roots = [ 'src/main/java' ],
224 # test_target = ':' + name + '-tests', 191 # test_target = ':' + name + '-tests',
225 # test_roots = [ 'src/test/java' ], 192 # test_roots = [ 'src/test/java' ],
...@@ -247,6 +214,8 @@ def osgi_jar( ...@@ -247,6 +214,8 @@ def osgi_jar(
247 def osgi_jar_with_tests( 214 def osgi_jar_with_tests(
248 name = None, 215 name = None,
249 deps = [], 216 deps = [],
217 + group_id = ONOS_GROUP_ID,
218 + version = ONOS_VERSION,
250 test_srcs = None, 219 test_srcs = None,
251 test_deps = [ '//lib:TEST' ], 220 test_deps = [ '//lib:TEST' ],
252 test_resources = None, 221 test_resources = None,
...@@ -260,7 +229,10 @@ def osgi_jar_with_tests( ...@@ -260,7 +229,10 @@ def osgi_jar_with_tests(
260 229
261 osgi_jar(name = name, 230 osgi_jar(name = name,
262 deps = deps, 231 deps = deps,
232 + group_id = group_id,
233 + version = version,
263 visibility = visibility, 234 visibility = visibility,
235 + tests = [':' + name + '-tests'],
264 **kwargs) 236 **kwargs)
265 237
266 if test_resources and not test_resources_root: 238 if test_resources and not test_resources_root:
...@@ -275,16 +247,18 @@ def osgi_jar_with_tests( ...@@ -275,16 +247,18 @@ def osgi_jar_with_tests(
275 if test_srcs is None: 247 if test_srcs is None:
276 test_srcs = glob([TEST + '/*.java']) 248 test_srcs = glob([TEST + '/*.java'])
277 249
250 + mvn_coords = group_id + ':' + name + ':jar:tests:' + version
251 +
278 java_test( 252 java_test(
279 name = name + '-tests', 253 name = name + '-tests',
280 srcs = test_srcs, 254 srcs = test_srcs,
281 deps = deps + 255 deps = deps +
282 test_deps + 256 test_deps +
283 - [':' + name + '-jar'], 257 + [':' + name + '#non-osgi'],
284 - source_under_test = [':' + name + '-jar'],
285 resources = test_resources, 258 resources = test_resources,
286 resources_root = test_resources_root, 259 resources_root = test_resources_root,
287 - visibility = visibility 260 + maven_coords = mvn_coords,
261 + visibility = visibility,
288 ) 262 )
289 263
290 checkstyle( 264 checkstyle(
...@@ -292,5 +266,3 @@ def osgi_jar_with_tests( ...@@ -292,5 +266,3 @@ def osgi_jar_with_tests(
292 srcs = test_srcs, 266 srcs = test_srcs,
293 jar_target = ':' + name + '-tests', 267 jar_target = ':' + name + '-tests',
294 ) 268 )
295 -
296 - #FIXME need to run checkstyle on test sources
......
1 +# Comment the remote_jar out for local buck development
1 remote_jar ( 2 remote_jar (
2 name = 'buck-api', 3 name = 'buck-api',
3 out = 'buck.jar', 4 out = 'buck.jar',
4 - url = 'https://github.com/bocon13/buck/releases/download/v2016.07.29.01-wip/buck.jar', 5 + url = 'https://github.com/bocon13/buck/releases/download/v2016.09.13.01/buck.jar',
5 - sha1 = 'f89324cb869b74fdcd4db9972233065a93d890a2', 6 + sha1 = 'd5415b4326e5316675532a8cd48001a8456e8c9e',
6 visibility = [], 7 visibility = [],
7 ) 8 )
8 9
10 +# Uncomment the prebuilt_jar and copy buck-api to lib/buck.jar for local buck development
11 +# prebuilt_jar (
12 +# name = 'buck-api',
13 +# binary_jar = 'lib/buck.jar'
14 +# )
15 +
9 COMPILE = [ 16 COMPILE = [
10 '//lib:qdox', 17 '//lib:qdox',
11 - #'//lib:jackson-core', 18 + '//lib:guava',
12 - #'//lib:jackson-databind', 19 + '//lib:bndlib',
13 - #'//lib:jackson-annotations', 20 + '//lib:org.apache.felix.scr.bnd'
14 -]
15 -
16 -RUNTIME = [
17 ] 21 ]
18 22
19 java_library( 23 java_library(
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.onosjar;
18 +
19 +import aQute.bnd.header.Attrs;
20 +import aQute.bnd.header.Parameters;
21 +import aQute.bnd.osgi.Analyzer;
22 +import aQute.bnd.osgi.Builder;
23 +import aQute.bnd.osgi.FileResource;
24 +import aQute.bnd.osgi.Jar;
25 +import aQute.bnd.osgi.Resource;
26 +import com.facebook.buck.step.ExecutionContext;
27 +import com.facebook.buck.step.Step;
28 +import com.facebook.buck.step.StepExecutionResult;
29 +import com.google.common.base.MoreObjects;
30 +import com.google.common.collect.ImmutableSortedSet;
31 +import com.google.common.collect.Lists;
32 +import com.google.common.collect.Maps;
33 +import com.google.common.collect.Sets;
34 +import org.apache.felix.scrplugin.bnd.SCRDescriptorBndPlugin;
35 +
36 +import java.io.File;
37 +import java.io.IOException;
38 +import java.io.PrintStream;
39 +import java.nio.file.FileVisitResult;
40 +import java.nio.file.FileVisitor;
41 +import java.nio.file.Path;
42 +import java.nio.file.Paths;
43 +import java.nio.file.SimpleFileVisitor;
44 +import java.nio.file.attribute.BasicFileAttributes;
45 +import java.util.HashSet;
46 +import java.util.List;
47 +import java.util.Map;
48 +import java.util.Set;
49 +import java.util.jar.Manifest;
50 +import java.util.stream.Collectors;
51 +
52 +import static java.nio.file.Files.walkFileTree;
53 +
54 +/**
55 + * BND-based wrapper to convert Buck JARs to OSGi-compatible JARs.
56 + */
57 +public class OSGiWrapper implements Step {
58 +
59 + private Path inputJar;
60 + private Path outputJar;
61 + private Path sourcesDir;
62 + private Path classesDir;
63 + private List<String> classpath;
64 +
65 + private String bundleName;
66 + private String groupId;
67 + private String bundleSymbolicName;
68 + private String bundleVersion;
69 +
70 + private String importPackages;
71 + private String dynamicimportPackages;
72 +
73 + private String exportPackages;
74 + private String includeResources;
75 + private Set<String> includedResources = Sets.newHashSet();
76 +
77 + private String bundleDescription;
78 + private String bundleLicense;
79 +
80 + private String webContext;
81 +
82 + private PrintStream stderr = System.err;
83 +
84 + public OSGiWrapper(Path inputJar,
85 + Path outputJar,
86 + Path sourcesDir,
87 + Path classesDir,
88 + ImmutableSortedSet<Path> classpath,
89 + String bundleName,
90 + String groupId,
91 + String bundleVersion,
92 + String bundleLicense,
93 + String importPackages,
94 + String exportPackages,
95 + String includeResources,
96 + String webContext,
97 + String dynamicimportPackages,
98 + String bundleDescription) {
99 + this.inputJar = inputJar;
100 + this.sourcesDir = sourcesDir;
101 + this.classesDir = classesDir;
102 + this.classpath = Lists.newArrayList(
103 + classpath.stream().map(Path::toString).collect(Collectors.toList()));
104 + if (!this.classpath.contains(inputJar.toString())) {
105 + this.classpath.add(0, inputJar.toString());
106 + }
107 + this.outputJar = outputJar;
108 +
109 + this.bundleName = bundleName;
110 + this.groupId = groupId;
111 + this.bundleSymbolicName = String.format("%s.%s", groupId, bundleName);
112 +
113 + this.bundleVersion = bundleVersion;
114 + this.bundleLicense = bundleLicense;
115 + this.bundleDescription = bundleDescription;
116 +
117 + this.importPackages = importPackages;
118 + this.dynamicimportPackages = dynamicimportPackages;
119 + this.exportPackages = exportPackages;
120 + this.includeResources = includeResources;
121 +
122 + this.webContext = webContext;
123 + }
124 +
125 + private void setProperties(Analyzer analyzer) {
126 + analyzer.setProperty(Analyzer.BUNDLE_NAME, bundleName);
127 + analyzer.setProperty(Analyzer.BUNDLE_SYMBOLICNAME, bundleSymbolicName);
128 + analyzer.setProperty(Analyzer.BUNDLE_VERSION, bundleVersion.replace('-', '.'));
129 +
130 + if (bundleDescription != null) {
131 + analyzer.setProperty(Analyzer.BUNDLE_DESCRIPTION, bundleDescription);
132 + }
133 + if (bundleLicense != null) {
134 + analyzer.setProperty(Analyzer.BUNDLE_LICENSE, bundleLicense);
135 + }
136 +
137 + //TODO consider using stricter version policy
138 + //analyzer.setProperty("-provider-policy", "${range;[===,==+)}");
139 + //analyzer.setProperty("-consumer-policy", "${range;[===,==+)}");
140 +
141 + // There are no good defaults so make sure you set the Import-Package
142 + analyzer.setProperty(Analyzer.IMPORT_PACKAGE, importPackages);
143 +
144 + analyzer.setProperty(Analyzer.DYNAMICIMPORT_PACKAGE, dynamicimportPackages);
145 +
146 + // TODO include version in export, but not in import
147 + analyzer.setProperty(Analyzer.EXPORT_PACKAGE, exportPackages);
148 +
149 + // TODO we may need INCLUDE_RESOURCE, or that might be done by Buck
150 + if (includeResources != null) {
151 + analyzer.setProperty(Analyzer.INCLUDE_RESOURCE, includeResources);
152 + }
153 +
154 + if (isWab()) {
155 + analyzer.setProperty(Analyzer.WAB, "src/main/webapp/");
156 + analyzer.setProperty("Web-ContextPath", webContext);
157 + analyzer.setProperty(Analyzer.IMPORT_PACKAGE, "*,org.glassfish.jersey.servlet,org.jvnet.mimepull\n");
158 + }
159 + }
160 +
161 + public boolean execute() {
162 + Analyzer analyzer = new Builder();
163 + try {
164 +
165 + Jar jar = new Jar(inputJar.toFile()); // where our data is
166 + analyzer.setJar(jar); // give bnd the contents
167 +
168 + // You can provide additional class path entries to allow
169 + // bnd to pickup export version from the packageinfo file,
170 + // Version annotation, or their manifests.
171 + analyzer.addClasspath(classpath);
172 +
173 + setProperties(analyzer);
174 +
175 + //analyzer.setBase(classesDir.toFile());
176 +
177 +// analyzer.setProperty("DESTDIR");
178 +// analyzer.setBase();
179 +
180 + // ------------- let's begin... -------------------------
181 +
182 + // Analyze the target JAR first
183 + analyzer.analyze();
184 +
185 + // Scan the JAR for Felix SCR annotations and generate XML files
186 + Map<String, String> properties = Maps.newHashMap();
187 + properties.put("destdir", classesDir.toAbsolutePath().toString());
188 + SCRDescriptorBndPlugin scrDescriptorBndPlugin = new SCRDescriptorBndPlugin();
189 + scrDescriptorBndPlugin.setProperties(properties);
190 + scrDescriptorBndPlugin.setReporter(analyzer);
191 + scrDescriptorBndPlugin.analyzeJar(analyzer);
192 +
193 + if (includeResources != null) {
194 + doIncludeResources(analyzer);
195 + }
196 +
197 + // Repack the JAR as a WAR
198 + doWabStaging(analyzer);
199 +
200 + // Calculate the manifest
201 + Manifest manifest = analyzer.calcManifest();
202 + //OutputStream s = new FileOutputStream("/tmp/foo2.txt");
203 + //manifest.write(s);
204 + //s.close();
205 +
206 + if (analyzer.isOk()) {
207 + analyzer.getJar().setManifest(manifest);
208 + if (analyzer.save(outputJar.toFile(), true)) {
209 + log("Saved!\n");
210 + } else {
211 + warn("Failed to create jar \n");
212 + return false;
213 + }
214 + } else {
215 + warn("Analyzer Errors:\n%s\n", analyzer.getErrors());
216 + return false;
217 + }
218 +
219 + analyzer.close();
220 +
221 + return true;
222 + } catch (Exception e) {
223 + e.printStackTrace();
224 + return false;
225 + }
226 + }
227 +
228 + private boolean isWab() {
229 + return webContext != null;
230 + }
231 +
232 + private void doWabStaging(Analyzer analyzer) throws Exception {
233 + if (!isWab()) {
234 + return;
235 + }
236 + String wab = analyzer.getProperty(analyzer.WAB);
237 + Jar dot = analyzer.getJar();
238 +
239 + log("wab %s", wab);
240 + analyzer.setBundleClasspath("WEB-INF/classes," +
241 + analyzer.getProperty(analyzer.BUNDLE_CLASSPATH));
242 +
243 + Set<String> paths = new HashSet<>(dot.getResources().keySet());
244 +
245 + for (String path : paths) {
246 + if (path.indexOf('/') > 0 && !Character.isUpperCase(path.charAt(0))) {
247 + log("wab: moving: %s", path);
248 + dot.rename(path, "WEB-INF/classes/" + path);
249 + }
250 + }
251 +
252 + Path wabRoot = Paths.get(wab);
253 + includeFiles(dot, null, wabRoot.toString());
254 + }
255 +
256 + /**
257 + * Parse the Bundle-Includes header. Files in the bundles Include header are
258 + * included in the jar. The source can be a directory or a file.
259 + *
260 + * @throws Exception
261 + */
262 + private void doIncludeResources(Analyzer analyzer) throws Exception {
263 + String includes = analyzer.getProperty(Analyzer.INCLUDE_RESOURCE);
264 + if (includes == null) {
265 + return;
266 + }
267 + Parameters clauses = analyzer.parseHeader(includes);
268 + Jar jar = analyzer.getJar();
269 +
270 + for (Map.Entry<String, Attrs> entry : clauses.entrySet()) {
271 + String name = entry.getKey();
272 + Map<String, String> extra = entry.getValue();
273 + // TODO consider doing something with extras
274 +
275 + String[] parts = name.split("\\s*=\\s*");
276 + String source = parts[0];
277 + String destination = parts[0];
278 + if (parts.length == 2) {
279 + source = parts[1];
280 + }
281 +
282 + includeFiles(jar, destination, source);
283 + }
284 + }
285 +
286 + private void includeFiles(Jar jar, String destinationRoot, String sourceRoot)
287 + throws IOException {
288 +
289 + Path classesBasedPath = classesDir.resolve(sourceRoot);
290 + Path sourceBasedPath = sourcesDir.resolve(sourceRoot);
291 +
292 + File classFile = classesBasedPath.toFile();
293 + File sourceFile = sourceBasedPath.toFile();
294 +
295 + if (classFile.isFile()) {
296 + addFileToJar(jar, destinationRoot, classesBasedPath.toAbsolutePath().toString());
297 + } else if (sourceFile.isFile()) {
298 + addFileToJar(jar, destinationRoot, sourceBasedPath.toAbsolutePath().toString());
299 + } else if (classFile.isDirectory()) {
300 + includeDirectory(jar, destinationRoot, classesBasedPath);
301 + } else if (sourceFile.isDirectory()) {
302 + includeDirectory(jar, destinationRoot, sourceBasedPath);
303 + } else {
304 + warn("Skipping resource in bundle %s: %s (File Not Found)\n",
305 + bundleSymbolicName, sourceRoot);
306 + }
307 + }
308 +
309 + private void includeDirectory(Jar jar, String destinationRoot, Path sourceRoot)
310 + throws IOException {
311 + // iterate through sources
312 + // put each source on the jar
313 + FileVisitor<Path> visitor = new SimpleFileVisitor<Path>() {
314 + @Override
315 + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
316 + Path relativePath = sourceRoot.relativize(file);
317 + String destination = destinationRoot != null ?
318 + destinationRoot + "/" + relativePath.toString() : //TODO
319 + relativePath.toString();
320 +
321 + addFileToJar(jar, destination, file.toAbsolutePath().toString());
322 + return FileVisitResult.CONTINUE;
323 + }
324 + };
325 +
326 + walkFileTree(sourceRoot, visitor);
327 + }
328 +
329 + private boolean addFileToJar(Jar jar, String destination, String sourceAbsPath) {
330 + if (includedResources.contains(sourceAbsPath)) {
331 + log("Skipping already included resource: %s\n", sourceAbsPath);
332 + return false;
333 + }
334 + File file = new File(sourceAbsPath);
335 + if (!file.isFile()) {
336 + throw new RuntimeException(
337 + String.format("Skipping non-existent file: %s\n", sourceAbsPath));
338 + }
339 + Resource resource = new FileResource(file);
340 + if (jar.getResource(destination) != null) {
341 + warn("Skipping duplicate resource: %s\n", destination);
342 + return false;
343 + }
344 + jar.putResource(destination, resource);
345 + includedResources.add(sourceAbsPath);
346 + log("Adding resource: %s\n", destination);
347 + return true;
348 + }
349 +
350 + private void log(String format, Object... objects) {
351 + //System.err.printf(format, objects);
352 + }
353 +
354 + private void warn(String format, Object... objects) {
355 + stderr.printf(format, objects);
356 + }
357 +
358 + @Override
359 + public String toString() {
360 + return MoreObjects.toStringHelper(this)
361 + .add("inputJar", inputJar)
362 + .add("outputJar", outputJar)
363 + .add("classpath", classpath)
364 + .add("bundleName", bundleName)
365 + .add("groupId", groupId)
366 + .add("bundleSymbolicName", bundleSymbolicName)
367 + .add("bundleVersion", bundleVersion)
368 + .add("bundleDescription", bundleDescription)
369 + .add("bundleLicense", bundleLicense)
370 + .toString();
371 +
372 + }
373 +
374 + @Override
375 + public StepExecutionResult execute(ExecutionContext executionContext)
376 + throws IOException, InterruptedException {
377 + stderr = executionContext.getStdErr();
378 + boolean success = execute();
379 + stderr = System.err;
380 + return success ? StepExecutionResult.SUCCESS : StepExecutionResult.ERROR;
381 + }
382 +
383 + @Override
384 + public String getShortName() {
385 + return "osgiwrap";
386 + }
387 +
388 + @Override
389 + public String getDescription(ExecutionContext executionContext) {
390 + return "osgiwrap"; //FIXME
391 + }
392 +}
...@@ -17,6 +17,10 @@ package org.onosproject.onosjar; ...@@ -17,6 +17,10 @@ package org.onosproject.onosjar;
17 17
18 import com.facebook.buck.jvm.java.CompileToJarStepFactory; 18 import com.facebook.buck.jvm.java.CompileToJarStepFactory;
19 import com.facebook.buck.jvm.java.DefaultJavaLibrary; 19 import com.facebook.buck.jvm.java.DefaultJavaLibrary;
20 +import com.facebook.buck.jvm.java.HasClasspathEntries;
21 +import com.facebook.buck.jvm.java.HasMavenCoordinates;
22 +import com.facebook.buck.jvm.java.JavaLibrary;
23 +import com.facebook.buck.jvm.java.MavenPublishable;
20 import com.facebook.buck.model.BuildTarget; 24 import com.facebook.buck.model.BuildTarget;
21 import com.facebook.buck.rules.AddToRuleKey; 25 import com.facebook.buck.rules.AddToRuleKey;
22 import com.facebook.buck.rules.BuildRule; 26 import com.facebook.buck.rules.BuildRule;
...@@ -24,6 +28,7 @@ import com.facebook.buck.rules.BuildRuleParams; ...@@ -24,6 +28,7 @@ import com.facebook.buck.rules.BuildRuleParams;
24 import com.facebook.buck.rules.SourcePath; 28 import com.facebook.buck.rules.SourcePath;
25 import com.facebook.buck.rules.SourcePathResolver; 29 import com.facebook.buck.rules.SourcePathResolver;
26 import com.google.common.base.Optional; 30 import com.google.common.base.Optional;
31 +import com.google.common.base.Preconditions;
27 import com.google.common.collect.ImmutableList; 32 import com.google.common.collect.ImmutableList;
28 import com.google.common.collect.ImmutableSet; 33 import com.google.common.collect.ImmutableSet;
29 import com.google.common.collect.ImmutableSortedSet; 34 import com.google.common.collect.ImmutableSortedSet;
...@@ -36,7 +41,8 @@ import java.util.regex.Pattern; ...@@ -36,7 +41,8 @@ import java.util.regex.Pattern;
36 * Implementation of a build rule that generates a onosjar.json file for a set 41 * Implementation of a build rule that generates a onosjar.json file for a set
37 * of Java sources. 42 * of Java sources.
38 */ 43 */
39 -public class OnosJar extends DefaultJavaLibrary { 44 +public class OnosJar extends DefaultJavaLibrary
45 + implements MavenPublishable{
40 46
41 @AddToRuleKey 47 @AddToRuleKey
42 final Optional<String> webContext; 48 final Optional<String> webContext;
...@@ -53,6 +59,8 @@ public class OnosJar extends DefaultJavaLibrary { ...@@ -53,6 +59,8 @@ public class OnosJar extends DefaultJavaLibrary {
53 @AddToRuleKey 59 @AddToRuleKey
54 final Optional<String> apiDescription; 60 final Optional<String> apiDescription;
55 61
62 + private final ImmutableSortedSet<HasMavenCoordinates> mavenDeps;
63 +
56 public OnosJar(BuildRuleParams params, 64 public OnosJar(BuildRuleParams params,
57 SourcePathResolver resolver, 65 SourcePathResolver resolver,
58 Set<? extends SourcePath> srcs, 66 Set<? extends SourcePath> srcs,
...@@ -84,5 +92,32 @@ public class OnosJar extends DefaultJavaLibrary { ...@@ -84,5 +92,32 @@ public class OnosJar extends DefaultJavaLibrary {
84 this.apiVersion = apiVersion; 92 this.apiVersion = apiVersion;
85 this.apiPackage = apiPackage; 93 this.apiPackage = apiPackage;
86 this.apiDescription = apiDescription; 94 this.apiDescription = apiDescription;
95 + this.mavenDeps = computeMavenDeps();
96 + }
97 +
98 + private ImmutableSortedSet<HasMavenCoordinates> computeMavenDeps() {
99 + ImmutableSortedSet.Builder<HasMavenCoordinates> mavenDeps = ImmutableSortedSet.naturalOrder();
100 + for (JavaLibrary javaLibrary : getTransitiveClasspathDeps()) {
101 + if (this.equals(javaLibrary)) {
102 + // no need to include ourself
103 + continue;
104 + } else if (HasMavenCoordinates.MAVEN_COORDS_PRESENT_PREDICATE.apply(javaLibrary)) {
105 + mavenDeps.add(javaLibrary);
106 + //FIXME BOC do we always want to exclude all of a maven jar's dependencies? probably.
107 + mavenDeps.addAll(javaLibrary.getTransitiveClasspathDeps());
108 + }
109 + }
110 + return mavenDeps.build();
111 + }
112 +
113 + @Override
114 + public Iterable<HasMavenCoordinates> getMavenDeps() {
115 + return mavenDeps;
116 + }
117 +
118 + @Override
119 + public Iterable<BuildRule> getPackagedDependencies() {
120 + //FIXME this is not supported at the moment
121 + return ImmutableList.of();
87 } 122 }
88 } 123 }
......
...@@ -19,13 +19,21 @@ import com.facebook.buck.cli.BuckConfig; ...@@ -19,13 +19,21 @@ import com.facebook.buck.cli.BuckConfig;
19 import com.facebook.buck.jvm.java.CalculateAbi; 19 import com.facebook.buck.jvm.java.CalculateAbi;
20 import com.facebook.buck.jvm.java.DefaultJavaLibrary; 20 import com.facebook.buck.jvm.java.DefaultJavaLibrary;
21 import com.facebook.buck.jvm.java.JavaBuckConfig; 21 import com.facebook.buck.jvm.java.JavaBuckConfig;
22 +import com.facebook.buck.jvm.java.JavaLibrary;
22 import com.facebook.buck.jvm.java.JavaLibraryDescription; 23 import com.facebook.buck.jvm.java.JavaLibraryDescription;
23 import com.facebook.buck.jvm.java.JavaOptions; 24 import com.facebook.buck.jvm.java.JavaOptions;
25 +import com.facebook.buck.jvm.java.JavaSourceJar;
24 import com.facebook.buck.jvm.java.JavacOptions; 26 import com.facebook.buck.jvm.java.JavacOptions;
25 import com.facebook.buck.jvm.java.JavacOptionsAmender; 27 import com.facebook.buck.jvm.java.JavacOptionsAmender;
26 import com.facebook.buck.jvm.java.JavacOptionsFactory; 28 import com.facebook.buck.jvm.java.JavacOptionsFactory;
29 +import com.facebook.buck.jvm.java.JavacToJarStepFactory;
30 +import com.facebook.buck.jvm.java.JavadocJar;
31 +import com.facebook.buck.jvm.java.MavenUberJar;
32 +import com.facebook.buck.maven.AetherUtil;
27 import com.facebook.buck.model.BuildTarget; 33 import com.facebook.buck.model.BuildTarget;
28 import com.facebook.buck.model.Flavor; 34 import com.facebook.buck.model.Flavor;
35 +import com.facebook.buck.model.Flavored;
36 +import com.facebook.buck.model.ImmutableFlavor;
29 import com.facebook.buck.parser.NoSuchBuildTargetException; 37 import com.facebook.buck.parser.NoSuchBuildTargetException;
30 import com.facebook.buck.rules.BuildRule; 38 import com.facebook.buck.rules.BuildRule;
31 import com.facebook.buck.rules.BuildRuleParams; 39 import com.facebook.buck.rules.BuildRuleParams;
...@@ -37,7 +45,9 @@ import com.facebook.buck.rules.Description; ...@@ -37,7 +45,9 @@ import com.facebook.buck.rules.Description;
37 import com.facebook.buck.rules.SourcePathResolver; 45 import com.facebook.buck.rules.SourcePathResolver;
38 import com.facebook.buck.rules.SourcePaths; 46 import com.facebook.buck.rules.SourcePaths;
39 import com.facebook.buck.rules.TargetGraph; 47 import com.facebook.buck.rules.TargetGraph;
48 +import com.google.common.base.Function;
40 import com.google.common.base.Optional; 49 import com.google.common.base.Optional;
50 +import com.google.common.base.Preconditions;
41 import com.google.common.collect.ImmutableSet; 51 import com.google.common.collect.ImmutableSet;
42 import com.google.common.collect.ImmutableSortedSet; 52 import com.google.common.collect.ImmutableSortedSet;
43 import com.google.common.collect.Iterables; 53 import com.google.common.collect.Iterables;
...@@ -51,8 +61,16 @@ import static com.facebook.buck.jvm.common.ResourceValidator.validateResources; ...@@ -51,8 +61,16 @@ import static com.facebook.buck.jvm.common.ResourceValidator.validateResources;
51 * 61 *
52 * Currently, this only does Swagger generation. 62 * Currently, this only does Swagger generation.
53 */ 63 */
54 -public class OnosJarDescription implements Description<OnosJarDescription.Arg> { 64 +public class OnosJarDescription implements Description<OnosJarDescription.Arg>, Flavored {
55 public static final BuildRuleType TYPE = BuildRuleType.of("onos_jar"); 65 public static final BuildRuleType TYPE = BuildRuleType.of("onos_jar");
66 + public static final Flavor NON_OSGI_JAR = ImmutableFlavor.of("non-osgi");
67 +
68 + public static final ImmutableSet<Flavor> SUPPORTED_FLAVORS = ImmutableSet.of(
69 + JavaLibrary.SRC_JAR,
70 + JavaLibrary.MAVEN_JAR,
71 + JavaLibrary.JAVADOC_JAR,
72 + NON_OSGI_JAR);
73 +
56 private final JavacOptions defaultJavacOptions; 74 private final JavacOptions defaultJavacOptions;
57 private final JavaOptions defaultJavaOptions; 75 private final JavaOptions defaultJavaOptions;
58 76
...@@ -89,6 +107,63 @@ public class OnosJarDescription implements Description<OnosJarDescription.Arg> { ...@@ -89,6 +107,63 @@ public class OnosJarDescription implements Description<OnosJarDescription.Arg> {
89 ImmutableSortedSet<Flavor> flavors = target.getFlavors(); 107 ImmutableSortedSet<Flavor> flavors = target.getFlavors();
90 BuildRuleParams paramsWithMavenFlavor = null; 108 BuildRuleParams paramsWithMavenFlavor = null;
91 109
110 + if (flavors.contains(JavaLibrary.MAVEN_JAR)) {
111 + paramsWithMavenFlavor = params;
112 +
113 + // Maven rules will depend upon their vanilla versions, so the latter have to be constructed
114 + // without the maven flavor to prevent output-path conflict
115 + params = params.copyWithBuildTarget(
116 + params.getBuildTarget().withoutFlavors(ImmutableSet.of(JavaLibrary.MAVEN_JAR)));
117 + }
118 +
119 + if (flavors.contains(JavaLibrary.SRC_JAR)) {
120 + args.mavenCoords = args.mavenCoords.transform(
121 + new Function<String, String>() {
122 + @Override
123 + public String apply(String input) {
124 + return AetherUtil.addClassifier(input, AetherUtil.CLASSIFIER_SOURCES);
125 + }
126 + });
127 +
128 + if (!flavors.contains(JavaLibrary.MAVEN_JAR)) {
129 + return new JavaSourceJar(
130 + params,
131 + pathResolver,
132 + args.srcs.get(),
133 + args.mavenCoords);
134 + } else {
135 + return MavenUberJar.SourceJar.create(
136 + Preconditions.checkNotNull(paramsWithMavenFlavor),
137 + pathResolver,
138 + args.srcs.get(),
139 + args.mavenCoords);
140 + }
141 + }
142 +
143 + if (flavors.contains(JavaLibrary.JAVADOC_JAR)) {
144 + args.mavenCoords = args.mavenCoords.transform(
145 + new Function<String, String>() {
146 + @Override
147 + public String apply(String input) {
148 + return AetherUtil.addClassifier(input, AetherUtil.CLASSIFIER_JAVADOC);
149 + }
150 + });
151 +
152 + if (!flavors.contains(JavaLibrary.MAVEN_JAR)) {
153 + return new JavadocJar(
154 + params,
155 + pathResolver,
156 + args.srcs.get(),
157 + args.mavenCoords);
158 + } else {
159 + return MavenUberJar.MavenJavadocJar.create(
160 + Preconditions.checkNotNull(paramsWithMavenFlavor),
161 + pathResolver,
162 + args.srcs.get(),
163 + args.mavenCoords);
164 + }
165 + }
166 +
92 JavacOptions javacOptions = JavacOptionsFactory.create( 167 JavacOptions javacOptions = JavacOptionsFactory.create(
93 defaultJavacOptions, 168 defaultJavacOptions,
94 params, 169 params,
...@@ -101,7 +176,9 @@ public class OnosJarDescription implements Description<OnosJarDescription.Arg> { ...@@ -101,7 +176,9 @@ public class OnosJarDescription implements Description<OnosJarDescription.Arg> {
101 176
102 ImmutableSortedSet<BuildRule> exportedDeps = resolver.getAllRules(args.exportedDeps.get()); 177 ImmutableSortedSet<BuildRule> exportedDeps = resolver.getAllRules(args.exportedDeps.get());
103 178
104 - DefaultJavaLibrary defaultJavaLibrary = 179 + final DefaultJavaLibrary defaultJavaLibrary;
180 + if (!flavors.contains(NON_OSGI_JAR)) {
181 + defaultJavaLibrary =
105 resolver.addToIndex( 182 resolver.addToIndex(
106 new OnosJar( 183 new OnosJar(
107 params.appendExtraDeps( 184 params.appendExtraDeps(
...@@ -130,7 +207,10 @@ public class OnosJarDescription implements Description<OnosJarDescription.Arg> { ...@@ -130,7 +207,10 @@ public class OnosJarDescription implements Description<OnosJarDescription.Arg> {
130 /* additionalClasspathEntries */ ImmutableSet.<Path>of(), 207 /* additionalClasspathEntries */ ImmutableSet.<Path>of(),
131 new OnosJarStepFactory(javacOptions, JavacOptionsAmender.IDENTITY, 208 new OnosJarStepFactory(javacOptions, JavacOptionsAmender.IDENTITY,
132 args.webContext, args.apiTitle, args.apiVersion, 209 args.webContext, args.apiTitle, args.apiVersion,
133 - args.apiPackage, args.apiDescription, args.resources), 210 + args.apiPackage, args.apiDescription, args.resources,
211 + args.groupId, args.bundleName, args.bundleVersion,
212 + args.bundleLicense, args.bundleDescription, args.importPackages,
213 + args.exportPackages, args.includeResources, args.dynamicimportPackages),
134 args.resourcesRoot, 214 args.resourcesRoot,
135 args.mavenCoords, 215 args.mavenCoords,
136 args.tests.get(), 216 args.tests.get(),
...@@ -140,6 +220,40 @@ public class OnosJarDescription implements Description<OnosJarDescription.Arg> { ...@@ -140,6 +220,40 @@ public class OnosJarDescription implements Description<OnosJarDescription.Arg> {
140 args.apiVersion, 220 args.apiVersion,
141 args.apiPackage, 221 args.apiPackage,
142 args.apiDescription)); 222 args.apiDescription));
223 + } else {
224 + defaultJavaLibrary =
225 + resolver.addToIndex(
226 + new DefaultJavaLibrary(
227 + params.appendExtraDeps(
228 + Iterables.concat(
229 + BuildRules.getExportedRules(
230 + Iterables.concat(
231 + params.getDeclaredDeps().get(),
232 + exportedDeps,
233 + resolver.getAllRules(args.providedDeps.get()))),
234 + pathResolver.filterBuildRuleInputs(
235 + javacOptions.getInputs(pathResolver)))),
236 + pathResolver,
237 + args.srcs.get(),
238 + validateResources(
239 + pathResolver,
240 + params.getProjectFilesystem(),
241 + args.resources.get()),
242 + javacOptions.getGeneratedSourceFolderName(),
243 + args.proguardConfig.transform(
244 + SourcePaths.toSourcePath(params.getProjectFilesystem())),
245 + args.postprocessClassesCommands.get(),
246 + exportedDeps,
247 + resolver.getAllRules(args.providedDeps.get()),
248 + new BuildTargetSourcePath(abiJarTarget),
249 + javacOptions.trackClassUsage(),
250 + /* additionalClasspathEntries */ ImmutableSet.<Path>of(),
251 + new JavacToJarStepFactory(javacOptions, JavacOptionsAmender.IDENTITY),
252 + args.resourcesRoot,
253 + args.mavenCoords,
254 + args.tests.get(),
255 + javacOptions.getClassesToRemoveFromJar()));
256 + }
143 257
144 resolver.addToIndex( 258 resolver.addToIndex(
145 CalculateAbi.of( 259 CalculateAbi.of(
...@@ -151,6 +265,10 @@ public class OnosJarDescription implements Description<OnosJarDescription.Arg> { ...@@ -151,6 +265,10 @@ public class OnosJarDescription implements Description<OnosJarDescription.Arg> {
151 return defaultJavaLibrary; 265 return defaultJavaLibrary;
152 } 266 }
153 267
268 + @Override
269 + public boolean hasFlavors(ImmutableSet<Flavor> flavors) {
270 + return SUPPORTED_FLAVORS.containsAll(flavors);
271 + }
154 272
155 public static class Arg extends JavaLibraryDescription.Arg { 273 public static class Arg extends JavaLibraryDescription.Arg {
156 public Optional<String> webContext; 274 public Optional<String> webContext;
...@@ -158,5 +276,16 @@ public class OnosJarDescription implements Description<OnosJarDescription.Arg> { ...@@ -158,5 +276,16 @@ public class OnosJarDescription implements Description<OnosJarDescription.Arg> {
158 public Optional<String> apiVersion; 276 public Optional<String> apiVersion;
159 public Optional<String> apiPackage; 277 public Optional<String> apiPackage;
160 public Optional<String> apiDescription; 278 public Optional<String> apiDescription;
279 +
280 + public Optional<String> groupId;
281 + public Optional<String> bundleName;
282 + public Optional<String> bundleVersion;
283 + public Optional<String> bundleLicense;
284 + public Optional<String> bundleDescription;
285 +
286 + public Optional<String> importPackages;
287 + public Optional<String> exportPackages;
288 + public Optional<String> includeResources;
289 + public Optional<String> dynamicimportPackages;
161 } 290 }
162 } 291 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -28,12 +28,14 @@ import com.facebook.buck.rules.BuildableContext; ...@@ -28,12 +28,14 @@ import com.facebook.buck.rules.BuildableContext;
28 import com.facebook.buck.rules.SourcePath; 28 import com.facebook.buck.rules.SourcePath;
29 import com.facebook.buck.rules.SourcePathResolver; 29 import com.facebook.buck.rules.SourcePathResolver;
30 import com.facebook.buck.step.Step; 30 import com.facebook.buck.step.Step;
31 +import com.facebook.buck.step.fs.CopyStep;
31 import com.google.common.base.Optional; 32 import com.google.common.base.Optional;
32 import com.google.common.collect.ImmutableList; 33 import com.google.common.collect.ImmutableList;
33 import com.google.common.collect.ImmutableSet; 34 import com.google.common.collect.ImmutableSet;
34 import com.google.common.collect.ImmutableSortedSet; 35 import com.google.common.collect.ImmutableSortedSet;
35 36
36 import java.nio.file.Path; 37 import java.nio.file.Path;
38 +import java.nio.file.Paths;
37 import java.util.regex.Pattern; 39 import java.util.regex.Pattern;
38 import java.util.stream.Collectors; 40 import java.util.stream.Collectors;
39 41
...@@ -49,6 +51,15 @@ public class OnosJarStepFactory extends JavacToJarStepFactory { ...@@ -49,6 +51,15 @@ public class OnosJarStepFactory extends JavacToJarStepFactory {
49 private final String apiPackage; 51 private final String apiPackage;
50 private final String apiDescription; 52 private final String apiDescription;
51 private final Optional<ImmutableSortedSet<SourcePath>> resources; 53 private final Optional<ImmutableSortedSet<SourcePath>> resources;
54 + private final String groupId;
55 + private final String bundleName;
56 + private final String bundleVersion;
57 + private final String bundleLicense;
58 + private final String bundleDescription;
59 + private final String importPackages;
60 + private final String exportPackages;
61 + private final String includeResources;
62 + private final String dynamicimportPackages;
52 63
53 public OnosJarStepFactory(JavacOptions javacOptions, 64 public OnosJarStepFactory(JavacOptions javacOptions,
54 JavacOptionsAmender amender, 65 JavacOptionsAmender amender,
...@@ -57,8 +68,26 @@ public class OnosJarStepFactory extends JavacToJarStepFactory { ...@@ -57,8 +68,26 @@ public class OnosJarStepFactory extends JavacToJarStepFactory {
57 Optional<String> apiVersion, 68 Optional<String> apiVersion,
58 Optional<String> apiPackage, 69 Optional<String> apiPackage,
59 Optional<String> apiDescription, 70 Optional<String> apiDescription,
60 - Optional<ImmutableSortedSet<SourcePath>> resources) { 71 + Optional<ImmutableSortedSet<SourcePath>> resources,
72 + Optional<String> groupId,
73 + Optional<String> bundleName,
74 + Optional<String> bundleVersion,
75 + Optional<String> bundleLicense,
76 + Optional<String> bundleDescription,
77 + Optional<String> importPackages,
78 + Optional<String> exportPackages,
79 + Optional<String> includeResources,
80 + Optional<String> dynamicimportPackages) {
61 super(javacOptions, amender); 81 super(javacOptions, amender);
82 + this.bundleDescription = processParameter(bundleDescription);
83 + this.importPackages = processParameter(importPackages);
84 + this.exportPackages = processParameter(exportPackages);
85 + this.includeResources = processParameter(includeResources);
86 + this.dynamicimportPackages = processParameter(dynamicimportPackages);
87 + this.groupId = processParameter(groupId);
88 + this.bundleName = processParameter(bundleName);
89 + this.bundleVersion = processParameter(bundleVersion);
90 + this.bundleLicense = processParameter(bundleLicense);
62 this.webContext = processParameter(webContext); 91 this.webContext = processParameter(webContext);
63 this.apiTitle = processParameter(apiTitle); 92 this.apiTitle = processParameter(apiTitle);
64 this.apiVersion = processParameter(apiVersion); 93 this.apiVersion = processParameter(apiVersion);
...@@ -114,6 +143,11 @@ public class OnosJarStepFactory extends JavacToJarStepFactory { ...@@ -114,6 +143,11 @@ public class OnosJarStepFactory extends JavacToJarStepFactory {
114 apiPackage, apiDescription); 143 apiPackage, apiDescription);
115 sourceFilePathBuilder.add(swaggerStep.apiRegistratorPath()); 144 sourceFilePathBuilder.add(swaggerStep.apiRegistratorPath());
116 steps.add(swaggerStep); 145 steps.add(swaggerStep);
146 +
147 +// steps.addAll(sourceFilePaths.stream()
148 +// .filter(sp -> sp.startsWith("src/main/webapp/"))
149 +// .map(sp -> CopyStep.forFile(filesystem, sp, outputDirectory))
150 +// .iterator());
117 } 151 }
118 152
119 createCompileStep(context, 153 createCompileStep(context,
...@@ -132,6 +166,7 @@ public class OnosJarStepFactory extends JavacToJarStepFactory { ...@@ -132,6 +166,7 @@ public class OnosJarStepFactory extends JavacToJarStepFactory {
132 166
133 // post compilation steps 167 // post compilation steps
134 168
169 +
135 // FIXME BOC: add mechanism to inject new Steps 170 // FIXME BOC: add mechanism to inject new Steps
136 //context.additionalStepFactory(JavaStep.class); 171 //context.additionalStepFactory(JavaStep.class);
137 172
...@@ -143,6 +178,28 @@ public class OnosJarStepFactory extends JavacToJarStepFactory { ...@@ -143,6 +178,28 @@ public class OnosJarStepFactory extends JavacToJarStepFactory {
143 manifestFile.orNull(), 178 manifestFile.orNull(),
144 true, 179 true,
145 blacklistBuilder.build())); 180 blacklistBuilder.build()));
181 +
182 + OSGiWrapper osgiStep = new OSGiWrapper(
183 + outputJar, //input jar
184 + outputJar, //Paths.get(outputJar.toString() + ".jar"), //output jar
185 + invokingRule.getBasePath(), // sources dir
186 + outputDirectory, // classes dir
187 + declaredClasspathEntries, // classpath
188 + bundleName, // bundle name
189 + groupId, // groupId
190 + bundleVersion, // bundle version
191 + bundleLicense, // bundle license
192 + importPackages, // import packages
193 + exportPackages, // export packages
194 + includeResources, // include resources
195 + webContext, // web context
196 + dynamicimportPackages, // dynamic import packages
197 + bundleDescription // bundle description
198 + );
199 + steps.add(osgiStep);
200 +
201 + //steps.add(CopyStep.forFile(filesystem, Paths.get(outputJar.toString() + ".jar"), outputJar));
202 +
146 } 203 }
147 204
148 private ImmutableSortedSet<Path> findSwaggerModelDefs(SourcePathResolver resolver, 205 private ImmutableSortedSet<Path> findSwaggerModelDefs(SourcePathResolver resolver,
......
...@@ -102,11 +102,13 @@ public class SwaggerGenerator { ...@@ -102,11 +102,13 @@ public class SwaggerGenerator {
102 } 102 }
103 if (srcs != null) { 103 if (srcs != null) {
104 srcs.forEach(src -> { 104 srcs.forEach(src -> {
105 + if (src.toString().endsWith(".java")) {
105 try { 106 try {
106 builder.addSource(src); 107 builder.addSource(src);
107 } catch (IOException e) { 108 } catch (IOException e) {
108 throw new RuntimeException(e); 109 throw new RuntimeException(e);
109 } 110 }
111 + }
110 }); 112 });
111 } 113 }
112 114
......