diff --git a/bigbluebutton-web/grails-app/conf/bigbluebutton.properties b/bigbluebutton-web/grails-app/conf/bigbluebutton.properties index 4d2449ac1c..90b0159b6a 100644 --- a/bigbluebutton-web/grails-app/conf/bigbluebutton.properties +++ b/bigbluebutton-web/grails-app/conf/bigbluebutton.properties @@ -34,21 +34,11 @@ swfToolsDir=/usr/bin # Directory where ImageMagick's convert executable is located imageMagickDir=/usr/bin -#---------------------------------------------------- -# Use fullpath to ghostscript executable since the exec names are different -# for each platform. -ghostScriptExec=/usr/bin/gs - #---------------------------------------------------- # Fonts directory passed into PDF2SWF to support highlighting of texts # in the SWF slides. fontsDir=/usr/share/fonts -#---------------------------------------------------- -# This is a workaround for a problem converting PDF files, referenced at -# http://groups.google.com/group/comp.lang.postscript/browse_thread/thread/c2e264ca76534ce0?pli=1 -noPdfMarkWorkaround=/etc/bigbluebutton/nopdfmark.ps - #---------------------------------------------------- # These will be copied in cases where the conversion process # fails to generate a slide from the uploaded presentation diff --git a/bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml b/bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml index ef45191fb0..c5e483f0af 100755 --- a/bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml +++ b/bigbluebutton-web/grails-app/conf/spring/doc-conversion.xml @@ -21,8 +21,7 @@ with BigBlueButton; if not, see . + http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> @@ -37,15 +36,8 @@ with BigBlueButton; if not, see . - - - - - - - - - + + @@ -64,21 +56,13 @@ with BigBlueButton; if not, see . - - - - - - - - @@ -98,7 +82,6 @@ with BigBlueButton; if not, see . - diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/PdfToSwfSlide.java b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/PdfToSwfSlide.java index 7abc436273..b3b00f667c 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/PdfToSwfSlide.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/PdfToSwfSlide.java @@ -25,7 +25,6 @@ import java.util.HashMap; import java.util.Map; import org.apache.commons.io.FileUtils; -import org.bigbluebutton.presentation.imp.PdfPageToImageConversionService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,7 +36,6 @@ public class PdfToSwfSlide { private UploadedPresentation pres; private int page; private PageConverter pdfToSwfConverter; - private PdfPageToImageConversionService imageConvertService; private String BLANK_SLIDE; private int MAX_SWF_FILE_SIZE; @@ -49,28 +47,16 @@ public class PdfToSwfSlide { this.page = page; } - public PdfToSwfSlide createSlide() { + public PdfToSwfSlide createSlide() { File presentationFile = pres.getUploadedFile(); - slide = new File(presentationFile.getParent() + File.separatorChar + "slide-" + page + ".swf"); - if (! pdfToSwfConverter.convert(presentationFile, slide, page, pres)) { - Map logData = new HashMap(); - logData.put("meetingId", pres.getMeetingId()); - logData.put("presId", pres.getId()); - logData.put("filename", pres.getName()); - logData.put("page", page); - logData.put("size(KB)", slide.length()/1024); - - Gson gson = new Gson(); - String logStr = gson.toJson(logData); - - log.warn("Failed to convert slide: data={}", logStr); - - imageConvertService.convertPageAsAnImage(presentationFile, slide, page, pres); - } + slide = new File(presentationFile.getParent() + File.separatorChar + + "slide-" + page + ".swf"); + pdfToSwfConverter.convert(presentationFile, slide, page, pres); // If all fails, generate a blank slide. if (!slide.exists()) { - log.warn("Failed to create slide. Creating blank slide for " + slide.getAbsolutePath()); + log.warn("Failed to create slide. Creating blank slide for " + + slide.getAbsolutePath()); generateBlankSlide(); } @@ -79,13 +65,6 @@ public class PdfToSwfSlide { return this; } - private boolean slideMayHaveTooManyObjects(File slide) { - // If the resulting swf file is greater than 500K, it probably contains a lot of objects - // that it becomes very slow to render on the client. Take an image snapshot instead and - // use it to generate the SWF file. (ralam Sept 2, 2009) - return slide.length() > MAX_SWF_FILE_SIZE; - } - public void generateBlankSlide() { if (BLANK_SLIDE != null) { Map logData = new HashMap(); @@ -95,7 +74,7 @@ public class PdfToSwfSlide { logData.put("page", page); Gson gson = new Gson(); - String logStr = gson.toJson(logData); + String logStr = gson.toJson(logData); log.warn("Creating blank slide: data={}", logStr); @@ -108,10 +87,10 @@ public class PdfToSwfSlide { logData.put("page", page); Gson gson = new Gson(); - String logStr = gson.toJson(logData); + String logStr = gson.toJson(logData); log.warn("Failed to create blank slide: data={}", logStr); - } + } } private void copyBlankSlide(File slide) { @@ -126,10 +105,6 @@ public class PdfToSwfSlide { this.pdfToSwfConverter = converter; } - public void setPdfPageToImageConversionService(PdfPageToImageConversionService service) { - this.imageConvertService = service; - } - public void setBlankSlide(String blankSlide) { this.BLANK_SLIDE = blankSlide; } diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/GhostscriptPageExtractor.java b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/GhostscriptPageExtractor.java index 87b2f16a47..3fd17a7499 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/GhostscriptPageExtractor.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/GhostscriptPageExtractor.java @@ -26,35 +26,17 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class GhostscriptPageExtractor implements PageExtractor { - private static Logger log = LoggerFactory - .getLogger(GhostscriptPageExtractor.class); + private static Logger log = LoggerFactory + .getLogger(GhostscriptPageExtractor.class); - private String GHOSTSCRIPT_EXEC; - private String noPdfMarkWorkaround; - private String SPACE = " "; + private String SPACE = " "; - public boolean extractPage(File presentationFile, File output, int page) { - String OPTIONS = "-sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH"; - String FIRST_PAGE = "-dFirstPage=" + page; - String LAST_PAGE = "-dLastPage=" + page; - String DESTINATION = output.getAbsolutePath(); - String OUTPUT_FILE = "-sOutputFile=" + DESTINATION; + public boolean extractPage(File presentationFile, File output, int page) { + String COMMAND = "pdfseparate -f " + page + " -l " + page + SPACE + + presentationFile.getAbsolutePath() + SPACE + output.getAbsolutePath(); - // extract that specific page and create a temp-pdf(only one page) with - // GhostScript - String COMMAND = GHOSTSCRIPT_EXEC + SPACE + OPTIONS + SPACE - + FIRST_PAGE + SPACE + LAST_PAGE + SPACE + OUTPUT_FILE + SPACE - + noPdfMarkWorkaround + SPACE - + presentationFile.getAbsolutePath(); - - return new ExternalProcessExecutor().exec(COMMAND, 60000); - } - - public void setGhostscriptExec(String exec) { - GHOSTSCRIPT_EXEC = exec; - } - - public void setNoPdfMarkWorkaround(String noPdfMarkWorkaround) { - this.noPdfMarkWorkaround = noPdfMarkWorkaround; - } + log.info("Extracting page {} for document {}", page, + presentationFile.getAbsolutePath()); + return new ExternalProcessExecutor().exec(COMMAND, 60000); + } } diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/ImageMagickPageConverter.java b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/ImageMagickPageConverter.java deleted file mode 100755 index 05985617a3..0000000000 --- a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/ImageMagickPageConverter.java +++ /dev/null @@ -1,54 +0,0 @@ -/** - * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ - * - * Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below). - * - * This program is free software; you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation; either version 3.0 of the License, or (at your option) any later - * version. - * - * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along - * with BigBlueButton; if not, see . - * - */ - -package org.bigbluebutton.presentation.imp; - -import java.io.File; - -import org.bigbluebutton.presentation.PageConverter; -import org.bigbluebutton.presentation.UploadedPresentation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ImageMagickPageConverter implements PageConverter { - private static Logger log = LoggerFactory.getLogger(ImageMagickPageConverter.class); - - private String IMAGEMAGICK_DIR; - - public boolean convert(File presentationFile, File output, int page, UploadedPresentation pres){ - - String COMMAND = IMAGEMAGICK_DIR + "/convert -depth 8 " + presentationFile.getAbsolutePath() + " " + output.getAbsolutePath(); - - boolean done = new ExternalProcessExecutor().exec(COMMAND, 60000); - - if (done && output.exists()) { - return true; - } else { - log.warn("Failed to convert: " + output.getAbsolutePath() + " does not exist."); - return false; - } - - } - - public void setImageMagickDir(String dir) { - IMAGEMAGICK_DIR = dir; - } -} - - diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Jpeg2SwfPageConverter.java b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Jpeg2SwfPageConverter.java index 16e4b28056..508f503936 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Jpeg2SwfPageConverter.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Jpeg2SwfPageConverter.java @@ -33,7 +33,7 @@ public class Jpeg2SwfPageConverter implements PageConverter { public boolean convert(File presentationFile, File output, int page, UploadedPresentation pres){ - String COMMAND = SWFTOOLS_DIR + "/jpeg2swf -o " + output.getAbsolutePath() + " " + presentationFile.getAbsolutePath(); + String COMMAND = SWFTOOLS_DIR + File.separator + "jpeg2swf -o " + output.getAbsolutePath() + " " + presentationFile.getAbsolutePath(); boolean done = new ExternalProcessExecutor().exec(COMMAND, 60000); diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Pdf2SwfPageConverter.java b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Pdf2SwfPageConverter.java index 97a9d8c1b6..be9d068f0c 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Pdf2SwfPageConverter.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Pdf2SwfPageConverter.java @@ -44,10 +44,8 @@ public class Pdf2SwfPageConverter implements PageConverter { private static Logger log = LoggerFactory .getLogger(Pdf2SwfPageConverter.class); - private String GHOSTSCRIPT_EXEC; private String SWFTOOLS_DIR; private String fontsDir; - private String noPdfMarkWorkaround; private long placementsThreshold; private long defineTextThreshold; private long imageTagThreshold; @@ -86,13 +84,6 @@ public class Pdf2SwfPageConverter implements PageConverter { long pdf2SwfEnd = System.currentTimeMillis(); log.debug("Pdf2Swf conversion duration: {} sec", (pdf2SwfEnd - pdf2SwfStart) / 1000); - boolean timedOut = pdf2SwfEnd - - pdf2SwfStart >= Integer.parseInt(convTimeout.replaceFirst("s", "")) - * 1000; - boolean twiceTotalObjects = pHandler.numberOfPlacements() - + pHandler.numberOfTextTags() - + pHandler.numberOfImageTags() >= (placementsThreshold - + defineTextThreshold + imageTagThreshold) * 2; File destFile = new File(dest); if (pHandler.isConversionSuccessful() && destFile.exists() @@ -122,7 +113,6 @@ public class Pdf2SwfPageConverter implements PageConverter { log.warn("Potential problem with generated SWF: data={}", logStr); - File tempPdfPage = null; File tempPng = null; String basePresentationame = FilenameUtils .getBaseName(presentation.getName()); @@ -135,14 +125,12 @@ public class Pdf2SwfPageConverter implements PageConverter { long gsStart = System.currentTimeMillis(); - // Step 1: Convert a PDF page to PNG using a raw GhostScript command + // Step 1: Convert a PDF page to PNG using a raw pdftocairo NuProcessBuilder pbPng = new NuProcessBuilder(Arrays.asList("timeout", - convTimeout, GHOSTSCRIPT_EXEC, "-sDEVICE=png16m", "-dNOPAUSE", - "-dQUIET", "-dBATCH", - !timedOut && !twiceTotalObjects ? "-r150" : "-r72", - "-dGraphicsAlphaBits=4", "-dTextAlphaBits=4", "-dFirstPage=" + page, - "-dLastPage=" + page, "-sOutputFile=" + tempPng.getAbsolutePath(), - noPdfMarkWorkaround, presentation.getAbsolutePath())); + convTimeout, "pdftocairo", "-png", "-singlefile", "-r", "150", "-f", + String.valueOf(page), "-l", String.valueOf(page), + presentation.getAbsolutePath(), tempPng.getAbsolutePath().substring(0, + tempPng.getAbsolutePath().lastIndexOf('.')))); Pdf2PngPageConverterHandler pbPngHandler = new Pdf2PngPageConverterHandler(); pbPng.setProcessListener(pbPngHandler); @@ -154,12 +142,13 @@ public class Pdf2SwfPageConverter implements PageConverter { } long gsEnd = System.currentTimeMillis(); - log.debug("Ghostscript conversion duration: {} sec", + log.debug("pdftocairo conversion duration: {} sec", (gsEnd - gsStart) / 1000); long png2swfStart = System.currentTimeMillis(); // Step 2: Convert a PNG image to SWF + // We need to update the file path as pdftocairo adds "-page.png" source = tempPng.getAbsolutePath(); NuProcessBuilder pbSwf = new NuProcessBuilder( Arrays.asList("timeout", convTimeout, @@ -174,7 +163,7 @@ public class Pdf2SwfPageConverter implements PageConverter { } long png2swfEnd = System.currentTimeMillis(); - log.debug("ImageMagick conversion duration: {} sec", + log.debug("SwfTools conversion duration: {} sec", (png2swfEnd - png2swfStart) / 1000); // Delete the temporary PNG and PDF files after finishing the image @@ -225,13 +214,4 @@ public class Pdf2SwfPageConverter implements PageConverter { public void setImageTagThreshold(long threshold) { imageTagThreshold = threshold; } - - public void setGhostscriptExec(String exec) { - GHOSTSCRIPT_EXEC = exec; - } - - public void setNoPdfMarkWorkaround(String noPdfMarkWorkaround) { - this.noPdfMarkWorkaround = noPdfMarkWorkaround; - } - } diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Pdf2SwfPageCounter.java b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Pdf2SwfPageCounter.java index 2e917caf12..1e7aa0248c 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Pdf2SwfPageCounter.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Pdf2SwfPageCounter.java @@ -40,7 +40,7 @@ public class Pdf2SwfPageCounter implements PageCounter { public int countNumberOfPages(File presentationFile) { int numPages = 0; //total numbers of this pdf - String COMMAND = SWFTOOLS_DIR + "/pdf2swf -I " + presentationFile.getAbsolutePath(); + String COMMAND = SWFTOOLS_DIR + File.separator + "pdf2swf -I " + presentationFile.getAbsolutePath(); Timer timer = null; Process p = null; diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/PdfPageToImageConversionService.java b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/PdfPageToImageConversionService.java deleted file mode 100755 index 6d6bac6985..0000000000 --- a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/PdfPageToImageConversionService.java +++ /dev/null @@ -1,67 +0,0 @@ -/** - * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/ - * - * Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below). - * - * This program is free software; you can redistribute it and/or modify it under the - * terms of the GNU Lesser General Public License as published by the Free Software - * Foundation; either version 3.0 of the License, or (at your option) any later - * version. - * - * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License along - * with BigBlueButton; if not, see . - * - */ - -package org.bigbluebutton.presentation.imp; - -import java.io.File; - -import org.bigbluebutton.presentation.PageConverter; -import org.bigbluebutton.presentation.PageExtractor; -import org.bigbluebutton.presentation.UploadedPresentation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PdfPageToImageConversionService { - private static Logger log = LoggerFactory.getLogger(PdfPageToImageConversionService.class); - - private PageExtractor extractor; - private PageConverter pdfToImageConverter; - private PageConverter imageToSwfConverter; - - public boolean convertPageAsAnImage(File presentationFile, File output, int page, UploadedPresentation pres) { - File tempDir = new File(presentationFile.getParent() + File.separatorChar + "temp"); - tempDir.mkdir(); - - File tempPdfFile = new File(tempDir.getAbsolutePath() + File.separator + "temp-" + page + ".pdf"); - - if (extractor.extractPage(presentationFile, tempPdfFile, page)) { - File tempPngFile = new File(tempDir.getAbsolutePath() + "/temp-" + page + ".svg"); - - if (pdfToImageConverter.convert(tempPdfFile, tempPngFile, 1, pres)) { - if (imageToSwfConverter.convert(tempPngFile, output, 1, pres)) { - return true; - } - } - } - - return false; - } - - public void setPageExtractor(PageExtractor extractor) { - this.extractor = extractor; - } - - public void setPdfToImageConverter(PageConverter imageConverter) { - this.pdfToImageConverter = imageConverter; - } - - public void setImageToSwfConverter(PageConverter swfConverter) { - this.imageToSwfConverter = swfConverter; - } -} diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/PdfToSwfSlidesGenerationService.java b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/PdfToSwfSlidesGenerationService.java index 929dcfb259..a1e6995f73 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/PdfToSwfSlidesGenerationService.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/PdfToSwfSlidesGenerationService.java @@ -48,22 +48,21 @@ import org.slf4j.LoggerFactory; import com.google.gson.Gson; public class PdfToSwfSlidesGenerationService { - private static Logger log = LoggerFactory.getLogger(PdfToSwfSlidesGenerationService.class); + private static Logger log = LoggerFactory + .getLogger(PdfToSwfSlidesGenerationService.class); private SwfSlidesGenerationProgressNotifier notifier; private PageCounterService counterService; private PageConverter pdfToSwfConverter; - private PdfPageToImageConversionService imageConvertService; - private ExecutorService executor; + private ExecutorService executor; private ThumbnailCreator thumbnailCreator; private TextFileCreator textFileCreator; private SvgImageCreator svgImageCreator; - private long MAX_CONVERSION_TIME = 5*60*1000; + private long MAX_CONVERSION_TIME = 5 * 60 * 1000; private String BLANK_SLIDE; private int MAX_SWF_FILE_SIZE; private boolean svgImagesRequired; private final long CONVERSION_TIMEOUT = 20000000000L; // 20s - private int NUM_CONVERSION_THREADS = 2; public PdfToSwfSlidesGenerationService(int numConversionThreads) { executor = Executors.newFixedThreadPool(numConversionThreads); @@ -82,7 +81,7 @@ public class PdfToSwfSlidesGenerationService { } notifier.sendConversionCompletedMessage(pres); - } + } } private boolean determineNumberOfPages(UploadedPresentation pres) { @@ -95,12 +94,15 @@ public class PdfToSwfSlidesGenerationService { return false; } - private void sendFailedToCountPageMessage(CountingPageException e, UploadedPresentation pres) { + private void sendFailedToCountPageMessage(CountingPageException e, + UploadedPresentation pres) { MessageBuilder builder = new ConversionUpdateMessage.MessageBuilder(pres); - if (e.getExceptionType() == CountingPageException.ExceptionType.PAGE_COUNT_EXCEPTION) { - builder.messageKey(ConversionMessageConstants.PAGE_COUNT_FAILED_KEY); - } else if (e.getExceptionType() == CountingPageException.ExceptionType.PAGE_EXCEEDED_EXCEPTION) { + if (e + .getExceptionType() == CountingPageException.ExceptionType.PAGE_COUNT_EXCEPTION) { + builder.messageKey(ConversionMessageConstants.PAGE_COUNT_FAILED_KEY); + } else if (e + .getExceptionType() == CountingPageException.ExceptionType.PAGE_EXCEEDED_EXCEPTION) { builder.numberOfPages(e.getPageCount()); builder.maxNumberPages(e.getMaxNumberOfPages()); builder.messageKey(ConversionMessageConstants.PAGE_COUNT_EXCEEDED_KEY); @@ -124,16 +126,19 @@ public class PdfToSwfSlidesGenerationService { } private void convertPdfToSwf(UploadedPresentation pres) { - int numPages = pres.getNumberOfPages(); + int numPages = pres.getNumberOfPages(); List slides = setupSlides(pres, numPages); - CompletionService completionService = new ExecutorCompletionService(executor); + CompletionService completionService = new ExecutorCompletionService( + executor); - generateSlides(pres, slides, completionService); + generateSlides(pres, slides, completionService); } - private void generateSlides(UploadedPresentation pres, List slides, CompletionService completionService) { - long MAXWAIT = MAX_CONVERSION_TIME * 60 /*seconds*/ * 1000 /*millis*/; + private void generateSlides(UploadedPresentation pres, + List slides, + CompletionService completionService) { + long MAXWAIT = MAX_CONVERSION_TIME * 60 /* seconds */ * 1000 /* millis */; int slidesCompleted = 0; long presConvStart = System.currentTimeMillis(); @@ -150,12 +155,12 @@ public class PdfToSwfSlidesGenerationService { Future f = executor.submit(c); long endNanos = System.nanoTime() + CONVERSION_TIMEOUT; try { - // Only wait for the remaining time budget - long timeLeft = endNanos - System.nanoTime(); + // Only wait for the remaining time budget + long timeLeft = endNanos - System.nanoTime(); PdfToSwfSlide s = f.get(timeLeft, TimeUnit.NANOSECONDS); slidesCompleted++; notifier.sendConversionUpdateMessage(slidesCompleted, pres); - } catch (ExecutionException e) { + } catch (ExecutionException e) { Map logData = new HashMap(); logData.put("meetingId", pres.getMeetingId()); logData.put("presId", pres.getId()); @@ -163,11 +168,11 @@ public class PdfToSwfSlidesGenerationService { logData.put("page", slide.getPageNumber()); Gson gson = new Gson(); - String logStr = gson.toJson(logData); + String logStr = gson.toJson(logData); log.warn("ExecutionException while converting page: data={}", logStr); log.error(e.getMessage()); - } catch (InterruptedException e) { + } catch (InterruptedException e) { Map logData = new HashMap(); logData.put("meetingId", pres.getMeetingId()); logData.put("presId", pres.getId()); @@ -175,11 +180,11 @@ public class PdfToSwfSlidesGenerationService { logData.put("page", slide.getPageNumber()); Gson gson = new Gson(); - String logStr = gson.toJson(logData); + String logStr = gson.toJson(logData); log.warn("InterruptedException while converting page: data={}", logStr); - Thread.currentThread().interrupt(); - } catch (TimeoutException e) { + Thread.currentThread().interrupt(); + } catch (TimeoutException e) { Map logData = new HashMap(); logData.put("meetingId", pres.getMeetingId()); logData.put("presId", pres.getId()); @@ -187,11 +192,11 @@ public class PdfToSwfSlidesGenerationService { logData.put("page", slide.getPageNumber()); Gson gson = new Gson(); - String logStr = gson.toJson(logData); + String logStr = gson.toJson(logData); log.warn("TimeoutException while converting page: data={}", logStr); - f.cancel(true); - } + f.cancel(true); + } long pageConvEnd = System.currentTimeMillis(); Map logData = new HashMap(); @@ -199,18 +204,18 @@ public class PdfToSwfSlidesGenerationService { logData.put("presId", pres.getId()); logData.put("filename", pres.getName()); logData.put("page", slide.getPageNumber()); - logData.put("conversionTime(sec)", (pageConvEnd - pageConvStart)/1000); + logData.put("conversionTime(sec)", (pageConvEnd - pageConvStart) / 1000); Gson gson = new Gson(); - String logStr = gson.toJson(logData); + String logStr = gson.toJson(logData); log.debug("Page conversion duration(sec): data={}", logStr); - } + } for (final PdfToSwfSlide slide : slides) { - if (! slide.isDone()){ + if (!slide.isDone()) { - slide.generateBlankSlide(); + slide.generateBlankSlide(); Map logData = new HashMap(); logData.put("meetingId", pres.getMeetingId()); @@ -218,12 +223,12 @@ public class PdfToSwfSlidesGenerationService { logData.put("filename", pres.getName()); Gson gson = new Gson(); - String logStr = gson.toJson(logData); + String logStr = gson.toJson(logData); log.warn("Creating blank slide: data={}", logStr); notifier.sendConversionUpdateMessage(slidesCompleted++, pres); - } + } } long presConvEnd = System.currentTimeMillis(); @@ -231,23 +236,22 @@ public class PdfToSwfSlidesGenerationService { logData.put("meetingId", pres.getMeetingId()); logData.put("presId", pres.getId()); logData.put("filename", pres.getName()); - logData.put("conversionTime(sec)", (presConvEnd - presConvStart)/1000); + logData.put("conversionTime(sec)", (presConvEnd - presConvStart) / 1000); Gson gson = new Gson(); - String logStr = gson.toJson(logData); + String logStr = gson.toJson(logData); log.debug("Presentation conversion duration (sec): data={}", logStr); } - - private List setupSlides(UploadedPresentation pres, int numPages) { + private List setupSlides(UploadedPresentation pres, + int numPages) { List slides = new ArrayList(numPages); - for (int page = 1; page <= numPages; page++) { + for (int page = 1; page <= numPages; page++) { PdfToSwfSlide slide = new PdfToSwfSlide(pres, page); slide.setBlankSlide(BLANK_SLIDE); slide.setMaxSwfFileSize(MAX_SWF_FILE_SIZE); slide.setPageConverter(pdfToSwfConverter); - slide.setPdfPageToImageConversionService(imageConvertService); slides.add(slide); } @@ -255,8 +259,6 @@ public class PdfToSwfSlidesGenerationService { return slides; } - - public void setCounterService(PageCounterService counterService) { this.counterService = counterService; } @@ -265,10 +267,6 @@ public class PdfToSwfSlidesGenerationService { this.pdfToSwfConverter = converter; } - public void setPdfPageToImageConversionService(PdfPageToImageConversionService service) { - this.imageConvertService = service; - } - public void setBlankSlide(String blankSlide) { this.BLANK_SLIDE = blankSlide; } @@ -284,17 +282,21 @@ public class PdfToSwfSlidesGenerationService { public void setThumbnailCreator(ThumbnailCreator thumbnailCreator) { this.thumbnailCreator = thumbnailCreator; } + public void setTextFileCreator(TextFileCreator textFileCreator) { this.textFileCreator = textFileCreator; } + public void setSvgImageCreator(SvgImageCreator svgImageCreator) { this.svgImageCreator = svgImageCreator; } + public void setMaxConversionTime(int minutes) { MAX_CONVERSION_TIME = minutes * 60 * 1000; } - public void setSwfSlidesGenerationProgressNotifier(SwfSlidesGenerationProgressNotifier notifier) { + public void setSwfSlidesGenerationProgressNotifier( + SwfSlidesGenerationProgressNotifier notifier) { this.notifier = notifier; } diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Png2SwfPageConverter.java b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Png2SwfPageConverter.java index e7c72f6703..92def9c6d7 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Png2SwfPageConverter.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/Png2SwfPageConverter.java @@ -32,7 +32,7 @@ public class Png2SwfPageConverter implements PageConverter { private String SWFTOOLS_DIR; public boolean convert(File presentationFile, File output, int page, UploadedPresentation pres){ - String COMMAND = SWFTOOLS_DIR + "/png2swf -o " + output.getAbsolutePath() + " " + presentationFile.getAbsolutePath(); + String COMMAND = SWFTOOLS_DIR + File.separator + "png2swf -o " + output.getAbsolutePath() + " " + presentationFile.getAbsolutePath(); boolean done = new ExternalProcessExecutor().exec(COMMAND, 60000); diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/SvgImageCreatorImp.java b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/SvgImageCreatorImp.java index f9ee00f0ab..58834724cd 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/SvgImageCreatorImp.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/SvgImageCreatorImp.java @@ -9,113 +9,88 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class SvgImageCreatorImp implements SvgImageCreator { - private static Logger log = LoggerFactory - .getLogger(SvgImageCreatorImp.class); + private static Logger log = LoggerFactory.getLogger(SvgImageCreatorImp.class); - private String IMAGEMAGICK_DIR; + private String IMAGEMAGICK_DIR; - @Override - public boolean createSvgImages(UploadedPresentation pres) { - boolean success = false; - File svgImagesPresentationDir = determineSvgImagesDirectory(pres - .getUploadedFile()); - if (!svgImagesPresentationDir.exists()) - svgImagesPresentationDir.mkdir(); + @Override + public boolean createSvgImages(UploadedPresentation pres) { + boolean success = false; + File svgImagesPresentationDir = determineSvgImagesDirectory( + pres.getUploadedFile()); + if (!svgImagesPresentationDir.exists()) + svgImagesPresentationDir.mkdir(); - cleanDirectory(svgImagesPresentationDir); + cleanDirectory(svgImagesPresentationDir); - try { - extractPdfPages(pres); - success = generateSvgImages(svgImagesPresentationDir, pres); - } catch (InterruptedException e) { - log.warn("Interrupted Exception while generating images."); - success = false; + try { + success = generateSvgImages(svgImagesPresentationDir, pres); + } catch (InterruptedException e) { + log.warn("Interrupted Exception while generating images."); + success = false; + } + + return success; + } + + private boolean generateSvgImages(File imagePresentationDir, + UploadedPresentation pres) throws InterruptedException { + String source = pres.getUploadedFile().getAbsolutePath(); + String dest; + String COMMAND = ""; + boolean done = true; + if (SupportedFileTypes.isImageFile(pres.getFileType())) { + dest = imagePresentationDir.getAbsolutePath() + File.separator + + "slide1.pdf"; + COMMAND = IMAGEMAGICK_DIR + File.separator + "convert " + source + " " + + dest; + + done = new ExternalProcessExecutor().exec(COMMAND, 60000); + + source = imagePresentationDir.getAbsolutePath() + File.separator + + "slide1.pdf"; + dest = imagePresentationDir.getAbsolutePath() + File.separator + + "slide1.svg"; + COMMAND = "pdftocairo -rx 300 -ry 300 -svg -q -f 1 -l 1 " + source + " " + + dest; + + done = new ExternalProcessExecutor().exec(COMMAND, 60000); + + } else { + for (int i = 1; i <= pres.getNumberOfPages(); i++) { + File destsvg = new File(imagePresentationDir.getAbsolutePath() + + File.separatorChar + "slide" + i + ".svg"); + COMMAND = "pdftocairo -rx 300 -ry 300 -svg -q -f " + i + " -l " + i + + " " + File.separatorChar + source + " " + + destsvg.getAbsolutePath(); + + done = new ExternalProcessExecutor().exec(COMMAND, 60000); + if (!done) { + break; } - - return success; + } } - private void extractPdfPages(UploadedPresentation pres) { - File pdfDir = new File(pres.getUploadedFile().getParent() - + File.separatorChar + "pdfs"); - if (!pdfDir.exists()) - pdfDir.mkdir(); - - if (SupportedFileTypes.isPdfFile(pres.getFileType())) { - for (int i = 1; i <= pres.getNumberOfPages(); i++) { - File pdfFile = new File(pdfDir.getAbsolutePath() - + File.separatorChar + "slide" + i + ".pdf"); - String COMMAND = IMAGEMAGICK_DIR - + "/gs -sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH -dFirstPage=" - + i + " -dLastPage=" + i + " -sOutputFile=" - + pdfFile.getAbsolutePath() - + " /etc/bigbluebutton/nopdfmark.ps " - + pres.getUploadedFile().getAbsolutePath(); - new ExternalProcessExecutor().exec(COMMAND, 60000); - } - - } + if (done) { + return true; } + log.warn("Failed to create svg images: " + COMMAND); + return false; + } - private boolean generateSvgImages(File imagePresentationDir, - UploadedPresentation pres) throws InterruptedException { - String source = pres.getUploadedFile().getAbsolutePath(); - String dest; - String COMMAND = ""; - boolean done = true; - if (SupportedFileTypes.isImageFile(pres.getFileType())) { - dest = imagePresentationDir.getAbsolutePath() + File.separator - + "slide1.pdf"; - COMMAND = IMAGEMAGICK_DIR + "/convert " + source + " " + dest; - done = new ExternalProcessExecutor().exec(COMMAND, 60000); + private File determineSvgImagesDirectory(File presentationFile) { + return new File(presentationFile.getParent() + File.separatorChar + "svgs"); + } - source = imagePresentationDir.getAbsolutePath() + File.separator - + "slide1.pdf"; - dest = imagePresentationDir.getAbsolutePath() + File.separator - + "slide1.svg"; - COMMAND = "pdftocairo -rx 300 -ry 300 -svg -q -f 1 -l 1 " + source - + " " + dest; - done = new ExternalProcessExecutor().exec(COMMAND, 60000); - - } else { - for (int i = 1; i <= pres.getNumberOfPages(); i++) { - File pdfFile = new File(imagePresentationDir.getParent() - + File.separatorChar + "pdfs" + File.separatorChar - + "slide" + i + ".pdf"); - File destsvg = new File(imagePresentationDir.getAbsolutePath() - + File.separatorChar + "slide" + i + ".svg"); - COMMAND = "pdftocairo -rx 300 -ry 300 -svg -q -f 1 -l 1 " - + File.separatorChar + pdfFile.getAbsolutePath() + " " - + destsvg.getAbsolutePath(); - - done = new ExternalProcessExecutor().exec(COMMAND, 60000); - if (!done) { - break; - } - } - } - - if (done) { - return true; - } - log.warn("Failed to create svg images: " + COMMAND); - return false; + private void cleanDirectory(File directory) { + File[] files = directory.listFiles(); + for (int i = 0; i < files.length; i++) { + files[i].delete(); } + } - private File determineSvgImagesDirectory(File presentationFile) { - return new File(presentationFile.getParent() + File.separatorChar - + "svgs"); - } - - private void cleanDirectory(File directory) { - File[] files = directory.listFiles(); - for (int i = 0; i < files.length; i++) { - files[i].delete(); - } - } - - public void setImageMagickDir(String imageMagickDir) { - IMAGEMAGICK_DIR = imageMagickDir; - } + public void setImageMagickDir(String imageMagickDir) { + IMAGEMAGICK_DIR = imageMagickDir; + } } diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/TextFileCreatorImp.java b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/TextFileCreatorImp.java index 2bfe90bcdc..c3d3c2feec 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/TextFileCreatorImp.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/TextFileCreatorImp.java @@ -32,90 +32,95 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TextFileCreatorImp implements TextFileCreator { - private static Logger log = LoggerFactory.getLogger(TextFileCreatorImp.class); - - private String IMAGEMAGICK_DIR; - - @Override - public boolean createTextFiles(UploadedPresentation pres) { - boolean success = false; - File textfilesDir = determineTextfilesDirectory(pres.getUploadedFile()); - if (! textfilesDir.exists()) - textfilesDir.mkdir(); - - cleanDirectory(textfilesDir); - - try { - success = generateTextFiles(textfilesDir, pres); - } catch (InterruptedException e) { - log.warn("Interrupted Exception while generating thumbnails."); - success = false; - } - - //TODO: in case that it doesn't generated the textfile, we should create a textfile with some message - // createUnavailableTextFile - - return success; - } + private static Logger log = LoggerFactory.getLogger(TextFileCreatorImp.class); - private boolean generateTextFiles(File textfilesDir, UploadedPresentation pres) throws InterruptedException { - boolean success = true; - String source = pres.getUploadedFile().getAbsolutePath(); - String dest; - String COMMAND = ""; - - if(SupportedFileTypes.isImageFile(pres.getFileType())){ - dest = textfilesDir.getAbsolutePath() + File.separator + "slide-1.txt"; - String text = "No text could be retrieved for the slide"; - - File file = new File(dest); - Writer writer = null; - try { - writer = new BufferedWriter(new FileWriter(file)); - writer.write(text); - } catch (IOException e) { - log.error("Error: " + e.getMessage()); - success = false; - } finally { - try { - writer.close(); - } catch (IOException e) { - log.error("Error: " + e.getMessage()); - success = false; - } - } - - }else{ - dest = textfilesDir.getAbsolutePath() + File.separator + "slide-"; - // sudo apt-get install xpdf-utils - for( int i = 1; i <= pres.getNumberOfPages(); i++){ - COMMAND = IMAGEMAGICK_DIR + "/pdftotext -raw -nopgbrk -f "+ i +" -l " + i + " " + source + " " + dest + i + ".txt"; - boolean done = new ExternalProcessExecutor().exec(COMMAND, 60000); - if (!done) { - success = false; - log.warn("Failed to create textfiles: " + COMMAND); - break; - } - } - - } + private String IMAGEMAGICK_DIR; - return success; - } - - private File determineTextfilesDirectory(File presentationFile) { - return new File(presentationFile.getParent() + File.separatorChar + "textfiles"); - } - - private void cleanDirectory(File directory) { - File[] files = directory.listFiles(); - for (int i = 0; i < files.length; i++) { - files[i].delete(); - } - } + @Override + public boolean createTextFiles(UploadedPresentation pres) { + boolean success = false; + File textfilesDir = determineTextfilesDirectory(pres.getUploadedFile()); + if (!textfilesDir.exists()) + textfilesDir.mkdir(); - public void setImageMagickDir(String imageMagickDir) { - IMAGEMAGICK_DIR = imageMagickDir; - } + cleanDirectory(textfilesDir); + + try { + success = generateTextFiles(textfilesDir, pres); + } catch (InterruptedException e) { + log.warn("Interrupted Exception while generating thumbnails."); + success = false; + } + + // TODO: in case that it doesn't generated the textfile, we should create a + // textfile with some message + // createUnavailableTextFile + + return success; + } + + private boolean generateTextFiles(File textfilesDir, + UploadedPresentation pres) throws InterruptedException { + boolean success = true; + String source = pres.getUploadedFile().getAbsolutePath(); + String dest; + String COMMAND = ""; + + if (SupportedFileTypes.isImageFile(pres.getFileType())) { + dest = textfilesDir.getAbsolutePath() + File.separator + "slide-1.txt"; + String text = "No text could be retrieved for the slide"; + + File file = new File(dest); + Writer writer = null; + try { + writer = new BufferedWriter(new FileWriter(file)); + writer.write(text); + } catch (IOException e) { + log.error("Error: " + e.getMessage()); + success = false; + } finally { + try { + writer.close(); + } catch (IOException e) { + log.error("Error: " + e.getMessage()); + success = false; + } + } + + } else { + dest = textfilesDir.getAbsolutePath() + File.separator + "slide-"; + // sudo apt-get install xpdf-utils + for (int i = 1; i <= pres.getNumberOfPages(); i++) { + COMMAND = IMAGEMAGICK_DIR + File.separator + + "pdftotext -raw -nopgbrk -enc UTF-8 -f " + i + " -l " + i + " " + + source + " " + dest + i + ".txt"; + boolean done = new ExternalProcessExecutor().exec(COMMAND, 60000); + if (!done) { + success = false; + log.warn("Failed to create textfiles: " + COMMAND); + break; + } + } + + } + + return success; + } + + private File determineTextfilesDirectory(File presentationFile) { + return new File( + presentationFile.getParent() + File.separatorChar + "textfiles"); + } + + private void cleanDirectory(File directory) { + File[] files = directory.listFiles(); + for (int i = 0; i < files.length; i++) { + files[i].delete(); + } + } + + public void setImageMagickDir(String imageMagickDir) { + IMAGEMAGICK_DIR = imageMagickDir; + } } diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/ThumbnailCreatorImp.java b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/ThumbnailCreatorImp.java index 23978e7e3b..0ae777f479 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/ThumbnailCreatorImp.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/presentation/imp/ThumbnailCreatorImp.java @@ -32,132 +32,142 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ThumbnailCreatorImp implements ThumbnailCreator { - private static Logger log = LoggerFactory.getLogger(ThumbnailCreatorImp.class); - - private static final Pattern PAGE_NUMBER_PATTERN = Pattern.compile("(.+-thumb)-([0-9]+)(.png)"); - - private String IMAGEMAGICK_DIR; - private String BLANK_THUMBNAIL; - - private static String TEMP_THUMB_NAME = "temp-thumb"; - - public boolean createThumbnails(UploadedPresentation pres){ - boolean success = false; - File thumbsDir = determineThumbnailDirectory(pres.getUploadedFile()); - - if (! thumbsDir.exists()) - thumbsDir.mkdir(); - - cleanDirectory(thumbsDir); - - try { - success = generateThumbnails(thumbsDir, pres); - } catch (InterruptedException e) { - log.warn("Interrupted Exception while generating thumbnails."); - success = false; - } - - // Create blank thumbnails for pages that failed to generate a thumbnail. - createBlankThumbnails(thumbsDir, pres.getNumberOfPages()); - - renameThumbnails(thumbsDir); - - return true; - } + private static Logger log = LoggerFactory + .getLogger(ThumbnailCreatorImp.class); - private boolean generateThumbnails(File thumbsDir, UploadedPresentation pres) throws InterruptedException { - String source = pres.getUploadedFile().getAbsolutePath(); - String dest; - String COMMAND = ""; - if(SupportedFileTypes.isImageFile(pres.getFileType())){ - dest = thumbsDir.getAbsolutePath() + File.separator + TEMP_THUMB_NAME + ".png"; - COMMAND = IMAGEMAGICK_DIR + "/convert -thumbnail 150x150 " + source + " " + dest; - }else{ - dest = thumbsDir.getAbsolutePath() + File.separator + "thumb-"; - COMMAND = IMAGEMAGICK_DIR + "/gs -q -sDEVICE=pngalpha -dBATCH -dNOPAUSE -dNOPROMPT -dDOINTERPOLATE -dPDFFitPage -r16 -sOutputFile=" + dest +"%d.png " + source; - } + private static final Pattern PAGE_NUMBER_PATTERN = Pattern + .compile("(.+-thumb)-([0-9]+)(.png)"); - boolean done = new ExternalProcessExecutor().exec(COMMAND, 60000); + private String IMAGEMAGICK_DIR; + private String BLANK_THUMBNAIL; - if (done) { - return true; - } else { - log.warn("Failed to create thumbnails: " + COMMAND); - } + private static String TEMP_THUMB_NAME = "temp-thumb"; - return false; - } + public boolean createThumbnails(UploadedPresentation pres) { + boolean success = false; + File thumbsDir = determineThumbnailDirectory(pres.getUploadedFile()); - private File determineThumbnailDirectory(File presentationFile) { - return new File(presentationFile.getParent() + File.separatorChar + "thumbnails"); - } + if (!thumbsDir.exists()) + thumbsDir.mkdir(); - private void renameThumbnails(File dir) { - /* - * If more than 1 file, filename like 'temp-thumb-X.png' else filename is 'temp-thumb.png' - */ - if (dir.list().length > 1) { - File[] files = dir.listFiles(); - Matcher matcher; - for (int i = 0; i < files.length; i++) { - matcher = PAGE_NUMBER_PATTERN.matcher(files[i].getAbsolutePath()); - if (matcher.matches()) { - // Path should be something like 'c:/temp/bigluebutton/presname/thumbnails/temp-thumb-1.png' - // Extract the page number. There should be 4 matches. - // 0. c:/temp/bigluebutton/presname/thumbnails/temp-thumb-1.png - // 1. c:/temp/bigluebutton/presname/thumbnails/temp-thumb - // 2. 1 ---> what we are interested in - // 3. .png - // We are interested in the second match. - int pageNum = Integer.valueOf(matcher.group(2).trim()).intValue(); - String newFilename = "thumb-" + (pageNum + 1) + ".png"; - File renamedFile = new File(dir.getAbsolutePath() + File.separator + newFilename); - files[i].renameTo(renamedFile); - } - } - } else if (dir.list().length == 1) { - File oldFilename = new File(dir.getAbsolutePath() + File.separator + dir.list()[0]); - String newFilename = "thumb-1.png"; - File renamedFile = new File(oldFilename.getParent() + File.separator + newFilename); - oldFilename.renameTo(renamedFile); - } - } - - private void createBlankThumbnails(File thumbsDir, int pageCount) { - File[] thumbs = thumbsDir.listFiles(); - - if (thumbs.length != pageCount) { - for (int i = 0; i < pageCount; i++) { - File thumb = new File(thumbsDir.getAbsolutePath() + File.separator + TEMP_THUMB_NAME + "-" + i + ".png"); - if (! thumb.exists()) { - log.info("Copying blank thumbnail for slide " + i); - copyBlankThumbnail(thumb); - } - } - } - } + cleanDirectory(thumbsDir); - private void copyBlankThumbnail(File thumb) { - try { - FileUtils.copyFile(new File(BLANK_THUMBNAIL), thumb); - } catch (IOException e) { - log.error("IOException while copying blank thumbnail."); - } - } + try { + success = generateThumbnails(thumbsDir, pres); + } catch (InterruptedException e) { + log.warn("Interrupted Exception while generating thumbnails."); + success = false; + } - private void cleanDirectory(File directory) { - File[] files = directory.listFiles(); - for (int i = 0; i < files.length; i++) { - files[i].delete(); - } - } + // Create blank thumbnails for pages that failed to generate a thumbnail. + createBlankThumbnails(thumbsDir, pres.getNumberOfPages()); - public void setImageMagickDir(String imageMagickDir) { - IMAGEMAGICK_DIR = imageMagickDir; - } + renameThumbnails(thumbsDir); - public void setBlankThumbnail(String blankThumbnail) { - BLANK_THUMBNAIL = blankThumbnail; - } + return success; + } + + private boolean generateThumbnails(File thumbsDir, UploadedPresentation pres) + throws InterruptedException { + String source = pres.getUploadedFile().getAbsolutePath(); + String dest; + String COMMAND = ""; + dest = thumbsDir.getAbsolutePath() + File.separator + TEMP_THUMB_NAME; + if (SupportedFileTypes.isImageFile(pres.getFileType())) { + COMMAND = IMAGEMAGICK_DIR + File.separator + "convert -thumbnail 150x150 " + + source + " " + dest + ".png"; + } else { + COMMAND = "pdftocairo -png -scale-to 150 " + source + " " + dest; + } + + boolean done = new ExternalProcessExecutor().exec(COMMAND, 60000); + + if (done) { + return true; + } else { + log.warn("Failed to create thumbnails: " + COMMAND); + } + + return false; + } + + private File determineThumbnailDirectory(File presentationFile) { + return new File( + presentationFile.getParent() + File.separatorChar + "thumbnails"); + } + + private void renameThumbnails(File dir) { + /* + * If more than 1 file, filename like 'temp-thumb-X.png' else filename is + * 'temp-thumb.png' + */ + if (dir.list().length > 1) { + File[] files = dir.listFiles(); + Matcher matcher; + for (int i = 0; i < files.length; i++) { + matcher = PAGE_NUMBER_PATTERN.matcher(files[i].getAbsolutePath()); + if (matcher.matches()) { + // Path should be something like + // 'c:/temp/bigluebutton/presname/thumbnails/temp-thumb-1.png' + // Extract the page number. There should be 4 matches. + // 0. c:/temp/bigluebutton/presname/thumbnails/temp-thumb-1.png + // 1. c:/temp/bigluebutton/presname/thumbnails/temp-thumb + // 2. 1 ---> what we are interested in + // 3. .png + // We are interested in the second match. + int pageNum = Integer.valueOf(matcher.group(2).trim()).intValue(); + String newFilename = "thumb-" + (pageNum) + ".png"; + File renamedFile = new File( + dir.getAbsolutePath() + File.separator + newFilename); + files[i].renameTo(renamedFile); + } + } + } else if (dir.list().length == 1) { + File oldFilename = new File( + dir.getAbsolutePath() + File.separator + dir.list()[0]); + String newFilename = "thumb-1.png"; + File renamedFile = new File( + oldFilename.getParent() + File.separator + newFilename); + oldFilename.renameTo(renamedFile); + } + } + + private void createBlankThumbnails(File thumbsDir, int pageCount) { + File[] thumbs = thumbsDir.listFiles(); + + if (thumbs.length != pageCount) { + for (int i = 0; i < pageCount; i++) { + File thumb = new File(thumbsDir.getAbsolutePath() + File.separator + + TEMP_THUMB_NAME + "-" + i + ".png"); + if (!thumb.exists()) { + log.info("Copying blank thumbnail for slide " + i); + copyBlankThumbnail(thumb); + } + } + } + } + + private void copyBlankThumbnail(File thumb) { + try { + FileUtils.copyFile(new File(BLANK_THUMBNAIL), thumb); + } catch (IOException e) { + log.error("IOException while copying blank thumbnail."); + } + } + + private void cleanDirectory(File directory) { + File[] files = directory.listFiles(); + for (int i = 0; i < files.length; i++) { + files[i].delete(); + } + } + + public void setImageMagickDir(String imageMagickDir) { + IMAGEMAGICK_DIR = imageMagickDir; + } + + public void setBlankThumbnail(String blankThumbnail) { + BLANK_THUMBNAIL = blankThumbnail; + } }