use of com.cloudbees.jenkins.support.util.OutputStreamSelector in project support-core-plugin by jenkinsci.
the class SupportPlugin method writeBundle.
/**
* Generate a bundle for all components that are selected in the Global Configuration.
*
* @param outputStream an {@link OutputStream}
* @param components a list of {@link Component} to include in the bundle
* @param componentConsumer a {@link ComponentVisitor}
* @throws IOException if an error occurs while generating the bundle.
*/
public static void writeBundle(OutputStream outputStream, final List<? extends Component> components, ComponentVisitor componentConsumer) throws IOException {
StringBuilder manifest = new StringBuilder();
StringWriter errors = new StringWriter();
PrintWriter errorWriter = new PrintWriter(errors);
try {
try (BulkChange change = new BulkChange(ContentMappings.get());
ZipArchiveOutputStream binaryOut = new ZipArchiveOutputStream(new BufferedOutputStream(outputStream, 16384))) {
// Get the filter to be used
Optional<ContentFilter> maybeFilter = getContentFilter();
// Recalculate the mappings and stop words and save it to disk
if (maybeFilter.isPresent()) {
reloadAndSaveMappings(maybeFilter.get());
}
// Generate the content of the manifest.md going trough all the components which will be included. It
// also returns the contents to include. We pass maybeFilter to filter the names written in the manifest
appendManifestHeader(manifest);
List<Content> contents = appendManifestContents(manifest, errorWriter, components, componentConsumer, maybeFilter);
contents.add(new UnfilteredStringContent("manifest.md", manifest.toString()));
Optional<FilteredOutputStream> maybeFilteredOut = maybeFilter.map(filter -> new FilteredOutputStream(binaryOut, filter));
OutputStream textOut = maybeFilteredOut.map(OutputStream.class::cast).orElse(binaryOut);
OutputStreamSelector selector = new OutputStreamSelector(() -> binaryOut, () -> textOut);
IgnoreCloseOutputStream unfilteredOut = new IgnoreCloseOutputStream(binaryOut);
IgnoreCloseOutputStream filteredOut = new IgnoreCloseOutputStream(selector);
boolean entryCreated = false;
for (Content content : contents) {
if (content == null) {
continue;
}
final String name = getNameFiltered(maybeFilter, content.getName(), content.getFilterableParameters());
try {
final ZipArchiveEntry entry = new ZipArchiveEntry(name);
entry.setTime(content.getTime());
binaryOut.putArchiveEntry(entry);
entryCreated = true;
binaryOut.flush();
OutputStream out = content.shouldBeFiltered() ? filteredOut : unfilteredOut;
if (content instanceof PrefilteredContent && maybeFilter.isPresent()) {
((PrefilteredContent) content).writeTo(out, maybeFilter.get());
} else {
content.writeTo(out);
}
out.flush();
} catch (Throwable e) {
String msg = "Could not attach ''" + name + "'' to support bundle";
logger.log(e instanceof ChannelClosedException ? Level.FINE : Level.WARNING, msg, e);
errorWriter.println(msg);
errorWriter.println("-----------------------------------------------------------------------");
errorWriter.println();
Functions.printStackTrace(e, errorWriter);
errorWriter.println();
} finally {
maybeFilteredOut.ifPresent(FilteredOutputStream::reset);
selector.reset();
if (entryCreated) {
binaryOut.closeArchiveEntry();
entryCreated = false;
}
}
}
errorWriter.close();
String errorContent = errors.toString();
if (StringUtils.isNotBlank(errorContent)) {
try {
binaryOut.putArchiveEntry(new ZipArchiveEntry("manifest/errors.txt"));
entryCreated = true;
textOut.write(errorContent.getBytes(StandardCharsets.UTF_8));
textOut.flush();
} catch (IOException e) {
logger.log(Level.WARNING, "Could not write manifest/errors.txt to zip archive", e);
} finally {
if (entryCreated) {
binaryOut.closeArchiveEntry();
}
}
}
binaryOut.flush();
change.commit();
}
} finally {
outputStream.flush();
}
}
Aggregations