@Override public boolean exportData(String typeId, String dataId, File directory) { directory.mkdirs(); final File exportTempFile; try { exportTempFile = File.createTempFile( SafeFilenameUtils.makeSafeFilename(StringUtils.rightPad(dataId, 2, '-') + "-"), SafeFilenameUtils.makeSafeFilename("." + typeId), directory); } catch (IOException e) { throw new RuntimeException( "Could not create temp file to export " + typeId + " " + dataId, e); } try { final String fileName = this.exportData(typeId, dataId, new StreamResult(exportTempFile)); if (fileName == null) { logger.info("Skipped: type={} id={}", typeId, dataId); return false; } final File destFile = new File(directory, fileName + "." + typeId + ".xml"); if (destFile.exists()) { logger.warn( "Exporting " + typeId + " " + dataId + " but destination file already exists, it will be overwritten: " + destFile); destFile.delete(); } FileUtils.moveFile(exportTempFile, destFile); logger.info("Exported: {}", destFile); return true; } catch (Exception e) { if (e instanceof RuntimeException) { throw (RuntimeException) e; } throw new RuntimeException("Failed to export " + typeId + " " + dataId, e); } finally { FileUtils.deleteQuietly(exportTempFile); } }
/** * Used by batch import and export to wait for queued tasks to complete. Handles fail-fast * behavior if any of the tasks threw and exception by canceling all queued futures and logging a * summary of the failures. All completed futures are removed from the queue. * * @param futures Queued futures to check for completeness * @param wait If true it will wait for all futures to complete, if false only check for completed * futures * @return a list of futures that either threw exceptions or timed out */ protected List<FutureHolder<?>> waitForFutures( final Queue<? extends FutureHolder<?>> futures, final PrintWriter reportWriter, final File reportDirectory, final boolean wait) throws InterruptedException { final List<FutureHolder<?>> failedFutures = new LinkedList<FutureHolder<?>>(); for (Iterator<? extends FutureHolder<?>> futuresItr = futures.iterator(); futuresItr.hasNext(); ) { final FutureHolder<?> futureHolder = futuresItr.next(); // If waiting, or if not waiting but the future is already done do the get final Future<?> future = futureHolder.getFuture(); if (wait || (!wait && future.isDone())) { futuresItr.remove(); try { // Don't bother doing a get() on canceled futures if (!future.isCancelled()) { if (this.maxWait > 0) { future.get(this.maxWait, this.maxWaitTimeUnit); } else { future.get(); } reportWriter.printf( REPORT_FORMAT, "SUCCESS", futureHolder.getDescription(), futureHolder.getExecutionTimeMillis()); } } catch (CancellationException e) { // Ignore cancellation exceptions } catch (ExecutionException e) { logger.error("Failed: " + futureHolder); futureHolder.setError(e); failedFutures.add(futureHolder); reportWriter.printf( REPORT_FORMAT, "FAIL", futureHolder.getDescription(), futureHolder.getExecutionTimeMillis()); try { final String dataReportName = SafeFilenameUtils.makeSafeFilename( futureHolder.getDataType() + "_" + futureHolder.getDataName() + ".txt"); final File dataReportFile = new File(reportDirectory, dataReportName); final PrintWriter dataReportWriter = new PrintWriter(new BufferedWriter(new FileWriter(dataReportFile))); try { dataReportWriter.println( "FAIL: " + futureHolder.getDataType() + " - " + futureHolder.getDataName()); dataReportWriter.println( "--------------------------------------------------------------------------------"); e.getCause().printStackTrace(dataReportWriter); } finally { IOUtils.closeQuietly(dataReportWriter); } } catch (Exception re) { logger.warn( "Failed to write error report for failed " + futureHolder + ", logging root failure here", e.getCause()); } } catch (TimeoutException e) { logger.warn("Failed: " + futureHolder); futureHolder.setError(e); failedFutures.add(futureHolder); future.cancel(true); reportWriter.printf( REPORT_FORMAT, "TIMEOUT", futureHolder.getDescription(), futureHolder.getExecutionTimeMillis()); } } } return failedFutures; }