Skip to content

Commit

Permalink
Close resources when possible. And minor refactorings.
Browse files Browse the repository at this point in the history
  • Loading branch information
sebr72 committed Jun 7, 2024
1 parent c6b2c49 commit 6af0937
Show file tree
Hide file tree
Showing 5 changed files with 312 additions and 231 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.google.common.collect.HashBiMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.RecursiveTask;
Expand Down Expand Up @@ -67,22 +68,14 @@ private void addRequirement(final ProcessorGraphNode node) {
this.requirements.add(node);
}

protected Set<ProcessorGraphNode> getRequirements() {
Set<ProcessorGraphNode> getRequirements() {
return this.requirements;
}

protected Set<ProcessorGraphNode<?, ?>> getDependencies() {
Set<ProcessorGraphNode<?, ?>> getDependencies() {
return this.dependencies;
}

/**
* Returns true if the node has requirements, that is there are other nodes that should be run
* first.
*/
public boolean hasRequirements() {
return !this.requirements.isEmpty();
}

/**
* Create a ForkJoinTask for running in a fork join pool.
*
Expand Down Expand Up @@ -180,49 +173,11 @@ protected Values compute() {
final Values values = this.execContext.getValues();

final Processor<In, Out> process = this.node.processor;
final MetricRegistry registry = this.node.metricRegistry;
final String name =
final String timerName =
String.format(
"%s.compute.%s",
ProcessorGraphNode.class.getName(), process.getClass().getName());
Timer.Context timerContext = registry.timer(name).time();
try {
final In inputParameter = ProcessorUtils.populateInputParameter(process, values);

Out output;
boolean isThrowingException = false;
try {
LOGGER.debug("Executing process: {}", process);
output = process.execute(inputParameter, this.execContext.getContext());
LOGGER.debug("Succeeded in executing process: {}", process);
} catch (RuntimeException e) {
isThrowingException = true;
LOGGER.info("Error while executing process: {}", process, e);
throw e;
} catch (Exception e) {
isThrowingException = true;
LOGGER.info("Error while executing process: {}", process, e);
throw new PrintException("Failed to execute process:" + process, e);
} finally {
if (isThrowingException) {
// the processor is already canceled, so we don't care if something fails
this.execContext.getContext().stopIfCanceled();
registry.counter(name + ".error").inc();
}
}

if (output != null) {
ProcessorUtils.writeProcessorOutputToValues(output, process, values);
}
} finally {
this.execContext.finished(this.node);
final long processorTime =
TimeUnit.MILLISECONDS.convert(timerContext.stop(), TimeUnit.NANOSECONDS);
LOGGER.info(
"Time taken to run processor: '{}' was {} ms",
process.getClass(),
processorTime);
}
executeProcess(process, values, timerName);

this.execContext.getContext().stopIfCanceled();
ProcessorDependencyGraph.tryExecuteNodes(
Expand All @@ -231,5 +186,47 @@ protected Values compute() {
return values;
});
}

private void executeProcess(
final Processor<In, Out> process, final Values values, final String timerName) {
final Timer.Context timerContext = this.node.metricRegistry.timer(timerName).time();
try {
final In inputParameter = ProcessorUtils.populateInputParameter(process, values);

Out output;
try {
LOGGER.debug("Executing process: {}", process);
output = process.execute(inputParameter, this.execContext.getContext());
LOGGER.debug("Succeeded in executing process: {}", process);
} catch (RuntimeException e) {
throw handleException(e, e, process, timerName);
} catch (Exception e) {
throw handleException(e, null, process, timerName);
}

if (output != null) {
ProcessorUtils.writeProcessorOutputToValues(output, process, values);
}
} finally {
this.execContext.finished(this.node);
final long processorTime =
TimeUnit.MILLISECONDS.convert(timerContext.stop(), TimeUnit.NANOSECONDS);
LOGGER.info(
"Time taken to run processor: '{}' was {} ms", process.getClass(), processorTime);
}
}

private RuntimeException handleException(
final Exception cause,
final RuntimeException runtimeCause,
final Processor<In, Out> process,
final String timerName) {
LOGGER.info("Error while executing process: {}", process, cause);
// the processor is already canceled, so we don't care if something fails
this.execContext.getContext().stopIfCanceled();
this.node.metricRegistry.counter(timerName + ".error").inc();
return Objects.requireNonNullElseGet(
runtimeCause, () -> new PrintException("Failed to execute process:" + process, cause));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ public final class HttpImageResolver implements TableColumnConverter<BufferedIma
private static final int IMAGE_SIZE = 48;
private Pattern urlExtractor = Pattern.compile("(.*)");
private int urlGroup = 1;
private BufferedImage defaultImage;
private final BufferedImage defaultImage;

/** Constructor. */
public HttpImageResolver() {
this.defaultImage = new BufferedImage(IMAGE_SIZE, IMAGE_SIZE, BufferedImage.TYPE_4BYTE_ABGR);
}

/**
* Sets the RegExp pattern to use for extracting the url from the text. By default the whole
* Sets the RegExp pattern to use for extracting the url from the text. By default, the whole
* string is used.
*
* <p>For example: <code>.*&amp;img src="([^"]+)".*</code>
Expand All @@ -62,34 +62,44 @@ public BufferedImage resolve(final MfClientHttpRequestFactory requestFactory, fi
Matcher urlMatcher = this.urlExtractor.matcher(text);

if (urlMatcher.matches() && urlMatcher.group(this.urlGroup) != null) {
final String uriString = urlMatcher.group(this.urlGroup);
final String uriText = urlMatcher.group(this.urlGroup);
try {
URI url = new URI(uriString);
URI url = new URI(uriText);
final ClientHttpRequest request = requestFactory.createRequest(url, HttpMethod.GET);
final ClientHttpResponse response = request.execute();
if (response.getStatusCode() == HttpStatus.OK) {
try {
final BufferedImage image = ImageIO.read(response.getBody());
if (image == null) {
LOGGER.warn("The URL: {} is NOT an image format that can be decoded", url);
return this.defaultImage;
}
return image;
} catch (IOException e) {
LOGGER.warn("Image loaded from '{}'is not valid", url, e);
}
} else {
LOGGER.warn(
"Error loading the table row image: {}.\nStatus Code: {}\nStatus Text: {}",
url,
response.getStatusCode(),
response.getStatusText());
try (ClientHttpResponse response = request.execute()) {
return getImageFromResponse(response, url);
}
} catch (RuntimeException | URISyntaxException | IOException e) {
LOGGER.warn("Error loading table row image: {}", uriString, e);
LOGGER.warn(
"Ignored following exception while loading table row image: {} and fallback to default"
+ " image",
uriText,
e);
}
}
return this.defaultImage;
}

private BufferedImage getImageFromResponse(final ClientHttpResponse response, final URI url)
throws IOException {
if (response.getStatusCode() == HttpStatus.OK) {
try {
final BufferedImage image = ImageIO.read(response.getBody());
if (image == null) {
LOGGER.warn("The URL: {} is NOT an image format that can be decoded", url);
return this.defaultImage;
}
return image;
} catch (IOException e) {
LOGGER.warn("Image loaded from '{}'is not valid", url, e);
}
} else {
LOGGER.warn(
"Error loading the table row image: {}.\nStatus Code: {}\nStatus Text: {}",
url,
response.getStatusCode(),
response.getStatusText());
}
return this.defaultImage;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.mapfish.print.processor.jasper;

import static java.nio.file.Files.move;

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
import java.io.File;
Expand Down Expand Up @@ -77,28 +79,12 @@ File compileJasperReport(final File buildFile, final File jasperFile) throws JRE
// another thread is reading it, use a temporary file as a target instead and
// move it (atomic operation) when done. Worst case: we compile a file twice instead
// of once.
File tmpBuildFile =
File.createTempFile(
"temp_", JASPER_REPORT_COMPILED_FILE_EXT, buildFile.getParentFile());

LOGGER.info("Building Jasper report: {}", jasperFile.getAbsolutePath());
LOGGER.debug("To: {}", buildFile.getAbsolutePath());
final Timer.Context compileJasperReport =
this.metricRegistry.timer(getClass().getName() + ".compile." + jasperFile).time();
try {
JasperCompileManager.compileReportToFile(
jasperFile.getAbsolutePath(), tmpBuildFile.getAbsolutePath());
} catch (JRValidationException e) {
LOGGER.error("The report '{}' isn't valid.", jasperFile.getAbsolutePath());
throw e;
} finally {
final long compileTime =
TimeUnit.MILLISECONDS.convert(compileJasperReport.stop(), TimeUnit.NANOSECONDS);
LOGGER.info("Report '{}' built in {}ms.", jasperFile.getAbsolutePath(), compileTime);
final String timerName = getClass().getName() + ".compile." + jasperFile;
try (Timer.Context compileJasperReport = this.metricRegistry.timer(timerName).time()) {
doCompileAndMoveReport(buildFile, jasperFile, compileJasperReport);
}

java.nio.file.Files.move(
tmpBuildFile.toPath(), buildFile.toPath(), StandardCopyOption.ATOMIC_MOVE);
} catch (IOException e) {
throw new JRException(e);
}
Expand All @@ -108,11 +94,45 @@ File compileJasperReport(final File buildFile, final File jasperFile) throws JRE
return buildFile;
}

private static void doCompileAndMoveReport(
final File buildFile, final File jasperFile, final Timer.Context compileTimerContext)
throws JRException, IOException {
final File tmpBuildFile =
File.createTempFile("temp_", JASPER_REPORT_COMPILED_FILE_EXT, buildFile.getParentFile());
try {
JasperCompileManager.compileReportToFile(
jasperFile.getAbsolutePath(), tmpBuildFile.getAbsolutePath());
} catch (JRValidationException e) {
LOGGER.error("The report '{}' isn't valid.", jasperFile.getAbsolutePath());
throw e;
} finally {
final long compileTime =
TimeUnit.MILLISECONDS.convert(compileTimerContext.stop(), TimeUnit.NANOSECONDS);
LOGGER.info("Report '{}' built in {}ms.", jasperFile.getAbsolutePath(), compileTime);
}
move(tmpBuildFile.toPath(), buildFile.toPath(), StandardCopyOption.ATOMIC_MOVE);
}

private Iterable<File> jasperXmlFiles() {
File directoryToSearch = this.directory;
if (directoryToSearch == null) {
File directoryToSearch = getDirectoryToSearch();
final File[] children = directoryToSearch.listFiles();
if (children != null) {
return StreamSupport.stream(Arrays.spliterator(children), false)
.filter(input -> input != null && input.getName().endsWith(JASPER_REPORT_XML_FILE_EXT))
.collect(Collectors.toList());
} else {
throw new IllegalArgumentException(String.format("%s is not a directory", directoryToSearch));
}
}

private File getDirectoryToSearch() {
File directoryToSearch;
if (this.directory == null) {
directoryToSearch = this.configuration.getDirectory();
} else {
directoryToSearch = this.directory;
}

final String configurationAbsolutePath = this.configuration.getDirectory().getAbsolutePath();
if (!directoryToSearch.getAbsolutePath().startsWith(configurationAbsolutePath)) {
throw new IllegalArgumentException(
Expand All @@ -121,14 +141,7 @@ private Iterable<File> jasperXmlFiles() {
+ "configuration directory: %s is not in %s.",
directoryToSearch, this.configuration.getDirectory()));
}
final File[] children = directoryToSearch.listFiles();
if (children != null) {
return StreamSupport.stream(Arrays.spliterator(children), false)
.filter(input -> input != null && input.getName().endsWith(JASPER_REPORT_XML_FILE_EXT))
.collect(Collectors.toList());
} else {
throw new IllegalArgumentException(String.format("%s is not a directory", directoryToSearch));
}
return directoryToSearch;
}

@Override
Expand Down
Loading

0 comments on commit 6af0937

Please sign in to comment.