forked from bndtools/bnd
/
Index.java
293 lines (272 loc) · 8.43 KB
/
Index.java
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
package aQute.bnd.gradle;
import static aQute.bnd.gradle.BndUtils.builtBy;
import static aQute.bnd.gradle.BndUtils.logReport;
import static aQute.bnd.gradle.BndUtils.unwrap;
import static aQute.bnd.gradle.BndUtils.unwrapFile;
import static java.util.stream.Collectors.toList;
import static org.gradle.api.tasks.PathSensitivity.NONE;
import java.io.File;
import java.io.OutputStream;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.zip.GZIPOutputStream;
import aQute.bnd.osgi.Processor;
import aQute.bnd.osgi.repository.SimpleIndexer;
import aQute.lib.io.IO;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.publish.plugins.PublishingPlugin;
import org.gradle.api.tasks.CacheableTask;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.TaskAction;
/**
* Index task type for Gradle.
* <p>
* This task type can be used to index a set of bundles.
* <p>
* Here is an example of using the Index task type:
*
* <pre>
* import aQute.bnd.gradle.Index
* tasks.register("index", Index) {
* destinationDirectory = layout.buildDirectory.dir("libs")
* gzip = true
* bundles = fileTree(destinationDirectory) {
* include "**/*.jar"
* exclude "**/*-latest.jar"
* exclude "**/*-sources.jar"
* exclude "**/*-javadoc.jar"
* builtBy tasks.withType(Jar)
* }
* }
* </pre>
* <p>
* Properties:
* <ul>
* <li>base - The base URI for the generated index. The default is the file: URI
* of the destinationDirectory. The default value is buildDir.</li>
* <li>bundles - This is the bundles to be indexed. This property must be
* set.</li>
* <li>destinationDirectory - The destination directory for the index. This is
* used as the URI base of the generated index.</li>
* <li>gzip - If <code>true</code>, then a gzip'd copy of the index will be
* made. Otherwise, only the uncompressed index will be made. The default is
* <code>false</code>.</li>
* <li>indexName - The name of the index file. The default is
* <code>index.xml</code>.</li>
* <li>repositoryName - The name attribute in the generated index. The default
* is the name of the task.</li>
* </ul>
*/
@CacheableTask
public class Index extends DefaultTask {
private final Property<URI> base;
private final ConfigurableFileCollection bundles;
private final DirectoryProperty destinationDirectory;
private boolean gzip = false;
private final Property<String> indexName;
private final Property<String> repositoryName;
private final RegularFileProperty indexUncompressed;
private final RegularFileProperty indexCompressed;
/**
* The URI base of the generated index.
* <p>
* The default is the file: URI of the destinationDir.
*
* @return The property for the base of the generated index.
*/
@Input
public Property<URI> getBase() {
return base;
}
/**
* The bundles to be indexed.
*
* @return The property for the bundles to be indexed.
*/
@InputFiles
@PathSensitive(NONE)
public ConfigurableFileCollection getBundles() {
return bundles;
}
/**
* The destination directory for the index.
* <p>
* The default value is project.layout.buildDirectory.
*
* @return The property for the destination directory for the index.
*/
@Internal("Represented by indexUncompressed and indexCompressed")
public DirectoryProperty getDestinationDirectory() {
return destinationDirectory;
}
/**
* Whether a gzip'd index should be made.
*
* @return <code>true</code> if a gzip'd copy of the index will be made.
* Otherwise, only the uncompressed index will be made. The default
* is <code>false</code>.
*/
@Input
public boolean isGzip() {
return gzip;
}
/**
* Whether a gzip'd index should be made.
* <p>
* An alias for {@link #isGzip()}.
*
* @return <code>true</code> if a gzip'd copy of the index will be made.
* Otherwise, only the uncompressed index will be made. The default
* is <code>false</code>.
*/
@Internal
public boolean getGzip() {
return isGzip();
}
/**
* Set whether a gzip'd index should be made.
*
* @param gzip If <code>true</code>, then a gzip'd copy of the index will be
* made. Otherwise, only the uncompressed index will be made. The
* default is <code>false</code>.
*/
public void setGzip(boolean gzip) {
this.gzip = gzip;
}
/**
* The name of the index file.
* <p>
* The default is <code>index.xml</code>.
*
* @return The name of the index file.
*/
@Internal("Represented by indexUncompressed and indexCompressed")
public Property<String> getIndexName() {
return indexName;
}
/**
* The name attribute in the generated index.
* <p>
* The default is the name of the task.
*
* @return The name attribute in the generated index.
*/
@Input
public Property<String> getRepositoryName() {
return repositoryName;
}
/**
* The uncompressed index file.
* <p>
* The default is <code>destinationDirectory.file(indexName)</code>.
*
* @return The uncompressed index file.
*/
@OutputFile
public RegularFileProperty getIndexUncompressed() {
return indexUncompressed;
}
/**
* The compressed index file.
* <p>
* The default is <code>destinationDirectory.file(indexName+".gz")</code>.
*
* @return The compressed index file.
*/
@OutputFile
public RegularFileProperty getIndexCompressed() {
return indexCompressed;
}
/**
* Create an Index task.
*/
public Index() {
super();
setGroup(PublishingPlugin.PUBLISH_TASK_GROUP);
org.gradle.api.Project project = getProject();
ObjectFactory objects = project.getObjects();
indexName = objects.property(String.class)
.convention("index.xml");
repositoryName = objects.property(String.class)
.convention(getName());
bundles = objects.fileCollection();
destinationDirectory = objects.directoryProperty()
.convention(project.getLayout()
.getBuildDirectory());
base = objects.property(URI.class)
.convention(destinationDirectory.map(d -> unwrapFile(d).toURI()));
indexUncompressed = objects.fileProperty()
.convention(destinationDirectory.file(indexName));
indexCompressed = objects.fileProperty()
.convention(destinationDirectory.file(indexName.map(n -> n.concat(".gz"))));
}
/**
* Add files to the bundles to be indexed.
*
* @param paths The arguments will be handled using
* ConfigurableFileCollection.from().
* @return The property for the bundles to be indexed.
*/
public ConfigurableFileCollection bundles(Object... paths) {
return builtBy(getBundles().from(paths), paths);
}
/**
* Set the bundles to be indexed.
*
* @param path The argument will be handled using
* ConfigurableFileCollection.from().
*/
public void setBundles(Object path) {
getBundles().setFrom(Collections.emptyList());
getBundles().setBuiltBy(Collections.emptyList());
bundles(path);
}
/**
* Index the bundles.
*
* @throws Exception An exception during indexing.
*/
@TaskAction
public void indexerAction() throws Exception {
File indexUncompressedFile = unwrapFile(getIndexUncompressed());
try (Processor processor = new Processor()) {
List<File> sortedBundles = getBundles().getFiles()
.stream()
.sorted()
.collect(toList());
getLogger().info("Generating index for {}.", sortedBundles);
new SimpleIndexer().reporter(processor)
.files(sortedBundles)
.base(unwrap(getBase()))
.name(unwrap(getRepositoryName()))
.index(indexUncompressedFile);
logReport(processor, getLogger());
if (!processor.isOk()) {
failTask(String.format("Index %s has errors", indexUncompressedFile), indexUncompressedFile);
}
getLogger().info("Generated index {}.", indexUncompressedFile);
if (isGzip()) {
File indexCompressedFile = unwrapFile(getIndexCompressed());
try (OutputStream out = new GZIPOutputStream(IO.outputStream(indexCompressedFile))) {
IO.copy(indexUncompressedFile, out);
}
getLogger().info("Generated index {}.", indexCompressedFile);
}
}
}
private void failTask(String msg, File outputFile) {
IO.delete(outputFile);
throw new GradleException(msg);
}
}